Added project links to project edit page

This commit is contained in:
Asaf Gartner 2021-12-26 12:03:25 +02:00
parent 80f0e3b176
commit eb32b04437
5 changed files with 112 additions and 34 deletions

View File

@ -137,6 +137,19 @@
<div class="c--dim f7">Plaintext only. No links or markdown.</div> <div class="c--dim f7">Plaintext only. No links or markdown.</div>
</div> </div>
</div> </div>
<div class="edit-form-row">
<div class="pt-input-ns">Project links:</div>
<div>
<textarea class="links" name="links" id="links" maxlength="2048" data-max-chars="2048">
{{- .ProjectSettings.LinksText -}}
</textarea>
<div class="c--dim f7">
<div>Relevant links to put on the project page.</div>
<div>Format: url [Title] (e.g. <code>http://example.com/ Example Site</code>)</div>
<div>(1 per line, 10 max)</div>
</div>
</div>
</div>
<div class="edit-form-row"> <div class="edit-form-row">
<div class="pt-input-ns">Full description:</div> <div class="pt-input-ns">Full description:</div>
<div> <div>

View File

@ -146,6 +146,7 @@ type ProjectSettings struct {
Blurb string Blurb string
Description string Description string
LinksText string
Owners []User Owners []User
LightLogo string LightLogo string

View File

@ -0,0 +1,40 @@
package website
import (
"fmt"
"strings"
"git.handmade.network/hmn/hmn/src/models"
)
type ParsedLink struct {
Name string
Url string
}
func ParseLinks(text string) []ParsedLink {
lines := strings.Split(text, "\n")
res := make([]ParsedLink, 0, len(lines))
for _, line := range lines {
linkParts := strings.SplitN(line, " ", 2)
url := strings.TrimSpace(linkParts[0])
name := ""
if len(linkParts) > 1 {
name = strings.TrimSpace(linkParts[1])
}
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
continue
}
res = append(res, ParsedLink{Name: name, Url: url})
}
return res
}
func LinksToText(links []interface{}) string {
linksText := ""
for _, l := range links {
link := l.(*models.Link)
linksText += fmt.Sprintf("%s %s\n", link.URL, link.Name)
}
return linksText
}

View File

@ -496,6 +496,24 @@ func ProjectEdit(c *RequestContext) ResponseData {
if err != nil { if err != nil {
return c.ErrorResponse(http.StatusInternalServerError, err) return c.ErrorResponse(http.StatusInternalServerError, err)
} }
c.Perf.StartBlock("SQL", "Fetching project links")
projectLinkResult, err := db.Query(c.Context(), c.Conn, models.Link{},
`
SELECT $columns
FROM
handmade_links as link
WHERE
link.project_id = $1
ORDER BY link.ordering ASC
`,
p.Project.ID,
)
if err != nil {
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch project links"))
}
c.Perf.EndBlock()
projectSettings := templates.ProjectToProjectSettings( projectSettings := templates.ProjectToProjectSettings(
&p.Project, &p.Project,
p.Owners, p.Owners,
@ -504,6 +522,8 @@ func ProjectEdit(c *RequestContext) ResponseData {
c.Theme, c.Theme,
) )
projectSettings.LinksText = LinksToText(projectLinkResult)
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"),
@ -558,6 +578,7 @@ type ProjectPayload struct {
ProjectID int ProjectID int
Name string Name string
Blurb string Blurb string
Links []ParsedLink
Description string Description string
ParsedDescription string ParsedDescription string
Lifecycle models.ProjectLifecycle Lifecycle models.ProjectLifecycle
@ -600,6 +621,7 @@ func ParseProjectEditForm(c *RequestContext) ProjectEditFormResult {
res.RejectionReason = "Projects must have a short description" res.RejectionReason = "Projects must have a short description"
return res return res
} }
links := ParseLinks(c.Req.Form.Get("links"))
description := c.Req.Form.Get("description") description := c.Req.Form.Get("description")
parsedDescription := parsing.ParseMarkdown(description, parsing.ForumRealMarkdown) parsedDescription := parsing.ParseMarkdown(description, parsing.ForumRealMarkdown)
@ -650,6 +672,7 @@ func ParseProjectEditForm(c *RequestContext) ProjectEditFormResult {
res.Payload = ProjectPayload{ res.Payload = ProjectPayload{
Name: projectName, Name: projectName,
Blurb: shortDesc, Blurb: shortDesc,
Links: links,
Description: description, Description: description,
ParsedDescription: parsedDescription, ParsedDescription: parsedDescription,
Lifecycle: lifecycle, Lifecycle: lifecycle,
@ -714,28 +737,23 @@ func updateProject(ctx context.Context, tx pgx.Tx, user *models.User, payload *P
payload.OwnerUsernames = append(payload.OwnerUsernames, selfUsername) payload.OwnerUsernames = append(payload.OwnerUsernames, selfUsername)
} }
var qb db.QueryBuilder _, err := tx.Exec(ctx,
qb.Add(
` `
UPDATE handmade_project SET UPDATE handmade_project SET
name = $?, name = $2,
blurb = $?, blurb = $3,
description = $?, description = $4,
descparsed = $?, descparsed = $5,
lifecycle = $? lifecycle = $6
WHERE id = $1
`, `,
payload.ProjectID,
payload.Name, payload.Name,
payload.Blurb, payload.Blurb,
payload.Description, payload.Description,
payload.ParsedDescription, payload.ParsedDescription,
payload.Lifecycle, payload.Lifecycle,
) )
if user.IsStaff {
qb.Add(`, hidden = $?`, payload.Hidden)
}
qb.Add(`WHERE id = $?`, payload.ProjectID)
_, err := tx.Exec(ctx, qb.String(), qb.Args()...)
if err != nil { if err != nil {
return oops.New(err, "Failed to update project") return oops.New(err, "Failed to update project")
} }
@ -748,7 +766,8 @@ func updateProject(ctx context.Context, tx pgx.Tx, user *models.User, payload *P
UPDATE handmade_project SET UPDATE handmade_project SET
slug = $2, slug = $2,
featured = $3, featured = $3,
personal = $4 personal = $4,
hidden = $5
WHERE WHERE
id = $1 id = $1
`, `,
@ -756,6 +775,7 @@ func updateProject(ctx context.Context, tx pgx.Tx, user *models.User, payload *P
payload.Slug, payload.Slug,
payload.Featured, payload.Featured,
payload.Personal, payload.Personal,
payload.Hidden,
) )
if err != nil { if err != nil {
return oops.New(err, "Failed to update project with admin fields") return oops.New(err, "Failed to update project with admin fields")
@ -835,6 +855,26 @@ func updateProject(ctx context.Context, tx pgx.Tx, user *models.User, payload *P
} }
} }
_, err = tx.Exec(ctx, `DELETE FROM handmade_links WHERE project_id = $1`, payload.ProjectID)
if err != nil {
return oops.New(err, "Failed to delete project links")
}
for i, link := range payload.Links {
_, err = tx.Exec(ctx,
`
INSERT INTO handmade_links (name, url, ordering, project_id)
VALUES ($1, $2, $3, $4)
`,
link.Name,
link.Url,
i,
payload.ProjectID,
)
if err != nil {
return oops.New(err, "Failed to insert new project link")
}
}
return nil return nil
} }

View File

@ -235,11 +235,7 @@ func UserSettings(c *RequestContext) ResponseData {
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch user links")) return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch user links"))
} }
linksText := "" linksText := LinksToText(links)
for _, ilink := range links {
link := ilink.(*models.Link)
linksText += fmt.Sprintf("%s %s\n", link.URL, link.Name)
}
var tduser *templates.DiscordUser var tduser *templates.DiscordUser
var numUnsavedMessages int var numUnsavedMessages int
@ -365,31 +361,19 @@ func UserSettingsSave(c *RequestContext) ResponseData {
// Process links // Process links
linksText := form.Get("links") linksText := form.Get("links")
links := strings.Split(linksText, "\n") links := ParseLinks(linksText)
_, err = tx.Exec(c.Context(), `DELETE FROM handmade_links WHERE user_id = $1`, c.CurrentUser.ID) _, err = tx.Exec(c.Context(), `DELETE FROM handmade_links WHERE user_id = $1`, c.CurrentUser.ID)
if err != nil { if err != nil {
c.Logger.Warn().Err(err).Msg("failed to delete old links") c.Logger.Warn().Err(err).Msg("failed to delete old links")
} else { } else {
for i, link := range links { for i, link := range links {
link = strings.TrimSpace(link)
linkParts := strings.SplitN(link, " ", 2)
url := strings.TrimSpace(linkParts[0])
name := ""
if len(linkParts) > 1 {
name = strings.TrimSpace(linkParts[1])
}
if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") {
continue
}
_, err := tx.Exec(c.Context(), _, err := tx.Exec(c.Context(),
` `
INSERT INTO handmade_links (name, url, ordering, user_id) INSERT INTO handmade_links (name, url, ordering, user_id)
VALUES ($1, $2, $3, $4) VALUES ($1, $2, $3, $4)
`, `,
name, link.Name,
url, link.Url,
i, i,
c.CurrentUser.ID, c.CurrentUser.ID,
) )