WinslowFan Claude Opus 5.5 commited on
Commit
edf650c
·
1 Parent(s): cb1600f

Put the 3D compare button next to each partner and pin that column

Browse files
backend/space_app.py CHANGED
@@ -120,11 +120,13 @@ async def frontend(path: str):
120
  if path and requested.is_file():
121
  return FileResponse(requested)
122
 
 
 
123
  prerendered = requested / "index.html"
124
  if path and prerendered.is_file():
125
- return FileResponse(prerendered)
126
 
127
  index = FRONTEND_DIR / "index.html"
128
  if not index.is_file():
129
  raise HTTPException(status_code=503, detail="Frontend build is not available")
130
- return FileResponse(index)
 
120
  if path and requested.is_file():
121
  return FileResponse(requested)
122
 
123
+ # HTML must be revalidated so a new deploy (new hashed bundle) shows on reload
124
+ no_cache = {"Cache-Control": "no-cache"}
125
  prerendered = requested / "index.html"
126
  if path and prerendered.is_file():
127
+ return FileResponse(prerendered, headers=no_cache)
128
 
129
  index = FRONTEND_DIR / "index.html"
130
  if not index.is_file():
131
  raise HTTPException(status_code=503, detail="Frontend build is not available")
132
+ return FileResponse(index, headers=no_cache)
frontend/src/components/Transitions.tsx CHANGED
@@ -1,4 +1,5 @@
1
  import { useMemo, useState } from 'react';
 
2
  import { ENERGY_TERMS, type EnergyTerm, type OrderChange, type Transition } from '../lib/api';
3
  import { FIDELITY_INFO, FIDELITY_ORDER, fidelityColor, fidelityKey } from '../lib/fidelity';
4
  import { chainLabel, fmtNum, fmtSigned, methodShort } from '../lib/format';
@@ -263,7 +264,7 @@ export function TransitionsTable({
263
  <EmptyState title="No partner observations in this view" />
264
  ) : (
265
  <div className="table-wrap">
266
- <table className="table table--dense table--rows">
267
  <thead>
268
  <tr>
269
  <th>Partner</th>
@@ -279,7 +280,6 @@ export function TransitionsTable({
279
  {th('resolution', 'Res. Å')}
280
  <th>Ligand</th>
281
  {th('date', 'Released')}
282
- {onView && <th>Structure</th>}
283
  </tr>
284
  </thead>
285
  <tbody>
@@ -295,7 +295,22 @@ export function TransitionsTable({
295
  }}
296
  >
297
  <td>
298
- <ChainLink pdb={t.pdb_id} chain={t.auth_asym_id} strong />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
299
  </td>
300
  <td className="num tabular">{t.state_id ?? '—'}</td>
301
  <td>
@@ -322,21 +337,7 @@ export function TransitionsTable({
322
  <LigandBadge status={t.binding_status} />
323
  </td>
324
  <td className="num tabular">{t.release_date ?? '—'}</td>
325
- {onView && (
326
- <td>
327
- <button
328
- type="button"
329
- className="btn btn--ghost btn--sm"
330
- onClick={(e) => {
331
- e.stopPropagation();
332
- onView(t);
333
- }}
334
- title="Superpose with this chain, coloured by per-residue deviation"
335
- >
336
- View
337
- </button>
338
- </td>
339
- )}
340
  </tr>
341
  );
342
  })}
 
1
  import { useMemo, useState } from 'react';
2
+ import { Box } from 'lucide-react';
3
  import { ENERGY_TERMS, type EnergyTerm, type OrderChange, type Transition } from '../lib/api';
4
  import { FIDELITY_INFO, FIDELITY_ORDER, fidelityColor, fidelityKey } from '../lib/fidelity';
5
  import { chainLabel, fmtNum, fmtSigned, methodShort } from '../lib/format';
 
264
  <EmptyState title="No partner observations in this view" />
265
  ) : (
266
  <div className="table-wrap">
267
+ <table className="table table--dense table--rows table--sticky-first">
268
  <thead>
269
  <tr>
270
  <th>Partner</th>
 
280
  {th('resolution', 'Res. Å')}
281
  <th>Ligand</th>
282
  {th('date', 'Released')}
 
283
  </tr>
284
  </thead>
285
  <tbody>
 
295
  }}
296
  >
297
  <td>
298
+ <span className="partner-cell">
299
+ <ChainLink pdb={t.pdb_id} chain={t.auth_asym_id} strong />
300
+ {onView && (
301
+ <button
302
+ type="button"
303
+ className="btn-3d"
304
+ onClick={(e) => {
305
+ e.stopPropagation();
306
+ onView(t);
307
+ }}
308
+ title="View both structures superposed, coloured by per-residue deviation"
309
+ >
310
+ <Box aria-hidden /> 3D
311
+ </button>
312
+ )}
313
+ </span>
314
  </td>
315
  <td className="num tabular">{t.state_id ?? '—'}</td>
316
  <td>
 
337
  <LigandBadge status={t.binding_status} />
338
  </td>
339
  <td className="num tabular">{t.release_date ?? '—'}</td>
340
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  </tr>
342
  );
343
  })}
frontend/src/styles/ui.css CHANGED
@@ -1369,3 +1369,52 @@ main {
1369
  .state__retry {
1370
  margin-top: 10px;
1371
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1369
  .state__retry {
1370
  margin-top: 10px;
1371
  }
1372
+
1373
+ /* first column stays in view while a wide table scrolls sideways */
1374
+ .table--sticky-first th:first-child,
1375
+ .table--sticky-first td:first-child {
1376
+ position: sticky;
1377
+ left: 0;
1378
+ z-index: 1;
1379
+ box-shadow: 1px 0 0 var(--line);
1380
+ }
1381
+
1382
+ .table--sticky-first td:first-child {
1383
+ background: var(--surface);
1384
+ }
1385
+
1386
+ .table--sticky-first th:first-child {
1387
+ z-index: 2;
1388
+ }
1389
+
1390
+ .partner-cell {
1391
+ display: inline-flex;
1392
+ align-items: center;
1393
+ gap: 8px;
1394
+ }
1395
+
1396
+ .btn-3d {
1397
+ display: inline-flex;
1398
+ align-items: center;
1399
+ gap: 3px;
1400
+ height: 22px;
1401
+ padding: 0 7px;
1402
+ border-radius: 6px;
1403
+ border: 1px solid color-mix(in srgb, var(--accent) 45%, var(--line));
1404
+ background: var(--accent-soft);
1405
+ color: var(--accent-ink);
1406
+ font-size: 11.5px;
1407
+ font-weight: 650;
1408
+ white-space: nowrap;
1409
+ }
1410
+
1411
+ .btn-3d svg {
1412
+ width: 12px;
1413
+ height: 12px;
1414
+ }
1415
+
1416
+ .btn-3d:hover {
1417
+ background: var(--accent);
1418
+ border-color: var(--accent);
1419
+ color: #fff;
1420
+ }