diff --git a/src/open_inwoner/openklant/admin.py b/src/open_inwoner/openklant/admin.py index bca5941f29..7d8a54a124 100644 --- a/src/open_inwoner/openklant/admin.py +++ b/src/open_inwoner/openklant/admin.py @@ -5,7 +5,13 @@ from ordered_model.admin import OrderedInlineModelAdminMixin, OrderedTabularInline from solo.admin import SingletonModelAdmin -from .models import ContactFormSubject, KlantContactMomentAnswer, OpenKlantConfig +from .models import ( + ContactFormSubject, + KlantContactMomentAnswer, + KlantenInteractiesConfig, + OpenKlant2Config2, + OpenKlantConfig, +) class ContactFormSubjectForm(forms.ModelForm): @@ -49,8 +55,8 @@ def clean(self, *args, **kwargs): self.add_error(field_name, msg) -@admin.register(OpenKlantConfig) -class OpenKlantConfigAdmin(OrderedInlineModelAdminMixin, SingletonModelAdmin): +class OpenKlantConfigAdmin(admin.StackedInline): + model = OpenKlantConfig form = OpenKlantConfigAdminForm inlines = [ ContactFormSubjectInlineAdmin, @@ -108,3 +114,54 @@ class KlantContactMomentAnswerAdmin(admin.ModelAdmin): ] list_filter = ["is_seen"] list_display = ["user", "contactmoment_url", "is_seen"] + + +# +# OpenKlant2 +# + + +class OpenKlant2ConfigAdminForm(forms.ModelForm): + class Meta: + model = OpenKlantConfig + fields = "__all__" + + +class OpenKlant2Config2Admin(admin.StackedInline): + model = OpenKlant2Config2 + form = OpenKlant2ConfigAdminForm + fieldsets = [ + ( + _("API configuration"), + { + "fields": [ + "api_root", + "api_token", + ] + }, + ), + ( + _("Vragen"), + { + "fields": [ + "mijn_vragen_kanaal", + "mijn_vragen_organisatie_naam", + "mijn_vragen_actor", + "interne_taak_gevraagde_handeling", + "interne_taak_toelichting", + ] + }, + ), + ] + + class Media: + css = {"all": ("css/custom_admin.css",)} + + +@admin.register(KlantenInteractiesConfig) +class KlantenInteractiesConfigAdmin(OrderedInlineModelAdminMixin, SingletonModelAdmin): + inlines = [ + OpenKlant2Config2Admin, + OpenKlantConfigAdmin, + ContactFormSubjectInlineAdmin, + ] diff --git a/src/open_inwoner/openklant/migrations/0015_klanteninteractiesconfig_and_more.py b/src/open_inwoner/openklant/migrations/0015_klanteninteractiesconfig_and_more.py new file mode 100644 index 0000000000..1ebb6fb7d3 --- /dev/null +++ b/src/open_inwoner/openklant/migrations/0015_klanteninteractiesconfig_and_more.py @@ -0,0 +1,100 @@ +# Generated by Django 4.2.16 on 2024-12-05 11:49 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("openklant", "0014_contactformconfig"), + ] + + operations = [ + migrations.CreateModel( + name="KlantenInteractiesConfig", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ], + options={ + "verbose_name": "Configuratie Klanten Interacties", + }, + ), + migrations.AlterModelOptions( + name="openklantconfig", + options={"verbose_name": "Esuite configuration"}, + ), + migrations.CreateModel( + name="OpenKlant2Config2", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("api_root", models.URLField(verbose_name="API root url")), + ("api_token", models.CharField(verbose_name="API key token")), + ( + "mijn_vragen_kanaal", + models.CharField(verbose_name="Mijn vragen kanaal"), + ), + ( + "mijn_vragen_organisatie_naam", + models.CharField(verbose_name="Mijn vragen organisatie naam"), + ), + ( + "mijn_vragen_actor", + models.CharField(verbose_name="Mijn vragen actor"), + ), + ( + "interne_taak_gevraagde_handeling", + models.CharField(verbose_name="Interne taak gevraagde handeling"), + ), + ( + "interne_taak_toelichting", + models.CharField(verbose_name="Interne taak toelichting"), + ), + ( + "config", + models.OneToOneField( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="openklant.klanteninteractiesconfig", + ), + ), + ], + options={ + "verbose_name": "Open Klant configuration", + }, + ), + migrations.AddField( + model_name="openklantconfig", + name="config", + field=models.OneToOneField( + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="openklant.klanteninteractiesconfig", + ), + ), + migrations.AlterField( + model_name="contactformsubject", + name="config", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="openklant.klanteninteractiesconfig", + ), + ), + ] diff --git a/src/open_inwoner/openklant/models.py b/src/open_inwoner/openklant/models.py index c1d0029910..1dc2652401 100644 --- a/src/open_inwoner/openklant/models.py +++ b/src/open_inwoner/openklant/models.py @@ -115,6 +115,13 @@ class OpenKlantConfig(SingletonModel): validators=[validate_array_contents_non_empty], ) + # FK for easy inline admins + config = models.OneToOneField( + "KlantenInteractiesConfig", + null=True, + on_delete=models.CASCADE, + ) + register_api_required_fields = ( "register_contact_moment", "contactmomenten_service", @@ -126,7 +133,7 @@ class OpenKlantConfig(SingletonModel): objects = OpenKlantConfigManager() class Meta: - verbose_name = _("Open Klant configuration") + verbose_name = _("Esuite configuration") def has_register(self) -> bool: return self.register_email or self.has_api_configuration() @@ -150,7 +157,7 @@ class ContactFormSubject(OrderedModel): ) # FK for easy inline admins config = models.ForeignKey( - OpenKlantConfig, + "KlantenInteractiesConfig", on_delete=models.CASCADE, ) @@ -223,4 +230,45 @@ def from_django_settings(cls) -> Self: return cls(**config) - # TODO: add from_openklant_config_model or similar + +# TODO: rename after removing dataclass config +class OpenKlant2Config2(SingletonModel): + api_root = models.URLField( + verbose_name=_("API root url"), + ) + api_token = models.CharField( + verbose_name=_("API key token"), + ) + + # Vragen + mijn_vragen_kanaal = models.CharField( + verbose_name=_("Mijn vragen kanaal"), + ) + mijn_vragen_organisatie_naam = models.CharField( + verbose_name=_("Mijn vragen organisatie naam"), + ) + mijn_vragen_actor = models.CharField( + verbose_name=_("Mijn vragen actor"), + ) + interne_taak_gevraagde_handeling = models.CharField( + verbose_name=_("Interne taak gevraagde handeling"), + ) + interne_taak_toelichting = models.CharField( + verbose_name=_("Interne taak toelichting"), + ) + + # FK for admin inline + config = models.OneToOneField( + "KlantenInteractiesConfig", + null=True, + blank=True, + on_delete=models.CASCADE, + ) + + class Meta: + verbose_name = _("Open Klant configuration") + + +class KlantenInteractiesConfig(SingletonModel): + class Meta: + verbose_name = _("Configuratie Klanten Interacties") diff --git a/src/open_inwoner/scss/admin/_admin_inlines.scss b/src/open_inwoner/scss/admin/_admin_inlines.scss new file mode 100644 index 0000000000..545a8e6967 --- /dev/null +++ b/src/open_inwoner/scss/admin/_admin_inlines.scss @@ -0,0 +1,17 @@ +.inline-group { + margin-bottom: 16px; + + border: 1px solid #ddd; + border-radius: 5px; + + > fieldset > h2 { + margin-bottom: 5px; + background-color: #498fc9; + } +} + +.inline-related { + h3 { + display: none; + } +} diff --git a/src/open_inwoner/scss/admin/admin_overrides.scss b/src/open_inwoner/scss/admin/admin_overrides.scss index 2c988225bd..eaacb77a28 100644 --- a/src/open_inwoner/scss/admin/admin_overrides.scss +++ b/src/open_inwoner/scss/admin/admin_overrides.scss @@ -3,6 +3,7 @@ //Internal @import './admin_theme'; +@import './admin_inlines'; @import './app_overrides'; @import './ck_editor'; @import '../components/Map/Map.scss';