Compare commits

..

5 Commits

Author SHA1 Message Date
06813a87d4 Merge pull request 'dev' (#23) from dev into master
Reviewed-on: #23
2022-05-06 17:01:49 +02:00
Flummi
f5737e6f49 search lol 2022-05-06 17:02:03 +02:00
Flummi
2162f1565c fucking pagination 2022-05-06 17:01:42 +02:00
Flummi
7b2ad52fe0 fix undefined if searchstring is empty 2022-05-06 14:48:47 +02:00
Flummi
68ce51b892 chrome lol 2022-05-06 14:46:32 +02:00
8 changed files with 120 additions and 52 deletions

View File

@ -474,6 +474,12 @@ html, body {
overscroll-behavior-y: contain; overscroll-behavior-y: contain;
overflow: overlay; overflow: overlay;
font-size: 14px; font-size: 14px;
height: 100%;
}
@supports (-moz-appearance:none) {
html, body {
height: auto !important;
}
} }
.noscript-badge { .noscript-badge {
@ -570,6 +576,7 @@ div#posts > a:hover::after {
} }
.navbar { .navbar {
position: -webkit-sticky;
position: sticky; position: sticky;
top: 0; top: 0;
padding: 0; padding: 0;
@ -1532,7 +1539,6 @@ table.table {
min-width: max-content; min-width: max-content;
} }
table.table thead tr { table.table thead tr {
text-align: left;
font-weight: bolder; font-weight: bolder;
border-bottom: 1px solid var(--accent); border-bottom: 1px solid var(--accent);
} }
@ -1541,6 +1547,7 @@ table.table tr {
} }
table.table th, table.table td { table.table th, table.table td {
padding: 7px 15px; padding: 7px 15px;
text-align: center;
} }
table.table tbody tr:nth-of-type(odd) { table.table tbody tr:nth-of-type(odd) {
background-color: var(--badge-tag); background-color: var(--badge-tag);

View File

@ -64,8 +64,17 @@ export default new class {
if(env.tag) link.push("tag", env.tag); if(env.tag) link.push("tag", env.tag);
if(env.user) link.push("user", env.user, env.type ?? 'f0cks'); if(env.user) link.push("user", env.user, env.type ?? 'f0cks');
if(env.mime.length > 2) link.push(env.mime); if(env.mime.length > 2) link.push(env.mime);
if(env.page) link.push("p", env.page);
return link.join("/"); let tmp = link.length === 0 ? '/' : link.join('/');
if(!tmp.endsWith('/'))
tmp = tmp + '/';
if(!tmp.startsWith('/'))
tmp = '/' + tmp;
return {
main: tmp,
path: env.path ? env.path : ''
};
}; };
parseTag(tag) { parseTag(tag) {
if(!tag) if(!tag)

View File

@ -161,7 +161,7 @@ export default {
for(let i = Math.max(1, act_page - 3); i <= Math.min(act_page + 3, pages); i++) for(let i = Math.max(1, act_page - 3); i <= Math.min(act_page + 3, pages); i++)
cheat.push(i); cheat.push(i);
const link = lib.genLink({ user, tag, mime, type: o.fav ? 'favs' : 'f0cks' }); const link = lib.genLink({ user, tag, mime, type: o.fav ? 'favs' : 'f0cks', path: 'p/' });
data = { data = {
success: true, success: true,
@ -172,11 +172,10 @@ export default {
prev: (act_page > 1) ? act_page - 1 : null, prev: (act_page > 1) ? act_page - 1 : null,
next: (act_page < pages) ? act_page + 1 : null, next: (act_page < pages) ? act_page + 1 : null,
page: act_page, page: act_page,
cheat: cheat, cheat: cheat
uff: false
}, },
link: link, link,
tmp: tmp tmp
}; };
return data; return data;
}, },
@ -279,7 +278,7 @@ export default {
const tags = await lib.getTags(itemid); const tags = await lib.getTags(itemid);
const cheat = [...new Set(items.slice(Math.max(0, item - 3), item + 4).map(i => i.id))]; const cheat = [...new Set(items.slice(Math.max(0, item - 3), item + 4).map(i => i.id))];
const link = lib.genLink({ user, tag, mime, type: o.fav ? 'favs' : 'f0cks' }); const link = lib.genLink({ user, tag, mime, type: o.fav ? 'favs' : 'f0cks', path: '' });
const favorites = await db` const favorites = await db`
select "user".user, "user_options".avatar select "user".user, "user_options".avatar
from "favorites" from "favorites"
@ -327,12 +326,11 @@ export default {
next: items[item + 1]?.id, next: items[item + 1]?.id,
prev: items[item - 1]?.id, prev: items[item - 1]?.id,
page: actitem.id, page: actitem.id,
cheat: cheat, cheat: cheat
uff: true
}, },
phrase: cfg.websrv.phrases[~~(Math.random() * cfg.websrv.phrases.length)], phrase: cfg.websrv.phrases[~~(Math.random() * cfg.websrv.phrases.length)],
link: link, link,
tmp: tmp tmp
}; };
return data; return data;
}, },

View File

@ -2,33 +2,81 @@ import db from "../sql.mjs";
import lib from "../lib.mjs"; import lib from "../lib.mjs";
import search from "../routeinc/search.mjs"; import search from "../routeinc/search.mjs";
const _eps = 20;
export default (router, tpl) => { export default (router, tpl) => {
router.get(/^\/search(\/)?$/, lib.auth, async (req, res) => { router.get(/^\/search(\/)?$/, lib.auth, async (req, res) => {
let ret; let ret;
let tag = req.url.qs?.tag; let tag = req.url.qs.tag ?? [];
if(Object.keys(req.url.qs).length > 0) { let page = req.url.qs.page ?? 1;
let rows; let total = 0;
let pagination, link;
if(tag.length > 1) {
if(tag.startsWith('src:')) {
total = (await db`
select count(*) as total
from "items"
where src ilike ${'%' + tag.substring(4) + '%'}
group by "items".id, "tags".tag
`).length;
}
else {
total = (await db`
select count(*) as total
from "tags"
left join "tags_assign" on "tags_assign".tag_id = "tags".id
left join "items" on "items".id = "tags_assign".item_id
where "tags".tag ilike ${'%' + tag + '%'}
group by "items".id, "tags".tag
`).length;
}
const pages = +Math.ceil(total / _eps);
const act_page = Math.min(pages, page || 1);
const offset = Math.max(0, (act_page - 1) * _eps);
if(tag.startsWith('src:')) { if(tag.startsWith('src:')) {
tag = tag.substring(4);
ret = await db` ret = await db`
select * select *
from "items" from "items"
where src ilike ${'%' + tag + '%'} where src ilike ${'%' + tag.substring(4) + '%'}
limit 500 group by "items".id, "tags".tag
offset ${offset}
limit ${_eps}
`; `;
} }
else { else {
rows = await db` const rows = await db`
select "items".id, "items".username, "items".mime, "tags".tag select "items".id, "items".username, "items".mime, "tags".tag
from "tags" from "tags"
left join "tags_assign" on "tags_assign".tag_id = "tags".id left join "tags_assign" on "tags_assign".tag_id = "tags".id
left join "items" on "items".id = "tags_assign".item_id left join "items" on "items".id = "tags_assign".item_id
where "tags".tag ilike ${'%' + tag + '%'} where "tags".tag ilike ${'%' + tag + '%'}
limit 500 group by "items".id, "tags".tag
offset ${offset}
limit ${_eps}
`; `;
ret = search(rows, tag); ret = search(rows, tag);
} }
const cheat = [];
for(let i = Math.max(1, act_page - 3); i <= Math.min(act_page + 3, pages); i++)
cheat.push(i);
pagination = {
start: 1,
end: pages,
prev: (act_page > 1) ? act_page - 1 : null,
next: (act_page < pages) ? act_page + 1 : null,
page: act_page,
cheat: cheat,
uff: false
};
link = {
main: `/search/?tag=${tag}`,
path: '&page='
};
} }
res.reply({ res.reply({
@ -36,8 +84,10 @@ export default (router, tpl) => {
result: ret, result: ret,
totals: await lib.countf0cks(), totals: await lib.countf0cks(),
searchstring: tag, searchstring: tag,
session: req.session, count: total,
tmp: null tmp: null,
pagination,
link
}, req) }, req)
}); });
}); });

View File

@ -1,10 +1,10 @@
@include(snippets/header) @include(snippets/header)
<div class="index-container"> <div class="index-container">
@if(tmp.user)<h2>user: {!! tmp.user.toLowerCase() !!}@if(tmp.mime) ({{ tmp.mime }}s)@else (all)@endif</h2>@endif @if(tmp.user)<h2>user: {!! tmp.user.toLowerCase() !!}@if(tmp.mime) ({{ tmp.mime }}s)@else (all)@endif</h2>@endif
@if(tmp.tag)<h2>tag: @if(session)<a href="/admin/test?tag={!! tmp.tag.toLowerCase() !!}" target="_blank">{!! tmp.tag.toLowerCase() !!}</a>@else{!! tmp.tag.toLowerCase() !!}@endif@if(tmp.mime) ({{ tmp.mime }}s)@else (all)@endif</h2>@endif @if(tmp.tag)<h2>tag: @if(session)<a href="/search?tag={!! tmp.tag.toLowerCase() !!}" target="_blank">{!! tmp.tag.toLowerCase() !!}</a>@else{!! tmp.tag.toLowerCase() !!}@endif@if(tmp.mime) ({{ tmp.mime }}s)@else (all)@endif</h2>@endif
<div id="posts"> <div id="posts">
@each(items as item) @each(items as item)
<a href="/{{ link }}@if(link.length != 0)/@endif{{ item.id }}" data-mime="{{ item.mime }}" data-mode="{{ item.tag_id ? ['','sfw','nsfw'][item.tag_id] : 'null' }}" style="background-image: url('/t/{{ item.id }}.webp')"><p></p></a> <a href="{{ link.main }}{{ item.id }}" data-mime="{{ item.mime }}" data-mode="{{ item.tag_id ? ['','sfw','nsfw'][item.tag_id] : 'null' }}" style="background-image: url('/t/{{ item.id }}.webp')"><p></p></a>
@endeach @endeach
</div> </div>
<div id="footbar"> <div id="footbar">

View File

@ -4,7 +4,7 @@
<div class="next-post"> <div class="next-post">
@if(pagination.prev) @if(pagination.prev)
<div class="arrow-next"> <div class="arrow-next">
<a id="next" href="/{{ link }}@if(link.length != 0)/@endif{{ pagination.prev }}"></a> <a id="next" href="{{ link.main }}{{ pagination.prev }}"></a>
</div> </div>
@else @else
<div class="arrow-next"> <div class="arrow-next">
@ -34,7 +34,7 @@
<div class="previous-post"> <div class="previous-post">
@if(pagination.next) @if(pagination.next)
<div class="arrow-prev"> <div class="arrow-prev">
<a id="prev" href="/{{ link }}@if(link.length != 0)/@endif{{ pagination.next }}"></a> <a id="prev" href="{{ link.main }}{{ pagination.next }}"></a>
</div> </div>
@else @else
<div class="arrow-prev"> <div class="arrow-prev">

View File

@ -1,30 +1,34 @@
@include(snippets/header) @include(snippets/header)
<h1 style="text-align: center">f0ckgle</h1> <h1 style="text-align: center">f0ckgle</h1>
<form action="/search" class="admin-search"> <form action="/search" class="admin-search">
<input type="text" name="tag" value="{!! searchstring !!}" /><button type="submit"><b>f0ck</b></button> <input type="text" name="tag" value="{!! searchstring || '' !!}" /><button type="submit"><b>f0ck</b></button>
</form> </form>
<div class="results"> <div class="results">
@if(result) @if(result)
<h1>{{ result.length }} f0cks given:</h1> <h1>{{ count }} f0cks given (page {{ pagination.page }} of {{ pagination.end }}):</h1>
<table style="width: 100%;" class="table"> <table style="width: 100%" class="table">
<tr> <thead>
<th>Thumbnail</th> <tr>
<th>ID</th> <th>Thumbnail</th>
<th>Tag</th> <th>ID</th>
<th>Mime</th> <th>Tag</th>
<th>Username</th> <th>Mime</th>
<th>Score</th> <th>Username</th>
</tr> <th>Score</th>
</tr>
</thead>
<tbody>
@each(result as line) @each(result as line)
<tr> <tr>
<td style="width: 128px;"><a href="/tag/{!! line.tag !!}/{{ line.id }}" target="_blank"><img src="/t/{{ line.id }}.webp" /></a></td> <td style="width: 128px;"><a href="/tag/{!! line.tag !!}/{{ line.id }}" target="_blank"><img src="/t/{{ line.id }}.webp" /></a></td>
<td style="text-align: center;"><a href="/tag/{!! line.tag !!}/{{ line.id }}" target="_blank">{{ line.id }}</a></td> <td><a href="/tag/{!! line.tag !!}/{{ line.id }}" target="_blank">{{ line.id }}</a></td>
<td style="text-align: center;"><a href="/tag/{!! line.tag !!}">{!! line.tag !!}</a></td> <td><a href="/tag/{!! line.tag !!}">{!! line.tag !!}</a></td>
<td style="text-align: center;">{{ line.mime }}</td> <td>{{ line.mime }}</td>
<td style="text-align: center;"><a href="/user/{!! line.username !!}/f0cks/{{ line.id }}">{!! line.username !!}</a></td> <td><a href="/user/{!! line.username !!}/f0cks/{{ line.id }}">{!! line.username !!}</a></td>
<td style="text-align: center;">{{ line.score.toFixed(2) }}</td> <td>{{ line.score.toFixed(2) }}</td>
</tr> </tr>
@endeach @endeach
</tbody>
</table> </table>
@endif @endif
</div> </div>

View File

@ -64,17 +64,17 @@
<div class="pagination-wrapper"> <div class="pagination-wrapper">
@if(typeof pagination !== "undefined") @if(typeof pagination !== "undefined")
<nav class="pagination"> <nav class="pagination">
<a href="/{{ link }}@if(link.length != 0)/@endif@if(!pagination.uff)p/@endif{{ pagination.start }}" class="page-item-1 btn start@if(!pagination.prev) disabled@endif">&laquo;</a> <a href="{{ link.main }}{{ link.path }}{{ pagination.start }}" class="page-item-1 btn start@if(!pagination.prev) disabled@endif">&laquo;</a>
<a href="/{{ link }}@if(link.length != 0)/@endif@if(!pagination.uff)p/@endif{{ pagination.prev }}" class="page-item-2 btn prev@if(!pagination.prev) disabled@endif">&lsaquo;</a> <a href="{{ link.main }}{{ link.path }}{{ pagination.prev }}" class="page-item-2 btn prev@if(!pagination.prev) disabled@endif">&lsaquo;</a>
@each(pagination.cheat as i) @each(pagination.cheat as i)
@if(i == pagination.page) @if(i == pagination.page)
<span class="btn disabled">{{ i }}</span> <span class="btn disabled">{{ i }}</span>
@else @else
<a href="/{{ link }}@if(link.length != 0)/@endif@if(!pagination.uff)p/@endif{{ i }}" class="pagination-int-item btn">{{ i }}</a> <a href="{{ link.main }}{{ link.path }}{{ i }}" class="pagination-int-item btn">{{ i }}</a>
@endif @endif
@endeach @endeach
<a href="/{{ link }}@if(link.length != 0)/@endif@if(!pagination.uff)p/@endif{{ pagination.next }}" class="page-item-3 btn next@if(!pagination.next) disabled@endif">&rsaquo;</a> <a href="{{ link.main }}{{ link.path }}{{ pagination.next }}" class="page-item-3 btn next@if(!pagination.next) disabled@endif">&rsaquo;</a>
<a href="/{{ link }}@if(link.length != 0)/@endif@if(!pagination.uff)p/@endif{{ pagination.end }}" class="page-item-4 btn start@if(!pagination.next) disabled@endif">&raquo;</a> <a href="{{ link.main }}{{ link.path }}{{ pagination.end }}" class="page-item-4 btn start@if(!pagination.next) disabled@endif">&raquo;</a>
</nav> </nav>
@endif @endif
</div> </div>