diff --git a/src/migration/migrations/2021-07-04T213658Z_DropThreadFields.go b/src/migration/migrations/2021-07-04T213658Z_DropThreadFields.go
new file mode 100644
index 00000000..37f202cf
--- /dev/null
+++ b/src/migration/migrations/2021-07-04T213658Z_DropThreadFields.go
@@ -0,0 +1,45 @@
+package migrations
+
+import (
+ "context"
+ "time"
+
+ "git.handmade.network/hmn/hmn/src/migration/types"
+ "git.handmade.network/hmn/hmn/src/oops"
+ "github.com/jackc/pgx/v4"
+)
+
+func init() {
+ registerMigration(DropThreadFields{})
+}
+
+type DropThreadFields struct{}
+
+func (m DropThreadFields) Version() types.MigrationVersion {
+ return types.MigrationVersion(time.Date(2021, 7, 4, 21, 36, 58, 0, time.UTC))
+}
+
+func (m DropThreadFields) Name() string {
+ return "DropThreadFields"
+}
+
+func (m DropThreadFields) Description() string {
+ return "Drop unnecessary thread fields"
+}
+
+func (m DropThreadFields) Up(ctx context.Context, tx pgx.Tx) error {
+ _, err := tx.Exec(ctx, `
+ ALTER TABLE handmade_thread
+ DROP hits,
+ DROP reply_count;
+ `)
+ if err != nil {
+ return oops.New(err, "failed to drop thread fields")
+ }
+
+ return nil
+}
+
+func (m DropThreadFields) Down(ctx context.Context, tx pgx.Tx) error {
+ panic("Implement me")
+}
diff --git a/src/migration/migrations/2021-07-04T220228Z_FixPostConstraints.go b/src/migration/migrations/2021-07-04T220228Z_FixPostConstraints.go
new file mode 100644
index 00000000..a3684cb5
--- /dev/null
+++ b/src/migration/migrations/2021-07-04T220228Z_FixPostConstraints.go
@@ -0,0 +1,69 @@
+package migrations
+
+import (
+ "context"
+ "time"
+
+ "git.handmade.network/hmn/hmn/src/migration/types"
+ "git.handmade.network/hmn/hmn/src/oops"
+ "github.com/jackc/pgx/v4"
+)
+
+func init() {
+ registerMigration(FixPostConstraints{})
+}
+
+type FixPostConstraints struct{}
+
+func (m FixPostConstraints) Version() types.MigrationVersion {
+ return types.MigrationVersion(time.Date(2021, 7, 4, 22, 2, 28, 0, time.UTC))
+}
+
+func (m FixPostConstraints) Name() string {
+ return "FixPostConstraints"
+}
+
+func (m FixPostConstraints) Description() string {
+ return "Update post-related constraints to make insertion sane"
+}
+
+func (m FixPostConstraints) Up(ctx context.Context, tx pgx.Tx) error {
+ _, err := tx.Exec(ctx, `
+ ALTER TABLE handmade_thread
+ ALTER locked SET DEFAULT FALSE,
+ ALTER first_id SET NOT NULL,
+ ALTER last_id SET NOT NULL;
+ `)
+ if err != nil {
+ return oops.New(err, "failed to update thread constraints")
+ }
+
+ _, err = tx.Exec(ctx, `
+ ALTER TABLE handmade_post
+ ALTER deleted SET DEFAULT FALSE,
+ ALTER readonly SET DEFAULT FALSE,
+ ALTER CONSTRAINT handmade_post_current_id_fkey DEFERRABLE INITIALLY DEFERRED;
+ `)
+ if err != nil {
+ return oops.New(err, "failed to update project constraints")
+ }
+
+ _, err = tx.Exec(ctx, `
+ CREATE SEQUENCE handmade_postversion_id_seq
+ START WITH 40000 -- this is well out of the way of existing IDs
+ OWNED BY handmade_postversion.id;
+
+ ALTER TABLE handmade_postversion
+ ALTER id SET DEFAULT nextval('handmade_postversion_id_seq'),
+ ALTER CONSTRAINT handmade_postversion_post_id_fkey DEFERRABLE INITIALLY DEFERRED;
+ `)
+ if err != nil {
+ return oops.New(err, "failed to update postversion constraints")
+ }
+
+ return nil
+}
+
+func (m FixPostConstraints) Down(ctx context.Context, tx pgx.Tx) error {
+ panic("Implement me")
+}
diff --git a/src/models/thread.go b/src/models/thread.go
index 525fb47e..1d472468 100644
--- a/src/models/thread.go
+++ b/src/models/thread.go
@@ -5,12 +5,10 @@ type Thread struct {
CategoryID int `db:"category_id"`
- Title string `db:"title"`
- Hits int `db:"hits"`
- ReplyCount int `db:"reply_count"`
- Sticky bool `db:"sticky"`
- Locked bool `db:"locked"`
- Deleted bool `db:"deleted"`
+ Title string `db:"title"`
+ Sticky bool `db:"sticky"`
+ Locked bool `db:"locked"`
+ Deleted bool `db:"deleted"`
FirstID *int `db:"first_id"`
LastID *int `db:"last_id"`
diff --git a/src/templates/src/editor.html b/src/templates/src/editor.html
index dd3a4445..5fe8c8e9 100644
--- a/src/templates/src/editor.html
+++ b/src/templates/src/editor.html
@@ -46,33 +46,29 @@
-
- {{/*
- {% if are_editing %}
+ {{ if .IsEditing }}
-
+
- {% endif %}
+ {{ end }}
+ {{/* TODO: Sticky threads
{% if user.is_staff and post and post.depth == 0 %}
{% endif %}
+ */}}
-
-
- {% if are_previewing %}
- {% include "edit_preview.html" %}
- {% endif %}
+ {{/*
{% if context_reply_to %}
The post you're replying to:
diff --git a/src/website/forums.go b/src/website/forums.go
index 496a35ad..2ab5ff1f 100644
--- a/src/website/forums.go
+++ b/src/website/forums.go
@@ -3,6 +3,7 @@ package website
import (
"errors"
"math"
+ "net"
"net/http"
"strconv"
"strings"
@@ -518,18 +519,14 @@ func ForumPostRedirect(c *RequestContext) ResponseData {
type editorData struct {
templates.BaseData
- SubmitUrl string
- PostTitle string
- PostBody string
- SubmitLabel string
- PreviewLabel string
+ SubmitUrl string
+ PostTitle string
+ PostBody string
+ SubmitLabel string
+ IsEditing bool // false if new post, true if updating existing one
}
func ForumNewThread(c *RequestContext) ResponseData {
- if c.Req.Method == http.MethodPost {
- // TODO: Get preview data
- }
-
baseData := getBaseData(c)
baseData.Title = "Create New Thread"
baseData.MathjaxEnabled = true
@@ -547,19 +544,10 @@ func ForumNewThread(c *RequestContext) ResponseData {
var res ResponseData
err := res.WriteTemplate("editor.html", editorData{
- BaseData: baseData,
- SubmitUrl: hmnurl.BuildForumNewThread(c.CurrentProject.Slug, lineageBuilder.GetSubforumLineageSlugs(currentCatId), true),
- SubmitLabel: "Post New Thread",
- PreviewLabel: "Preview",
+ BaseData: baseData,
+ SubmitUrl: hmnurl.BuildForumNewThread(c.CurrentProject.Slug, lineageBuilder.GetSubforumLineageSlugs(currentCatId), true),
+ SubmitLabel: "Post New Thread",
}, c.Perf)
- // err := res.WriteTemplate("forum_thread.html", forumThreadData{
- // BaseData: baseData,
- // Thread: templates.ThreadToTemplate(&thread),
- // Posts: posts,
- // CategoryUrl: hmnurl.BuildForumCategory(c.CurrentProject.Slug, currentSubforumSlugs, 1),
- // ReplyUrl: hmnurl.BuildForumPostReply(c.CurrentProject.Slug, currentSubforumSlugs, thread.ID, *thread.FirstID),
- // Pagination: pagination,
- // }, c.Perf)
if err != nil {
panic(err)
}
@@ -572,6 +560,7 @@ func ForumNewThreadSubmit(c *RequestContext) ResponseData {
if err != nil {
panic(err)
}
+ defer tx.Rollback(c.Context())
c.Perf.StartBlock("SQL", "Fetch category tree")
categoryTree := models.GetFullCategoryTree(c.Context(), c.Conn)
@@ -593,41 +582,104 @@ func ForumNewThreadSubmit(c *RequestContext) ResponseData {
}
parsed := parsing.ParsePostInput(unparsed, false)
+ now := time.Now()
+
+ ip := net.ParseIP(c.Req.RemoteAddr)
// Create thread
var threadId int
err = tx.QueryRow(c.Context(),
`
- INSERT INTO handmade_thread (title, sticky, locked, category_id)
+ INSERT INTO handmade_thread (title, sticky, category_id, first_id, last_id)
+ VALUES ($1, $2, $3, $4, $5)
RETURNING id
`,
title,
sticky,
- false,
currentCatId,
+ -1,
+ -1,
).Scan(&threadId)
if err != nil {
panic(oops.New(err, "failed to create thread"))
}
- // Create post version
- _, err = tx.Exec(c.Context(),
+ // Create post
+ var postId int
+ err = tx.QueryRow(c.Context(),
`
- INSERT INTO handmade_postversion (post_id, text_raw, text_parsed)
- VALUES ($1, $2, $3)
+ INSERT INTO handmade_post (postdate, category_id, thread_id, preview, current_id, author_id, category_kind, project_id)
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
+ RETURNING id
`,
- // TODO: post id
+ now,
+ currentCatId,
+ threadId,
+ "lol", // TODO: Actual previews
+ -1,
+ c.CurrentUser.ID,
+ models.CatKindForum,
+ c.CurrentProject.ID,
+ ).Scan(&postId)
+ if err != nil {
+ panic(oops.New(err, "failed to create post"))
+ }
+
+ // Create post version
+ var versionId int
+ err = tx.QueryRow(c.Context(),
+ `
+ INSERT INTO handmade_postversion (post_id, text_raw, text_parsed, ip, date)
+ VALUES ($1, $2, $3, $4, $5)
+ RETURNING id
+ `,
+ postId,
unparsed,
parsed,
+ ip,
+ now,
+ ).Scan(&versionId)
+ if err != nil {
+ panic(oops.New(err, "failed to create post version"))
+ }
+
+ // Update post with version id
+ _, err = tx.Exec(c.Context(),
+ `
+ UPDATE handmade_post
+ SET current_id = $1
+ WHERE id = $2
+ `,
+ versionId,
+ postId,
)
+ if err != nil {
+ panic(oops.New(err, "failed to set current post version"))
+ }
+
+ // Update thread with post id
+ _, err = tx.Exec(c.Context(),
+ `
+ UPDATE handmade_thread
+ SET
+ first_id = $1,
+ last_id = $1
+ WHERE id = $2
+ `,
+ postId,
+ threadId,
+ )
+ if err != nil {
+ panic(oops.New(err, "failed to set thread post ids"))
+ }
err = tx.Commit(c.Context())
if err != nil {
return ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to create new forum thread"))
}
- // TODO: Redirect to newly created thread
- return c.Redirect(hmnurl.BuildForumNewThread(models.HMNProjectSlug, nil, false), http.StatusSeeOther)
+ newThreadUrl := hmnurl.BuildForumThread(c.CurrentProject.Slug, lineageBuilder.GetSubforumLineageSlugs(currentCatId), threadId, title, 1)
+ return c.Redirect(newThreadUrl, http.StatusSeeOther)
}
func validateSubforums(lineageBuilder *models.CategoryLineageBuilder, project *models.Project, catPath string) (int, bool) {