M TODO => TODO +5 -7
@@ 7,13 7,6 @@ better error handling on login
better ux for account creation
move lock to right place
links on home and thread list should go to the post
-
-NOTIFICATIONS:
-- @mentions
-- auto-hyperlink @mention maybe?
-
-"shortpsot" list -> use summary code
-
Login/Reigster:
add a reply button that uses @mentions
finish up oauth integration
@@ 23,6 16,11 @@ Search
----- alpha waterline ----- (may push lower to get something more complete out)
# DEFINITELY
+NOTIFICATIONS:
+- @mentions
+- auto-hyperlink @mention maybe?
+
+"shortpsot" list -> use summary code
block renaming of form
IP blocking / other antispam
split out config management for admins
M db.go => db.go +6 -1
@@ 10,7 10,7 @@ import (
_ "github.com/mattn/go-sqlite3"
)
-var stmtGetForumID, stmtUpdateMe,
+var stmtGetForumID, stmtUpdateMe, stmtSearchPosts,
stmtEditPost, stmtGetPost, stmtGetPostSlug, stmtGetForum,
stmtGetForumBySlug, stmtCreateUser, stmtGetForums, stmtUpdateForum,
stmtGetUser, stmtGetUsers, stmtGetPostAuthorID, stmtDeletePost,
@@ 163,6 163,11 @@ func prepareStatements(db *sql.DB) {
from posts
join users on posts.authorid = users.id
where threadid = ? limit ? offset ?`)
+ stmtSearchPosts = prepare(db, `
+ select posts.id, content, users.id, users.username, posts.created, posts.edited
+ from posts
+ join users on posts.authorid = users.id
+ where content like ?`)
stmtGetPost = prepare(db, `
select posts.id, content, users.id, users.username, posts.created, posts.edited
from posts
M post.go => post.go +20 -1
@@ 33,7 33,7 @@ const previewLength = 10
func (p Post) Preview() string {
text := html2text.HTML2Text(p.Content)
if len(text) > previewLength-3 {
- return text[:previewLength] + "..."
+ return text[:previewLength-3] + "..."
}
return text
}
@@ 68,6 68,25 @@ func getPostSlug(postid int) (string, error) {
return url, nil
}
+// TODO maybe consolidate with query builder
+func searchPosts(q string) ([]Post, error) {
+ var posts []Post
+ rows, err := stmtSearchPosts.Query("%" + q + "%")
+ if err != nil {
+ return nil, err
+ }
+ for rows.Next() {
+ var p Post
+ err := rows.Scan(&p.ID, &p.Content, &p.Author.ID, &p.Author.Username, &p.Created, &p.Edited)
+ fmt.Println(p)
+ if err != nil {
+ return nil, err
+ }
+ posts = append(posts, p)
+ }
+ return posts, nil
+}
+
// page is 1-indexed
func getPosts(threadid, page int) []Post {
var posts []Post
M schema.sql => schema.sql +5 -1
@@ 62,7 62,11 @@ create index idxposts_threadid on posts(threadid);
-- create table invitations ( );
-- create table reports
--- create table notifications
+create table notifications (
+ type text not null,
+ message text, -- markdown
+ created datetime default current_timestamp,
+);
pragma journal_mode = wal;
pragma busy_timeout = 5000;
M views/search.html => views/search.html +5 -1
@@ 1,8 1,12 @@
{{ template "header.html" . }}
<div class="div-header">Posts that match "{{.Query}}"</div>
<div class="body-padded">
-Search feature coming soon!
{{ range .Posts }}
+<div class="shortpost">
+ <img style="vertical-align:middle" src="/a?a={{.Author.Username}}" width=18>
+ <a href="/user/{{.Author.ID}}">{{.Author.Username}}</a> <a href="#{{.ID}}" title="Link to this post">#</a>
+ {{ .Preview }}
+</div>
{{ end }}
</div>
{{ template "footer.html" . }}
A views/shortpost.html => views/shortpost.html +1 -0
M views/style.css => views/style.css +5 -0
@@ 269,3 269,8 @@ h1, h2, h3, h4, h5, h6 {
text-overflow: ellipsis;
vertical-align: top;
}
+
+.shortpost {
+ border-bottom: 1px solid var(--border);
+ padding: 0.3rem;
+}
M views/thread.html => views/thread.html +3 -1
@@ 15,7 15,9 @@
<div class="post-meta">
<div>
<img style="vertical-align:middle" src="/a?a={{.Author.Username}}" width=18>
- <a href="/user/{{.Author.ID}}">{{.Author.Username}}</a> <a href="#{{.ID}}" title="Link to this post">#</a> <span class="text-alt" title="{{ .Created }}">{{ timeago .Created}}
+ <a href="/user/{{.Author.ID}}">{{.Author.Username}}</a> <a href="#{{.ID}}"
+ title="Link to this post">#</a> <span class="text-alt" title="{{ .Created
+ }}">{{ timeago .Created}}
{{ if .Edited }}<em>(edited {{timeago .Edited}})</em>{{end}}
</span>
</div>
M web.go => web.go +8 -1
@@ 482,7 482,14 @@ func doChangePassword(w http.ResponseWriter, r *http.Request) {
func searchPage(w http.ResponseWriter, r *http.Request) {
tmpl := make(map[string]any)
- tmpl["Query"] = r.URL.Query().Get("q")
+ q := r.URL.Query().Get("q")
+ tmpl["Query"] = q
+ posts, err := searchPosts(q)
+ if err != nil {
+ serverError(w, r, err)
+ return
+ }
+ tmpl["Posts"] = posts
serveHTML(w, r, "search", tmpl)
}