diff --git a/src/objects/core/admin.py b/src/objects/core/admin.py index 57cb47a6..3381d696 100644 --- a/src/objects/core/admin.py +++ b/src/objects/core/admin.py @@ -1,6 +1,11 @@ from django.contrib import admin from django.contrib.gis import forms from django.contrib.gis.db.models import GeometryField +from django.http import JsonResponse +from django.urls import path + +import requests +from zgw_consumers.client import build_client from .models import Object, ObjectRecord, ObjectType @@ -13,6 +18,32 @@ class ObjectTypeAdmin(admin.ModelAdmin): ) readonly_fields = ("_name",) + def get_urls(self): + urls = super().get_urls() + my_urls = [ + path( + "/versions/", + self.admin_site.admin_view(self.versions_view), + ) + ] + return my_urls + urls + + def versions_view(self, request, objecttype_id): + versions = {} + if objecttype := self.get_object(request, objecttype_id): + client = build_client(objecttype.service) + try: + response = client.get(objecttype.versions_url) + response_data = response.json() + + # TODO: remove check once API V1 is removed + if "results" in response_data: + versions = response_data["results"] + + except (requests.RequestException, requests.JSONDecodeError): + pass + return JsonResponse(versions, safe=False) + class ObjectRecordInline(admin.TabularInline): model = ObjectRecord diff --git a/src/objects/core/models.py b/src/objects/core/models.py index 03addf37..3ad77620 100644 --- a/src/objects/core/models.py +++ b/src/objects/core/models.py @@ -42,6 +42,10 @@ def url(self): # zds_client.get_operation_url() can be used here but it increases HTTP overhead return f"{self.service.api_root}objecttypes/{self.uuid}" + @property + def versions_url(self): + return f"{self.url}/versions" + def clean_fields(self, exclude: Iterable[str] | None = None) -> None: super().clean_fields(exclude=exclude) diff --git a/src/objects/js/components/admin/permissions/auth-fields.js b/src/objects/js/components/admin/permissions/auth-fields.js index 95249ebf..e421345d 100644 --- a/src/objects/js/components/admin/permissions/auth-fields.js +++ b/src/objects/js/components/admin/permissions/auth-fields.js @@ -61,14 +61,6 @@ const authFields = (object_fields, dataFields, fields, setFields) => { }; const versionAuthFields = (objectType, objectFields, dataFieldChoices, fields, setFields) => { - if (!(objectType in dataFieldChoices)) { - return ( -
-

To be able to select fields, first you must save the instance and then you can edit the fields!

-

Click on button 'Save and continue editing'

-
- ); - } const dataFields = dataFieldChoices[objectType]; const objecttypeVersions = Object.entries(dataFieldChoices).reduce((acc, [k, v]) => { diff --git a/src/objects/js/components/admin/permissions/index.js b/src/objects/js/components/admin/permissions/index.js index f2a7f22a..ea25a390 100644 --- a/src/objects/js/components/admin/permissions/index.js +++ b/src/objects/js/components/admin/permissions/index.js @@ -12,7 +12,6 @@ const mount = () => { ReactDOM.render( { +const PermissionForm = ({objectFields, tokenChoices, objecttypeChoices, modeChoices, formData}) => { const {values, errors} = formData; const [mode, setMode] = useState(values["mode"]); const [useFields, setUseFields] = useState(values["use_fields"]); const [objectType, setObjectType] = useState(values["object_type"]); if (!values["fields"]) { values["fields"] = "{}" - } + } + const [fields, setFields] = useState( JSON.parse(values["fields"]) || {}) + const [dataFieldChoices, setDataFieldChoices] = useState(dataFieldChoices); + const fetchObjecttypeVersions = (objecttype_id) => { + fetch(`/admin/core/objecttype/`+ objecttype_id +`/versions/`, { + method: 'GET', + }) + .then(response => response.json()) + .then(response_data => { + const objecttypes = { + [objecttype_id]: response_data.reduce((acc, version) => { + const properties = Object.keys(version.jsonSchema?.properties || {}); + acc[version.version] = properties.reduce((propsAcc, prop) => { + propsAcc[prop] = `record__data__${prop}`; + return propsAcc; + }, {}); + return acc; + }, {}) + }; + setDataFieldChoices(objecttypes); + }) + .catch(error => { + console.error('An error occurred while fetching the Objecttype versions endpoint:', error); + }); + }; + useEffect(() => { + if (objectType) { + fetchObjecttypeVersions(objectType); + } + }, [objectType]); + return (
@@ -37,6 +67,7 @@ const PermissionForm = ({objectFields, dataFieldChoices, tokenChoices, objecttyp errors={errors["object_type"]} onChange={(value) => { setObjectType(value); + fetchObjecttypeVersions(value); setFields({}); }} /> @@ -78,7 +109,7 @@ const PermissionForm = ({objectFields, dataFieldChoices, tokenChoices, objecttyp value={useFields ? JSON.stringify(fields) : ""} /> - { useFields ? + { useFields && dataFieldChoices && objectType in dataFieldChoices ?
diff --git a/src/objects/templates/admin/token/permission/change_form.html b/src/objects/templates/admin/token/permission/change_form.html index 3b62f619..9cdf2249 100644 --- a/src/objects/templates/admin/token/permission/change_form.html +++ b/src/objects/templates/admin/token/permission/change_form.html @@ -5,7 +5,6 @@ {# Inject backend-controlled constants/content into the frontend state #} {{ object_fields|json_script:"object-fields" }} - {{ data_field_choices|json_script:"data-field-choices" }} {{ token_auth_choices|json_script:"token-auth-choices" }} {{ object_type_choices|json_script:"object-type-choices" }} {{ mode_choices|json_script:"mode-choices" }} diff --git a/src/objects/token/admin.py b/src/objects/token/admin.py index 2b5b79f0..3160567d 100644 --- a/src/objects/token/admin.py +++ b/src/objects/token/admin.py @@ -36,35 +36,6 @@ def get_object_fields(self): object_fields = build_spec(get_field_names(object_serializer.fields), ui=True) return object_fields - def get_data_field_choices(self, object_type_id): - data_fields = {} - object_type = ObjectType.objects.filter(id=object_type_id).first() - if not object_type: - return data_fields - - client = build_client(object_type.service) - try: - response = client.get(f"{object_type.url}/versions") - response_data = response.json() - - # TODO: remove check once API V1 is removed - if "results" in response_data: - response_data = response_data["results"] - - # use only first level of properties - data_fields[object_type_id] = { - version["version"]: { - prop: f"record__data__{prop}" - for prop in list(version["jsonSchema"].get("properties", {}).keys()) - } - for version in response_data - } - - except (requests.RequestException, requests.JSONDecodeError): - pass - - return data_fields - def get_form_data(self, request, object_id) -> dict: obj = self.get_object(request, unquote(object_id)) if object_id else None ModelForm = self.get_form(request, obj, change=not obj) @@ -96,20 +67,13 @@ def get_extra_context(self, request, object_id): (object_type.pk, str(object_type)) for object_type in ObjectType.objects.all() ] - objecttypes_available = can_connect_to_objecttypes() - data_field_choices = {} - obj = self.get_object(request, unquote(object_id)) if object_id else None - if objecttypes_available and obj and obj.object_type: - data_field_choices = self.get_data_field_choices(obj.object_type.id) - return { "object_fields": self.get_object_fields(), - "data_field_choices": data_field_choices, "token_auth_choices": token_auth_choices, "object_type_choices": object_type_choices, "mode_choices": mode_choices, "form_data": self.get_form_data(request, object_id), - "objecttypes_available": objecttypes_available, + "objecttypes_available": can_connect_to_objecttypes(), } def change_view(self, request, object_id, form_url="", extra_context=None):