vomebook commited on
Commit
9f23e46
·
1 Parent(s): 4c160fe

feat(ui): sort global sources and keep breadcrumb on one line

Browse files
static/app.js CHANGED
@@ -1323,7 +1323,10 @@ function renderCheckboxList(container, items, selected, onChange) {
1323
  }
1324
 
1325
  async function renderSourcesFilter() {
1326
- renderCheckboxList(DOM.filterSourceList, STATE.sources.map((source) => ({ key: source.slug, label: source.name, count: source.count })), STATE.selectedSources, (values) => {
 
 
 
1327
  STATE.selectedSources = values;
1328
  STATE.page = 1;
1329
  updateFilterCancelButtons();
@@ -1724,7 +1727,10 @@ function retrySidebar(source, path, routeId, requestSequence) {
1724
 
1725
  function renderSourceListSidebar(sources) {
1726
  DOM.sidebarTitle.textContent = "数据包";
1727
- DOM.sidebarContent.innerHTML = (sources || []).map((source) => `<button type="button" class="repo-list-item" data-source="${escapeHTML(source.slug)}" aria-label="打开数据包:${escapeHTML(source.name)}">${ICON_HTML.source}<span class="repo-name">${escapeHTML(source.name)}</span><span class="repo-count">${(source.count || 0).toLocaleString()}</span></button>`).join("");
 
 
 
1728
  }
1729
 
1730
  function browserContentHTML(data, path, includeBreadcrumb) {
 
1323
  }
1324
 
1325
  async function renderSourcesFilter() {
1326
+ const ordered = [...(STATE.sources || [])].sort((a, b) =>
1327
+ (a.count || 0) - (b.count || 0) ||
1328
+ String(a.name || "").localeCompare(String(b.name || ""), "zh-CN"));
1329
+ renderCheckboxList(DOM.filterSourceList, ordered.map((source) => ({ key: source.slug, label: source.name, count: source.count })), STATE.selectedSources, (values) => {
1330
  STATE.selectedSources = values;
1331
  STATE.page = 1;
1332
  updateFilterCancelButtons();
 
1727
 
1728
  function renderSourceListSidebar(sources) {
1729
  DOM.sidebarTitle.textContent = "数据包";
1730
+ const ordered = [...(sources || [])].sort((a, b) =>
1731
+ (a.count || 0) - (b.count || 0) ||
1732
+ String(a.name || "").localeCompare(String(b.name || ""), "zh-CN"));
1733
+ DOM.sidebarContent.innerHTML = ordered.map((source) => `<button type="button" class="repo-list-item" data-source="${escapeHTML(source.slug)}" aria-label="打开数据包:${escapeHTML(source.name)}">${ICON_HTML.source}<span class="repo-name">${escapeHTML(source.name)}</span><span class="repo-count">${(source.count || 0).toLocaleString()}</span></button>`).join("");
1734
  }
1735
 
1736
  function browserContentHTML(data, path, includeBreadcrumb) {
static/style.css CHANGED
@@ -774,12 +774,18 @@ body:not(.mobile) .preview-fullscreen .preview-body {
774
  gap: 2px;
775
  padding: 6px 8px;
776
  border-bottom: 1px solid var(--outline-variant);
777
- flex-wrap: wrap;
778
  font-size: 12px;
779
  flex-shrink: 0;
780
  min-height: 32px;
 
 
 
 
781
  }
782
 
 
 
783
  .sidebar-breadcrumb .crumb-item {
784
  border: 0;
785
  background: none;
 
774
  gap: 2px;
775
  padding: 6px 8px;
776
  border-bottom: 1px solid var(--outline-variant);
777
+ flex-wrap: nowrap;
778
  font-size: 12px;
779
  flex-shrink: 0;
780
  min-height: 32px;
781
+ overflow-x: auto;
782
+ overflow-y: hidden;
783
+ white-space: nowrap;
784
+ scrollbar-width: none;
785
  }
786
 
787
+ .sidebar-breadcrumb::-webkit-scrollbar { display: none; }
788
+
789
  .sidebar-breadcrumb .crumb-item {
790
  border: 0;
791
  background: none;
tests/test_browser.py CHANGED
@@ -610,6 +610,41 @@ class BrowserInteractionTests(unittest.TestCase):
610
  finally:
611
  context.close()
612
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
613
  def test_individual_batch_and_zip_downloads_are_browser_valid(self):
614
  context, page, errors = self.page()
615
  try:
 
610
  finally:
611
  context.close()
612
 
613
+ def test_global_source_order_and_breadcrumb_single_line(self):
614
+ context, page, errors = self.page()
615
+ try:
616
+ page.goto(self.base_url + "/CCRD", wait_until="domcontentloaded")
617
+ page.locator(".result-item").first.wait_for(timeout=30000)
618
+ result = page.evaluate("""() => {
619
+ STATE.sources = [
620
+ {slug: 'large', name: 'Large', count: 30},
621
+ {slug: 'small', name: 'Small', count: 2},
622
+ {slug: 'medium', name: 'Medium', count: 10},
623
+ ];
624
+ renderSourceListSidebar(STATE.sources);
625
+ renderSourcesFilter();
626
+ const sidebar = Array.from(DOM.sidebarContent.querySelectorAll('.repo-list-item'), node => node.dataset.source);
627
+ const filter = Array.from(DOM.filterSourceList.querySelectorAll('input'), node => node.value);
628
+ DOM.sidebarContent.innerHTML = browserContentHTML({folders: [], files: []}, 'a/b', true);
629
+ const crumb = document.querySelector('.sidebar-breadcrumb');
630
+ const style = getComputedStyle(crumb);
631
+ return {
632
+ sidebar,
633
+ filter,
634
+ wrap: style.flexWrap,
635
+ overflowX: style.overflowX,
636
+ whiteSpace: style.whiteSpace,
637
+ };
638
+ }""")
639
+ self.assertEqual(result["sidebar"], ["small", "medium", "large"])
640
+ self.assertEqual(result["filter"], ["small", "medium", "large"])
641
+ self.assertEqual(result["wrap"], "nowrap")
642
+ self.assertEqual(result["overflowX"], "auto")
643
+ self.assertEqual(result["whiteSpace"], "nowrap")
644
+ self.assertEqual(errors, [])
645
+ finally:
646
+ context.close()
647
+
648
  def test_individual_batch_and_zip_downloads_are_browser_valid(self):
649
  context, page, errors = self.page()
650
  try:
tests/test_search.py CHANGED
@@ -1130,6 +1130,15 @@ class FrontendContractTests(unittest.TestCase):
1130
  ):
1131
  self.assertIn(selector, source)
1132
 
 
 
 
 
 
 
 
 
 
1133
  def test_mobile_result_paths_keep_separators_with_their_folder(self):
1134
  source = (Path(app.BASE_DIR) / "static" / "app.js").read_text(encoding="utf-8")
1135
  css = (Path(app.BASE_DIR) / "static" / "style.css").read_text(encoding="utf-8")
 
1130
  ):
1131
  self.assertIn(selector, source)
1132
 
1133
+ def test_global_source_lists_sort_by_count_and_breadcrumb_is_single_line(self):
1134
+ source = (Path(app.BASE_DIR) / "static" / "app.js").read_text(encoding="utf-8")
1135
+ css = (Path(app.BASE_DIR) / "static" / "style.css").read_text(encoding="utf-8")
1136
+ self.assertIn('(a.count || 0) - (b.count || 0)', source)
1137
+ self.assertIn('localeCompare(String(b.name || ""), "zh-CN")', source)
1138
+ self.assertIn("flex-wrap: nowrap", css)
1139
+ self.assertIn("overflow-x: auto", css)
1140
+ self.assertIn("white-space: nowrap", css)
1141
+
1142
  def test_mobile_result_paths_keep_separators_with_their_folder(self):
1143
  source = (Path(app.BASE_DIR) / "static" / "app.js").read_text(encoding="utf-8")
1144
  css = (Path(app.BASE_DIR) / "static" / "style.css").read_text(encoding="utf-8")