Skip to content

Commit

Permalink
[#464] Create endpoint objecttype versions_view + js call
Browse files Browse the repository at this point in the history
  • Loading branch information
danielmursa-dev committed Jan 7, 2025
1 parent f8cced2 commit 1dedca2
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 51 deletions.
31 changes: 31 additions & 0 deletions src/objects/core/admin.py
Original file line number Diff line number Diff line change
@@ -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

Expand All @@ -13,6 +18,32 @@ class ObjectTypeAdmin(admin.ModelAdmin):
)
readonly_fields = ("_name",)

def get_urls(self):
urls = super().get_urls()
my_urls = [
path(
"<int:objecttype_id>/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
Expand Down
4 changes: 4 additions & 0 deletions src/objects/core/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
8 changes: 0 additions & 8 deletions src/objects/js/components/admin/permissions/auth-fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,6 @@ const authFields = (object_fields, dataFields, fields, setFields) => {
};

const versionAuthFields = (objectType, objectFields, dataFieldChoices, fields, setFields) => {
if (!(objectType in dataFieldChoices)) {
return (
<div className="errornote">
<p>To be able to select fields, first you must save the instance and then you can edit the fields!</p>
<p>Click on button <strong>'Save and continue editing'</strong></p>
</div>
);
}

const dataFields = dataFieldChoices[objectType];
const objecttypeVersions = Object.entries(dataFieldChoices).reduce((acc, [k, v]) => {
Expand Down
1 change: 0 additions & 1 deletion src/objects/js/components/admin/permissions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ const mount = () => {
ReactDOM.render(
<PermissionForm
objectFields={jsonScriptToVar('object-fields')}
dataFieldChoices={jsonScriptToVar('data-field-choices')}
tokenChoices={jsonScriptToVar('token-auth-choices')}
objecttypeChoices={jsonScriptToVar('object-type-choices')}
modeChoices={jsonScriptToVar('mode-choices')}
Expand Down
39 changes: 35 additions & 4 deletions src/objects/js/components/admin/permissions/permission-form.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,49 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";

import { CheckboxInput, TextInput, SelectInput } from "../../forms/inputs";
import { versionAuthFields } from "./auth-fields";


const PermissionForm = ({objectFields, dataFieldChoices, tokenChoices, objecttypeChoices, modeChoices, formData}) => {
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 (
<fieldset className="module aligned">
<div className="form-row">
Expand All @@ -37,6 +67,7 @@ const PermissionForm = ({objectFields, dataFieldChoices, tokenChoices, objecttyp
errors={errors["object_type"]}
onChange={(value) => {
setObjectType(value);
fetchObjecttypeVersions(value);
setFields({});
}}
/>
Expand Down Expand Up @@ -78,7 +109,7 @@ const PermissionForm = ({objectFields, dataFieldChoices, tokenChoices, objecttyp
value={useFields ? JSON.stringify(fields) : ""}
/>

{ useFields ?
{ useFields && dataFieldChoices && objectType in dataFieldChoices ?

<div className="form-row">
<label htmlFor="id_selected_fields">Fields:</label>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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" }}
Expand Down
38 changes: 1 addition & 37 deletions src/objects/token/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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):
Expand Down

0 comments on commit 1dedca2

Please sign in to comment.