diff --git a/src/bpp/admin/wydawnictwo_zwarte.py b/src/bpp/admin/wydawnictwo_zwarte.py index fd374e538..644643b41 100644 --- a/src/bpp/admin/wydawnictwo_zwarte.py +++ b/src/bpp/admin/wydawnictwo_zwarte.py @@ -273,6 +273,9 @@ def _sprawdz_isbn_z_nadrzednym( wydawca = forms.ModelChoiceField( required=False, queryset=Wydawca.objects.all(), + help_text="Przy rozdziale (gdy wskazano wydawnictwo nadrzędne) wydawca " + "jest dziedziczony po wydawnictwie nadrzędnym, o ile pozostawisz to pole " + "puste. Możesz wpisać innego wydawcę ręcznie.", widget=autocomplete.ModelSelect2( url="bpp:wydawca-autocomplete", attrs={"class": "bpp-autocomplete-wide"} ), @@ -345,8 +348,32 @@ def clean(self): if message: self._warnings.append(message) + self._dziedzicz_wydawce_po_nadrzednym(cleaned_data, wydawnictwo_nadrzedne) + return cleaned_data + def _dziedzicz_wydawce_po_nadrzednym(self, cleaned_data, wydawnictwo_nadrzedne): + """Dziedziczenie wydawcy po wydawnictwie nadrzędnym (rozdziale). + + Freshdesk #385. Jeżeli rekord ma wskazane wydawnictwo nadrzędne + (czyli jest rozdziałem), a operator nie podał własnego wydawcy — + podstaw wydawcę z wydawnictwa nadrzędnego. Jawnie wpisany wydawca + NIE jest nadpisywany. Mutuje ``cleaned_data`` w miejscu. + """ + if not wydawnictwo_nadrzedne: + return + if cleaned_data.get("wydawca"): + return + if wydawnictwo_nadrzedne.wydawca_id is None: + return + + cleaned_data["wydawca"] = wydawnictwo_nadrzedne.wydawca + self._warnings.append( + "Wydawca został odziedziczony po wydawnictwie nadrzędnym " + f"'{wydawnictwo_nadrzedne.tytul_oryginalny}': " + f"{wydawnictwo_nadrzedne.wydawca}." + ) + class Meta: model = Wydawnictwo_Zwarte fields = [ @@ -427,6 +454,13 @@ class Meta: "slowa_kluczowe": TextareaTagWidget(attrs={"rows": 2}), } + class Media: + # Freshdesk #385: podświetlenie wymaganego pola "wydawca" przy + # rozdziale (rekord z wydawnictwem nadrzędnym). Warstwa wyłącznie + # wizualna — dziedziczenie wydawcy realizuje serwer w clean(). + js = ["/static/bpp/js/wydawnictwo_zwarte_wydawca.js"] + css = {"all": ["/static/bpp/css/wydawnictwo_zwarte_wydawca.css"]} + class Wydawnictwo_Zwarte_Zewnetrzna_Baza_DanychForm(forms.ModelForm): class Meta: diff --git a/src/bpp/static/bpp/css/wydawnictwo_zwarte_wydawca.css b/src/bpp/static/bpp/css/wydawnictwo_zwarte_wydawca.css new file mode 100644 index 000000000..0effc52fc --- /dev/null +++ b/src/bpp/static/bpp/css/wydawnictwo_zwarte_wydawca.css @@ -0,0 +1,17 @@ +/* + * Freshdesk #385 — podświetlenie wymaganego pola "wydawca" przy rozdziale. + * Aktywowane klasą .bpp-wydawca-wymagany dodawaną przez + * wydawnictwo_zwarte_wydawca.js, gdy wskazano wydawnictwo nadrzędne, + * a pole wydawca jest puste. + */ +.bpp-wydawca-wymagany { + border-left: 4px solid #e6a700; + padding-left: 8px; + background-color: rgba(230, 167, 0, 0.08); +} + +.bpp-wydawca-required-marker { + color: #b35900; + font-weight: bold; + font-size: 0.85em; +} diff --git a/src/bpp/static/bpp/js/wydawnictwo_zwarte_wydawca.js b/src/bpp/static/bpp/js/wydawnictwo_zwarte_wydawca.js new file mode 100644 index 000000000..e725501bf --- /dev/null +++ b/src/bpp/static/bpp/js/wydawnictwo_zwarte_wydawca.js @@ -0,0 +1,71 @@ +/* + * Freshdesk #385 — Rozdział: podświetlanie wymaganego pola "wydawca". + * + * Gdy rekord wydawnictwa zwartego ma wskazane wydawnictwo nadrzędne + * (czyli jest rozdziałem), pole "wydawca" jest istotne i łatwo je + * przeoczyć. Ten skrypt podświetla je wizualnie jako wymagane, dopóki + * pozostaje puste. Faktyczne dziedziczenie wydawcy po wydawnictwie + * nadrzędnym realizuje serwer (Wydawnictwo_ZwarteForm.clean) — to jest + * wyłącznie warstwa UI i nie jest wymagana do działania mechanizmu. + */ +(function ($) { + "use strict"; + + function wydawcaInput() { + return $("#id_wydawca"); + } + + function wydawcaRow() { + // Wiersz formularza admina opakowujący pole wydawca (div.form-row / + // div.field-wydawca w zależności od wersji szablonu). + return wydawcaInput().closest(".form-row, .field-wydawca"); + } + + function nadrzedneWybrane() { + var val = $("#id_wydawnictwo_nadrzedne").val(); + return val !== null && val !== undefined && val !== ""; + } + + function wydawcaPusty() { + var val = wydawcaInput().val(); + return val === null || val === undefined || val === ""; + } + + function odswiezPodswietlenie() { + var row = wydawcaRow(); + if (!row.length) { + return; + } + var wymagany = nadrzedneWybrane() && wydawcaPusty(); + row.toggleClass("bpp-wydawca-wymagany", wymagany); + + var label = row.find("label").first(); + if (!label.length) { + return; + } + var marker = label.find(".bpp-wydawca-required-marker"); + if (wymagany) { + if (!marker.length) { + label.append( + ' ' + + "❗ wymagane przy rozdziale" + ); + } + } else { + marker.remove(); + } + } + + $(function () { + odswiezPodswietlenie(); + // django-autocomplete-light (Select2) emituje "change" na ukrytym + //