-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuiManager.js
More file actions
132 lines (114 loc) · 4.85 KB
/
uiManager.js
File metadata and controls
132 lines (114 loc) · 4.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// uiManager.js start
import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7/+esm';
import { loadData, populateDataTable, updateTextZone, attemptPubMedFetch, getData, addAnnotation } from './dataManager.js';
import { createCubesFromData, getCubes, highlightCubeByPmid, centerCameraOnCube, initCubeManager } from './cubeManager.js';
import { hidePubMedFetchOverlay } from './pubmedOverlay.js';
import { deleteSelectedFromData } from './deleteCubes.js';
import { exportFilteredData } from './saveCubes.js';
import * as THREE from 'three';
export function createUI(callbacks) {
const uiContainer = d3.select('#data-container');
return {
updateTable: (data) => {
const tbody = d3.select('#data-table tbody');
tbody.selectAll('tr').remove();
const rows = tbody.selectAll('tr')
.data(data)
.enter()
.append('tr')
.attr('data-pmid', d => d.PMID);
rows.append('td')
.text(d => d.Title?.substring(0, 50) + (d.Title?.length > 50 ? '...' : ''));
rows.append('td')
.append('input')
.attr('type', 'checkbox')
.attr('class', 'select-checkbox')
.on('change', function(event, d) {
const isSelected = event.target.checked;
d3.select(this.closest('tr')).classed('selected', isSelected);
callbacks.onSelect(d.PMID, isSelected);
});
}
};
}
export function setupUI(data, getSelectedCubes, getLastSelectedCube, onSelectCallback) {
populateDataTable(data, (pmid, isSelected) => {
const currentSelected = getSelectedCubes();
const currentLast = getLastSelectedCube();
const result = highlightCubeByPmid(pmid, isSelected, currentSelected, currentLast);
if (result) {
onSelectCallback(result.selectedCubes, result.lastSelectedCube);
// Force text zone update for any selection change
if (result.lastSelectedCube) {
console.log('Updating text zone from selection change');
updateTextZone(result.lastSelectedCube.userData);
} else if (result.selectedCubes.length === 0) {
console.log('Clearing text zone - no selections');
clearTextZone();
}
}
});
}
export function showLoadingIndicator() {
let loader = document.getElementById('loading-indicator');
if (!loader) {
loader = document.createElement('div');
loader.id = 'loading-indicator';
loader.style.position = 'fixed';
loader.style.top = '20px';
loader.style.right = '20px';
loader.style.maxWidth = '380px';
loader.style.padding = '10px 12px';
loader.style.background = 'rgba(0,0,0,0.78)';
loader.style.color = 'white';
loader.style.borderRadius = '8px';
loader.style.boxShadow = '0 10px 24px rgba(0,0,0,0.22)';
loader.style.fontSize = '0.9rem';
loader.style.lineHeight = '1.4';
loader.style.zIndex = '5000';
document.body.appendChild(loader);
}
loader.textContent = 'Loading...';
}
export function updateLoadingIndicator(message) {
const loader = document.getElementById('loading-indicator');
if (loader) {
loader.textContent = message;
}
}
export function removeLoadingIndicator() {
const loader = document.getElementById('loading-indicator');
if (loader) loader.remove();
}
export function showErrorToUser(message) {
alert(`Error: ${message}`);
}
export function clearTextZone() {
document.getElementById('selected-title').textContent = 'No article selected';
document.getElementById('pmid-text').textContent = '-';
document.getElementById('year-text').textContent = '-';
document.getElementById('source-text').textContent = '-';
document.getElementById('doi-link').textContent = '-';
document.getElementById('pmc-link').textContent = '-';
document.getElementById('abstract-text').textContent = 'Select an article to view its abstract';
}
export function createFallbackScene() {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera();
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
}
// uiManager.js end