2026-06-12 01:58:46 +02:00
|
|
|
// retoor <retoor@molodetz.nl>
|
|
|
|
|
|
2026-05-23 08:34:13 +02:00
|
|
|
import { Http } from "./Http.js";
|
|
|
|
|
import { Avatar } from "./Avatar.js";
|
feat: add leaderboard router, gamification backfill, and shared content creation helpers
Introduce a new `/leaderboard` endpoint ranking top 50 members by total stars, wire it into the app router and documentation. Implement `_backfill_gamification()` in `database.py` to compute XP/levels for existing accounts from prior posts, comments, votes, and follows. Extract `is_owner()`, `create_content_item()`, and `detail_context()` into `content.py` to centralize content creation, reward awarding, mention notifications, and attachment linking. Update comment creation/deletion in `comments.py` to use `award_rewards()` with `XP_COMMENT` and the new `is_owner()` helper. Add shared template partials documentation for vote bars, star buttons, post headers, and topic selectors to `AGENTS.md`.
2026-05-30 20:16:39 +02:00
|
|
|
import { DomUtils } from "./DomUtils.js";
|
2026-06-19 10:06:09 +02:00
|
|
|
import { ListNav } from "./ListNav.js";
|
2026-05-23 08:34:13 +02:00
|
|
|
|
2026-05-23 01:50:31 +02:00
|
|
|
export class MessageSearch {
|
|
|
|
|
constructor() {
|
|
|
|
|
this.initMessageSearch();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
initMessageSearch() {
|
|
|
|
|
const searchInput = document.getElementById("message-search");
|
|
|
|
|
if (!searchInput) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const wrap = searchInput.parentElement;
|
|
|
|
|
const dropdown = document.createElement("div");
|
|
|
|
|
dropdown.className = "search-dropdown";
|
2026-06-19 10:06:09 +02:00
|
|
|
dropdown.setAttribute("role", "listbox");
|
2026-05-23 01:50:31 +02:00
|
|
|
wrap.appendChild(dropdown);
|
|
|
|
|
|
2026-06-19 10:06:09 +02:00
|
|
|
const hide = () => {
|
|
|
|
|
DomUtils.hide(dropdown);
|
|
|
|
|
nav.closed();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const nav = new ListNav(searchInput, dropdown, {
|
|
|
|
|
itemSelector: ".search-dropdown-item",
|
|
|
|
|
activeClass: "active",
|
|
|
|
|
chooseOnTab: false,
|
|
|
|
|
isOpen: () => DomUtils.isShown(dropdown),
|
|
|
|
|
onChoose: (item) => { window.location.href = item.href; },
|
|
|
|
|
onEscape: hide,
|
|
|
|
|
});
|
|
|
|
|
|
2026-05-23 01:50:31 +02:00
|
|
|
let debounceTimer = null;
|
|
|
|
|
|
|
|
|
|
searchInput.addEventListener("input", () => {
|
|
|
|
|
clearTimeout(debounceTimer);
|
|
|
|
|
const q = searchInput.value.trim();
|
|
|
|
|
if (q.length < 1) {
|
|
|
|
|
dropdown.innerHTML = "";
|
2026-06-19 10:06:09 +02:00
|
|
|
hide();
|
2026-05-23 01:50:31 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
debounceTimer = setTimeout(async () => {
|
|
|
|
|
try {
|
2026-05-23 08:34:13 +02:00
|
|
|
const data = await Http.getJson(`/messages/search?q=${encodeURIComponent(q)}`);
|
2026-05-23 01:50:31 +02:00
|
|
|
const results = data.results || [];
|
|
|
|
|
if (results.length === 0) {
|
2026-06-19 10:06:09 +02:00
|
|
|
hide();
|
2026-05-23 01:50:31 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
dropdown.innerHTML = "";
|
|
|
|
|
for (const r of results) {
|
|
|
|
|
const item = document.createElement("a");
|
|
|
|
|
item.className = "search-dropdown-item";
|
|
|
|
|
item.href = `/messages?with_uid=${r.uid}`;
|
2026-06-02 23:17:51 +02:00
|
|
|
const label = document.createElement("span");
|
|
|
|
|
label.textContent = r.username;
|
|
|
|
|
item.append(Avatar.imgElement(r.username), label);
|
2026-05-23 01:50:31 +02:00
|
|
|
dropdown.appendChild(item);
|
|
|
|
|
}
|
feat: add leaderboard router, gamification backfill, and shared content creation helpers
Introduce a new `/leaderboard` endpoint ranking top 50 members by total stars, wire it into the app router and documentation. Implement `_backfill_gamification()` in `database.py` to compute XP/levels for existing accounts from prior posts, comments, votes, and follows. Extract `is_owner()`, `create_content_item()`, and `detail_context()` into `content.py` to centralize content creation, reward awarding, mention notifications, and attachment linking. Update comment creation/deletion in `comments.py` to use `award_rewards()` with `XP_COMMENT` and the new `is_owner()` helper. Add shared template partials documentation for vote bars, star buttons, post headers, and topic selectors to `AGENTS.md`.
2026-05-30 20:16:39 +02:00
|
|
|
DomUtils.show(dropdown);
|
2026-06-19 10:06:09 +02:00
|
|
|
nav.opened();
|
2026-05-23 01:50:31 +02:00
|
|
|
} catch (e) {
|
2026-06-19 10:06:09 +02:00
|
|
|
hide();
|
2026-05-23 01:50:31 +02:00
|
|
|
}
|
|
|
|
|
}, 200);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
document.addEventListener("click", (e) => {
|
|
|
|
|
if (!wrap.contains(e.target)) {
|
2026-06-19 10:06:09 +02:00
|
|
|
hide();
|
2026-05-23 01:50:31 +02:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|