Support post signatures
This enables users to add a signature to all blog posts, and update it from a single location. Requires database migration with: writefreely db migrate Closes T582
This commit is contained in:
parent
5c94d23466
commit
a25664bb97
|
@ -47,6 +47,7 @@ type (
|
|||
Language string `schema:"lang" json:"lang,omitempty"`
|
||||
StyleSheet string `datastore:"style_sheet" schema:"style_sheet" json:"style_sheet"`
|
||||
Script string `datastore:"script" schema:"script" json:"script,omitempty"`
|
||||
Signature string `datastore:"post_signature" schema:"signature" json:"-"`
|
||||
Public bool `datastore:"public" json:"public"`
|
||||
Visibility collVisibility `datastore:"private" json:"-"`
|
||||
Format string `datastore:"format" json:"format,omitempty"`
|
||||
|
@ -91,6 +92,7 @@ type (
|
|||
Description *string `schema:"description" json:"description"`
|
||||
StyleSheet *sql.NullString `schema:"style_sheet" json:"style_sheet"`
|
||||
Script *sql.NullString `schema:"script" json:"script"`
|
||||
Signature *sql.NullString `schema:"signature" json:"signature"`
|
||||
Visibility *int `schema:"visibility" json:"public"`
|
||||
Format *sql.NullString `schema:"format" json:"format"`
|
||||
}
|
||||
|
|
13
database.go
13
database.go
|
@ -791,10 +791,10 @@ func (db *datastore) GetCollectionBy(condition string, value interface{}) (*Coll
|
|||
c := &Collection{}
|
||||
|
||||
// FIXME: change Collection to reflect database values. Add helper functions to get actual values
|
||||
var styleSheet, script, format zero.String
|
||||
row := db.QueryRow("SELECT id, alias, title, description, style_sheet, script, format, owner_id, privacy, view_count FROM collections WHERE "+condition, value)
|
||||
var styleSheet, script, signature, format zero.String
|
||||
row := db.QueryRow("SELECT id, alias, title, description, style_sheet, script, post_signature, format, owner_id, privacy, view_count FROM collections WHERE "+condition, value)
|
||||
|
||||
err := row.Scan(&c.ID, &c.Alias, &c.Title, &c.Description, &styleSheet, &script, &format, &c.OwnerID, &c.Visibility, &c.Views)
|
||||
err := row.Scan(&c.ID, &c.Alias, &c.Title, &c.Description, &styleSheet, &script, &signature, &format, &c.OwnerID, &c.Visibility, &c.Views)
|
||||
switch {
|
||||
case err == sql.ErrNoRows:
|
||||
return nil, impart.HTTPError{http.StatusNotFound, "Collection doesn't exist."}
|
||||
|
@ -806,6 +806,7 @@ func (db *datastore) GetCollectionBy(condition string, value interface{}) (*Coll
|
|||
}
|
||||
c.StyleSheet = styleSheet.String
|
||||
c.Script = script.String
|
||||
c.Signature = signature.String
|
||||
c.Format = format.String
|
||||
c.Public = c.IsPublic()
|
||||
|
||||
|
@ -849,7 +850,8 @@ func (db *datastore) UpdateCollection(c *SubmittedCollection, alias string) erro
|
|||
SetStringPtr(c.Title, "title").
|
||||
SetStringPtr(c.Description, "description").
|
||||
SetNullString(c.StyleSheet, "style_sheet").
|
||||
SetNullString(c.Script, "script")
|
||||
SetNullString(c.Script, "script").
|
||||
SetNullString(c.Signature, "post_signature")
|
||||
|
||||
if c.Format != nil {
|
||||
cf := &CollectionFormat{Format: c.Format.String}
|
||||
|
@ -1150,6 +1152,7 @@ func (db *datastore) GetPosts(cfg *config.Config, c *Collection, page int, inclu
|
|||
break
|
||||
}
|
||||
p.extractData()
|
||||
p.augmentContent(c)
|
||||
p.formatContent(cfg, c, includeFuture)
|
||||
|
||||
posts = append(posts, p.processPost())
|
||||
|
@ -1214,6 +1217,7 @@ func (db *datastore) GetPostsTagged(cfg *config.Config, c *Collection, tag strin
|
|||
break
|
||||
}
|
||||
p.extractData()
|
||||
p.augmentContent(c)
|
||||
p.formatContent(cfg, c, includeFuture)
|
||||
|
||||
posts = append(posts, p.processPost())
|
||||
|
@ -1590,6 +1594,7 @@ func (db *datastore) GetPinnedPosts(coll *CollectionObj, includeFuture bool) (*[
|
|||
break
|
||||
}
|
||||
p.extractData()
|
||||
p.augmentContent(&coll.Collection)
|
||||
|
||||
pp := p.processPost()
|
||||
pp.Collection = coll
|
||||
|
|
|
@ -78,3 +78,10 @@ func (db *datastore) engine() string {
|
|||
}
|
||||
return " ENGINE = InnoDB"
|
||||
}
|
||||
|
||||
func (db *datastore) after(colName string) string {
|
||||
if db.driverName == driverSQLite {
|
||||
return ""
|
||||
}
|
||||
return " AFTER " + colName
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ var migrations = []Migration{
|
|||
New("support oauth attach", oauthAttach), // V6 -> V7
|
||||
New("support oauth via invite", oauthInvites), // V7 -> V8 (v0.12.0)
|
||||
New("optimize drafts retrieval", optimizeDrafts), // V8 -> V9
|
||||
New("support post signatures", supportPostSignatures), // V9 -> V10
|
||||
}
|
||||
|
||||
// CurrentVer returns the current migration version the application is on
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright © 2020 A Bunch Tell LLC.
|
||||
*
|
||||
* This file is part of WriteFreely.
|
||||
*
|
||||
* WriteFreely is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, included
|
||||
* in the LICENSE file in this source code package.
|
||||
*/
|
||||
|
||||
package migrations
|
||||
|
||||
func supportPostSignatures(db *datastore) error {
|
||||
t, err := db.Begin()
|
||||
if err != nil {
|
||||
t.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = t.Exec(`ALTER TABLE collections ADD COLUMN post_signature ` + db.typeText() + db.collateMultiByte() + ` NULL` + db.after("script"))
|
||||
if err != nil {
|
||||
t.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
err = t.Commit()
|
||||
if err != nil {
|
||||
t.Rollback()
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -58,6 +58,17 @@ func (p *PublicPost) formatContent(cfg *config.Config, isOwner bool) {
|
|||
p.Post.formatContent(cfg, &p.Collection.Collection, isOwner)
|
||||
}
|
||||
|
||||
func (p *Post) augmentContent(c *Collection) {
|
||||
// Add post signatures
|
||||
if c.Signature != "" {
|
||||
p.Content += "\n\n" + c.Signature
|
||||
}
|
||||
}
|
||||
|
||||
func (p *PublicPost) augmentContent() {
|
||||
p.Post.augmentContent(&p.Collection.Collection)
|
||||
}
|
||||
|
||||
func applyMarkdown(data []byte, baseURL string, cfg *config.Config) string {
|
||||
return applyMarkdownSpecial(data, false, baseURL, cfg)
|
||||
}
|
||||
|
|
3
posts.go
3
posts.go
|
@ -1140,6 +1140,7 @@ func (p *PublicPost) ActivityObject(app *App) *activitystreams.Object {
|
|||
p.Collection.FederatedAccount() + "/followers",
|
||||
}
|
||||
o.Name = p.DisplayTitle()
|
||||
p.augmentContent()
|
||||
if p.HTMLContent == template.HTML("") {
|
||||
p.formatContent(cfg, false)
|
||||
}
|
||||
|
@ -1430,6 +1431,8 @@ Are you sure it was ever here?`,
|
|||
return impart.HTTPError{http.StatusGone, "Post was unpublished."}
|
||||
}
|
||||
|
||||
p.augmentContent()
|
||||
|
||||
// Serve collection post
|
||||
if isRaw {
|
||||
contentType := "text/plain"
|
||||
|
|
|
@ -5,6 +5,15 @@
|
|||
{{define "collection"}}
|
||||
{{template "header" .}}
|
||||
|
||||
<style>
|
||||
textarea.section.norm {
|
||||
font-family: Lora,'Palatino Linotype','Book Antiqua','New York','DejaVu serif',serif !important;
|
||||
min-height: 10em;
|
||||
max-height: 20em;
|
||||
resize: vertical;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="content-container snug">
|
||||
<div id="overlay"></div>
|
||||
|
||||
|
@ -129,6 +138,14 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="option">
|
||||
<h2>Post Signature</h2>
|
||||
<div class="section">
|
||||
<p class="explain">This content will be added to the end of every post on this blog, as if it were part of the post itself. Markdown, HTML, and shortcodes are allowed.</p>
|
||||
<textarea id="signature" class="section norm" name="signature">{{.Signature}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="option" style="text-align: center; margin-top: 4em;">
|
||||
<input type="submit" id="save-changes" value="Save changes" />
|
||||
<p><a href="{{if .SingleUser}}/{{else}}/{{.Alias}}/{{end}}">View Blog</a></p>
|
||||
|
|
Loading…
Reference in New Issue