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"))