From 86e228d845103db7afc7c0772e2cbc744b8c2fe9 Mon Sep 17 00:00:00 2001 From: Ben Visness Date: Sun, 4 Jul 2021 15:25:28 -0500 Subject: [PATCH] WIP broken schema changes for forum editing --- .../2021-07-03T200233Z_RemoveParserField.go | 44 ++++++++++++++ src/models/post.go | 27 +++------ src/website/forums.go | 60 +++++++++++++++++++ src/website/timeline_helper.go | 10 ++-- 4 files changed, 118 insertions(+), 23 deletions(-) create mode 100644 src/migration/migrations/2021-07-03T200233Z_RemoveParserField.go diff --git a/src/migration/migrations/2021-07-03T200233Z_RemoveParserField.go b/src/migration/migrations/2021-07-03T200233Z_RemoveParserField.go new file mode 100644 index 00000000..5d6b2520 --- /dev/null +++ b/src/migration/migrations/2021-07-03T200233Z_RemoveParserField.go @@ -0,0 +1,44 @@ +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(RemoveParserField{}) +} + +type RemoveParserField struct{} + +func (m RemoveParserField) Version() types.MigrationVersion { + return types.MigrationVersion(time.Date(2021, 7, 3, 20, 2, 33, 0, time.UTC)) +} + +func (m RemoveParserField) Name() string { + return "RemoveParserField" +} + +func (m RemoveParserField) Description() string { + return "Remove the parser field on post versions, since we now have a universal parser" +} + +func (m RemoveParserField) Up(ctx context.Context, tx pgx.Tx) error { + _, err := tx.Exec(ctx, ` + ALTER TABLE handmade_postversion + DROP parser; + `) + if err != nil { + return oops.New(err, "failed to delete parser field") + } + + return nil +} + +func (m RemoveParserField) Down(ctx context.Context, tx pgx.Tx) error { + panic("Implement me") +} diff --git a/src/models/post.go b/src/models/post.go index 6236b176..e0dbcbe7 100644 --- a/src/models/post.go +++ b/src/models/post.go @@ -18,36 +18,27 @@ type Post struct { CategoryKind CategoryKind `db:"category_kind"` - Depth int `db:"depth"` - Slug string `db:"slug"` + Depth int `db:"depth"` // TODO: Drop this. + Slug string `db:"slug"` // TODO: Drop this. AuthorName string `db:"author_name"` // TODO: Drop this. - PostDate time.Time `db:"postdate"` - IP net.IPNet `db:"ip"` - Sticky bool `db:"sticky"` - Deleted bool `db:"deleted"` // TODO: I'm not sure this is ever meaningfully used. It always seems to be 0 / false? - Hits int `db:"hits"` - Featured bool `db:"featured"` - FeatureVotes int `db:"featurevotes"` // TODO: Remove this column from the db, it's never used + PostDate time.Time `db:"postdate"` // TODO: Drop this. + IP net.IPNet `db:"ip"` // TODO: Drop this. + Sticky bool `db:"sticky"` // TODO: Drop this. + Deleted bool `db:"deleted"` + Hits int `db:"hits"` // TODO: Drop this. + Featured bool `db:"featured"` // TODO: Drop this. + FeatureVotes int `db:"featurevotes"` // TODO: Drop this. Preview string `db:"preview"` ReadOnly bool `db:"readonly"` } -type Parser int - -const ( - ParserBBCode Parser = 1 - ParserCleanHTML = 2 - ParserMarkdown = 3 -) - type PostVersion struct { ID int `db:"id"` PostID int `db:"post_id"` TextRaw string `db:"text_raw"` TextParsed string `db:"text_parsed"` - Parser Parser `db:"parser"` EditIP *net.IPNet `db:"edit_ip"` EditDate time.Time `db:"edit_date"` diff --git a/src/website/forums.go b/src/website/forums.go index 1e92854b..6da652a3 100644 --- a/src/website/forums.go +++ b/src/website/forums.go @@ -12,6 +12,7 @@ import ( "git.handmade.network/hmn/hmn/src/hmnurl" "git.handmade.network/hmn/hmn/src/models" "git.handmade.network/hmn/hmn/src/oops" + "git.handmade.network/hmn/hmn/src/parsing" "git.handmade.network/hmn/hmn/src/templates" "git.handmade.network/hmn/hmn/src/utils" ) @@ -567,6 +568,65 @@ func ForumNewThread(c *RequestContext) ResponseData { } func ForumNewThreadSubmit(c *RequestContext) ResponseData { + tx, err := c.Conn.Begin(c.Context()) + if err != nil { + panic(err) + } + + c.Perf.StartBlock("SQL", "Fetch category tree") + categoryTree := models.GetFullCategoryTree(c.Context(), c.Conn) + lineageBuilder := models.MakeCategoryLineageBuilder(categoryTree) + c.Perf.EndBlock() + + currentCatId, valid := validateSubforums(lineageBuilder, c.CurrentProject, c.PathParams["cats"]) + if !valid { + return FourOhFour(c) + } + + c.Req.ParseForm() + + title := c.Req.Form.Get("title") + unparsed := c.Req.Form.Get("body") + sticky := false + if c.CurrentUser.IsStaff && c.Req.Form.Get("sticky") != "" { + sticky = true + } + + parsed := parsing.ParsePostInput(unparsed, false) + + // Create thread + var threadId int + err = tx.QueryRow(c.Context(), + ` + INSERT INTO handmade_thread (title, sticky, locked, category_id) + RETURNING id + `, + title, + sticky, + false, + currentCatId, + ).Scan(&threadId) + if err != nil { + panic(oops.New(err, "failed to create thread")) + } + + // Create post version + _, err = tx.Exec(c.Context(), + ` + INSERT INTO handmade_postversion (post_id, text_raw, text_parsed) + VALUES ($1, $2, $3) + `, + // TODO: post id + unparsed, + parsed, + ) + + 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) } diff --git a/src/website/timeline_helper.go b/src/website/timeline_helper.go index 27e8f3cb..c85bc928 100644 --- a/src/website/timeline_helper.go +++ b/src/website/timeline_helper.go @@ -11,11 +11,11 @@ import ( ) var TimelineTypeMap = map[models.CategoryKind][]templates.TimelineType{ - // No parent, Has parent - models.CatKindBlog: []templates.TimelineType{templates.TimelineTypeBlogPost, templates.TimelineTypeBlogComment}, - models.CatKindForum: []templates.TimelineType{templates.TimelineTypeForumThread, templates.TimelineTypeForumReply}, - models.CatKindWiki: []templates.TimelineType{templates.TimelineTypeWikiCreate, templates.TimelineTypeWikiTalk}, - models.CatKindLibraryResource: []templates.TimelineType{templates.TimelineTypeLibraryComment, templates.TimelineTypeLibraryComment}, + // { No parent , Has parent } + models.CatKindBlog: {templates.TimelineTypeBlogPost, templates.TimelineTypeBlogComment}, + models.CatKindForum: {templates.TimelineTypeForumThread, templates.TimelineTypeForumReply}, + models.CatKindWiki: {templates.TimelineTypeWikiCreate, templates.TimelineTypeWikiTalk}, + models.CatKindLibraryResource: {templates.TimelineTypeLibraryComment, templates.TimelineTypeLibraryComment}, } var TimelineItemClassMap = map[templates.TimelineType]string{