Skip to content
Merged
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
34 changes: 34 additions & 0 deletions src/bpp/admin/wydawnictwo_zwarte.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"}
),
Expand Down Expand Up @@ -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 = [
Expand Down Expand Up @@ -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:
Expand Down
17 changes: 17 additions & 0 deletions src/bpp/static/bpp/css/wydawnictwo_zwarte_wydawca.css
Original file line number Diff line number Diff line change
@@ -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;
}
71 changes: 71 additions & 0 deletions src/bpp/static/bpp/js/wydawnictwo_zwarte_wydawca.js
Original file line number Diff line number Diff line change
@@ -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(
' <span class="bpp-wydawca-required-marker" ' +
'title="Przy rozdziale podaj wydawcę (lub zostanie ' +
'odziedziczony po wydawnictwie nadrzędnym)">' +
"❗ wymagane przy rozdziale</span>"
);
}
} else {
marker.remove();
}
}

$(function () {
odswiezPodswietlenie();
// django-autocomplete-light (Select2) emituje "change" na ukrytym
// <select>; nasłuchujemy obu pól.
$(document).on(
"change",
"#id_wydawnictwo_nadrzedne, #id_wydawca",
odswiezPodswietlenie
);
});
})(window.django ? window.django.jQuery : window.jQuery);
77 changes: 74 additions & 3 deletions src/bpp/tests/test_admin/test_wydawnictwo_zwarte.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
from django.urls import reverse
from model_bakery import baker

from pbn_api.models import Publication

from bpp.models import Wydawnictwo_Zwarte
from bpp.admin.wydawnictwo_zwarte import Wydawnictwo_ZwarteForm
from bpp.models import Wydawca, Wydawnictwo_Zwarte
from bpp.tests import normalize_html
from pbn_api.models import Publication

TEST_PBN_ID = 50000

Expand Down Expand Up @@ -42,3 +42,74 @@ def test_Wydawnictwo_Zwarte_Admin_sprawdz_duplikaty_www_doi(admin_app, fld, valu
assert "inne rekordy z identycznym polem" in normalize_html(
res.content.decode("utf-8")
)


# Freshdesk #385: dziedziczenie wydawcy po wydawnictwie nadrzędnym (rozdziale).


def _form_z_pustym_cleaned_data():
"""Zwraca instancję formularza gotową do testu helpera dziedziczenia.

Helper ``_dziedzicz_wydawce_po_nadrzednym`` operuje wyłącznie na
przekazanym ``cleaned_data`` i ``self._warnings`` — nie wymaga
pełnego zbindowania formularza."""
form = Wydawnictwo_ZwarteForm()
form._warnings = []
return form


@pytest.mark.django_db
def test_dziedziczenie_wydawcy_rozdzial_bez_wlasnego_wydawcy(wydawca):
"""Rozdział bez własnego wydawcy dziedziczy wydawcę po nadrzędnym."""
nadrzedne = baker.make(
Wydawnictwo_Zwarte, tytul_oryginalny="Monografia", wydawca=wydawca
)

form = _form_z_pustym_cleaned_data()
cleaned_data = {"wydawca": None}
form._dziedzicz_wydawce_po_nadrzednym(cleaned_data, nadrzedne)

assert cleaned_data["wydawca"] == wydawca
assert form._warnings # operator dostaje informację o dziedziczeniu


@pytest.mark.django_db
def test_dziedziczenie_wydawcy_nie_nadpisuje_jawnie_podanego(wydawca):
"""Jawnie wpisany wydawca NIE jest nadpisywany wydawcą nadrzędnego."""
inny_wydawca = Wydawca.objects.create(nazwa="Inny Wydawca")
nadrzedne = baker.make(
Wydawnictwo_Zwarte, tytul_oryginalny="Monografia", wydawca=wydawca
)

form = _form_z_pustym_cleaned_data()
cleaned_data = {"wydawca": inny_wydawca}
form._dziedzicz_wydawce_po_nadrzednym(cleaned_data, nadrzedne)

assert cleaned_data["wydawca"] == inny_wydawca
assert not form._warnings


@pytest.mark.django_db
def test_dziedziczenie_wydawcy_nadrzedne_bez_wydawcy_nic_nie_robi():
"""Gdy nadrzędne nie ma wydawcy — pole pozostaje puste, bez ostrzeżeń."""
nadrzedne = baker.make(
Wydawnictwo_Zwarte, tytul_oryginalny="Monografia", wydawca=None
)

form = _form_z_pustym_cleaned_data()
cleaned_data = {"wydawca": None}
form._dziedzicz_wydawce_po_nadrzednym(cleaned_data, nadrzedne)

assert cleaned_data["wydawca"] is None
assert not form._warnings


@pytest.mark.django_db
def test_dziedziczenie_wydawcy_brak_nadrzednego_nic_nie_robi(wydawca):
"""Bez wydawnictwa nadrzędnego (nie-rozdział) nic się nie dzieje."""
form = _form_z_pustym_cleaned_data()
cleaned_data = {"wydawca": None}
form._dziedzicz_wydawce_po_nadrzednym(cleaned_data, None)

assert cleaned_data["wydawca"] is None
assert not form._warnings
Loading