a mini social media app for small communities

fix search page a bit and add user search code

Changed files
+80 -9
src
database
entity
templates
+1 -1
src/database/post.v
··· 160 return results 161 } 162 163 - // search_for_post searches for posts matching the given query. 164 // todo: query options/filters, such as user:beep, !excluded-text, etc 165 pub fn (app &DatabaseAccess) search_for_posts(query string, limit int, offset int) []PostSearchResult { 166 sql_query := "\
··· 160 return results 161 } 162 163 + // search_for_posts searches for posts matching the given query. 164 // todo: query options/filters, such as user:beep, !excluded-text, etc 165 pub fn (app &DatabaseAccess) search_for_posts(query string, limit int, offset int) []PostSearchResult { 166 sql_query := "\
+21
src/database/user.v
··· 206 207 return true 208 }
··· 206 207 return true 208 } 209 + 210 + // search_for_users searches for posts matching the given query. 211 + // todo: query options/filters, such as created-after:<date>, created-before:<date>, etc 212 + pub fn (app &DatabaseAccess) search_for_users(query string, limit int, offset int) []User { 213 + sql_query := "\ 214 + SELECT *, CASE 215 + WHEN username LIKE '%${query}%' THEN 1 216 + WHEN nickname LIKE '%${query}%' THEN 2 217 + END AS priority 218 + FROM \"User\" 219 + WHERE username LIKE '%${query}%' OR nickname LIKE '%${query}%' 220 + ORDER BY priority ASC LIMIT ${limit} OFFSET ${offset}" 221 + 222 + queried_users := app.db.q_strings(sql_query) or { 223 + eprintln('search_for_users error in app.db.q_strings: ${err}') 224 + [] 225 + } 226 + 227 + users := queried_users.map(|it| User.from_row(it)) 228 + return users 229 + }
+1 -1
src/entity/post.v
··· 18 posted_at time.Time = time.now() 19 } 20 21 - // Post.from_row creates a post from the given database row. 22 // see src/database/post.v#search_for_posts for usage. 23 @[inline] 24 pub fn Post.from_row(row pg.Row) Post {
··· 18 posted_at time.Time = time.now() 19 } 20 21 + // Post.from_row creates a post object from the given database row. 22 // see src/database/post.v#search_for_posts for usage. 23 @[inline] 24 pub fn Post.from_row(row pg.Row) Post {
+27
src/entity/user.v
··· 1 module entity 2 3 import time 4 5 pub struct User { 6 pub mut: ··· 37 .replace(user.password, '*'.repeat(16)) 38 .replace(user.password_salt, '*'.repeat(16)) 39 }
··· 1 module entity 2 3 + import db.pg 4 import time 5 + import util 6 7 pub struct User { 8 pub mut: ··· 39 .replace(user.password, '*'.repeat(16)) 40 .replace(user.password_salt, '*'.repeat(16)) 41 } 42 + 43 + // User.from_row creates a user object from the given database row. 44 + // see src/database/user.v#search_for_users for usage. 45 + @[inline] 46 + pub fn User.from_row(row pg.Row) User { 47 + // this throws a cgen error when put in User{} 48 + //todo: report this 49 + created_at := time.parse(util.or_throw[string](row.vals[10])) or { panic(err) } 50 + 51 + return User{ 52 + id: util.or_throw[string](row.vals[0]).int() 53 + username: util.or_throw[string](row.vals[1]) 54 + nickname: if row.vals[2] == none { ?string(none) } else { 55 + util.or_throw[string](row.vals[3]) 56 + } 57 + password: 'haha lol, nope' 58 + password_salt: 'haha lol, nope' 59 + muted: util.map_or_throw[string, bool](row.vals[5], |it| it.bool()) 60 + admin: util.map_or_throw[string, bool](row.vals[6], |it| it.bool()) 61 + theme: util.or_throw[string](row.vals[7]) 62 + bio: util.or_throw[string](row.vals[8]) 63 + pronouns: util.or_throw[string](row.vals[9]) 64 + created_at: created_at 65 + } 66 + }
+30 -7
src/templates/search.html
··· 29 query.value = params.get('q') 30 } 31 32 let offset = params.get('offset') 33 - if (!offset) { 34 offset = 0 35 } 36 ··· 38 results.innerHTML = '' // yeet the children! 39 pages.innerHTML = '' // yeet more children! 40 41 - const search_results = await search(query.value, 10, Number(offset.value)) 42 if (search_results.length >= 0) { 43 for (result of search_results) { 44 // same as components/post_mini.html except js ··· 66 67 // set up pagination 68 if (offset > 0) { 69 - const back_link = document.createElement('a') 70 // we escape the $ here because otherwise V will try to perform replacements at compile-time. 71 //todo: report this, this behaviour should be changed or at least looked into further. 72 - back_link.href = '/search?q=' + query.value + '&limit=10&offset=' + Math.min(0, offset.value - 10) 73 - back_link.innerText = '<-' 74 pages.appendChild(back_link) 75 76 const next_link = document.createElement('a') 77 - next_link.href = '/search?q=' + query.value + '&limit=10&offset=' + (offset.value + 10) 78 - next_link.innerText = '->' 79 pages.appendChild(next_link) 80 } 81 } else {
··· 29 query.value = params.get('q') 30 } 31 32 + let limit = params.get('limit') 33 + if (!limit) { 34 + limit = 10 35 + } 36 + 37 let offset = params.get('offset') 38 + if (!limit) { 39 offset = 0 40 } 41 ··· 43 results.innerHTML = '' // yeet the children! 44 pages.innerHTML = '' // yeet more children! 45 46 + console.log('search: ', query.value, limit, offset) 47 + 48 + const search_results = await search(query.value, limit, offset) 49 if (search_results.length >= 0) { 50 for (result of search_results) { 51 // same as components/post_mini.html except js ··· 73 74 // set up pagination 75 if (offset > 0) { 76 + // creates a separator 77 + function sep() { 78 + const span = document.createElement('span') 79 + span.innerText = ' - ' 80 + pages.appendChild(span) 81 + } 82 + 83 + const first_link = document.createElement('a') 84 // we escape the $ here because otherwise V will try to perform replacements at compile-time. 85 //todo: report this, this behaviour should be changed or at least looked into further. 86 + first_link.href = '/search?q=' + query.value + '&limit=' + limit + '&offset=0' 87 + first_link.innerText = '0' 88 + pages.appendChild(first_link) 89 + 90 + sep() 91 + 92 + const back_link = document.createElement('a') 93 + back_link.href = '/search?q=' + query.value + '&limit=' + limit + '&offset=' + Math.min(0, offset - 10) 94 + back_link.innerText = '<' 95 pages.appendChild(back_link) 96 + 97 + sep() 98 99 const next_link = document.createElement('a') 100 + next_link.href = '/search?q=' + query.value + '&limit=' + limit + '&offset=' + (offset + 10) 101 + next_link.innerText = '>' 102 pages.appendChild(next_link) 103 } 104 } else {