wop commited on
Commit
26d901b
·
verified ·
1 Parent(s): d697163

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +86 -1
templates/index.html CHANGED
@@ -139,6 +139,24 @@
139
  gap: 8px;
140
  }
141
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  .pill {
143
  border: 1px solid var(--line);
144
  background: #18233d;
@@ -457,6 +475,8 @@
457
  .btn, .pill { width: 100%; text-align: center; }
458
  .pager-actions { width: 100%; }
459
  .pager-actions .btn { flex: 1; }
 
 
460
  }
461
  </style>
462
  </head>
@@ -485,6 +505,15 @@
485
  <div class="meta-line" id="listSummary"></div>
486
  </div>
487
  <div class="filters" id="statusFilters"></div>
 
 
 
 
 
 
 
 
 
488
  <form id="searchForm" class="search-form">
489
  <input id="searchInput" type="search" placeholder="Search questions, answers, or versions" />
490
  <button class="btn primary" type="submit">Search</button>
@@ -545,7 +574,7 @@
545
  (() => {
546
  const S = {
547
  clientId: null,
548
- filters: { status: "unanswered", q: "", page: 1, page_size: 20 },
549
  list: null,
550
  detail: null,
551
  };
@@ -597,12 +626,18 @@
597
  status: S.filters.status,
598
  q: S.filters.q,
599
  page: S.filters.page,
 
 
 
600
  ...extra,
601
  };
602
  if (merged.status) params.set("status", merged.status);
603
  if (merged.q) params.set("q", merged.q);
604
  if (merged.page && Number(merged.page) > 1) params.set("page", String(merged.page));
605
  if (merged.conversation_id) params.set("conversation_id", merged.conversation_id);
 
 
 
606
  return params.toString();
607
  }
608
 
@@ -669,10 +704,33 @@
669
  });
670
  }
671
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
672
  function renderList() {
673
  const list = S.list || { items: [], total: 0, page: 1, page_size: 20, has_next: false, has_prev: false };
674
  $("listSummary").textContent = `${list.total} question${list.total === 1 ? "" : "s"} in queue`;
675
  $("searchInput").value = S.filters.q || "";
 
 
676
 
677
  const items = Array.isArray(list.items) ? list.items : [];
678
  $("queueList").innerHTML = items.map((item) => {
@@ -809,6 +867,9 @@
809
  status: S.filters.status,
810
  q: S.filters.q,
811
  page: S.filters.page,
 
 
 
812
  });
813
  if (!res.ok) {
814
  showToast(res.error || "Could not load question list");
@@ -816,6 +877,7 @@
816
  }
817
  S.list = res;
818
  renderStatusFilters();
 
819
  renderList();
820
  showView("list");
821
  pushListUrl();
@@ -853,6 +915,22 @@
853
  await loadList();
854
  };
855
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
856
  $("prevPageBtn").onclick = async () => {
857
  if (!S.list?.has_prev) return;
858
  S.filters.page = Math.max(1, Number(S.filters.page || 1) - 1);
@@ -940,11 +1018,15 @@
940
  S.filters = {
941
  ...S.filters,
942
  ...(init.filters || {}),
 
 
 
943
  };
944
  S.list = init.list || null;
945
  S.detail = init.detail || null;
946
 
947
  renderStatusFilters();
 
948
  renderList();
949
  bindListHandlers();
950
 
@@ -961,6 +1043,9 @@
961
  S.filters.status = params.get("status") || "unanswered";
962
  S.filters.q = params.get("q") || "";
963
  S.filters.page = Number(params.get("page") || 1);
 
 
 
964
  const conversationId = params.get("conversation_id");
965
  await loadList();
966
  if (conversationId) {
 
139
  gap: 8px;
140
  }
141
 
142
+ .word-filter-row {
143
+ display: flex;
144
+ flex-wrap: wrap;
145
+ gap: 8px;
146
+ align-items: center;
147
+ }
148
+
149
+ .word-input {
150
+ border: 1px solid var(--line);
151
+ border-radius: 14px;
152
+ padding: 9px 12px;
153
+ background: #0e1528;
154
+ color: var(--text);
155
+ width: 80px;
156
+ }
157
+
158
+ .word-input::placeholder { color: #7381a6; }
159
+
160
  .pill {
161
  border: 1px solid var(--line);
162
  background: #18233d;
 
475
  .btn, .pill { width: 100%; text-align: center; }
476
  .pager-actions { width: 100%; }
477
  .pager-actions .btn { flex: 1; }
478
+ .word-filter-row { flex-direction: column; align-items: stretch; }
479
+ .word-input { width: 100%; }
480
  }
481
  </style>
482
  </head>
 
505
  <div class="meta-line" id="listSummary"></div>
506
  </div>
507
  <div class="filters" id="statusFilters"></div>
508
+ <div class="filters" id="sortFilters"></div>
509
+ <div class="word-filter-row">
510
+ <span class="muted" style="align-self:center;white-space:nowrap">Question words:</span>
511
+ <input id="minWordsInput" type="number" class="word-input" placeholder="Min" min="0" />
512
+ <span class="muted" style="align-self:center">–</span>
513
+ <input id="maxWordsInput" type="number" class="word-input" placeholder="Max" min="0" />
514
+ <button class="btn" type="button" id="applyWordsBtn">Apply</button>
515
+ <button class="btn" type="button" id="clearWordsBtn">Clear</button>
516
+ </div>
517
  <form id="searchForm" class="search-form">
518
  <input id="searchInput" type="search" placeholder="Search questions, answers, or versions" />
519
  <button class="btn primary" type="submit">Search</button>
 
574
  (() => {
575
  const S = {
576
  clientId: null,
577
+ filters: { status: "unanswered", q: "", page: 1, page_size: 20, sort: "newest", min_words: 0, max_words: 0 },
578
  list: null,
579
  detail: null,
580
  };
 
626
  status: S.filters.status,
627
  q: S.filters.q,
628
  page: S.filters.page,
629
+ sort: S.filters.sort,
630
+ min_words: S.filters.min_words,
631
+ max_words: S.filters.max_words,
632
  ...extra,
633
  };
634
  if (merged.status) params.set("status", merged.status);
635
  if (merged.q) params.set("q", merged.q);
636
  if (merged.page && Number(merged.page) > 1) params.set("page", String(merged.page));
637
  if (merged.conversation_id) params.set("conversation_id", merged.conversation_id);
638
+ if (merged.sort && merged.sort !== "newest") params.set("sort", merged.sort);
639
+ if (Number(merged.min_words) > 0) params.set("min_words", String(merged.min_words));
640
+ if (Number(merged.max_words) > 0) params.set("max_words", String(merged.max_words));
641
  return params.toString();
642
  }
643
 
 
704
  });
705
  }
706
 
707
+ function renderSortFilters() {
708
+ const sorts = [
709
+ ["newest", "Newest"],
710
+ ["oldest", "Oldest"],
711
+ ["most_votes", "Most Votes"],
712
+ ["most_answers", "Most Answers"],
713
+ ["longest_answer", "Longest Answer"],
714
+ ["shortest_answer", "Shortest Answer"],
715
+ ];
716
+ $("sortFilters").innerHTML = sorts.map(([value, label]) => `
717
+ <button class="pill ${S.filters.sort === value ? "active" : ""}" type="button" data-sort="${value}">${label}</button>
718
+ `).join("");
719
+ document.querySelectorAll("[data-sort]").forEach((button) => {
720
+ button.onclick = () => {
721
+ S.filters.sort = button.getAttribute("data-sort");
722
+ S.filters.page = 1;
723
+ loadList();
724
+ };
725
+ });
726
+ }
727
+
728
  function renderList() {
729
  const list = S.list || { items: [], total: 0, page: 1, page_size: 20, has_next: false, has_prev: false };
730
  $("listSummary").textContent = `${list.total} question${list.total === 1 ? "" : "s"} in queue`;
731
  $("searchInput").value = S.filters.q || "";
732
+ $("minWordsInput").value = S.filters.min_words > 0 ? S.filters.min_words : "";
733
+ $("maxWordsInput").value = S.filters.max_words > 0 ? S.filters.max_words : "";
734
 
735
  const items = Array.isArray(list.items) ? list.items : [];
736
  $("queueList").innerHTML = items.map((item) => {
 
867
  status: S.filters.status,
868
  q: S.filters.q,
869
  page: S.filters.page,
870
+ sort: S.filters.sort,
871
+ min_words: S.filters.min_words || 0,
872
+ max_words: S.filters.max_words || 0,
873
  });
874
  if (!res.ok) {
875
  showToast(res.error || "Could not load question list");
 
877
  }
878
  S.list = res;
879
  renderStatusFilters();
880
+ renderSortFilters();
881
  renderList();
882
  showView("list");
883
  pushListUrl();
 
915
  await loadList();
916
  };
917
 
918
+ $("applyWordsBtn").onclick = async () => {
919
+ S.filters.min_words = Number($("minWordsInput").value) || 0;
920
+ S.filters.max_words = Number($("maxWordsInput").value) || 0;
921
+ S.filters.page = 1;
922
+ await loadList();
923
+ };
924
+
925
+ $("clearWordsBtn").onclick = async () => {
926
+ $("minWordsInput").value = "";
927
+ $("maxWordsInput").value = "";
928
+ S.filters.min_words = 0;
929
+ S.filters.max_words = 0;
930
+ S.filters.page = 1;
931
+ await loadList();
932
+ };
933
+
934
  $("prevPageBtn").onclick = async () => {
935
  if (!S.list?.has_prev) return;
936
  S.filters.page = Math.max(1, Number(S.filters.page || 1) - 1);
 
1018
  S.filters = {
1019
  ...S.filters,
1020
  ...(init.filters || {}),
1021
+ sort: (init.filters || {}).sort || "newest",
1022
+ min_words: Number((init.filters || {}).min_words || 0),
1023
+ max_words: Number((init.filters || {}).max_words || 0),
1024
  };
1025
  S.list = init.list || null;
1026
  S.detail = init.detail || null;
1027
 
1028
  renderStatusFilters();
1029
+ renderSortFilters();
1030
  renderList();
1031
  bindListHandlers();
1032
 
 
1043
  S.filters.status = params.get("status") || "unanswered";
1044
  S.filters.q = params.get("q") || "";
1045
  S.filters.page = Number(params.get("page") || 1);
1046
+ S.filters.sort = params.get("sort") || "newest";
1047
+ S.filters.min_words = Number(params.get("min_words") || 0);
1048
+ S.filters.max_words = Number(params.get("max_words") || 0);
1049
  const conversationId = params.get("conversation_id");
1050
  await loadList();
1051
  if (conversationId) {