diff --git a/web-app/django/VIM/apps/instruments/views/instrument_detail.py b/web-app/django/VIM/apps/instruments/views/instrument_detail.py index 18add74b..4b751a43 100644 --- a/web-app/django/VIM/apps/instruments/views/instrument_detail.py +++ b/web-app/django/VIM/apps/instruments/views/instrument_detail.py @@ -4,6 +4,8 @@ from django.http import Http404 from django.views.generic import DetailView from VIM.apps.instruments.models import Instrument, Language +from django.db.models import Case, When, Value +from collections import defaultdict, OrderedDict class InstrumentDetail(DetailView): @@ -34,47 +36,89 @@ def get_object(self, queryset=None): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) - # Query the instrument names in all languages + # Get the active language from the session; fallback to English. + active_language_en = self.request.session.get("active_language_en", "English") + try: + active_lang = Language.objects.get(en_label=active_language_en) + except Language.DoesNotExist: + active_lang = Language.objects.get(en_label="English") + context["active_language"] = active_lang + + # Query the instrument names in all languages, sorted instrument_names = ( - context["instrument"].instrumentname_set.all().select_related("language") + context["instrument"] + .instrumentname_set.all() + .select_related("language") + .annotate( + active_lang_first=Case( + When(language=active_lang, then=Value(1)), + default=Value(0), + ) + ) + .order_by( + "-active_lang_first", # active_lang matched names come first for display + "-umil_label", + "id", # earlier created names come first + ) ) + + # Determine label in the active language, prioritizing umil_label and earliest created + active_label_qs = instrument_names.filter(language=active_lang, umil_label=True) + if active_label_qs.exists(): + context["active_instrument_label"] = active_label_qs.earliest("id") + elif instrument_names.filter(language=active_lang).exists(): + context["active_instrument_label"] = instrument_names.filter( + language=active_lang + ).earliest("id") + else: + context["active_instrument_label"] = "" + + # Control visibility of names: verified only for guests if self.request.user.is_authenticated: - # Show all names for authenticated users - context["instrument_names"] = instrument_names.all() + instrument_names_visible = instrument_names.all() else: - # Show only verified names for unauthenticated users - context["instrument_names"] = instrument_names.filter( + instrument_names_visible = instrument_names.filter( verification_status="verified" ) + context["instrument_names"] = instrument_names_visible - # Initialize a dictionary to store label and aliases by language - label_aliases_dict = {} + # Build names by language + names_by_lang = defaultdict(list) for instrumentname in instrument_names: - language = instrumentname.language - if language not in label_aliases_dict: - label_aliases_dict[language] = {"label": None, "aliases": []} - if instrumentname.umil_label: - label_aliases_dict[language]["label"] = instrumentname + names_by_lang[instrumentname.language].append(instrumentname) + + # Build the language order: active first (if present), then all others by earliest InstrumentName creation + lang_candidate_order = [ + lang for lang in names_by_lang.keys() if lang != active_lang + ] + # Sort non-active languages by the minimum id of their names + lang_candidate_order.sort( + key=lambda language: min(n.id for n in names_by_lang[language]) + ) + lang_order = [active_lang] if active_lang in names_by_lang else [] + lang_order.extend(lang_candidate_order) + + label_aliases_dict = OrderedDict() + for language in lang_order: + namelist = names_by_lang[language] + label = None + aliases = [] + + # Find earliest umil_label for label + umil_labels = [n for n in namelist if n.umil_label] + if umil_labels: + label = sorted(umil_labels, key=lambda n: n.id)[0] + aliases = [n for n in namelist if n != label] else: - label_aliases_dict[language]["aliases"].append(instrumentname) - context["label_aliases_dict"] = label_aliases_dict + # No umil_label, use earliest name as label + ordered = sorted(namelist, key=lambda n: n.id) + if ordered: + label = ordered[0] + aliases = ordered[1:] - # Get the active language - active_language_en = self.request.session.get("active_language_en", None) - context["active_language"] = ( - Language.objects.get(en_label=active_language_en) - if active_language_en - else Language.objects.get(en_label="English") # default in English - ) + label_aliases_dict[language] = {"label": label, "aliases": aliases} - # Get the instrument label in the active language - # Set label to the first instrument name added in the language if there is no "umil_label" set - active_labels = instrument_names.filter(language=context["active_language"]) - umil_label = active_labels.filter(umil_label=True) - if umil_label.exists(): - context["active_instrument_label"] = umil_label.first() - else: - context["active_instrument_label"] = active_labels.first() + context["label_aliases_dict"] = label_aliases_dict # Get all languages for the dropdown context["languages"] = json.dumps( diff --git a/web-app/django/VIM/templates/instruments/create.html b/web-app/django/VIM/templates/instruments/create.html index ee9673a5..20f638d7 100644 --- a/web-app/django/VIM/templates/instruments/create.html +++ b/web-app/django/VIM/templates/instruments/create.html @@ -93,11 +93,23 @@