Skip to content

Commit 2de19a5

Browse files
committed
Fix #66
1 parent 3bae1dc commit 2de19a5

File tree

5 files changed

+122
-115
lines changed

5 files changed

+122
-115
lines changed

src/py_semantic_taxonomy/adapters/routers/templates/base.html

Lines changed: 108 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!DOCTYPE html>
2-
<html lang="en">
2+
<html lang="{{ language }}">
33
<head>
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@@ -38,6 +38,7 @@
3838
</kbd>
3939
</div>
4040
<input type="hidden" name="semantic" value="true" />
41+
<input type="hidden" name="language" value="{{ language }}" />
4142
</div>
4243
<div id="suggestions" class="absolute w-full mt-1 border rounded-lg shadow-lg hidden z-50" style="background-color: var(--header-bg); border-color: var(--border-color)">
4344
<!-- Suggestions will be populated here -->
@@ -94,122 +95,128 @@
9495
</div>
9596
</footer>
9697
<script>
97-
// Theme handling
98-
const themeToggle = document.getElementById('theme-toggle');
99-
const themeIcon = themeToggle.querySelector('i');
100-
101-
// Check for saved theme preference
102-
const savedTheme = localStorage.getItem('theme') || 'light';
103-
document.documentElement.setAttribute('data-theme', savedTheme);
104-
updateThemeIcon(savedTheme);
105-
106-
themeToggle.addEventListener('click', () => {
107-
const currentTheme = document.documentElement.getAttribute('data-theme');
108-
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
109-
document.documentElement.setAttribute('data-theme', newTheme);
110-
localStorage.setItem('theme', newTheme);
111-
updateThemeIcon(newTheme);
112-
});
113-
114-
function updateThemeIcon(theme) {
115-
themeIcon.className = theme === 'dark' ? 'fas fa-sun' : 'fas fa-moon';
116-
}
98+
document.addEventListener('DOMContentLoaded', function() {
99+
document.getElementById('language').addEventListener('change', function(e) {
100+
window.location.href = e.target.value;
101+
});
117102

118-
// Prevent clicks on disabled links
119-
document.querySelectorAll('a[aria-disabled="true"]').forEach(link => {
120-
link.addEventListener('click', (e) => {
121-
e.preventDefault();
122-
e.stopPropagation();
103+
// Theme handling
104+
const themeToggle = document.getElementById('theme-toggle');
105+
const themeIcon = themeToggle.querySelector('i');
106+
107+
// Check for saved theme preference
108+
const savedTheme = localStorage.getItem('theme') || 'light';
109+
document.documentElement.setAttribute('data-theme', savedTheme);
110+
updateThemeIcon(savedTheme);
111+
112+
themeToggle.addEventListener('click', () => {
113+
const currentTheme = document.documentElement.getAttribute('data-theme');
114+
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
115+
document.documentElement.setAttribute('data-theme', newTheme);
116+
localStorage.setItem('theme', newTheme);
117+
updateThemeIcon(newTheme);
123118
});
124-
});
125119

126-
// Detect OS and update shortcut key
127-
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
128-
if (isMac) {
129-
document.getElementById('shortcut-key').textContent = '⌘';
130-
} else {
131-
document.getElementById('shortcut-key').textContent = 'Ctrl';
132-
}
120+
function updateThemeIcon(theme) {
121+
themeIcon.className = theme === 'dark' ? 'fas fa-sun' : 'fas fa-moon';
122+
}
133123

134-
// Search functionality
135-
document.addEventListener('DOMContentLoaded', function() {
136-
const searchInput = document.querySelector('input[name="query"]');
137-
const suggestionsDiv = document.getElementById('suggestions');
138-
let debounceTimer;
139-
140-
// Handle keyboard shortcut
141-
document.addEventListener('keydown', function(e) {
142-
// Check for Cmd+K (Mac) or Ctrl+K (Windows/Linux)
143-
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
124+
// Prevent clicks on disabled links
125+
document.querySelectorAll('a[aria-disabled="true"]').forEach(link => {
126+
link.addEventListener('click', (e) => {
144127
e.preventDefault();
145-
searchInput.focus();
146-
}
128+
e.stopPropagation();
129+
});
147130
});
148131

149-
// Debounce function
150-
function debounce(func, delay) {
151-
return function() {
152-
const context = this;
153-
const args = arguments;
154-
clearTimeout(debounceTimer);
155-
debounceTimer = setTimeout(() => func.apply(context, args), delay);
156-
};
132+
// Detect OS and update shortcut key
133+
const isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
134+
if (isMac) {
135+
document.getElementById('shortcut-key').textContent = '⌘';
136+
} else {
137+
document.getElementById('shortcut-key').textContent = 'Ctrl';
157138
}
158139

159-
// Fetch suggestions
160-
async function fetchSuggestions(query) {
161-
if (!query) {
162-
suggestionsDiv.classList.add('hidden');
163-
return;
140+
// Search functionality
141+
document.addEventListener('DOMContentLoaded', function() {
142+
const searchInput = document.querySelector('input[name="query"]');
143+
const suggestionsDiv = document.getElementById('suggestions');
144+
let debounceTimer;
145+
146+
// Handle keyboard shortcut
147+
document.addEventListener('keydown', function(e) {
148+
// Check for Cmd+K (Mac) or Ctrl+K (Windows/Linux)
149+
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
150+
e.preventDefault();
151+
searchInput.focus();
152+
}
153+
});
154+
155+
// Debounce function
156+
function debounce(func, delay) {
157+
return function() {
158+
const context = this;
159+
const args = arguments;
160+
clearTimeout(debounceTimer);
161+
debounceTimer = setTimeout(() => func.apply(context, args), delay);
162+
};
164163
}
165164

166-
try {
167-
const response = await fetch(`{{ suggest_api_url }}?query=${encodeURIComponent(query)}&language=en`);
168-
const suggestions = await response.json();
169-
170-
if (suggestions.length > 0) {
171-
const limitedSuggestions = suggestions.slice(0, 5);
172-
const hasMore = suggestions.length > 5;
173-
174-
suggestionsDiv.innerHTML = `
175-
${limitedSuggestions.map(suggestion => `
176-
<div class="p-2 cursor-pointer transition-colors duration-150 hover-row" onclick="selectSuggestion('${suggestion.label}')" style="color: var(--text-color)">
177-
${suggestion.label}
178-
</div>
179-
`).join('')}
180-
${hasMore ? `
181-
<div class="p-2 text-sm text-center border-t" style="color: var(--text-secondary); border-color: var(--border-color)">
182-
+${suggestions.length - 5} more results
183-
</div>
184-
` : ''}
185-
`;
186-
suggestionsDiv.classList.remove('hidden');
187-
} else {
165+
// Fetch suggestions
166+
async function fetchSuggestions(query) {
167+
if (!query) {
168+
suggestionsDiv.classList.add('hidden');
169+
return;
170+
}
171+
172+
try {
173+
const response = await fetch(`{{ suggest_api_url }}?query=${encodeURIComponent(query)}&language={{ language }}`);
174+
const suggestions = await response.json();
175+
176+
if (suggestions.length > 0) {
177+
const limitedSuggestions = suggestions.slice(0, 5);
178+
const hasMore = suggestions.length > 5;
179+
180+
suggestionsDiv.innerHTML = `
181+
${limitedSuggestions.map(suggestion => `
182+
<div class="p-2 cursor-pointer transition-colors duration-150 hover-row" onclick="selectSuggestion('${suggestion.label}')" style="color: var(--text-color)">
183+
${suggestion.label}
184+
</div>
185+
`).join('')}
186+
${hasMore ? `
187+
<div class="p-2 text-sm text-center border-t" style="color: var(--text-secondary); border-color: var(--border-color)">
188+
+${suggestions.length - 5} more results
189+
</div>
190+
` : ''}
191+
`;
192+
suggestionsDiv.classList.remove('hidden');
193+
} else {
194+
suggestionsDiv.classList.add('hidden');
195+
}
196+
} catch (error) {
197+
console.error('Error fetching suggestions:', error);
188198
suggestionsDiv.classList.add('hidden');
189199
}
190-
} catch (error) {
191-
console.error('Error fetching suggestions:', error);
192-
suggestionsDiv.classList.add('hidden');
193200
}
194-
}
195201

196-
// Handle input with debounce
197-
searchInput.addEventListener('input', debounce(function(e) {
198-
fetchSuggestions(e.target.value);
199-
}, 300));
200-
201-
// Handle suggestion selection
202-
window.selectSuggestion = function(suggestion) {
203-
searchInput.value = suggestion;
204-
suggestionsDiv.classList.add('hidden');
205-
document.getElementById('searchForm').submit();
206-
};
207-
208-
// Close suggestions when clicking outside
209-
document.addEventListener('click', function(e) {
210-
if (!searchInput.contains(e.target) && !suggestionsDiv.contains(e.target)) {
202+
// Handle input with debounce
203+
searchInput.addEventListener('input', debounce(function(e) {
204+
fetchSuggestions(e.target.value);
205+
}, 300));
206+
207+
// Handle suggestion selection
208+
window.selectSuggestion = function(suggestion) {
209+
searchInput.value = suggestion;
211210
suggestionsDiv.classList.add('hidden');
212-
}
211+
document.getElementById('searchForm').submit();
212+
};
213+
214+
// Close suggestions when clicking outside
215+
document.addEventListener('click', function(e) {
216+
if (!searchInput.contains(e.target) && !suggestionsDiv.contains(e.target)) {
217+
suggestionsDiv.classList.add('hidden');
218+
}
219+
});
213220
});
214221
});
215222
</script>

src/py_semantic_taxonomy/adapters/routers/templates/concept_scheme_view.html

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,6 @@ <h3 class="text-sm font-medium" style="color: var(--text-secondary)">Notation</h
166166
</div>
167167

168168
<script>
169-
document.getElementById('language').addEventListener('change', function(e) {
170-
window.location.href = e.target.value;
171-
});
172-
173169
var iri_clicker = document.getElementById("cs_iri_clicker");
174170
iri_clicker.onclick = function(){
175171
navigator.clipboard.writeText("{{ concept_scheme.id_ }}").then(this.querySelector('#cs_iri_clicker_icon').classList.replace("fa-copy", "fa-check"))

src/py_semantic_taxonomy/adapters/routers/templates/concept_schemes.html

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,4 @@ <h1>Concept Schemes</h1>
8181
</div>
8282
</div>
8383
</div>
84-
85-
<script>
86-
document.getElementById('language').addEventListener('change', function(e) {
87-
window.location.href = e.target.value;
88-
});
89-
</script>
9084
{% endblock %}

src/py_semantic_taxonomy/adapters/routers/templates/concept_view.html

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,10 +296,6 @@ <h3 class="text-sm font-medium" style="color: var(--text-secondary)">Hidden Labe
296296
</div>
297297

298298
<script>
299-
document.getElementById('language').addEventListener('change', function(e) {
300-
window.location.href = e.target.value;
301-
});
302-
303299
var iri_clicker = document.getElementById("concept_iri_clicker");
304300
iri_clicker.onclick = function(){
305301
navigator.clipboard.writeText("{{ concept.id_ }}").then(this.querySelector('#concept_iri_clicker_icon').classList.replace("fa-copy", "fa-check"))

src/py_semantic_taxonomy/adapters/routers/web_router.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,18 +357,32 @@ async def web_search(
357357
language: str = "en",
358358
semantic: bool = True,
359359
search_service=Depends(get_search_service),
360+
settings=Depends(get_settings),
360361
) -> HTMLResponse:
361362
"""Search for concepts."""
362363
try:
363364
results = []
364365
if query:
365366
results = await search_service.search(query=query, language=language, semantic=semantic)
367+
368+
languages = [(request.url, Language.get(language).display_name(language).title())] + [
369+
(
370+
str(request.url_for("web_search"))
371+
+ "?"
372+
+ urlencode({"query": query, "language": code, "semantic": semantic}),
373+
label,
374+
)
375+
for code, label in format_languages(settings.languages)
376+
if code != language
377+
]
378+
366379
return templates.TemplateResponse(
367380
"search.html",
368381
{
369382
"request": request,
370383
"query": query,
371384
"language": language,
385+
"language_selector": languages,
372386
"semantic": semantic,
373387
"results": results,
374388
"suggest_api_url": get_full_api_path("suggest"),

0 commit comments

Comments
 (0)