Repository: comic/grand-challenge.org

Issue:
FlexibleImageWidget does not show selected image when prepopulated 
**Describe the bug**
If an archive item or display set has an image CIV attached and the user wants to edit the item, the `FlexibleImageWidget` appears empty; as if no image was attached to the item. 

**To Reproduce**
Steps to reproduce the behavior:
1. Go to a display set edit view that has images attached, e.g.: https://grand-challenge.org/reader-studies/cirruscoreweb-release-default-answers/display-sets/d6a7c22b-b029-4775-a223-bde806c9cfb8/update/
2. The widget for the generic medical image interface appears empty: 
![image](https://github.com/comic/grand-challenge.org/assets/30069334/0e4af459-8132-41a0-9b73-e17ca343be8f)

**Expected behavior**
It should be clear that there already is an image for this interface on the display set / archive item. 
Either like this (this is what it looks like when you select an image)
![image](https://github.com/comic/grand-challenge.org/assets/30069334/79be7e28-c7b1-4855-9629-8f84945ce12c)
or alternatively a select with the chosen image (similar to how we do it for file interfaces), needs to be investigated what is easier to implement:
![image](https://github.com/comic/grand-challenge.org/assets/30069334/0c89688d-7540-4036-8f1c-dfb58b4402df)



Discussion:

Resolving patch:
diff --git a/app/grandchallenge/components/form_fields.py b/app/grandchallenge/components/form_fields.py
--- a/app/grandchallenge/components/form_fields.py
+++ b/app/grandchallenge/components/form_fields.py
@@ -1,6 +1,7 @@
 from django import forms
 
 from grandchallenge.cases.widgets import FlexibleImageWidget
+from grandchallenge.components.models import ComponentInterfaceValue
 from grandchallenge.components.schemas import INTERFACE_VALUE_SCHEMA
 from grandchallenge.core.guardian import get_objects_for_user
 from grandchallenge.core.validators import JSONValidator
@@ -45,7 +46,20 @@ def __init__(
     ):
         kwargs = {"required": required, "disabled": disabled}
 
-        if initial is not None:
+        if isinstance(initial, ComponentInterfaceValue) and initial.has_value:
+            if instance.is_image_kind:
+                kwargs["initial"] = initial.image.pk
+            elif instance.requires_file:
+                # for file interfaces, initial will either be None or
+                # the UUID of an upload, not an existing CIV, for the latter
+                # we use a different widget that is defined in MultipleCIVForm
+                kwargs["initial"] = initial
+            else:
+                kwargs["initial"] = initial.value
+        elif initial is not None:
+            # in the AlgorithmJobCreateForm,
+            # the initial value is the default_value for the interface,
+            # not an existing CIV
             kwargs["initial"] = initial
 
         field_type = instance.default_field
@@ -54,6 +68,9 @@ def __init__(
             kwargs["widget"] = FlexibleImageWidget(
                 help_text=help_text,
                 user=user,
+                current_value=initial,
+                # also passing the CIV as current value here so that we can
+                # show the image name to the user rather than its pk
             )
             upload_queryset = get_objects_for_user(
                 user,
diff --git a/app/grandchallenge/components/forms.py b/app/grandchallenge/components/forms.py
--- a/app/grandchallenge/components/forms.py
+++ b/app/grandchallenge/components/forms.py
@@ -233,8 +233,6 @@ def _get_select_upload_widget_field(
         )
 
     def _get_default_field(self, *, interface, current_value):
-        if isinstance(current_value, ComponentInterfaceValue):
-            current_value = current_value.value
         return InterfaceFormField(
             instance=interface,
             initial=current_value,


Test patch:
diff --git a/app/tests/cases_tests/test_widget.py b/app/tests/cases_tests/test_widget.py
--- a/app/tests/cases_tests/test_widget.py
+++ b/app/tests/cases_tests/test_widget.py
@@ -3,10 +3,14 @@
 from guardian.shortcuts import assign_perm
 
 from grandchallenge.cases.widgets import FlexibleImageField, WidgetChoices
+from grandchallenge.components.form_fields import InterfaceFormField
 from grandchallenge.components.models import ComponentInterface
 from grandchallenge.core.guardian import get_objects_for_user
 from grandchallenge.uploads.models import UserUpload
-from tests.components_tests.factories import ComponentInterfaceFactory
+from tests.components_tests.factories import (
+    ComponentInterfaceFactory,
+    ComponentInterfaceValueFactory,
+)
 from tests.factories import ImageFactory, UserFactory
 from tests.uploads_tests.factories import UserUploadFactory
 from tests.utils import get_view_for_user
@@ -143,3 +147,14 @@ def test_flexible_image_widget(client):
         },
     )
     assert response3.content == b""
+
+
+@pytest.mark.django_db
+def test_flexible_image_widget_prepopulated_value():
+    user = UserFactory()
+    im = ImageFactory(name="test_image")
+    ci = ComponentInterfaceFactory(kind=ComponentInterface.Kind.IMAGE)
+    civ = ComponentInterfaceValueFactory(interface=ci, image=im)
+    field = InterfaceFormField(instance=ci, user=user, initial=civ)
+    assert field.field.widget.attrs["current_value"] == civ
+    assert field.field.initial == civ.image.pk