ddd
This commit is contained in:
1 parent
d72ef520cd
commit
b96e1e19df
3 files changed
+90
-1
No files matched your search
@@ -131,6 +131,24 @@ func main() {
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string][]flashcardSummary{"flashcards": summaries})
|
||||
})))
|
||||
mux.Handle("/api/v1/flashcards/search", withAuth(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
writeJSON(w, http.StatusMethodNotAllowed, map[string]string{"error": "method not allowed"})
|
||||
return
|
||||
}
|
||||
query := r.URL.Query().Get("q")
|
||||
if query == "" {
|
||||
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "missing query parameter 'q'"})
|
||||
return
|
||||
}
|
||||
results, err := searchEngine.Search(r.Context(), query, 50)
|
||||
if err != nil {
|
||||
logger.Error("search flashcards", zap.Error(err))
|
||||
writeJSON(w, http.StatusInternalServerError, map[string]string{"error": "internal error"})
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]any{"results": results, "query": query})
|
||||
})))
|
||||
mux.Handle("/api/v1/flashcards/", withAuth(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodGet {
|
||||
writeJSON(w, http.StatusMethodNotAllowed, map[string]string{"error": "method not allowed"})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import m from "https://esm.sh/mithril@2.3.8";
|
||||
|
||||
const API = "/api/v1/flashcards";
|
||||
const SEARCH_API = "/api/v1/flashcards/search";
|
||||
const AUTH = "/api/v1/auth";
|
||||
const USERS = "/api/v1/users";
|
||||
const SESSIONS = "/api/v1/sessions";
|
||||
@@ -221,6 +222,8 @@ const List = {
|
||||
oninit: async function (v) {
|
||||
v.state.cards = [];
|
||||
v.state.loading = true;
|
||||
v.state.query = "";
|
||||
v.state.searching = false;
|
||||
const res = await fetch(API);
|
||||
const data = await res.json();
|
||||
v.state.cards = data.flashcards || [];
|
||||
@@ -235,10 +238,78 @@ const List = {
|
||||
m("p.cyber-text-muted.cyber-mt-md", "loading\u2026"),
|
||||
]);
|
||||
}
|
||||
|
||||
const doSearch = async () => {
|
||||
const q = v.state.query.trim();
|
||||
if (!q) {
|
||||
v.state.searching = true;
|
||||
const res = await fetch(API);
|
||||
const data = await res.json();
|
||||
v.state.cards = data.flashcards || [];
|
||||
v.state.searching = false;
|
||||
v.state.page = 1;
|
||||
m.redraw();
|
||||
return;
|
||||
}
|
||||
v.state.searching = true;
|
||||
m.redraw();
|
||||
const res = await fetch(SEARCH_API + "?q=" + encodeURIComponent(q));
|
||||
const data = await res.json();
|
||||
v.state.cards = (data.results || []).map((r) => ({
|
||||
id: r.id,
|
||||
version: r.version,
|
||||
note: r.note,
|
||||
tags: r.tags,
|
||||
host: r.host,
|
||||
user: r.user,
|
||||
score: r.score,
|
||||
}));
|
||||
v.state.searching = false;
|
||||
v.state.page = 1;
|
||||
m.redraw();
|
||||
};
|
||||
|
||||
const totalPages = Math.max(1, Math.ceil(v.state.cards.length / PAGE_SIZE));
|
||||
const page = Math.min(v.state.page, totalPages);
|
||||
const slice = v.state.cards.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE);
|
||||
return m(".cyber-p-lg", { style: "max-width:720px;margin:0 auto" }, [
|
||||
m(
|
||||
"form.cyber-flex.cyber-gap-sm.cyber-mb-md",
|
||||
{
|
||||
onsubmit: (e) => {
|
||||
e.preventDefault();
|
||||
doSearch();
|
||||
},
|
||||
},
|
||||
[
|
||||
m("input.cyber-input", {
|
||||
style: "flex:1",
|
||||
placeholder: "Search flashcards\u2026",
|
||||
value: v.state.query,
|
||||
oninput: (e) => {
|
||||
v.state.query = e.target.value;
|
||||
},
|
||||
}),
|
||||
m(
|
||||
"button.cyber-btn.cyber-btn--primary",
|
||||
{ type: "submit", disabled: v.state.searching },
|
||||
v.state.searching ? "..." : "Search",
|
||||
),
|
||||
v.state.query
|
||||
? m(
|
||||
"button.cyber-btn.cyber-btn--ghost",
|
||||
{
|
||||
type: "button",
|
||||
onclick: () => {
|
||||
v.state.query = "";
|
||||
doSearch();
|
||||
},
|
||||
},
|
||||
"Clear",
|
||||
)
|
||||
: null,
|
||||
],
|
||||
),
|
||||
m(Pager, {
|
||||
page,
|
||||
total: totalPages,
|
||||
|
||||
@@ -216,7 +216,7 @@ func (s *sqliteStore) listAll(ctx context.Context) ([]flashcardSummary, error) {
|
||||
WHERE f.version = (SELECT MAX(f2.version) FROM flashcard f2 WHERE f2.public_id = f.public_id)
|
||||
AND f.delete_timestamp IS NULL
|
||||
AND f.public_id != 0
|
||||
ORDER BY f.public_id`,
|
||||
ORDER BY f.created DESC`,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list: %w", err)
|
||||
|
||||
Reference in new issue
Block a user