+1
-1
src/database/post.v
+1
-1
src/database/post.v
···
160
160
return results
161
161
}
162
162
163
-
// search_for_post searches for posts matching the given query.
163
+
// search_for_posts searches for posts matching the given query.
164
164
// todo: query options/filters, such as user:beep, !excluded-text, etc
165
165
pub fn (app &DatabaseAccess) search_for_posts(query string, limit int, offset int) []PostSearchResult {
166
166
sql_query := "\
+21
src/database/user.v
+21
src/database/user.v
···
206
206
207
207
return true
208
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
+1
-1
src/entity/post.v
···
18
18
posted_at time.Time = time.now()
19
19
}
20
20
21
-
// Post.from_row creates a post from the given database row.
21
+
// Post.from_row creates a post object from the given database row.
22
22
// see src/database/post.v#search_for_posts for usage.
23
23
@[inline]
24
24
pub fn Post.from_row(row pg.Row) Post {
+27
src/entity/user.v
+27
src/entity/user.v
···
1
1
module entity
2
2
3
+
import db.pg
3
4
import time
5
+
import util
4
6
5
7
pub struct User {
6
8
pub mut:
···
37
39
.replace(user.password, '*'.repeat(16))
38
40
.replace(user.password_salt, '*'.repeat(16))
39
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
+30
-7
src/templates/search.html
···
29
29
query.value = params.get('q')
30
30
}
31
31
32
+
let limit = params.get('limit')
33
+
if (!limit) {
34
+
limit = 10
35
+
}
36
+
32
37
let offset = params.get('offset')
33
-
if (!offset) {
38
+
if (!limit) {
34
39
offset = 0
35
40
}
36
41
···
38
43
results.innerHTML = '' // yeet the children!
39
44
pages.innerHTML = '' // yeet more children!
40
45
41
-
const search_results = await search(query.value, 10, Number(offset.value))
46
+
console.log('search: ', query.value, limit, offset)
47
+
48
+
const search_results = await search(query.value, limit, offset)
42
49
if (search_results.length >= 0) {
43
50
for (result of search_results) {
44
51
// same as components/post_mini.html except js
···
66
73
67
74
// set up pagination
68
75
if (offset > 0) {
69
-
const back_link = document.createElement('a')
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')
70
84
// we escape the $ here because otherwise V will try to perform replacements at compile-time.
71
85
//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 = '<-'
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 = '<'
74
95
pages.appendChild(back_link)
96
+
97
+
sep()
75
98
76
99
const next_link = document.createElement('a')
77
-
next_link.href = '/search?q=' + query.value + '&limit=10&offset=' + (offset.value + 10)
78
-
next_link.innerText = '->'
100
+
next_link.href = '/search?q=' + query.value + '&limit=' + limit + '&offset=' + (offset + 10)
101
+
next_link.innerText = '>'
79
102
pages.appendChild(next_link)
80
103
}
81
104
} else {