Merge pull request 'dev' (#22) from dev into master

Reviewed-on: #22
This commit is contained in:
Flummi 2022-05-06 14:20:30 +02:00
commit 4a1caac228
13 changed files with 174 additions and 90 deletions

26
package-lock.json generated
View File

@ -11,7 +11,7 @@
"dependencies": { "dependencies": {
"cuffeo": "^1.0.7-3", "cuffeo": "^1.0.7-3",
"flumm-fetch": "^1.0.1", "flumm-fetch": "^1.0.1",
"flummpress": "^2.0.4", "flummpress": "^2.0.5",
"postgres": "^3.0.1" "postgres": "^3.0.1"
} }
}, },
@ -40,14 +40,14 @@
} }
}, },
"node_modules/flummpress": { "node_modules/flummpress": {
"version": "2.0.4", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/flummpress/-/flummpress-2.0.4.tgz", "resolved": "https://registry.npmjs.org/flummpress/-/flummpress-2.0.5.tgz",
"integrity": "sha512-AuEf/VnfC9hWqw+/0aH+Y+c8UgZ6CX/wVN8RR8V9btvYhIzLTJzVlyC0oTg5yrqLMUGaL9y8YRBjg2hKbFm94A==" "integrity": "sha512-C/8Im6OvoZw67q9DvYIXKjKr28zHYLJdH4DucQ6zpVbN1eWPySmxkJTURbkq3uEwABXLngXLifS6mjxAC++umQ=="
}, },
"node_modules/postgres": { "node_modules/postgres": {
"version": "3.0.2", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/postgres/-/postgres-3.0.2.tgz", "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.1.0.tgz",
"integrity": "sha512-sHkEGAnPVqRclh5oIr9S9e/VNX0/MUb2PgS9bl/0wnI8WrHhzMmxqq/fAkMZKUUrC3Lfa4qaNh1dyDPH4Q8V0w==", "integrity": "sha512-yQbJtA7z6SsQuFiF01rmHlkG2gU5IEv9D/Pn2fu8Tz6x3/suNWZs4fIPd59rkL+dfVfhDqYQ7DU3YnUqzEDB5Q==",
"funding": { "funding": {
"type": "individual", "type": "individual",
"url": "https://github.com/sponsors/porsager" "url": "https://github.com/sponsors/porsager"
@ -77,14 +77,14 @@
} }
}, },
"flummpress": { "flummpress": {
"version": "2.0.4", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/flummpress/-/flummpress-2.0.4.tgz", "resolved": "https://registry.npmjs.org/flummpress/-/flummpress-2.0.5.tgz",
"integrity": "sha512-AuEf/VnfC9hWqw+/0aH+Y+c8UgZ6CX/wVN8RR8V9btvYhIzLTJzVlyC0oTg5yrqLMUGaL9y8YRBjg2hKbFm94A==" "integrity": "sha512-C/8Im6OvoZw67q9DvYIXKjKr28zHYLJdH4DucQ6zpVbN1eWPySmxkJTURbkq3uEwABXLngXLifS6mjxAC++umQ=="
}, },
"postgres": { "postgres": {
"version": "3.0.2", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/postgres/-/postgres-3.0.2.tgz", "resolved": "https://registry.npmjs.org/postgres/-/postgres-3.1.0.tgz",
"integrity": "sha512-sHkEGAnPVqRclh5oIr9S9e/VNX0/MUb2PgS9bl/0wnI8WrHhzMmxqq/fAkMZKUUrC3Lfa4qaNh1dyDPH4Q8V0w==" "integrity": "sha512-yQbJtA7z6SsQuFiF01rmHlkG2gU5IEv9D/Pn2fu8Tz6x3/suNWZs4fIPd59rkL+dfVfhDqYQ7DU3YnUqzEDB5Q=="
} }
} }
} }

View File

@ -16,7 +16,7 @@
"dependencies": { "dependencies": {
"cuffeo": "^1.0.7-3", "cuffeo": "^1.0.7-3",
"flumm-fetch": "^1.0.1", "flumm-fetch": "^1.0.1",
"flummpress": "^2.0.4", "flummpress": "^2.0.5",
"postgres": "^3.0.1" "postgres": "^3.0.1"
} }
} }

View File

@ -40,6 +40,10 @@ html[theme='f0ck'] {
--scroller-bg: #424242; --scroller-bg: #424242;
} }
html[theme="f0ck"] .admin-search button {
color: var(--black)!important;
}
html[theme='p1nk'] { html[theme='p1nk'] {
--accent: #ff00d0; --accent: #ff00d0;
--bg: #171717; --bg: #171717;
@ -146,6 +150,23 @@ html[theme='amoled'] {
--scroller-bg: #424242; --scroller-bg: #424242;
} }
html[theme="amoled"] .admin-search button {
color: var(--black)!important;
}
html[theme="amoled"] table.table tbody tr:nth-of-type(2n+1) a {
color: var(--white) !important;
text-decoration: underline;
}
html[theme="amoled"] table.table tbody tr:nth-of-type(2n+1) {
color: var(--white) !important;
}
html[theme="amoled"] table.table a {
text-decoration: underline;
}
html[theme="paper"] { html[theme="paper"] {
--accent: #000; --accent: #000;
--bg: #fff; --bg: #fff;
@ -265,6 +286,28 @@ html[theme="paper"] span#favs {
border: 1px solid var(--white); border: 1px solid var(--white);
} }
html[theme="paper"] .admin-search button {
color: var(--white)!important;
opacity: 0.9;
}
html[theme="paper"] table.table tbody tr:nth-of-type(2n+1) a {
color: var(--white) !important;
text-decoration: underline;
}
html[theme="paper"] table.table tbody tr:nth-of-type(2n+1) {
color: var(--white) !important;
}
html[theme="paper"] table.table a {
text-decoration: underline;
}
html[theme="paper"] a {
color: var(--black);
}
html[theme="atmos"] { html[theme="atmos"] {
--accent: #1fb2b0; --accent: #1fb2b0;
--bg: #161618; --bg: #161618;
@ -438,7 +481,7 @@ html, body {
} }
a { a {
color: var(--accent) !important; color: var(--accent) /* !important */;
cursor: pointer; cursor: pointer;
text-decoration: none; text-decoration: none;
} }
@ -616,7 +659,7 @@ span.f0ck {
border-radius: 3px; border-radius: 3px;
background-image: linear-gradient(to bottom,var(--nav-link-background-linear-gradient)); background-image: linear-gradient(to bottom,var(--nav-link-background-linear-gradient));
box-shadow: var(--nav-link-box-shadow); box-shadow: var(--nav-link-box-shadow);
color: transparent; /* color: transparent; */
} }
.navbar-expand-lg .navbar-nav .nav-link, .pagination > a, .pagination > span { .navbar-expand-lg .navbar-nav .nav-link, .pagination > a, .pagination > span {
@ -710,6 +753,7 @@ span.f0ck {
span.placeholder { span.placeholder {
border-left: 1px solid var(--accent); border-left: 1px solid var(--accent);
margin-left: 7px; margin-left: 7px;
user-select: none;
} }
.navbar .nav-item .dropdown-menu { .navbar .nav-item .dropdown-menu {
@ -1705,3 +1749,36 @@ a[data-mime^="audio"] {
margin: 10px; margin: 10px;
align-self: center; align-self: center;
} }
/* Admin search css early test */
.admin-search {
margin-top: 15px;
display: flex;
justify-content: center;
}
.admin-search button {
background: var(--accent);
border: none;
color: var(--white);
padding: 15px;
}
.admin-search button:hover {
transition: .2s all;
opacity: 0.7;
cursor: pointer;
}
.admin-search input {
padding: 15px;
border: 1px solid var(--accent);
}
table img {
border: 1px solid;
}
.results {
padding: 5px;
}

View File

@ -249,7 +249,7 @@ const flash = ({ type, msg }) => {
const a = document.createElement('a'); const a = document.createElement('a');
a.href = `/user/${f.user}/favs`; a.href = `/user/${f.user}/favs`;
a.setAttribute('tooltip', f.user); a.setAttribute('tooltip', f.user);
a.setAttribute('flow', 'down'); a.setAttribute('flow', 'up');
const img = document.createElement('img'); const img = document.createElement('img');
img.src = `/t/${f.avatar}.webp`; img.src = `/t/${f.avatar}.webp`;

View File

@ -227,6 +227,7 @@ export default {
? db`group by st.tag, st.item_id, "items".id` ? db`group by st.tag, st.item_id, "items".id`
: db`group by "items".id, "favorites".user_id, "favorites".item_id, "user".id` : db`group by "items".id, "favorites".user_id, "favorites".item_id, "user".id`
} }
order by "items".id desc
`; `;
} }
else { else {

View File

@ -1,7 +1,6 @@
import db from "../sql.mjs"; import db from "../sql.mjs";
import lib from "../lib.mjs"; import lib from "../lib.mjs";
import { exec } from "child_process"; import { exec } from "child_process";
import search from "../routeinc/search.mjs";
const auth = async (req, res, next) => { const auth = async (req, res, next) => {
if(!req.session) { if(!req.session) {
@ -120,43 +119,6 @@ export default (router, tpl) => {
}, req) }, req)
}); });
}); });
router.get(/^\/admin\/test(\/)?$/, auth, async (req, res) => {
let ret;
if(Object.keys(req.url.qs).length > 0) {
let tag = req.url.qs.tag;
let rows;
if(tag.startsWith('src:')) {
tag = tag.substring(4);
ret = await db`
select *
from "items"
where src ilike ${'%' + tag + '%'}
limit 500
`;
}
else {
rows = await db`
select "items".id, "items".username, "tags".tag
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 + '%'}
limit 500
`;
ret = search(rows, tag);
}
}
res.reply({
body: tpl.render("admin/search", {
result: ret,
totals: await lib.countf0cks(),
session: req.session
}, req)
});
});
router.get(/^\/admin\/log(\/)?$/, auth, async (req, res) => { router.get(/^\/admin\/log(\/)?$/, auth, async (req, res) => {
exec("journalctl -qeu f0ck --no-pager", (err, stdout) => { exec("journalctl -qeu f0ck --no-pager", (err, stdout) => {

44
src/inc/routes/search.mjs Normal file
View File

@ -0,0 +1,44 @@
import db from "../sql.mjs";
import lib from "../lib.mjs";
import search from "../routeinc/search.mjs";
export default (router, tpl) => {
router.get(/^\/search(\/)?$/, lib.auth, async (req, res) => {
let ret;
let tag = req.url.qs?.tag;
if(Object.keys(req.url.qs).length > 0) {
let rows;
if(tag.startsWith('src:')) {
tag = tag.substring(4);
ret = await db`
select *
from "items"
where src ilike ${'%' + tag + '%'}
limit 500
`;
}
else {
rows = await db`
select "items".id, "items".username, "items".mime, "tags".tag
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 + '%'}
limit 500
`;
ret = search(rows, tag);
}
}
res.reply({
body: tpl.render("search", {
result: ret,
totals: await lib.countf0cks(),
searchstring: tag,
session: req.session,
tmp: null
}, req)
});
});
};

View File

@ -1,27 +0,0 @@
@include(snippets/header_admin)
<form action="/admin/test" style="margin-top: 15px;">
<input type="text" name="tag" /><button type="submit">search</button>
</form>
<hr />
@if(result)
<h1>{{ result.length }} f0cks given</h1>
<table style="width: 100%;">
<tr>
<td style="text-align: center;">Thumbnail</td>
<td style="text-align: center;">ID</td>
<td style="text-align: center;">Tag</td>
<td style="text-align: center;">Username</td>
<td style="text-align: center;">Score</td>
</tr>
@each(result as line)
<tr>
<td style="width: 128px;"><a href="/{{ line.id }}" target="_blank"><img src="/t/{{ line.id }}.webp" /></a></td>
<td style="text-align: center;"><a href="/{{ line.id }}" target="_blank">{{ line.id }}</a></td>
<td style="text-align: center;"><a href="/admin/test?tag={{ line.tag?.replace(/\s/g, "+") }}">{{ line.tag }}</a></td>
<td style="text-align: center;">{{ line.username }}</td>
<td style="text-align: center;">{{ line.score }}</td>
</tr>
@endeach
</table>
@endif
@include(snippets/footer)

View File

@ -79,7 +79,7 @@
<span class="badge" id="favs"@if(!item.favorites.length || !session) hidden@endif> <span class="badge" id="favs"@if(!item.favorites.length || !session) hidden@endif>
@if(item.favorites.length && session) @if(item.favorites.length && session)
@each(item.favorites as fav) @each(item.favorites as fav)
<a href="/user/{{ fav.user.toLowerCase() }}/favs" tooltip="{{ fav.user }}" flow="down"><img src="@if(fav.avatar)/t/{{ fav.avatar }}.webp@else/s/img/default.png@endif" style="height: 32px; width: 32px" /></a> <a href="/user/{{ fav.user.toLowerCase() }}/favs" tooltip="{{ fav.user }}" flow="up"><img src="@if(fav.avatar)/t/{{ fav.avatar }}.webp@else/s/img/default.png@endif" style="height: 32px; width: 32px" /></a>
@endeach @endeach
@endif @endif
</span> </span>

View File

@ -10,8 +10,8 @@
@for(let i = 0; i < list.length; i++) @for(let i = 0; i < list.length; i++)
<tr> <tr>
<td>{{ i + 1 }}</td> <td>{{ i + 1 }}</td>
<td><img class="avatar" src="/t/{{ list[i].avatar }}.webp" /></td> <td><a href="/{{ list[i].avatar }}"><img class="avatar" src="/t/{{ list[i].avatar }}.webp" /></a></td>
<td>{!! list[i].user !!}</td> <td><a href="/user/{!! list[i].user !!}">{!! list[i].user !!}</a></td>
<td>{{ list[i].count }}</td> <td>{{ list[i].count }}</td>
</tr> </tr>
@endfor @endfor

31
views/search.html Normal file
View File

@ -0,0 +1,31 @@
@include(snippets/header)
<h1 style="text-align: center">f0ckgle</h1>
<form action="/search" class="admin-search">
<input type="text" name="tag" value="{!! searchstring !!}" /><button type="submit"><b>f0ck</b></button>
</form>
<div class="results">
@if(result)
<h1>{{ result.length }} f0cks given:</h1>
<table style="width: 100%;" class="table">
<tr>
<th>Thumbnail</th>
<th>ID</th>
<th>Tag</th>
<th>Mime</th>
<th>Username</th>
<th>Score</th>
</tr>
@each(result as line)
<tr>
<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 style="text-align: center;"><a href="/tag/{!! line.tag !!}">{!! line.tag !!}</a></td>
<td style="text-align: center;">{{ line.mime }}</td>
<td style="text-align: center;"><a href="/user/{!! line.username !!}/f0cks/{{ line.id }}">{!! line.username !!}</a></td>
<td style="text-align: center;">{{ line.score.toFixed(2) }}</td>
</tr>
@endeach
</table>
@endif
</div>
@include(snippets/footer)

View File

@ -12,6 +12,7 @@
<li><a href="/user/{{ session.user.toLowerCase() }}/f0cks">my f0cks</a></li> <li><a href="/user/{{ session.user.toLowerCase() }}/f0cks">my f0cks</a></li>
<li><a href="/user/{{ session.user.toLowerCase() }}/favs">my favs</a></li> <li><a href="/user/{{ session.user.toLowerCase() }}/favs">my favs</a></li>
<li><a href="/settings">settings</a></li> <li><a href="/settings">settings</a></li>
<li><a href="/search">search</a></li>
<li><a href="/about">About</a></li> <li><a href="/about">About</a></li>
<li><a href="/ranking">Ranking</a></li> <li><a href="/ranking">Ranking</a></li>
<li><a href="/logout">logout</a></li> <li><a href="/logout">logout</a></li>

View File

@ -15,11 +15,6 @@
<span class="nav-link-identifier">sessions</span> <span class="nav-link-identifier">sessions</span>
</a> </a>
</li> </li>
<li class="nav-item">
<a class="nav-link" href="/admin/test">
<span class="nav-link-identifier">search&nbsp;(wip)</span>
</a>
</li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="/admin/log"> <a class="nav-link" href="/admin/log">
<span class="nav-link-identifier">Log</span> <span class="nav-link-identifier">Log</span>