Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 50 additions & 24 deletions web-app/django/VIM/apps/main/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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]
)

Expand Down
12 changes: 6 additions & 6 deletions web-app/django/VIM/templates/main/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,11 @@ <h3 class="stat-number text-info mb-1">{{ total_users|default:"0" }}</h3>
<!-- First Chart: Top Instruments by Languages -->
<div class="row mb-5 align-items-center">
<div class="col-lg-8 order-2 order-lg-1">
<div class="chart-container p-4 ">
<div id="instruments-chart" class="force-ltr"></div>
<div class="chart-container p-4 force-ltr">
<div id="instruments-chart"></div>
</div>
</div>
<div class="col-lg-4 order-1 order-lg-2 text-center text-lg-start mb-4 mb-lg-0">
<div class="col-lg-4 order-1 order-lg-2 mb-4 mb-lg-0 d-flex flex-column mx-auto align-items-center align-items-lg-start">
<h3 class="text-primary mb-3">Top Instruments by Language Diversity</h3>
<p class="text-muted">
Discover which musical instruments have names in the most languages,
Expand All @@ -158,16 +158,16 @@ <h3 class="text-primary mb-3">Top Instruments by Language Diversity</h3>
</div>
<!-- Second Chart: Top Languages by Instrument Names -->
<div class="row align-items-center">
<div class="col-lg-4 text-center text-lg-start mb-4 mb-lg-0">
<div class="col-lg-4 mb-4 mb-lg-0 d-flex flex-column mx-auto align-items-center align-items-lg-start">
<h3 class="text-primary mb-3">Top Languages by Instrument Coverage</h3>
<p class="text-muted">
Explore which languages contribute the most instrument names to our lexicon,
highlighting linguistic diversity in musical terminology.
</p>
</div>
<div class="col-lg-8">
<div class="chart-container p-4">
<div id="languages-chart" class="force-ltr"></div>
<div class="chart-container p-4 force-ltr">
<div id="languages-chart"></div>
</div>
</div>
</div>
Expand Down
20 changes: 20 additions & 0 deletions web-app/frontend/src/GoogleTranslate.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { setCookie, readCookie, deleteCookie } from './utils/cookies';
import { barChartsInstance, ChartData } from './stats/BarCharts';

declare namespace google {
namespace translate {
Expand Down Expand Up @@ -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"
Expand Down
28 changes: 25 additions & 3 deletions web-app/frontend/src/stats/BarCharts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

Expand Down Expand Up @@ -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;
Loading