Repository: iiif-prezi/iiif-prezi3

Issue:
make_manifest() helper on Collection drops homepage property when provided
### Expected behaviour:

In order to use `iiif-prezi3` to easily iterate over a list of manifests and create a new Collection manifest, I'd like to use the make_manifest() helper. Doing something simple like this should allow me to create a list of manifests with an id, label, homepage, and thumbnail.

```
        for document in self.iiif_works:
            collection.make_manifest(
                id=document['manifest'],
                label={'en': document['sourceResource']['title']},
                homepage=[{
                    'id': document['isShownAt'],
                    'label': {'en': document['sourceResource']['title']},
                    'type': 'Text',
                    "language": ["en"],
                    "format": "text/html"}],
                thumbnail={
                    'id': document['object'].replace('http://', 'https://'),
                    "type": "Image",
                    "format": "image/jpeg"
                }
            )
```

### Observed behaviour:

Unfortunately, when using this helper method, the homepage property is always dropped from the resulting `Collection`.

### Potential bug location(s):
<!-- Optional: Links to code potentially causing this issue -->

### Any other comments:

A thread about this was brought up a few days ago here:
https://iiif.slack.com/archives/C04EWD70FCH/p1696253869888859

Hints from issue comments:
@glenrobson: Glen to check schema@markpbaggett: @glenrobson I finally had some time to revisit this during lunch.  I don't think it's the schema and here is why:

If I take collection json like this:

```
example={
  "@context": "http://iiif.io/api/presentation/3/context.json",
  "id": "https://digital.lib.utk.edu/assemble/metadata/subject/Cats",
  "type": "Collection",
  "label": {
    "none": [
      "Items about \"Cats\""
    ]
  },
  "items": [
    {
      "id": "https://digital.lib.utk.edu/assemble/manifest/rftaart/42",
      "type": "Manifest",
      "label": {
        "none": [
          "Topper"
        ]
      },
      "homepage": [
        {
          "id": "https://digital.lib.utk.edu/collections/islandora/object/rftaart:42",
          "label": {
            "en": [
              "Topper"
            ]
          },
          "type": "Text",
          "format": "text/html"
        }
      ]
    },
    {
      "id": "https://digital.lib.utk.edu/assemble/manifest/rftaart/51",
      "type": "Manifest",
      "label": {
        "none": [
          "Topper"
        ]
      },
      "homepage": [
        {
          "id": "https://digital.lib.utk.edu/collections/islandora/object/rftaart:51",
          "label": {
            "en": [
              "Topper"
            ]
          },
          "type": "Text",
          "format": "text/html"
        }
      ]
    },
  ],
  "homepage": [
    {
      "id": "https://projectmirador.org/embed/?iiif-content=https://digital.lib.utk.edu/assemble/metadata/subject/Cats",
      "type": "Text",
      "label": {
        "en": [
          "View Collection in Mirador"
        ]
      },
      "format": "text/html"
    }
  ]
}
```

and pass it to `Collection` like this:

```
example_as_collection=Collection(**example)
print(example_as_collection)
```

I get this:

```
id=Id(__root__=AnyUrl('https://digital.lib.utk.edu/assemble/metadata/subject/Cats', scheme='https', host='digital.lib.utk.edu', tld='edu', host_type='domain', path='/assemble/metadata/subject/Cats')) type='Collection' label=LngString(__root__={'none': ['Items about "Cats"']}) metadata=None summary=None requiredStatement=None rendering=None rights=None navDate=None navPlace=None provider=None seeAlso=None services=None service=None placeholderCanvas=None accompanyingCanvas=None thumbnail=None homepage=Homepage(__root__=[HomepageItem(id=Id(__root__=AnyUrl('https://projectmirador.org/embed/?iiif-content=https://digital.lib.utk.edu/assemble/metadata/subject/Cats', scheme='https', host='projectmirador.org', tld='org', host_type='domain', path='/embed/', query='iiif-content=https://digital.lib.utk.edu/assemble/metadata/subject/Cats')), type='Text', label=LngString(__root__={'en': ['View Collection in Mirador']}), format=Format(__root__='text/html'), language=None)]) behavior=None partOf=None items=[ManifestRef(id=Id(__root__=AnyUrl('https://digital.lib.utk.edu/assemble/manifest/rftaart/42', scheme='https', host='digital.lib.utk.edu', tld='edu', host_type='domain', path='/assemble/manifest/rftaart/42')), label=LngString(__root__={'none': ['Topper']}), type='Manifest', thumbnail=None, homepage=[{'id': 'https://digital.lib.utk.edu/collections/islandora/object/rftaart:42', 'label': {'en': ['Topper']}, 'type': 'Text', 'format': 'text/html'}]), ManifestRef(id=Id(__root__=AnyUrl('https://digital.lib.utk.edu/assemble/manifest/rftaart/51', scheme='https', host='digital.lib.utk.edu', tld='edu', host_type='domain', path='/assemble/manifest/rftaart/51')), label=LngString(__root__={'none': ['Topper']}), type='Manifest', thumbnail=None, homepage=[{'id': 'https://digital.lib.utk.edu/collections/islandora/object/rftaart:51', 'label': {'en': ['Topper']}, 'type': 'Text', 'format': 'text/html'}])] annotations=None
```

If it were a schema problem, wouldn't it get dropped here too?


Solution patch:
diff --git a/docs/recipes/0266-full-canvas-annotation.md b/docs/recipes/0266-full-canvas-annotation.md
new file mode 100644
index 0000000..ca1c7ab
--- /dev/null
+++ b/docs/recipes/0266-full-canvas-annotation.md
@@ -0,0 +1,10 @@
+# Simplest Annotation
+|              | **Cookbook URLs** |
+|--------------|-------------------|
+| **Recipe:**  | [https://iiif.io/api/cookbook/recipe/0266-full-canvas-annotation/](https://iiif.io/api/cookbook/recipe/0266-full-canvas-annotation/) |
+| **JSON-LD:** | [https://iiif.io/api/cookbook/recipe/0266-full-canvas-annotation/manifest.json](https://iiif.io/api/cookbook/recipe/0266-full-canvas-annotation/manifest.json) |
+
+### Method 1 - Use make_annotation() helper
+```python
+--8<-- "docs/recipes/scripts/0266-full-canvas-annotation-method1.py"
+```
\ No newline at end of file
diff --git a/docs/recipes/scripts/0266-full-canvas-annotation-method1.py b/docs/recipes/scripts/0266-full-canvas-annotation-method1.py
new file mode 100644
index 0000000..ae23493
--- /dev/null
+++ b/docs/recipes/scripts/0266-full-canvas-annotation-method1.py
@@ -0,0 +1,52 @@
+from iiif_prezi3 import Manifest, ResourceItem, ResourceItem1, AnnotationPage, Annotation, config
+
+config.configs['helpers.auto_fields.AutoLang'].auto_lang = "en"
+base_url = "https://iiif.io/api/cookbook/recipe/0266-full-canvas-annotation"
+
+manifest = Manifest(
+    id=f"{base_url}/manifest.json",
+    label="Picture of Göttingen taken during the 2019 IIIF Conference",
+)
+
+anno_page = AnnotationPage(
+    id=f"{base_url}/canvas-1/annopage-1"
+)
+painting_body = ResourceItem(
+    id="https://iiif.io/api/image/3.0/example/reference/918ecd18c2592080851777620de9bcb5-gottingen/full/max/0/default.jpg",
+    type="Image",
+    format="image/jpeg",
+)
+painting_body.make_service(
+    id="https://iiif.io/api/image/3.0/example/reference/918ecd18c2592080851777620de9bcb5-gottingen",
+    type="ImageService3",
+    profile="level1"
+)
+painting_anno = Annotation(
+    id=f"{base_url}/canvas-1/annopage-1/anno-1",
+    motivation="painting",
+    body=painting_body,
+    target=f"{base_url}/canvas-1"
+)
+anno_page.add_item(painting_anno)
+hw = {"height": 3024, "width": 4032}
+canvas = manifest.make_canvas(
+    id=f"{base_url}/canvas-1",
+)
+painting_body.set_hwd(**hw)
+canvas.set_hwd(**hw)
+canvas.add_item(anno_page)
+anno_body = ResourceItem1(
+    type="TextualBody",
+    language="de",
+    format="text/plain",
+    value="Göttinger Marktplatz mit Gänseliesel Brunnen"
+)
+anno = canvas.make_annotation(
+    id=f"{base_url}/canvas-1/annopage-2/anno-1",
+    motivation="commenting",
+    body=anno_body,
+    target=canvas.id,
+    anno_page_id=f"{base_url}/canvas-1/annopage-2"
+)
+
+print(manifest.json(indent=2))
diff --git a/iiif_prezi3/helpers/auto_fields.py b/iiif_prezi3/helpers/auto_fields.py
index 5fbaf6e..58611ef 100644
--- a/iiif_prezi3/helpers/auto_fields.py
+++ b/iiif_prezi3/helpers/auto_fields.py
@@ -2,8 +2,8 @@ import uuid
 
 from ..config.config import Config, register_config
 from ..skeleton import (AnnotationPage, Canvas, Class, HomepageItem,
-                        KeyValueString, NavPlace, ProviderItem, Range,
-                        Reference, ResourceItem, ServiceItem1)
+                        KeyValueString, ManifestRef, NavPlace, ProviderItem,
+                        Range, Reference, ResourceItem, ServiceItem1)
 
 
 class AutoConfig(Config):
@@ -179,8 +179,8 @@ ait = AutoItems(aitcfg)
 alst = AutoList(alstcfg, name="General")
 allst = AutoList(allstcfg, name="Language")
 # Set up some obvious defaults
-ai.register_on_class(AnnotationPage, Class)
-al.register_on_class(KeyValueString, Class, Reference, ResourceItem)
+ai.register_on_class(AnnotationPage, Class, ManifestRef)
+al.register_on_class(KeyValueString, Class, Reference, ResourceItem, ManifestRef)
 ait.register_on_class(Canvas, Range, AnnotationPage)
 alst.register_on_class(Class, AnnotationPage, ResourceItem, ServiceItem1, NavPlace, Reference, ProviderItem)
 allst.register_on_class(HomepageItem)
diff --git a/iiif_prezi3/helpers/make_manifest.py b/iiif_prezi3/helpers/make_manifest.py
index fe6db55..742e65e 100644
--- a/iiif_prezi3/helpers/make_manifest.py
+++ b/iiif_prezi3/helpers/make_manifest.py
@@ -1,19 +1,19 @@
 from ..loader import monkeypatch_schema
-from ..skeleton import Collection, Manifest
+from ..skeleton import Collection, ManifestRef
 
 
 class MakeManifest:
 
     def make_manifest(self, **kwargs):
-        """Add a Manifest to a Collection.
+        """Add a Manifest to a Collection as a ManifestRef.
 
         Creates a new Manifest, adds a Reference to it to the
         calling Collection items and returns the newly created Manifest.
         Accepts keyword arguments to customize the resulting instance.
         """
-        manifest = Manifest(**kwargs)
+        manifest = ManifestRef(**kwargs)
         self.add_item(manifest)
-        return manifest
 
+        return manifest
 
 monkeypatch_schema(Collection, MakeManifest)


Test patch:
diff --git a/tests/test_make_manifest.py b/tests/test_make_manifest.py
index 1c180d2..712c8eb 100644
--- a/tests/test_make_manifest.py
+++ b/tests/test_make_manifest.py
@@ -1,6 +1,6 @@
 import unittest
 
-from iiif_prezi3 import Collection, Reference
+from iiif_prezi3 import Collection, HomepageItem, Reference, config
 
 
 class MakeManifestTest(unittest.TestCase):
@@ -9,9 +9,21 @@ class MakeManifestTest(unittest.TestCase):
         self.collection = Collection()
 
     def test_make_manifest(self):
+        config.configs['helpers.auto_fields.AutoLang'].auto_lang = "en"
+        homepage = HomepageItem(
+            id="https://www.getty.edu/art/collection/object/103RQQ",
+            type="Text",
+            label="Home page at the Getty Museum Collection",
+            format="text/html",
+            language=["en"]
+        )
         manifest = self.collection.make_manifest(
-            label={'en': ['default label']})
+            id='http://example.org/iiif/1',
+            label='default label',
+            homepage=homepage,
+        )
         self.assertEqual(len(self.collection.items), 1)
         self.assertIsInstance(self.collection.items[0], Reference)
         self.assertEqual(manifest.label,
                          {'en': ['default label']})
+        self.assertEqual(manifest.homepage, homepage)