diff --git a/web-app/django/VIM/apps/main/views.py b/web-app/django/VIM/apps/main/views.py index 25987f9d..0462d09a 100644 --- a/web-app/django/VIM/apps/main/views.py +++ b/web-app/django/VIM/apps/main/views.py @@ -4,7 +4,7 @@ from django.contrib import messages from django.contrib.auth import authenticate, login from django.contrib.auth.models import User -from django.db.models import Count +from django.db.models import Count, Q from django.shortcuts import redirect, render from django.urls import reverse from django.utils.http import url_has_allowed_host_and_scheme @@ -33,47 +33,73 @@ def home(request): # Fetch statistics from database total_instruments = Instrument.objects.count() total_languages = Language.objects.count() - total_names = InstrumentName.objects.count() - total_users = User.objects.filter( - is_active=True - ).count() # Users who have completed email registration + total_names = InstrumentName.objects.filter(verification_status="verified").count() + total_editors = User.objects.count() - # Chart data: Top 5 instruments with most languages + # Chart data: Top 5 instruments with most languages (only verified names) top_instruments_by_languages = ( Instrument.objects.annotate( - language_count=Count("instrumentname__language", distinct=True) + language_count=Count( + "instrumentname__language", + filter=Q(instrumentname__verification_status="verified"), + distinct=True, + ) ) - .filter(language_count__gt=0) # Only instruments with at least one language + .filter(language_count__gt=0) .order_by("-language_count")[:5] ) + # Get language from cookie (default 'en') + try: + user_language = request.COOKIES.get("googtrans", "/en/en") + user_language_code = user_language.split("/")[-1] + target_language_obj = Language.objects.filter( + wikidata_code=user_language_code + ).first() + target_language_label = ( + target_language_obj.en_label if target_language_obj else "English" + ) + except: + target_language_label = "English" + instruments_chart_data = [] for instrument in top_instruments_by_languages: - # Get the English name if available, otherwise use the first available name - try: - english_name = instrument.instrumentname_set.filter( - language__en_label="English" + # Try user-selected language + instrument_name_obj = instrument.instrumentname_set.filter( + language__en_label=target_language_label, verification_status="verified" + ).first() + + # Fallback to English + if not instrument_name_obj: + instrument_name_obj = instrument.instrumentname_set.filter( + language__en_label="English", verification_status="verified" ).first() - name = ( - english_name.name - if english_name - else instrument.instrumentname_set.first().name - ) - except: - name = f"Instrument {instrument.wikidata_id}" + # Fallback to first available (must be verified) + if not instrument_name_obj: + instrument_name_obj = instrument.instrumentname_set.filter( + verification_status="verified" + ).first() + + name = ( + instrument_name_obj.name + if instrument_name_obj + else f"Instrument {instrument.wikidata_id}" + ) instruments_chart_data.append( {"name": name, "count": instrument.language_count} ) - # Chart data: Top 5 languages with most instrument names + # Chart data: Top 5 languages with most instrument names (only verified instrument names) top_languages_by_names = ( Language.objects.annotate( - instrument_count=Count("instrumentname", distinct=True) + instrument_count=Count( + "instrumentname", + filter=Q(instrumentname__verification_status="verified"), + distinct=True, + ) ) - .filter( - instrument_count__gt=0 - ) # Only languages with at least one instrument name + .filter(instrument_count__gt=0) .order_by("-instrument_count")[:5] ) diff --git a/web-app/django/VIM/templates/main/index.html b/web-app/django/VIM/templates/main/index.html index f17b6c18..495e130a 100644 --- a/web-app/django/VIM/templates/main/index.html +++ b/web-app/django/VIM/templates/main/index.html @@ -144,11 +144,11 @@

{{ total_users|default:"0" }}

-
-
+
+
-
+

Top Instruments by Language Diversity

Discover which musical instruments have names in the most languages, @@ -158,7 +158,7 @@

Top Instruments by Language Diversity

-
+

Top Languages by Instrument Coverage

Explore which languages contribute the most instrument names to our lexicon, @@ -166,8 +166,8 @@

Top Languages by Instrument Coverage

-
-
+
+
diff --git a/web-app/frontend/src/GoogleTranslate.ts b/web-app/frontend/src/GoogleTranslate.ts index a9de2bfe..7839f1c8 100644 --- a/web-app/frontend/src/GoogleTranslate.ts +++ b/web-app/frontend/src/GoogleTranslate.ts @@ -1,4 +1,5 @@ import { setCookie, readCookie, deleteCookie } from './utils/cookies'; +import { barChartsInstance, ChartData } from './stats/BarCharts'; declare namespace google { namespace translate { @@ -92,6 +93,25 @@ function customizeGoogleTranslate() { // Set up observer to watch for Google Translate widget changes watchGTDefaultText(googleSelect); + + googleSelect.addEventListener('change', () => + setTimeout(async () => { + const doc = new DOMParser().parseFromString( + await ( + await fetch(location.pathname, { credentials: 'same-origin' }) + ).text(), + 'text/html', + ); + (window as any).barChartsInstance.update( + JSON.parse( + doc.getElementById('instruments-chart-data')?.textContent || '[]', + ), + JSON.parse( + doc.getElementById('languages-chart-data')?.textContent || '[]', + ), + ); + }, 500), + ); } // Watch for the default text of the Google Translate widget to be "Select Language" diff --git a/web-app/frontend/src/stats/BarCharts.ts b/web-app/frontend/src/stats/BarCharts.ts index 75d1bc0b..9eb4d2c1 100644 --- a/web-app/frontend/src/stats/BarCharts.ts +++ b/web-app/frontend/src/stats/BarCharts.ts @@ -18,9 +18,13 @@ class BarCharts { private init(): void { // Wait for DOM to be ready if (document.readyState === 'loading') { - document.addEventListener('DOMContentLoaded', () => this.createCharts()); + document.addEventListener('DOMContentLoaded', () => { + this.createCharts(); + this.setupResizeObserver(); + }); } else { this.createCharts(); + this.setupResizeObserver(); } } @@ -347,7 +351,25 @@ class BarCharts { .delay((d: ChartData, i: number) => labelStartDelay + i * 50) .style('opacity', 1); } + + public update(instruments: ChartData[], languages: ChartData[]): void { + this.createInstrumentsChart(instruments); + this.createLanguagesChart(languages); + this.setupIntersectionObserver(); + this.setupResizeObserver(); + } + + private setupResizeObserver(): void { + let resizeTimeout: number; + + window.addEventListener('resize', () => { + clearTimeout(resizeTimeout); + resizeTimeout = window.setTimeout(() => { + this.createCharts(); + }, 250); + }); + } } -// Initialize the charts when this module is loaded -new BarCharts(); +export const barChartsInstance = new BarCharts(); +(window as any).barChartsInstance = barChartsInstance;