diff --git a/src/templates/src/project_edit.html b/src/templates/src/project_edit.html
index 7f085759..3fb5d1cf 100644
--- a/src/templates/src/project_edit.html
+++ b/src/templates/src/project_edit.html
@@ -137,6 +137,19 @@
Plaintext only. No links or markdown.
+
Full description:
diff --git a/src/templates/types.go b/src/templates/types.go
index 73bda64e..915a1e73 100644
--- a/src/templates/types.go
+++ b/src/templates/types.go
@@ -146,6 +146,7 @@ type ProjectSettings struct {
Blurb string
Description string
+ LinksText string
Owners []User
LightLogo string
diff --git a/src/website/links_helper.go b/src/website/links_helper.go
new file mode 100644
index 00000000..93eeef16
--- /dev/null
+++ b/src/website/links_helper.go
@@ -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
+}
diff --git a/src/website/projects.go b/src/website/projects.go
index a85ba98a..b86d6d13 100644
--- a/src/website/projects.go
+++ b/src/website/projects.go
@@ -496,6 +496,24 @@ func ProjectEdit(c *RequestContext) ResponseData {
if err != nil {
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(
&p.Project,
p.Owners,
@@ -504,6 +522,8 @@ func ProjectEdit(c *RequestContext) ResponseData {
c.Theme,
)
+ projectSettings.LinksText = LinksToText(projectLinkResult)
+
var res ResponseData
res.MustWriteTemplate("project_edit.html", ProjectEditData{
BaseData: getBaseDataAutocrumb(c, "Edit Project"),
@@ -558,6 +578,7 @@ type ProjectPayload struct {
ProjectID int
Name string
Blurb string
+ Links []ParsedLink
Description string
ParsedDescription string
Lifecycle models.ProjectLifecycle
@@ -600,6 +621,7 @@ func ParseProjectEditForm(c *RequestContext) ProjectEditFormResult {
res.RejectionReason = "Projects must have a short description"
return res
}
+ links := ParseLinks(c.Req.Form.Get("links"))
description := c.Req.Form.Get("description")
parsedDescription := parsing.ParseMarkdown(description, parsing.ForumRealMarkdown)
@@ -650,6 +672,7 @@ func ParseProjectEditForm(c *RequestContext) ProjectEditFormResult {
res.Payload = ProjectPayload{
Name: projectName,
Blurb: shortDesc,
+ Links: links,
Description: description,
ParsedDescription: parsedDescription,
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)
}
- var qb db.QueryBuilder
- qb.Add(
+ _, err := tx.Exec(ctx,
`
UPDATE handmade_project SET
- name = $?,
- blurb = $?,
- description = $?,
- descparsed = $?,
- lifecycle = $?
+ name = $2,
+ blurb = $3,
+ description = $4,
+ descparsed = $5,
+ lifecycle = $6
+ WHERE id = $1
`,
+ payload.ProjectID,
payload.Name,
payload.Blurb,
payload.Description,
payload.ParsedDescription,
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 {
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
slug = $2,
featured = $3,
- personal = $4
+ personal = $4,
+ hidden = $5
WHERE
id = $1
`,
@@ -756,6 +775,7 @@ func updateProject(ctx context.Context, tx pgx.Tx, user *models.User, payload *P
payload.Slug,
payload.Featured,
payload.Personal,
+ payload.Hidden,
)
if err != nil {
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
}
diff --git a/src/website/user.go b/src/website/user.go
index 2b6b9ad9..61f6b92b 100644
--- a/src/website/user.go
+++ b/src/website/user.go
@@ -235,11 +235,7 @@ func UserSettings(c *RequestContext) ResponseData {
return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to fetch user links"))
}
- linksText := ""
- for _, ilink := range links {
- link := ilink.(*models.Link)
- linksText += fmt.Sprintf("%s %s\n", link.URL, link.Name)
- }
+ linksText := LinksToText(links)
var tduser *templates.DiscordUser
var numUnsavedMessages int
@@ -365,31 +361,19 @@ func UserSettingsSave(c *RequestContext) ResponseData {
// Process 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)
if err != nil {
c.Logger.Warn().Err(err).Msg("failed to delete old links")
} else {
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(),
`
INSERT INTO handmade_links (name, url, ordering, user_id)
VALUES ($1, $2, $3, $4)
`,
- name,
- url,
+ link.Name,
+ link.Url,
i,
c.CurrentUser.ID,
)