diff --git a/src/migration/migrations/2024-07-06T153432Z_AddFeaturedToUser.go b/src/migration/migrations/2024-07-06T153432Z_AddFeaturedToUser.go new file mode 100644 index 00000000..5d6b3929 --- /dev/null +++ b/src/migration/migrations/2024-07-06T153432Z_AddFeaturedToUser.go @@ -0,0 +1,50 @@ +package migrations + +import ( + "context" + "time" + + "git.handmade.network/hmn/hmn/src/migration/types" + "git.handmade.network/hmn/hmn/src/utils" + "github.com/jackc/pgx/v5" +) + +func init() { + registerMigration(AddFeaturedToUser{}) +} + +type AddFeaturedToUser struct{} + +func (m AddFeaturedToUser) Version() types.MigrationVersion { + return types.MigrationVersion(time.Date(2024, 7, 6, 15, 34, 32, 0, time.UTC)) +} + +func (m AddFeaturedToUser) Name() string { + return "AddFeaturedToUser" +} + +func (m AddFeaturedToUser) Description() string { + return "Add featured flag to users" +} + +func (m AddFeaturedToUser) Up(ctx context.Context, tx pgx.Tx) error { + utils.Must1(tx.Exec(ctx, + ` + ALTER TABLE hmn_user + ADD COLUMN featured BOOLEAN NOT NULL DEFAULT false; + CREATE INDEX hmn_user_featured ON hmn_user(featured); + `, + )) + return nil +} + +func (m AddFeaturedToUser) Down(ctx context.Context, tx pgx.Tx) error { + utils.Must1(tx.Exec(ctx, + ` + DROP INDEX hmn_user_featured; + ALTER TABLE hmn_user + DROP COLUMN featured; + `, + )) + return nil +} diff --git a/src/models/user.go b/src/models/user.go index d971b0c1..a7960fcd 100644 --- a/src/models/user.go +++ b/src/models/user.go @@ -31,6 +31,7 @@ type User struct { IsStaff bool `db:"is_staff"` Status UserStatus `db:"status"` EducationRole EduRole `db:"education_role"` + Featured bool `db:"featured"` Name string `db:"name"` Bio string `db:"bio"` diff --git a/src/templates/mapping.go b/src/templates/mapping.go index 69140b16..c92d405a 100644 --- a/src/templates/mapping.go +++ b/src/templates/mapping.go @@ -217,6 +217,7 @@ func UserToTemplate(u *models.User) User { Email: email, IsStaff: u.IsStaff, Status: int(u.Status), + Featured: u.Featured, Name: u.BestName(), Bio: u.Bio, diff --git a/src/templates/src/user_profile.html b/src/templates/src/user_profile.html index ba30e279..73dbb60b 100644 --- a/src/templates/src/user_profile.html +++ b/src/templates/src/user_profile.html @@ -125,6 +125,12 @@ +
+
+ + +
+
diff --git a/src/templates/types.go b/src/templates/types.go index 399c29db..332a6669 100644 --- a/src/templates/types.go +++ b/src/templates/types.go @@ -208,6 +208,7 @@ type User struct { Email string IsStaff bool Status int + Featured bool Name string Blurb string diff --git a/src/website/landing.go b/src/website/landing.go index 90a1e612..2ff4d315 100644 --- a/src/website/landing.go +++ b/src/website/landing.go @@ -4,6 +4,7 @@ import ( "html/template" "net/http" + "git.handmade.network/hmn/hmn/src/db" "git.handmade.network/hmn/hmn/src/hmndata" "git.handmade.network/hmn/hmn/src/hmnurl" "git.handmade.network/hmn/hmn/src/models" @@ -65,18 +66,29 @@ func Index(c *RequestContext) ResponseData { } } - featuredProjects, err := hmndata.FetchProjects(c, c.Conn, c.CurrentUser, hmndata.ProjectsQuery{ - FeaturedOnly: true, - }) + featuredProjectIDs, err := db.QueryScalar[int](c, c.Conn, + ` + SELECT id + FROM project + WHERE featured = true + `, + ) if err != nil { c.Logger.Warn().Err(err).Msg("failed to fetch featured projects") } - var featuredProjectIDs []int - for _, p := range featuredProjects { - featuredProjectIDs = append(featuredProjectIDs, p.Project.ID) + featuredUserIDs, err := db.QueryScalar[int](c, c.Conn, + ` + SELECT id + FROM hmn_user + WHERE featured = true + `, + ) + if err != nil { + c.Logger.Warn().Err(err).Msg("failed to fetch featured users") } featuredItems, err = FetchTimeline(c, c.Conn, c.CurrentUser, lineageBuilder, hmndata.TimelineQuery{ ProjectIDs: featuredProjectIDs, + OwnerIDs: featuredUserIDs, Limit: maxPostsPerTab, }) if err != nil { diff --git a/src/website/user.go b/src/website/user.go index 3ad6bbfe..570725e9 100644 --- a/src/website/user.go +++ b/src/website/user.go @@ -500,15 +500,19 @@ func UserProfileAdminSetOptions(c *RequestContext) ResponseData { return c.RejectRequest("the education role is bad and you should feel bad") } + featuredFlag := c.Req.Form.Get("featured") + featured := featuredFlag != "" + _, err = c.Conn.Exec(c, ` UPDATE hmn_user - SET status = $2, education_role = $3 + SET status = $2, education_role = $3, featured = $4 WHERE id = $1 `, userId, desiredStatus, desiredEduRole, + featured, ) if err != nil { return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to update user admin settings"))