Fossil SCM
PoC for sticky forum posts, where a 'sticky' tag set on the first version of the root post of a thread will cause it to sort to the top of the list. Pending is a way for Setup users (only) to set/unset the sticky tag (it currently requires tagging from the CLI).
Commit
70ac3f6e836d3c8820c56deea5f05e1785718711e84b48b23d064d8296af4286
Parent
5079ffb0278d122…
2 files changed
+5
+17
-6
+5
| --- src/default.css | ||
| +++ src/default.css | ||
| @@ -1113,10 +1113,15 @@ | ||
| 1113 | 1113 | |
| 1114 | 1114 | div.setup_forum-column { |
| 1115 | 1115 | display: flex; |
| 1116 | 1116 | flex-direction: column; |
| 1117 | 1117 | } |
| 1118 | + | |
| 1119 | +body.forum div.forumPosts table tr.sticky > td:nth-child(1):before { | |
| 1120 | + padding-right: 0.25em; | |
| 1121 | + content: "📌"; | |
| 1122 | +} | |
| 1118 | 1123 | |
| 1119 | 1124 | body.cpage-setup_forum > .content table { |
| 1120 | 1125 | margin-bottom: 1em; |
| 1121 | 1126 | } |
| 1122 | 1127 | body.cpage-setup_forum > .content table.bordered { |
| 1123 | 1128 |
| --- src/default.css | |
| +++ src/default.css | |
| @@ -1113,10 +1113,15 @@ | |
| 1113 | |
| 1114 | div.setup_forum-column { |
| 1115 | display: flex; |
| 1116 | flex-direction: column; |
| 1117 | } |
| 1118 | |
| 1119 | body.cpage-setup_forum > .content table { |
| 1120 | margin-bottom: 1em; |
| 1121 | } |
| 1122 | body.cpage-setup_forum > .content table.bordered { |
| 1123 |
| --- src/default.css | |
| +++ src/default.css | |
| @@ -1113,10 +1113,15 @@ | |
| 1113 | |
| 1114 | div.setup_forum-column { |
| 1115 | display: flex; |
| 1116 | flex-direction: column; |
| 1117 | } |
| 1118 | |
| 1119 | body.forum div.forumPosts table tr.sticky > td:nth-child(1):before { |
| 1120 | padding-right: 0.25em; |
| 1121 | content: "📌"; |
| 1122 | } |
| 1123 | |
| 1124 | body.cpage-setup_forum > .content table { |
| 1125 | margin-bottom: 1em; |
| 1126 | } |
| 1127 | body.cpage-setup_forum > .content table.bordered { |
| 1128 |
+17
-6
| --- src/forum.c | ||
| +++ src/forum.c | ||
| @@ -2168,42 +2168,53 @@ | ||
| 2168 | 2168 | style_submenu_entry("n","Max:",4,0); |
| 2169 | 2169 | iOfst = atoi(PD("x","0")); |
| 2170 | 2170 | iCnt = 0; |
| 2171 | 2171 | if( db_table_exists("repository","forumpost") ){ |
| 2172 | 2172 | db_prepare(&q, |
| 2173 | - "WITH thread(age,duration,cnt,root,last) AS (" | |
| 2173 | + "WITH thread(age,duration,cnt,root,last,sticky) AS (" | |
| 2174 | 2174 | " SELECT" |
| 2175 | 2175 | " julianday('now') - max(fmtime)," |
| 2176 | 2176 | " max(fmtime) - min(fmtime)," |
| 2177 | 2177 | " sum(fprev IS NULL)," |
| 2178 | 2178 | " froot," |
| 2179 | 2179 | " (SELECT fpid FROM forumpost AS y" |
| 2180 | 2180 | " WHERE y.froot=x.froot %s" |
| 2181 | - " ORDER BY y.fmtime DESC LIMIT 1)" | |
| 2181 | + " ORDER BY y.fmtime DESC LIMIT 1)," | |
| 2182 | + " CASE WHEN" | |
| 2183 | + " firt IS NULL AND" | |
| 2184 | + " (SELECT 1 FROM tagxref ref, tag t" | |
| 2185 | + " WHERE ref.rid=x.fpid AND ref.tagtype>0" | |
| 2186 | + " AND ref.tagid=t.tagid" | |
| 2187 | + " AND t.tagname='sticky')" | |
| 2188 | + " THEN 1" | |
| 2189 | + " ELSE 0" | |
| 2190 | + " END" | |
| 2182 | 2191 | " FROM forumpost AS x" |
| 2183 | 2192 | " WHERE %s" |
| 2184 | 2193 | " GROUP BY froot" |
| 2185 | - " ORDER BY 1 LIMIT %d OFFSET %d" | |
| 2194 | + " ORDER BY 6 DESC, 1 LIMIT %d OFFSET %d" | |
| 2186 | 2195 | ")" |
| 2187 | 2196 | "SELECT" |
| 2188 | 2197 | " thread.age," /* 0 */ |
| 2189 | 2198 | " thread.duration," /* 1 */ |
| 2190 | 2199 | " thread.cnt," /* 2 */ |
| 2191 | 2200 | " blob.uuid," /* 3 */ |
| 2192 | 2201 | " substr(event.comment,instr(event.comment,':')+1)," /* 4 */ |
| 2193 | - " thread.last" /* 5 */ | |
| 2202 | + " thread.last," /* 5 */ | |
| 2203 | + " thread.sticky" /* 6 */ | |
| 2194 | 2204 | " FROM thread, blob, event" |
| 2195 | 2205 | " WHERE blob.rid=thread.last" |
| 2196 | 2206 | " AND event.objid=thread.last" |
| 2197 | - " ORDER BY 1;", | |
| 2207 | + " ORDER BY 7 DESC, 1;", | |
| 2198 | 2208 | g.perm.ModForum ? "" : "AND y.fpid NOT IN private" /*safe-for-%s*/, |
| 2199 | 2209 | g.perm.ModForum ? "true" : "fpid NOT IN private" /*safe-for-%s*/, |
| 2200 | 2210 | iLimit+1, iOfst |
| 2201 | 2211 | ); |
| 2202 | 2212 | while( db_step(&q)==SQLITE_ROW ){ |
| 2203 | 2213 | char *zAge = human_readable_age(db_column_double(&q,0)); |
| 2204 | 2214 | int nMsg = db_column_int(&q, 2); |
| 2215 | + int bSticky = db_column_int(&q, 6); | |
| 2205 | 2216 | const char *zUuid = db_column_text(&q, 3); |
| 2206 | 2217 | const char *zTitle = db_column_text(&q, 4); |
| 2207 | 2218 | if( iCnt==0 ){ |
| 2208 | 2219 | if( iOfst>0 ){ |
| 2209 | 2220 | @ <h1>Threads at least %s(zAge) old</h1> |
| @@ -2228,11 +2239,11 @@ | ||
| 2228 | 2239 | @ %z(href("%R/forum?x=%d&n=%d",iOfst+iLimit,iLimit))\ |
| 2229 | 2240 | @ ↓ Older...</a></td></tr> |
| 2230 | 2241 | fossil_free(zAge); |
| 2231 | 2242 | break; |
| 2232 | 2243 | } |
| 2233 | - @ <tr><td>%h(zAge) ago</td> | |
| 2244 | + @ <tr%s(bSticky ? " class='sticky'" : "")><td>%h(zAge) ago</td> | |
| 2234 | 2245 | @ <td>%z(href("%R/forumpost/%S",zUuid))%h(zTitle)</a></td> |
| 2235 | 2246 | @ <td>\ |
| 2236 | 2247 | if( g.perm.ModForum && moderation_pending(db_column_int(&q,5)) ){ |
| 2237 | 2248 | @ <span class="modpending">\ |
| 2238 | 2249 | @ Awaiting Moderator Approval</span><br> |
| 2239 | 2250 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -2168,42 +2168,53 @@ | |
| 2168 | style_submenu_entry("n","Max:",4,0); |
| 2169 | iOfst = atoi(PD("x","0")); |
| 2170 | iCnt = 0; |
| 2171 | if( db_table_exists("repository","forumpost") ){ |
| 2172 | db_prepare(&q, |
| 2173 | "WITH thread(age,duration,cnt,root,last) AS (" |
| 2174 | " SELECT" |
| 2175 | " julianday('now') - max(fmtime)," |
| 2176 | " max(fmtime) - min(fmtime)," |
| 2177 | " sum(fprev IS NULL)," |
| 2178 | " froot," |
| 2179 | " (SELECT fpid FROM forumpost AS y" |
| 2180 | " WHERE y.froot=x.froot %s" |
| 2181 | " ORDER BY y.fmtime DESC LIMIT 1)" |
| 2182 | " FROM forumpost AS x" |
| 2183 | " WHERE %s" |
| 2184 | " GROUP BY froot" |
| 2185 | " ORDER BY 1 LIMIT %d OFFSET %d" |
| 2186 | ")" |
| 2187 | "SELECT" |
| 2188 | " thread.age," /* 0 */ |
| 2189 | " thread.duration," /* 1 */ |
| 2190 | " thread.cnt," /* 2 */ |
| 2191 | " blob.uuid," /* 3 */ |
| 2192 | " substr(event.comment,instr(event.comment,':')+1)," /* 4 */ |
| 2193 | " thread.last" /* 5 */ |
| 2194 | " FROM thread, blob, event" |
| 2195 | " WHERE blob.rid=thread.last" |
| 2196 | " AND event.objid=thread.last" |
| 2197 | " ORDER BY 1;", |
| 2198 | g.perm.ModForum ? "" : "AND y.fpid NOT IN private" /*safe-for-%s*/, |
| 2199 | g.perm.ModForum ? "true" : "fpid NOT IN private" /*safe-for-%s*/, |
| 2200 | iLimit+1, iOfst |
| 2201 | ); |
| 2202 | while( db_step(&q)==SQLITE_ROW ){ |
| 2203 | char *zAge = human_readable_age(db_column_double(&q,0)); |
| 2204 | int nMsg = db_column_int(&q, 2); |
| 2205 | const char *zUuid = db_column_text(&q, 3); |
| 2206 | const char *zTitle = db_column_text(&q, 4); |
| 2207 | if( iCnt==0 ){ |
| 2208 | if( iOfst>0 ){ |
| 2209 | @ <h1>Threads at least %s(zAge) old</h1> |
| @@ -2228,11 +2239,11 @@ | |
| 2228 | @ %z(href("%R/forum?x=%d&n=%d",iOfst+iLimit,iLimit))\ |
| 2229 | @ ↓ Older...</a></td></tr> |
| 2230 | fossil_free(zAge); |
| 2231 | break; |
| 2232 | } |
| 2233 | @ <tr><td>%h(zAge) ago</td> |
| 2234 | @ <td>%z(href("%R/forumpost/%S",zUuid))%h(zTitle)</a></td> |
| 2235 | @ <td>\ |
| 2236 | if( g.perm.ModForum && moderation_pending(db_column_int(&q,5)) ){ |
| 2237 | @ <span class="modpending">\ |
| 2238 | @ Awaiting Moderator Approval</span><br> |
| 2239 |
| --- src/forum.c | |
| +++ src/forum.c | |
| @@ -2168,42 +2168,53 @@ | |
| 2168 | style_submenu_entry("n","Max:",4,0); |
| 2169 | iOfst = atoi(PD("x","0")); |
| 2170 | iCnt = 0; |
| 2171 | if( db_table_exists("repository","forumpost") ){ |
| 2172 | db_prepare(&q, |
| 2173 | "WITH thread(age,duration,cnt,root,last,sticky) AS (" |
| 2174 | " SELECT" |
| 2175 | " julianday('now') - max(fmtime)," |
| 2176 | " max(fmtime) - min(fmtime)," |
| 2177 | " sum(fprev IS NULL)," |
| 2178 | " froot," |
| 2179 | " (SELECT fpid FROM forumpost AS y" |
| 2180 | " WHERE y.froot=x.froot %s" |
| 2181 | " ORDER BY y.fmtime DESC LIMIT 1)," |
| 2182 | " CASE WHEN" |
| 2183 | " firt IS NULL AND" |
| 2184 | " (SELECT 1 FROM tagxref ref, tag t" |
| 2185 | " WHERE ref.rid=x.fpid AND ref.tagtype>0" |
| 2186 | " AND ref.tagid=t.tagid" |
| 2187 | " AND t.tagname='sticky')" |
| 2188 | " THEN 1" |
| 2189 | " ELSE 0" |
| 2190 | " END" |
| 2191 | " FROM forumpost AS x" |
| 2192 | " WHERE %s" |
| 2193 | " GROUP BY froot" |
| 2194 | " ORDER BY 6 DESC, 1 LIMIT %d OFFSET %d" |
| 2195 | ")" |
| 2196 | "SELECT" |
| 2197 | " thread.age," /* 0 */ |
| 2198 | " thread.duration," /* 1 */ |
| 2199 | " thread.cnt," /* 2 */ |
| 2200 | " blob.uuid," /* 3 */ |
| 2201 | " substr(event.comment,instr(event.comment,':')+1)," /* 4 */ |
| 2202 | " thread.last," /* 5 */ |
| 2203 | " thread.sticky" /* 6 */ |
| 2204 | " FROM thread, blob, event" |
| 2205 | " WHERE blob.rid=thread.last" |
| 2206 | " AND event.objid=thread.last" |
| 2207 | " ORDER BY 7 DESC, 1;", |
| 2208 | g.perm.ModForum ? "" : "AND y.fpid NOT IN private" /*safe-for-%s*/, |
| 2209 | g.perm.ModForum ? "true" : "fpid NOT IN private" /*safe-for-%s*/, |
| 2210 | iLimit+1, iOfst |
| 2211 | ); |
| 2212 | while( db_step(&q)==SQLITE_ROW ){ |
| 2213 | char *zAge = human_readable_age(db_column_double(&q,0)); |
| 2214 | int nMsg = db_column_int(&q, 2); |
| 2215 | int bSticky = db_column_int(&q, 6); |
| 2216 | const char *zUuid = db_column_text(&q, 3); |
| 2217 | const char *zTitle = db_column_text(&q, 4); |
| 2218 | if( iCnt==0 ){ |
| 2219 | if( iOfst>0 ){ |
| 2220 | @ <h1>Threads at least %s(zAge) old</h1> |
| @@ -2228,11 +2239,11 @@ | |
| 2239 | @ %z(href("%R/forum?x=%d&n=%d",iOfst+iLimit,iLimit))\ |
| 2240 | @ ↓ Older...</a></td></tr> |
| 2241 | fossil_free(zAge); |
| 2242 | break; |
| 2243 | } |
| 2244 | @ <tr%s(bSticky ? " class='sticky'" : "")><td>%h(zAge) ago</td> |
| 2245 | @ <td>%z(href("%R/forumpost/%S",zUuid))%h(zTitle)</a></td> |
| 2246 | @ <td>\ |
| 2247 | if( g.perm.ModForum && moderation_pending(db_column_int(&q,5)) ){ |
| 2248 | @ <span class="modpending">\ |
| 2249 | @ Awaiting Moderator Approval</span><br> |
| 2250 |