Featured users
This commit is contained in:
parent
ed41600061
commit
5ea589dbfa
|
@ -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
|
||||||
|
}
|
|
@ -31,6 +31,7 @@ type User struct {
|
||||||
IsStaff bool `db:"is_staff"`
|
IsStaff bool `db:"is_staff"`
|
||||||
Status UserStatus `db:"status"`
|
Status UserStatus `db:"status"`
|
||||||
EducationRole EduRole `db:"education_role"`
|
EducationRole EduRole `db:"education_role"`
|
||||||
|
Featured bool `db:"featured"`
|
||||||
|
|
||||||
Name string `db:"name"`
|
Name string `db:"name"`
|
||||||
Bio string `db:"bio"`
|
Bio string `db:"bio"`
|
||||||
|
|
|
@ -217,6 +217,7 @@ func UserToTemplate(u *models.User) User {
|
||||||
Email: email,
|
Email: email,
|
||||||
IsStaff: u.IsStaff,
|
IsStaff: u.IsStaff,
|
||||||
Status: int(u.Status),
|
Status: int(u.Status),
|
||||||
|
Featured: u.Featured,
|
||||||
|
|
||||||
Name: u.BestName(),
|
Name: u.BestName(),
|
||||||
Bio: u.Bio,
|
Bio: u.Bio,
|
||||||
|
|
|
@ -125,6 +125,12 @@
|
||||||
<option value="author" {{ if .ProfileUser.IsEduAuthor }}selected{{ end }}>Author</option>
|
<option value="author" {{ if .ProfileUser.IsEduAuthor }}selected{{ end }}>Author</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="input-group">
|
||||||
|
<div>
|
||||||
|
<input id="featured" name="featured" type="checkbox" {{ if .ProfileUser.Featured }}checked{{ end }} />
|
||||||
|
<label for="featured">Featured</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input class="btn-primary" type="submit" value="Save" />
|
<input class="btn-primary" type="submit" value="Save" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -208,6 +208,7 @@ type User struct {
|
||||||
Email string
|
Email string
|
||||||
IsStaff bool
|
IsStaff bool
|
||||||
Status int
|
Status int
|
||||||
|
Featured bool
|
||||||
|
|
||||||
Name string
|
Name string
|
||||||
Blurb string
|
Blurb string
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"git.handmade.network/hmn/hmn/src/db"
|
||||||
"git.handmade.network/hmn/hmn/src/hmndata"
|
"git.handmade.network/hmn/hmn/src/hmndata"
|
||||||
"git.handmade.network/hmn/hmn/src/hmnurl"
|
"git.handmade.network/hmn/hmn/src/hmnurl"
|
||||||
"git.handmade.network/hmn/hmn/src/models"
|
"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{
|
featuredProjectIDs, err := db.QueryScalar[int](c, c.Conn,
|
||||||
FeaturedOnly: true,
|
`
|
||||||
})
|
SELECT id
|
||||||
|
FROM project
|
||||||
|
WHERE featured = true
|
||||||
|
`,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Logger.Warn().Err(err).Msg("failed to fetch featured projects")
|
c.Logger.Warn().Err(err).Msg("failed to fetch featured projects")
|
||||||
}
|
}
|
||||||
var featuredProjectIDs []int
|
featuredUserIDs, err := db.QueryScalar[int](c, c.Conn,
|
||||||
for _, p := range featuredProjects {
|
`
|
||||||
featuredProjectIDs = append(featuredProjectIDs, p.Project.ID)
|
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{
|
featuredItems, err = FetchTimeline(c, c.Conn, c.CurrentUser, lineageBuilder, hmndata.TimelineQuery{
|
||||||
ProjectIDs: featuredProjectIDs,
|
ProjectIDs: featuredProjectIDs,
|
||||||
|
OwnerIDs: featuredUserIDs,
|
||||||
Limit: maxPostsPerTab,
|
Limit: maxPostsPerTab,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -500,15 +500,19 @@ func UserProfileAdminSetOptions(c *RequestContext) ResponseData {
|
||||||
return c.RejectRequest("the education role is bad and you should feel bad")
|
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,
|
_, err = c.Conn.Exec(c,
|
||||||
`
|
`
|
||||||
UPDATE hmn_user
|
UPDATE hmn_user
|
||||||
SET status = $2, education_role = $3
|
SET status = $2, education_role = $3, featured = $4
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
`,
|
`,
|
||||||
userId,
|
userId,
|
||||||
desiredStatus,
|
desiredStatus,
|
||||||
desiredEduRole,
|
desiredEduRole,
|
||||||
|
featured,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to update user admin settings"))
|
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to update user admin settings"))
|
||||||
|
|
Loading…
Reference in New Issue