| <!DOCTYPE html>
|
| <html lang="en">
|
| <head>
|
| <meta charset="UTF-8">
|
| <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| <title>URAAS - New Features Demo</title>
|
| <script src="https://cdn.tailwindcss.com"></script>
|
| </head>
|
| <body class="bg-gray-900 text-white p-8">
|
| <div class="max-w-6xl mx-auto">
|
| <h1 class="text-4xl font-bold mb-8 text-blue-400">🚀 URAAS New Features Demo</h1>
|
|
|
|
|
| <div class="bg-gray-800 rounded-lg p-6 mb-6">
|
| <h2 class="text-2xl font-bold mb-4">🔍 Advanced Search (Scopus-style)</h2>
|
| <div class="mb-4">
|
| <input type="text" id="searchQuery"
|
| placeholder='Try: "machine learning" AND author:smith OR year:2020'
|
| class="w-full p-3 bg-gray-700 rounded text-white">
|
| </div>
|
| <div class="flex gap-2 mb-4">
|
| <button onclick="testSearch()" class="bg-blue-600 px-6 py-2 rounded hover:bg-blue-700">
|
| Search
|
| </button>
|
| <select id="sortBy" class="bg-gray-700 px-4 py-2 rounded">
|
| <option value="relevance">Relevance</option>
|
| <option value="date">Date</option>
|
| <option value="citations">Citations</option>
|
| <option value="title">Title</option>
|
| </select>
|
| </div>
|
| <div id="searchResults" class="text-sm"></div>
|
| </div>
|
|
|
|
|
| <div class="bg-gray-800 rounded-lg p-6 mb-6">
|
| <h2 class="text-2xl font-bold mb-4">📊 Citation Tracking</h2>
|
| <div class="mb-4">
|
| <input type="number" id="paperId" placeholder="Enter Paper ID"
|
| class="p-3 bg-gray-700 rounded text-white w-64">
|
| <button onclick="getCitations()" class="bg-green-600 px-6 py-2 rounded hover:bg-green-700 ml-2">
|
| Get Citations
|
| </button>
|
| <button onclick="updateCitations()" class="bg-yellow-600 px-6 py-2 rounded hover:bg-yellow-700 ml-2">
|
| Update from OpenAlex
|
| </button>
|
| </div>
|
| <div id="citationResults" class="text-sm"></div>
|
| </div>
|
|
|
|
|
| <div class="bg-gray-800 rounded-lg p-6 mb-6">
|
| <h2 class="text-2xl font-bold mb-4">👤 Author Bibliometrics (H-index)</h2>
|
| <div class="mb-4">
|
| <input type="number" id="authorId" placeholder="Enter Author ID"
|
| class="p-3 bg-gray-700 rounded text-white w-64">
|
| <button onclick="getAuthorMetrics()" class="bg-purple-600 px-6 py-2 rounded hover:bg-purple-700 ml-2">
|
| Get Metrics
|
| </button>
|
| </div>
|
| <div id="authorResults" class="text-sm"></div>
|
| </div>
|
|
|
|
|
| <div class="bg-gray-800 rounded-lg p-6">
|
| <h2 class="text-2xl font-bold mb-4">💡 Quick Examples</h2>
|
| <div class="grid grid-cols-2 gap-4 text-sm">
|
| <div>
|
| <h3 class="font-bold text-blue-400 mb-2">Search Queries:</h3>
|
| <ul class="space-y-1 text-gray-300">
|
| <li>• <code>health</code> - Simple keyword</li>
|
| <li>• <code>"machine learning"</code> - Exact phrase</li>
|
| <li>• <code>author:okonkwo</code> - By author</li>
|
| <li>• <code>year:2020</code> - By year</li>
|
| <li>• <code>faculty:science</code> - By faculty</li>
|
| <li>• <code>health AND education</code> - Boolean AND</li>
|
| <li>• <code>title:cancer NOT lung</code> - Boolean NOT</li>
|
| </ul>
|
| </div>
|
| <div>
|
| <h3 class="font-bold text-green-400 mb-2">API Endpoints:</h3>
|
| <ul class="space-y-1 text-gray-300">
|
| <li>• <code>/api/search/advanced?q=...</code></li>
|
| <li>• <code>/api/citations/<id></code></li>
|
| <li>• <code>/api/author/<id>/metrics</code></li>
|
| <li>• <code>/api/citations/update/<id></code></li>
|
| <li>• <code>/api/search/suggest?q=...</code></li>
|
| </ul>
|
| </div>
|
| </div>
|
| </div>
|
| </div>
|
|
|
| <script>
|
| const API_BASE = 'http://localhost:8080';
|
|
|
| async function testSearch() {
|
| const query = document.getElementById('searchQuery').value;
|
| const sortBy = document.getElementById('sortBy').value;
|
| const resultsDiv = document.getElementById('searchResults');
|
|
|
| resultsDiv.innerHTML = '<p class="text-yellow-400">Searching...</p>';
|
|
|
| try {
|
| const response = await fetch(`${API_BASE}/api/search/advanced?q=${encodeURIComponent(query)}&sort=${sortBy}&limit=10`);
|
| const data = await response.json();
|
|
|
| let html = `<div class="bg-gray-700 p-4 rounded mb-4">
|
| <p class="text-green-400">✓ Found ${data.total} results in ${data.took_ms}ms</p>
|
| <p class="text-gray-400 text-xs mt-1">Query parsed: ${data.query_parsed}</p>
|
| </div>`;
|
|
|
| if (data.results && data.results.length > 0) {
|
| html += '<div class="space-y-3">';
|
| data.results.forEach(paper => {
|
| html += `<div class="bg-gray-700 p-4 rounded">
|
| <h3 class="font-bold text-blue-300">${paper.title}</h3>
|
| <p class="text-gray-400 text-xs mt-1">
|
| ${paper.authors.join(', ')} (${paper.year || 'N/A'})
|
| </p>
|
| ${paper.doi ? `<p class="text-xs text-gray-500 mt-1">DOI: ${paper.doi}</p>` : ''}
|
| ${paper.faculty ? `<p class="text-xs text-purple-400 mt-1">${paper.faculty}</p>` : ''}
|
| </div>`;
|
| });
|
| html += '</div>';
|
| } else {
|
| html += '<p class="text-gray-400">No results found</p>';
|
| }
|
|
|
| resultsDiv.innerHTML = html;
|
| } catch (error) {
|
| resultsDiv.innerHTML = `<p class="text-red-400">Error: ${error.message}</p>`;
|
| }
|
| }
|
|
|
| async function getCitations() {
|
| const paperId = document.getElementById('paperId').value;
|
| const resultsDiv = document.getElementById('citationResults');
|
|
|
| if (!paperId) {
|
| resultsDiv.innerHTML = '<p class="text-red-400">Please enter a paper ID</p>';
|
| return;
|
| }
|
|
|
| resultsDiv.innerHTML = '<p class="text-yellow-400">Fetching citations...</p>';
|
|
|
| try {
|
| const response = await fetch(`${API_BASE}/api/citations/${paperId}`);
|
| const data = await response.json();
|
|
|
| let html = `<div class="bg-gray-700 p-4 rounded">
|
| <p class="text-2xl font-bold text-green-400">${data.citation_count} Citations</p>
|
| ${data.last_updated ? `<p class="text-xs text-gray-400 mt-1">Last updated: ${new Date(data.last_updated).toLocaleString()}</p>` : ''}
|
| </div>`;
|
|
|
| if (data.citing_papers && data.citing_papers.length > 0) {
|
| html += '<div class="mt-4 space-y-2">';
|
| html += '<h3 class="font-bold text-blue-300 mb-2">Citing Papers:</h3>';
|
| data.citing_papers.forEach(cite => {
|
| html += `<div class="bg-gray-700 p-3 rounded text-sm">
|
| <p class="font-semibold">${cite.title}</p>
|
| <p class="text-gray-400 text-xs">${cite.authors.join(', ')} (${cite.year || 'N/A'})</p>
|
| </div>`;
|
| });
|
| html += '</div>';
|
| }
|
|
|
| resultsDiv.innerHTML = html;
|
| } catch (error) {
|
| resultsDiv.innerHTML = `<p class="text-red-400">Error: ${error.message}</p>`;
|
| }
|
| }
|
|
|
| async function updateCitations() {
|
| const paperId = document.getElementById('paperId').value;
|
| const resultsDiv = document.getElementById('citationResults');
|
|
|
| if (!paperId) {
|
| resultsDiv.innerHTML = '<p class="text-red-400">Please enter a paper ID</p>';
|
| return;
|
| }
|
|
|
| resultsDiv.innerHTML = '<p class="text-yellow-400">Updating from OpenAlex... (this may take 5-10 seconds)</p>';
|
|
|
| try {
|
| const response = await fetch(`${API_BASE}/api/citations/update/${paperId}`, {method: 'POST'});
|
| const data = await response.json();
|
|
|
| if (data.success) {
|
| resultsDiv.innerHTML = '<p class="text-green-400">✓ Citations updated! Click "Get Citations" to see results.</p>';
|
| } else {
|
| resultsDiv.innerHTML = '<p class="text-red-400">Update failed. Paper may not have a DOI or not be in OpenAlex.</p>';
|
| }
|
| } catch (error) {
|
| resultsDiv.innerHTML = `<p class="text-red-400">Error: ${error.message}</p>`;
|
| }
|
| }
|
|
|
| async function getAuthorMetrics() {
|
| const authorId = document.getElementById('authorId').value;
|
| const resultsDiv = document.getElementById('authorResults');
|
|
|
| if (!authorId) {
|
| resultsDiv.innerHTML = '<p class="text-red-400">Please enter an author ID</p>';
|
| return;
|
| }
|
|
|
| resultsDiv.innerHTML = '<p class="text-yellow-400">Fetching author metrics...</p>';
|
|
|
| try {
|
| const response = await fetch(`${API_BASE}/api/author/${authorId}/metrics`);
|
| const data = await response.json();
|
|
|
| if (data.author_name) {
|
| let html = `<div class="bg-gray-700 p-4 rounded">
|
| <h3 class="text-xl font-bold text-purple-300 mb-3">${data.author_name}</h3>
|
| <div class="grid grid-cols-2 gap-4">
|
| <div>
|
| <p class="text-gray-400 text-sm">Total Papers</p>
|
| <p class="text-2xl font-bold">${data.total_papers}</p>
|
| </div>
|
| <div>
|
| <p class="text-gray-400 text-sm">Total Citations</p>
|
| <p class="text-2xl font-bold text-green-400">${data.total_citations}</p>
|
| </div>
|
| <div>
|
| <p class="text-gray-400 text-sm">H-index</p>
|
| <p class="text-2xl font-bold text-blue-400">${data.h_index}</p>
|
| </div>
|
| <div>
|
| <p class="text-gray-400 text-sm">i10-index</p>
|
| <p class="text-2xl font-bold text-yellow-400">${data.i10_index}</p>
|
| </div>
|
| </div>
|
| <p class="text-xs text-gray-400 mt-3">Citations per paper: ${data.citations_per_paper}</p>
|
| <p class="text-xs text-gray-500 mt-1">Last updated: ${new Date(data.last_updated).toLocaleString()}</p>
|
| </div>`;
|
| resultsDiv.innerHTML = html;
|
| } else {
|
| resultsDiv.innerHTML = '<p class="text-gray-400">No metrics found. Author may not have papers with citation data.</p>';
|
| }
|
| } catch (error) {
|
| resultsDiv.innerHTML = `<p class="text-red-400">Error: ${error.message}</p>`;
|
| }
|
| }
|
|
|
|
|
| document.getElementById('searchQuery').value = 'health AND education';
|
| </script>
|
| </body>
|
| </html>
|
|
|