Skip to content

Commit 28ddcfa

Browse files
authored
Merge pull request #79 from NorwegianVeterinaryInstitute/feature/itables-2.9.1
Upgrade itables to 2.9.1 with Scroller, ColReorder, and layout fixes
2 parents 38ce68d + 6defdfd commit 28ddcfa

9 files changed

Lines changed: 1804 additions & 1605 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88
push:
99
branches:
1010
- main # Trigger when pushing to main
11-
- feature/run-to-samples-filter
11+
- feature/itables-2.9.1
1212
jobs:
1313
update-branches:
1414
env:

deploy_mode.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
prod
1+
test

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ readme = "README.md"
1010
requires-python = ">=3.11.5"
1111
dependencies = [
1212
"faicons==0.2.2",
13-
"itables==2.7.3",
13+
"itables==2.9.1",
1414
"pandas==2.2.2",
1515
"pins==0.8.5",
1616
"psycopg[binary]>=3.3.3,<4",

src/shinylims/assets/styles.css

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717
--text-muted: rgba(9, 26, 62, 0.76);
1818
--shadow-soft: 0 4px 12px rgba(9, 26, 62, 0.05);
1919
--shadow-hover: 0 10px 24px rgba(28, 79, 185, 0.12);
20+
/* itables >=2.9 paints its widget/table container with this instead of
21+
leaving it transparent; match the app background so it doesn't show
22+
as a white block against --surface-page. itables injects its own
23+
:root/:host rule for this variable via an inline <style> tag added
24+
to <head> after this stylesheet loads, so !important is required to
25+
win the cascade regardless of load order. */
26+
--dt-html-background: var(--surface-page) !important;
2027
}
2128

2229
html,
@@ -107,7 +114,10 @@ table.dataTable td.left-column {
107114
/* Modal Backdrop Fix for Scaled UI */
108115
/* ─────────────────────────────────────────────────────────────── */
109116

110-
/* Ensures modal backdrop covers entire viewport even after scaling */
117+
/* Ensures modal backdrop covers entire viewport even after scaling. The
118+
backdrop is a child of body, so it's shrunk by body's own `zoom` just
119+
like everything else; scale it back up by zoom's inverse so it still
120+
spans the true viewport instead of only 80% of it. */
111121
.modal-backdrop {
112122
position: fixed !important;
113123
top: 0 !important;
@@ -1358,13 +1368,14 @@ div.dt-button-collection:has(.dtsb-searchBuilder) {
13581368
/* ─────────────────────────────────────────────────────────────── */
13591369

13601370
@media (min-width: 992px) {
1361-
/* Scale entire app to 80% while compensating the width and height */
1371+
/* Shrink the entire app to 80% on desktop widths. `zoom` (unlike
1372+
`transform: scale`) resizes the actual layout box rather than just the
1373+
painted output, so body's real height/width already match what's
1374+
visible on screen -- no width/height/position compensation hack needed,
1375+
and no artificially inflated scrollHeight causing a residual outer
1376+
scrollbar. */
13621377
body {
1363-
transform: scale(0.8);
1364-
transform-origin: top left;
1365-
width: 125%;
1366-
height: 125%;
1367-
position: absolute;
1378+
zoom: 0.8;
13681379
}
13691380

13701381
/* Expand wrapper and table elements fully */

src/shinylims/features/projects.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
import pandas as pd
1010

1111
from shinylims.ui_helpers.table_controls import (
12+
COLVIS_COLUMN_TEXT,
1213
DATE_VALUE_RENDERER,
14+
FILTER_BUILDER_LANGUAGE,
1315
build_filter_status_bar,
1416
clear_all_filters_script,
1517
deselect_all_columns_button,
@@ -68,14 +70,18 @@ def projects_table():
6870
return ITable(
6971
dat,
7072
select=True,
71-
layout={"topStart": "buttons", "topEnd": "search"},
72-
column_filters="footer",
73+
layout={"topStart": "buttons", "topEnd": "search", "bottomEnd": None},
74+
column_filters="header",
7375
search={"smart": True, "regex": True, "caseInsensitive": True},
7476
lengthMenu=[[200, 500, 1000, 2000, -1], [200, 500, 1000, 2000, "All"]],
7577
classes="compact hover order-column cell-border",
7678
scrollY="84vh",
7779
scrollX=True,
7880
paging=True,
81+
scroller=True,
82+
deferRender=True,
83+
colReorder=True,
84+
language=FILTER_BUILDER_LANGUAGE,
7985
maxBytes=0,
8086
allow_html=True,
8187
autoWidth=True,
@@ -86,6 +92,7 @@ def projects_table():
8692
"extend": "colvis",
8793
"text": "Selection",
8894
"collectionLayout": "two-column",
95+
"columnText": COLVIS_COLUMN_TEXT,
8996
},
9097
{
9198
"extend": "collection",
@@ -95,8 +102,8 @@ def projects_table():
95102
deselect_all_columns_button(),
96103
],
97104
},
98-
{"extend": "spacer", "style": "bar", "text": "Rows"},
99-
"pageLength",
105+
{"extend": "spacer", "style": "bar", "text": "Filter"},
106+
{"extend": "searchBuilder"},
100107
{"extend": "spacer", "style": "bar", "text": "Export"},
101108
{
102109
"extend": "collection",
@@ -121,8 +128,6 @@ def projects_table():
121128
},
122129
],
123130
},
124-
{"extend": "spacer", "style": "bar", "text": "Filter"},
125-
{"extend": "searchBuilder"},
126131
{"extend": "spacer", "style": "bar"},
127132
],
128133
order=[[order_column_index, "desc"]],

src/shinylims/features/samples.py

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@
99
import pandas as pd
1010
import io
1111
from shinylims.ui_helpers.table_controls import (
12+
COLVIS_COLUMN_TEXT,
1213
DATE_VALUE_RENDERER,
14+
FILTER_BUILDER_LANGUAGE,
1315
batch_filter_button,
1416
build_filter_status_bar,
1517
clear_all_filters_script,
1618
deselect_all_columns_button,
1719
filter_state_draw_callback,
1820
select_all_columns_button,
21+
truncated_text_renderer,
1922
visibility_preset_button,
2023
)
2124
import re
@@ -440,17 +443,27 @@ def data_samples():
440443
column_index = 0
441444
date_column_index = -1
442445

446+
# Indices for columns whose content is truncated with a hover tooltip
447+
nird_filename_index = dat.columns.get_loc("NIRD Filename") if "NIRD Filename" in dat.columns else -1
448+
experiment_name_index = dat.columns.get_loc("Experiment Name") if "Experiment Name" in dat.columns else -1
449+
billing_description_index = dat.columns.get_loc("Billing Description") if "Billing Description" in dat.columns else -1
450+
reagent_label_index = dat.columns.get_loc("Reagent Label") if "Reagent Label" in dat.columns else -1
451+
443452
return ITable(
444453
dat,
445454
select=True,
446-
layout={"topStart": "buttons", "topEnd": "search"},
455+
layout={"topStart": "buttons", "topEnd": "search", "bottomEnd": None},
447456
lengthMenu=[[200, 500, 1000, 2000, -1], [200, 500, 1000, 2000, "All"]],
448-
column_filters="footer",
457+
column_filters="header",
449458
search={"smart": True},
450459
classes="nowrap compact hover order-column cell-border",
451460
scrollY="84vh",
452461
scrollX=True,
453462
paging=True,
463+
scroller=True,
464+
deferRender=True,
465+
colReorder=True,
466+
language=FILTER_BUILDER_LANGUAGE,
454467
autoWidth=True,
455468
maxBytes=0,
456469
allow_html=True,
@@ -464,6 +477,7 @@ def data_samples():
464477
"extend": "colvis",
465478
"text": "Selection",
466479
"collectionLayout": "two-column",
480+
"columnText": COLVIS_COLUMN_TEXT,
467481
},
468482
{
469483
"extend": "collection",
@@ -474,11 +488,11 @@ def data_samples():
474488
visibility_preset_button([2, 3, 4, 5, 9, 10, 21]),
475489
]
476490
},
477-
# ── Row settings ──────────────────────────────────────────
478491
{'extend': "spacer",
479492
'style': 'bar',
480-
'text': 'Rows'},
481-
"pageLength",
493+
'text': 'Filter'},
494+
batch_filter_button(),
495+
{"extend": "searchBuilder"},
482496
{
483497
"text": "☑️ Select All Filtered Rows",
484498
"action": JavascriptFunction("""
@@ -497,29 +511,25 @@ def data_samples():
497511
}
498512
""")
499513
},
500-
# ── Export ────────────────────────────────────────────────
501514
{'extend': "spacer",
502515
'style': 'bar',
503516
'text': 'Export'},
504517
{
505518
"extend": "collection",
506519
"text": "📤 Export",
507520
"buttons": [
508-
# Export to CSV — selected rows, visible columns
509521
{
510522
"extend": "csvHtml5",
511523
"exportOptions": {"columns": ":visible"},
512524
"text": "📄 Export to CSV",
513525
"title": "Sample Data Export"
514526
},
515-
# Export to Excel — selected rows, visible columns
516527
{
517528
"extend": "excelHtml5",
518529
"exportOptions": {"columns": ":visible"},
519530
"text": "📊 Export to Excel",
520531
"title": "Sample Data Export"
521532
},
522-
# Send selected rows to SAGA via FTP — triggers Shiny server logic
523533
{
524534
"text": "🖥️ Send to SAGA for ATLAS",
525535
"action": JavascriptFunction("""
@@ -537,11 +547,6 @@ def data_samples():
537547
},
538548
]
539549
},
540-
{'extend': "spacer",
541-
'style': 'bar',
542-
'text': 'Filter'},
543-
batch_filter_button(),
544-
{"extend": "searchBuilder"},
545550
{'extend': "spacer",
546551
'style': 'bar'},
547552
],
@@ -554,7 +559,31 @@ def data_samples():
554559
"targets": date_column_index,
555560
"type": "date",
556561
"render": DATE_VALUE_RENDERER
557-
}
562+
},
563+
{
564+
"targets": nird_filename_index,
565+
"className": "left-column",
566+
"width": "805px",
567+
"render": truncated_text_renderer(max_chars=172, max_width_px=805),
568+
} if nird_filename_index != -1 else {},
569+
{
570+
"targets": experiment_name_index,
571+
"className": "left-column",
572+
"width": "260px",
573+
"render": truncated_text_renderer(max_chars=60, max_width_px=260),
574+
} if experiment_name_index != -1 else {},
575+
{
576+
"targets": billing_description_index,
577+
"className": "left-column",
578+
"width": "320px",
579+
"render": truncated_text_renderer(max_chars=100, max_width_px=320),
580+
} if billing_description_index != -1 else {},
581+
{
582+
"targets": reagent_label_index,
583+
"className": "left-column",
584+
"width": "690px",
585+
"render": truncated_text_renderer(max_chars=156, max_width_px=690),
586+
} if reagent_label_index != -1 else {},
558587
]
559588
)
560589

0 commit comments

Comments
 (0)