YchKhan commited on
Commit
daf9357
·
verified ·
1 Parent(s): cef998e

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +637 -15
templates/index.html CHANGED
@@ -345,6 +345,9 @@
345
  row.parentNode.insertBefore(insightsRow, row.nextSibling);
346
  }
347
 
 
 
 
348
  // Send request to extract insights
349
  fetch('/post_insights', {
350
  method: 'POST',
@@ -371,25 +374,47 @@
371
  const insightsActions = document.createElement('div');
372
  insightsActions.className = 'insights-actions';
373
 
 
 
 
 
374
  const selectAllBtn = document.createElement('button');
375
- selectAllBtn.className = 'insights-button';
376
  selectAllBtn.textContent = 'Select All';
377
- selectAllBtn.onclick = function() {
378
- const tags = insightsContainer.querySelectorAll('.insight-tag');
 
 
 
 
 
379
  tags.forEach(tag => tag.classList.add('selected'));
380
- row.dataset.selectedInsights = JSON.stringify(data.result.insights);
381
- row.dataset.unselectedInsights = JSON.stringify([]);
382
- };
 
 
 
 
383
 
384
  const clearAllBtn = document.createElement('button');
385
- clearAllBtn.className = 'insights-button';
386
  clearAllBtn.textContent = 'Clear All';
387
- clearAllBtn.onclick = function() {
388
- const tags = insightsContainer.querySelectorAll('.insight-tag');
 
 
 
 
 
389
  tags.forEach(tag => tag.classList.remove('selected'));
390
- row.dataset.selectedInsights = JSON.stringify([]);
391
- row.dataset.unselectedInsights = JSON.stringify(data.result.insights);
392
- };
 
 
 
 
393
 
394
  insightsActions.appendChild(selectAllBtn);
395
  insightsActions.appendChild(clearAllBtn);
@@ -415,12 +440,15 @@
415
  const tagElement = document.createElement('div');
416
  tagElement.className = 'insight-tag';
417
  tagElement.textContent = insight;
418
- tagElement.onclick = function() {
419
- tagElement.classList.toggle('selected');
420
 
421
  // Update selected insights
422
  updateSelectedInsights(row, insightsContainer);
423
- };
 
 
 
424
 
425
  // Add to selected by default
426
  tagElement.classList.add('selected');
@@ -433,6 +461,9 @@
433
  row.dataset.selectedInsights = JSON.stringify(selectedInsights);
434
  row.dataset.unselectedInsights = JSON.stringify(unselectedInsights);
435
 
 
 
 
436
  } else {
437
  insightsContainer.innerHTML = '<div class="error">No insights found</div>';
438
  }
@@ -1202,6 +1233,584 @@
1202
 
1203
  return accordionSection;
1204
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1205
  </script>
1206
  </head>
1207
  <body>
@@ -1282,6 +1891,12 @@
1282
  <button id="enhanceProblemButton" class="btn enhance-problem-button floating-button disabled" title="Enhance Problem using Selected Insights" onclick="enhanceProblem()" disabled>
1283
  Enhance Problem
1284
  </button>
 
 
 
 
 
 
1285
  <button id="analyzeAllButton" class="btn btn-primary floating-button" title="Analyze All Unanalyzed Papers">
1286
  Analyze All
1287
  </button>
@@ -1310,9 +1925,16 @@
1310
  // Check for selected insights periodically to enable/disable enhance button
1311
  setInterval(checkSelectedInsights, 1000);
1312
 
 
 
 
 
 
 
1313
  // Analyze all button
1314
  document.getElementById('analyzeAllButton').addEventListener('click', function() {
1315
  analyzeAllPapers();
 
1316
  });
1317
 
1318
  // Remove failed button
 
345
  row.parentNode.insertBefore(insightsRow, row.nextSibling);
346
  }
347
 
348
+ // Store the row reference as a data attribute on the container for later access
349
+ insightsContainer.dataset.parentRow = row.rowIndex;
350
+
351
  // Send request to extract insights
352
  fetch('/post_insights', {
353
  method: 'POST',
 
374
  const insightsActions = document.createElement('div');
375
  insightsActions.className = 'insights-actions';
376
 
377
+ // Store the insights for this specific container
378
+ const containerInsights = [...data.result.insights];
379
+ insightsContainer.dataset.allInsights = JSON.stringify(containerInsights);
380
+
381
  const selectAllBtn = document.createElement('button');
382
+ selectAllBtn.className = 'insights-button select-all-btn';
383
  selectAllBtn.textContent = 'Select All';
384
+ // Use a closure to ensure the button has access to the correct container and row
385
+ selectAllBtn.addEventListener('click', function() {
386
+ const container = this.closest('.insights-container');
387
+ const parentRow = row;
388
+ const allInsights = JSON.parse(container.dataset.allInsights || '[]');
389
+
390
+ const tags = container.querySelectorAll('.insight-tag');
391
  tags.forEach(tag => tag.classList.add('selected'));
392
+
393
+ parentRow.dataset.selectedInsights = JSON.stringify(allInsights);
394
+ parentRow.dataset.unselectedInsights = JSON.stringify([]);
395
+
396
+ // Trigger check for enabling/disabling enhance button
397
+ checkSelectedInsights();
398
+ });
399
 
400
  const clearAllBtn = document.createElement('button');
401
+ clearAllBtn.className = 'insights-button clear-all-btn';
402
  clearAllBtn.textContent = 'Clear All';
403
+ // Use a closure to ensure the button has access to the correct container and row
404
+ clearAllBtn.addEventListener('click', function() {
405
+ const container = this.closest('.insights-container');
406
+ const parentRow = row;
407
+ const allInsights = JSON.parse(container.dataset.allInsights || '[]');
408
+
409
+ const tags = container.querySelectorAll('.insight-tag');
410
  tags.forEach(tag => tag.classList.remove('selected'));
411
+
412
+ parentRow.dataset.selectedInsights = JSON.stringify([]);
413
+ parentRow.dataset.unselectedInsights = JSON.stringify(allInsights);
414
+
415
+ // Trigger check for enabling/disabling enhance button
416
+ checkSelectedInsights();
417
+ });
418
 
419
  insightsActions.appendChild(selectAllBtn);
420
  insightsActions.appendChild(clearAllBtn);
 
440
  const tagElement = document.createElement('div');
441
  tagElement.className = 'insight-tag';
442
  tagElement.textContent = insight;
443
+ tagElement.addEventListener('click', function() {
444
+ this.classList.toggle('selected');
445
 
446
  // Update selected insights
447
  updateSelectedInsights(row, insightsContainer);
448
+
449
+ // Trigger check for enabling/disabling enhance button
450
+ checkSelectedInsights();
451
+ });
452
 
453
  // Add to selected by default
454
  tagElement.classList.add('selected');
 
461
  row.dataset.selectedInsights = JSON.stringify(selectedInsights);
462
  row.dataset.unselectedInsights = JSON.stringify(unselectedInsights);
463
 
464
+ // Trigger check for enabling/disabling enhance button immediately
465
+ checkSelectedInsights();
466
+
467
  } else {
468
  insightsContainer.innerHTML = '<div class="error">No insights found</div>';
469
  }
 
1233
 
1234
  return accordionSection;
1235
  }
1236
+
1237
+ // Extract insights from all analyzed documents
1238
+ function extractAllInsights() {
1239
+ const patentBackground = document.getElementById('userInput').value.trim();
1240
+ if (!patentBackground) {
1241
+ alert('Please provide a patent background in the input field');
1242
+ return;
1243
+ }
1244
+
1245
+ // Show loading overlay
1246
+ const loadingOverlay = document.getElementById('globalLoadingOverlay');
1247
+ if (loadingOverlay) {
1248
+ loadingOverlay.style.display = 'flex';
1249
+ loadingOverlay.querySelector('.progress-text').textContent = 'Extracting insights from all documents...';
1250
+ }
1251
+
1252
+ // Get all query items
1253
+ const queryItems = document.querySelectorAll('.query-item');
1254
+ let totalDocuments = 0;
1255
+ let completedDocuments = 0;
1256
+
1257
+ // Count total analyzed documents that need insights extraction
1258
+ const analyzedRows = [];
1259
+ queryItems.forEach(queryItem => {
1260
+ const rows = queryItem.querySelectorAll('tbody tr:not(.insights-row)');
1261
+ rows.forEach(row => {
1262
+ // Only include rows that have been analyzed (have score and justification cells)
1263
+ if (row.cells.length > 4 && row.cells[4].textContent.trim() !== 'Error' &&
1264
+ row.cells[4].textContent.trim() !== 'N/A' && row.cells[4].textContent.trim() !== '') {
1265
+ analyzedRows.push(row);
1266
+ totalDocuments++;
1267
+ }
1268
+ });
1269
+ });
1270
+
1271
+ if (totalDocuments === 0) {
1272
+ if (loadingOverlay) loadingOverlay.style.display = 'none';
1273
+ alert('No analyzed documents found. Please analyze documents first.');
1274
+ return;
1275
+ }
1276
+
1277
+ // Function to update progress
1278
+ function updateProgress() {
1279
+ completedDocuments++;
1280
+ if (loadingOverlay) {
1281
+ const progressElement = loadingOverlay.querySelector('.progress-text');
1282
+ if (progressElement) {
1283
+ progressElement.textContent = `Extracting insights: ${completedDocuments}/${totalDocuments}`;
1284
+ }
1285
+ }
1286
+
1287
+ if (completedDocuments >= totalDocuments) {
1288
+ if (loadingOverlay) loadingOverlay.style.display = 'none';
1289
+ checkSelectedInsights(); // Update enhance button state based on selected insights
1290
+ }
1291
+ }
1292
+
1293
+ // Process each analyzed document sequentially to avoid overwhelming the server
1294
+ function processNextDocument(index) {
1295
+ if (index >= analyzedRows.length) {
1296
+ return; // All documents processed
1297
+ }
1298
+
1299
+ const row = analyzedRows[index];
1300
+ const urlLink = row.querySelector('.url-link');
1301
+ const documentType = row.cells[0].textContent.toLowerCase();
1302
+
1303
+ if (!urlLink || !urlLink.href) {
1304
+ updateProgress();
1305
+ processNextDocument(index + 1);
1306
+ return;
1307
+ }
1308
+
1309
+ // Check if there's already an insights row for this document
1310
+ let insightsRow = row.nextElementSibling;
1311
+ if (insightsRow && insightsRow.className === 'insights-row') {
1312
+ // Insights row already exists, get the container
1313
+ insightsContainer = insightsRow.querySelector('.insights-container');
1314
+ insightsContainer.innerHTML = '<div class="loading-spinner"></div><div>Extracting insights...</div>';
1315
+ } else {
1316
+ // Create insights row that spans across all columns
1317
+ insightsRow = document.createElement('tr');
1318
+ insightsRow.className = 'insights-row';
1319
+
1320
+ const insightsTd = document.createElement('td');
1321
+ insightsTd.colSpan = row.cells.length;
1322
+
1323
+ insightsContainer = document.createElement('div');
1324
+ insightsContainer.className = 'insights-container';
1325
+ insightsContainer.innerHTML = '<div class="loading-spinner"></div><div>Extracting insights...</div>';
1326
+
1327
+ insightsTd.appendChild(insightsContainer);
1328
+ insightsRow.appendChild(insightsTd);
1329
+
1330
+ // Insert after the current row
1331
+ row.parentNode.insertBefore(insightsRow, row.nextSibling);
1332
+ }
1333
+
1334
+ // Store the row reference as a data attribute on the container for later access
1335
+ insightsContainer.dataset.parentRow = row.rowIndex;
1336
+
1337
+ // Send request to extract insights
1338
+ fetch('/post_insights', {
1339
+ method: 'POST',
1340
+ body: JSON.stringify({
1341
+ 'patent_background': patentBackground,
1342
+ 'pdf_url': urlLink.href,
1343
+ 'data_type': documentType
1344
+ }),
1345
+ headers: { 'Content-Type': 'application/json' }
1346
+ })
1347
+ .then(response => response.json())
1348
+ .then(data => {
1349
+ if (data.error) {
1350
+ insightsContainer.innerHTML = `<div class="error">Error: ${data.error}</div>`;
1351
+ } else if (data.result && data.result.insights) {
1352
+ // Create header with title and actions
1353
+ const insightsHeader = document.createElement('div');
1354
+ insightsHeader.className = 'insights-header';
1355
+
1356
+ const insightsTitle = document.createElement('div');
1357
+ insightsTitle.className = 'insights-title';
1358
+ insightsTitle.textContent = 'Document Insights';
1359
+
1360
+ const insightsActions = document.createElement('div');
1361
+ insightsActions.className = 'insights-actions';
1362
+
1363
+ // Store the insights for this specific container
1364
+ const containerInsights = [...data.result.insights];
1365
+ insightsContainer.dataset.allInsights = JSON.stringify(containerInsights);
1366
+
1367
+ const selectAllBtn = document.createElement('button');
1368
+ selectAllBtn.className = 'insights-button select-all-btn';
1369
+ selectAllBtn.textContent = 'Select All';
1370
+ selectAllBtn.addEventListener('click', function() {
1371
+ const container = this.closest('.insights-container');
1372
+ const parentRow = row;
1373
+ const allInsights = JSON.parse(container.dataset.allInsights || '[]');
1374
+
1375
+ const tags = container.querySelectorAll('.insight-tag');
1376
+ tags.forEach(tag => tag.classList.add('selected'));
1377
+
1378
+ parentRow.dataset.selectedInsights = JSON.stringify(allInsights);
1379
+ parentRow.dataset.unselectedInsights = JSON.stringify([]);
1380
+
1381
+ checkSelectedInsights();
1382
+ });
1383
+
1384
+ const clearAllBtn = document.createElement('button');
1385
+ clearAllBtn.className = 'insights-button clear-all-btn';
1386
+ clearAllBtn.textContent = 'Clear All';
1387
+ clearAllBtn.addEventListener('click', function() {
1388
+ const container = this.closest('.insights-container');
1389
+ const parentRow = row;
1390
+ const allInsights = JSON.parse(container.dataset.allInsights || '[]');
1391
+
1392
+ const tags = container.querySelectorAll('.insight-tag');
1393
+ tags.forEach(tag => tag.classList.remove('selected'));
1394
+
1395
+ parentRow.dataset.selectedInsights = JSON.stringify([]);
1396
+ parentRow.dataset.unselectedInsights = JSON.stringify(allInsights);
1397
+
1398
+ checkSelectedInsights();
1399
+ });
1400
+
1401
+ insightsActions.appendChild(selectAllBtn);
1402
+ insightsActions.appendChild(clearAllBtn);
1403
+
1404
+ insightsHeader.appendChild(insightsTitle);
1405
+ insightsHeader.appendChild(insightsActions);
1406
+
1407
+ // Create insight tags
1408
+ const insightsList = document.createElement('div');
1409
+ insightsList.className = 'insights-list';
1410
+
1411
+ // Clear the container and add the new elements
1412
+ insightsContainer.innerHTML = '';
1413
+ insightsContainer.appendChild(insightsHeader);
1414
+ insightsContainer.appendChild(insightsList);
1415
+
1416
+ // Initialize selected insights
1417
+ const selectedInsights = [];
1418
+ const unselectedInsights = [];
1419
+
1420
+ // Add insight tags
1421
+ data.result.insights.forEach(insight => {
1422
+ const tagElement = document.createElement('div');
1423
+ tagElement.className = 'insight-tag';
1424
+ tagElement.textContent = insight;
1425
+ tagElement.addEventListener('click', function() {
1426
+ this.classList.toggle('selected');
1427
+ updateSelectedInsights(row, insightsContainer);
1428
+ checkSelectedInsights();
1429
+ });
1430
+
1431
+ // Add to selected by default
1432
+ tagElement.classList.add('selected');
1433
+ selectedInsights.push(insight);
1434
+
1435
+ insightsList.appendChild(tagElement);
1436
+ });
1437
+
1438
+ // Store initial selections
1439
+ row.dataset.selectedInsights = JSON.stringify(selectedInsights);
1440
+ row.dataset.unselectedInsights = JSON.stringify(unselectedInsights);
1441
+
1442
+ } else {
1443
+ insightsContainer.innerHTML = '<div class="error">No insights found</div>';
1444
+ }
1445
+
1446
+ // Process next document
1447
+ updateProgress();
1448
+ processNextDocument(index + 1);
1449
+ })
1450
+ .catch(error => {
1451
+ console.error('Error:', error);
1452
+ insightsContainer.innerHTML = `<div class="error">Error extracting insights: ${error.message}</div>`;
1453
+
1454
+ // Continue with next document even if this one failed
1455
+ updateProgress();
1456
+ processNextDocument(index + 1);
1457
+ });
1458
+ }
1459
+
1460
+ // Start processing documents
1461
+ processNextDocument(0);
1462
+ }
1463
+
1464
+ // Check if any documents have been analyzed to enable/disable Extract All Insights button
1465
+ function checkAnalyzedDocuments() {
1466
+ const queryItems = document.querySelectorAll('.query-item');
1467
+ let hasAnalyzedDocuments = false;
1468
+
1469
+ queryItems.forEach(queryItem => {
1470
+ const rows = queryItem.querySelectorAll('tbody tr:not(.insights-row)');
1471
+ rows.forEach(row => {
1472
+ // Check if the row has score and justification cells (has been analyzed)
1473
+ if (row.cells.length > 4 && row.cells[4].textContent.trim() !== 'Error' &&
1474
+ row.cells[4].textContent.trim() !== '') {
1475
+ hasAnalyzedDocuments = true;
1476
+ }
1477
+ });
1478
+ });
1479
+
1480
+ const extractAllButton = document.getElementById('extractAllInsightsButton');
1481
+ if (hasAnalyzedDocuments) {
1482
+ extractAllButton.classList.remove('disabled');
1483
+ extractAllButton.disabled = false;
1484
+ } else {
1485
+ extractAllButton.classList.add('disabled');
1486
+ extractAllButton.disabled = true;
1487
+ }
1488
+ }
1489
+
1490
+ // Group insights by score and display in a consolidated table
1491
+ function groupInsightsByScore() {
1492
+ // Get all query items
1493
+ const queryItems = document.querySelectorAll('.query-item');
1494
+ let hasInsights = false;
1495
+
1496
+ // Create structure to hold insights grouped by score
1497
+ const insightsByScore = {
1498
+ 5: { insights: [], sources: [] },
1499
+ 4: { insights: [], sources: [] },
1500
+ 3: { insights: [], sources: [] },
1501
+ 2: { insights: [], sources: [] },
1502
+ 1: { insights: [], sources: [] },
1503
+ 0: { insights: [], sources: [] }
1504
+ };
1505
+
1506
+ // Collect all insights from all documents and group by score
1507
+ queryItems.forEach(queryItem => {
1508
+ const rows = queryItem.querySelectorAll('tbody tr:not(.insights-row)');
1509
+ rows.forEach(row => {
1510
+ // Skip if no score or insights
1511
+ if (row.cells.length <= 4 || !row.dataset.selectedInsights) {
1512
+ return;
1513
+ }
1514
+
1515
+ // Get the score
1516
+ const scoreText = row.cells[4].textContent.trim();
1517
+ if (scoreText === 'Error' || scoreText === 'N/A' || isNaN(parseFloat(scoreText))) {
1518
+ return;
1519
+ }
1520
+
1521
+ const score = Math.round(parseFloat(scoreText));
1522
+ const urlLink = row.querySelector('.url-link');
1523
+
1524
+ if (!urlLink) return;
1525
+
1526
+ // Get insights from this document
1527
+ try {
1528
+ const selectedInsights = JSON.parse(row.dataset.selectedInsights || '[]');
1529
+ const unselectedInsights = JSON.parse(row.dataset.unselectedInsights || '[]');
1530
+ const allInsights = [...selectedInsights, ...unselectedInsights];
1531
+
1532
+ // Add insights to the appropriate score group
1533
+ if (score >= 0 && score <= 5 && allInsights.length > 0) {
1534
+ hasInsights = true;
1535
+
1536
+ // For all insights in this document
1537
+ allInsights.forEach(insight => {
1538
+ // Check if this insight is already in the group
1539
+ const existingIndex = insightsByScore[score].insights.findIndex(i => i === insight);
1540
+
1541
+ if (existingIndex === -1) {
1542
+ // New insight
1543
+ insightsByScore[score].insights.push(insight);
1544
+ insightsByScore[score].sources.push({
1545
+ url: urlLink.href,
1546
+ title: row.cells[1].textContent.trim().substring(0, 30) + '...',
1547
+ selected: selectedInsights.includes(insight)
1548
+ });
1549
+ }
1550
+ });
1551
+ }
1552
+ } catch (e) {
1553
+ console.error('Error parsing insights:', e);
1554
+ }
1555
+ });
1556
+ });
1557
+
1558
+ if (!hasInsights) {
1559
+ alert('No insights found. Please analyze documents and extract insights first.');
1560
+ return;
1561
+ }
1562
+
1563
+ // Create or get the grouped insights container
1564
+ let container = document.getElementById('groupedInsightsContainer');
1565
+ if (!container) {
1566
+ container = document.createElement('div');
1567
+ container.id = 'groupedInsightsContainer';
1568
+ container.className = 'grouped-insights-container';
1569
+
1570
+ // Insert after the problem input card
1571
+ const card = document.querySelector('.card');
1572
+ card.parentNode.insertBefore(container, card.nextSibling);
1573
+ }
1574
+
1575
+ // Create header
1576
+ const header = document.createElement('div');
1577
+ header.className = 'grouped-insights-header';
1578
+ header.innerHTML = `
1579
+ <div>Insights Grouped by Score</div>
1580
+ <div class="grouped-insights-close" onclick="closeGroupedInsights()">&times;</div>
1581
+ `;
1582
+
1583
+ // Create content area
1584
+ const content = document.createElement('div');
1585
+ content.className = 'grouped-insights-content';
1586
+
1587
+ // Create score groups
1588
+ for (let score = 5; score >= 0; score--) {
1589
+ const insights = insightsByScore[score].insights;
1590
+ const sources = insightsByScore[score].sources;
1591
+
1592
+ if (insights.length === 0) continue;
1593
+
1594
+ const scoreGroup = document.createElement('div');
1595
+ scoreGroup.className = 'score-group';
1596
+ scoreGroup.dataset.score = score;
1597
+
1598
+ // Create score header
1599
+ const scoreHeader = document.createElement('div');
1600
+ scoreHeader.className = 'score-group-header';
1601
+
1602
+ let scoreColor = '';
1603
+ if (score >= 0 && score <= 5) {
1604
+ const redComponent = Math.floor((score / 5) * 255);
1605
+ const greenComponent = Math.floor(((5 - score) / 5) * 255);
1606
+ scoreColor = `background-color: rgb(${redComponent}, ${greenComponent}, 0); color: white;`;
1607
+ }
1608
+
1609
+ scoreHeader.innerHTML = `
1610
+ <div>
1611
+ <span style="display: inline-block; width: 25px; height: 25px; text-align: center; border-radius: 50%; ${scoreColor} font-weight: bold;">${score}</span>
1612
+ <span style="margin-left: 8px;">Score ${score} Insights (${insights.length})</span>
1613
+ </div>
1614
+ <div class="score-group-actions">
1615
+ <button class="insights-button select-score-all-btn" onclick="selectAllInScore(${score})">Select All</button>
1616
+ <button class="insights-button clear-score-all-btn" onclick="clearAllInScore(${score})">Clear All</button>
1617
+ </div>
1618
+ `;
1619
+
1620
+ // Create insights list
1621
+ const insightsList = document.createElement('div');
1622
+ insightsList.className = 'score-insights-list';
1623
+
1624
+ // Add each insight
1625
+ insights.forEach((insight, index) => {
1626
+ const source = sources[index];
1627
+ const tagElement = document.createElement('div');
1628
+ tagElement.className = `grouped-insight-tag${source.selected ? ' selected' : ''}`;
1629
+ tagElement.dataset.score = score;
1630
+ tagElement.dataset.index = index;
1631
+ tagElement.dataset.source = source.url;
1632
+
1633
+ // Create insight text with source link
1634
+ tagElement.innerHTML = `
1635
+ ${insight}
1636
+ <a href="${source.url}" target="_blank" class="insight-source" title="${source.title}">${score}</a>
1637
+ `;
1638
+
1639
+ // Add click event to toggle selection
1640
+ tagElement.addEventListener('click', function(e) {
1641
+ // Prevent clicking on the source link from toggling selection
1642
+ if (e.target.classList.contains('insight-source')) return;
1643
+
1644
+ this.classList.toggle('selected');
1645
+ updateGroupedInsightSelections();
1646
+ });
1647
+
1648
+ insightsList.appendChild(tagElement);
1649
+ });
1650
+
1651
+ // Add header and list to score group
1652
+ scoreGroup.appendChild(scoreHeader);
1653
+ scoreGroup.appendChild(insightsList);
1654
+
1655
+ // Add score group to content
1656
+ content.appendChild(scoreGroup);
1657
+ }
1658
+
1659
+ // Clear the container and add new content
1660
+ container.innerHTML = '';
1661
+ container.appendChild(header);
1662
+ container.appendChild(content);
1663
+
1664
+ // Show the container
1665
+ container.style.display = 'block';
1666
+
1667
+ // Collapse all accordions
1668
+ const accordions = document.querySelectorAll('.accordion-section');
1669
+ accordions.forEach(accordion => {
1670
+ const header = accordion.querySelector('.accordion-header');
1671
+ const body = accordion.querySelector('.accordion-body');
1672
+ if (header && body && !header.classList.contains('collapsed')) {
1673
+ header.classList.add('collapsed');
1674
+ body.classList.add('collapsed');
1675
+
1676
+ // Update the toggle icon
1677
+ const toggleIcon = header.querySelector('.toggle-icon');
1678
+ if (toggleIcon) toggleIcon.textContent = '▶';
1679
+ }
1680
+ });
1681
+
1682
+ // Scroll to the insights container
1683
+ container.scrollIntoView({ behavior: 'smooth' });
1684
+ }
1685
+
1686
+ // Close the grouped insights view
1687
+ function closeGroupedInsights() {
1688
+ const container = document.getElementById('groupedInsightsContainer');
1689
+ if (container) {
1690
+ container.style.display = 'none';
1691
+ }
1692
+ }
1693
+
1694
+ // Select all insights for a specific score
1695
+ function selectAllInScore(score) {
1696
+ const container = document.getElementById('groupedInsightsContainer');
1697
+ const tags = container.querySelectorAll(`.grouped-insight-tag[data-score="${score}"]`);
1698
+
1699
+ tags.forEach(tag => {
1700
+ tag.classList.add('selected');
1701
+ });
1702
+
1703
+ updateGroupedInsightSelections();
1704
+ }
1705
+
1706
+ // Clear all insights for a specific score
1707
+ function clearAllInScore(score) {
1708
+ const container = document.getElementById('groupedInsightsContainer');
1709
+ const tags = container.querySelectorAll(`.grouped-insight-tag[data-score="${score}"]`);
1710
+
1711
+ tags.forEach(tag => {
1712
+ tag.classList.remove('selected');
1713
+ });
1714
+
1715
+ updateGroupedInsightSelections();
1716
+ }
1717
+
1718
+ // Update the selection state of insights in their original document rows
1719
+ function updateGroupedInsightSelections() {
1720
+ // Get all selected insights from the grouped view
1721
+ const container = document.getElementById('groupedInsightsContainer');
1722
+ const selectedTags = container.querySelectorAll('.grouped-insight-tag.selected');
1723
+
1724
+ // Create a mapping of URL to selected insights
1725
+ const selectionsBySource = {};
1726
+
1727
+ // Process each selected tag
1728
+ selectedTags.forEach(tag => {
1729
+ const insight = tag.textContent.trim().replace(/\d+$/, '').trim(); // Remove the score number at the end
1730
+ const sourceUrl = tag.dataset.source;
1731
+
1732
+ if (!selectionsBySource[sourceUrl]) {
1733
+ selectionsBySource[sourceUrl] = [];
1734
+ }
1735
+
1736
+ selectionsBySource[sourceUrl].push(insight);
1737
+ });
1738
+
1739
+ // Now update the original document rows
1740
+ const queryItems = document.querySelectorAll('.query-item');
1741
+ queryItems.forEach(queryItem => {
1742
+ const rows = queryItem.querySelectorAll('tbody tr:not(.insights-row)');
1743
+ rows.forEach(row => {
1744
+ const urlLink = row.querySelector('.url-link');
1745
+ if (!urlLink) return;
1746
+
1747
+ const sourceUrl = urlLink.href;
1748
+
1749
+ // If we have selections for this source
1750
+ if (selectionsBySource[sourceUrl]) {
1751
+ // Get all insights for this row
1752
+ try {
1753
+ // Combine selected and unselected to get all insights
1754
+ const currentSelected = JSON.parse(row.dataset.selectedInsights || '[]');
1755
+ const currentUnselected = JSON.parse(row.dataset.unselectedInsights || '[]');
1756
+ const allInsights = [...currentSelected, ...currentUnselected];
1757
+
1758
+ // New selected and unselected based on grouped view
1759
+ const newSelected = [];
1760
+ const newUnselected = [];
1761
+
1762
+ // Process each insight
1763
+ allInsights.forEach(insight => {
1764
+ if (selectionsBySource[sourceUrl].includes(insight)) {
1765
+ newSelected.push(insight);
1766
+ } else {
1767
+ newUnselected.push(insight);
1768
+ }
1769
+ });
1770
+
1771
+ // Update the dataset
1772
+ row.dataset.selectedInsights = JSON.stringify(newSelected);
1773
+ row.dataset.unselectedInsights = JSON.stringify(newUnselected);
1774
+ } catch (e) {
1775
+ console.error('Error updating insights selections:', e);
1776
+ }
1777
+ }
1778
+ });
1779
+ });
1780
+
1781
+ // Update enhance button state
1782
+ checkSelectedInsights();
1783
+ }
1784
+
1785
+ // Check if any documents have been analyzed to enable/disable the Group Insights button
1786
+ function checkGroupInsightsButton() {
1787
+ const queryItems = document.querySelectorAll('.query-item');
1788
+ let hasInsights = false;
1789
+
1790
+ queryItems.forEach(queryItem => {
1791
+ const rows = queryItem.querySelectorAll('tbody tr:not(.insights-row)');
1792
+ rows.forEach(row => {
1793
+ if (row.dataset.selectedInsights || row.dataset.unselectedInsights) {
1794
+ try {
1795
+ const selected = JSON.parse(row.dataset.selectedInsights || '[]');
1796
+ const unselected = JSON.parse(row.dataset.unselectedInsights || '[]');
1797
+ if (selected.length > 0 || unselected.length > 0) {
1798
+ hasInsights = true;
1799
+ }
1800
+ } catch (e) {}
1801
+ }
1802
+ });
1803
+ });
1804
+
1805
+ const groupInsightsButton = document.getElementById('groupInsightsByScoreButton');
1806
+ if (hasInsights) {
1807
+ groupInsightsButton.classList.remove('disabled');
1808
+ groupInsightsButton.disabled = false;
1809
+ } else {
1810
+ groupInsightsButton.classList.add('disabled');
1811
+ groupInsightsButton.disabled = true;
1812
+ }
1813
+ }
1814
  </script>
1815
  </head>
1816
  <body>
 
1891
  <button id="enhanceProblemButton" class="btn enhance-problem-button floating-button disabled" title="Enhance Problem using Selected Insights" onclick="enhanceProblem()" disabled>
1892
  Enhance Problem
1893
  </button>
1894
+ <button id="groupInsightsByScoreButton" class="btn btn-group-insights floating-button disabled" title="Group All Insights by Score" onclick="groupInsightsByScore()" disabled>
1895
+ Group Insights
1896
+ </button>
1897
+ <button id="extractAllInsightsButton" class="btn btn-info floating-button disabled" title="Extract Insights for All Analyzed Documents" onclick="extractAllInsights()" disabled>
1898
+ Extract All Insights
1899
+ </button>
1900
  <button id="analyzeAllButton" class="btn btn-primary floating-button" title="Analyze All Unanalyzed Papers">
1901
  Analyze All
1902
  </button>
 
1925
  // Check for selected insights periodically to enable/disable enhance button
1926
  setInterval(checkSelectedInsights, 1000);
1927
 
1928
+ // Check for analyzed documents to enable/disable Extract All Insights button
1929
+ setInterval(checkAnalyzedDocuments, 1000);
1930
+
1931
+ // Check for insights to enable/disable Group Insights by Score button
1932
+ setInterval(checkGroupInsightsButton, 1000);
1933
+
1934
  // Analyze all button
1935
  document.getElementById('analyzeAllButton').addEventListener('click', function() {
1936
  analyzeAllPapers();
1937
+ // Button will be enabled when analyses complete and checkAnalyzedDocuments runs
1938
  });
1939
 
1940
  // Remove failed button