Photo Gallery API

Examples below mirror current production patterns in Project, Issue, Job and Installation surfaces.

For recipes intended for future AI/LLM edits, see README in this folder.

Example 1: Basic file_gallery (preview + mixed image/PDF)

Files
roof-overview.jpg · Otovo agent
roof-overview.jpg
inverter-closeup.jpg · Installer
inverter-closeup.jpg
meter-room.jpg · Otovo agent
meter-room.jpg
completion-report.pdf · Otovo agent
PDF
completion-report.pdf
{% from "rainbow/components/photos/file_gallery.html" import file_gallery %}
{{ file_gallery(
  files=files,
  id_prefix='my-gallery',
  request_app=request.app,
  show_preview=true,
  show_upload_tile=false,
  file_url_attr='file_url',
  file_url_method='',
  file_mimetype_attr='mimetype',
) }}

Example 2: Remove vs Delete semantics (Issue-style)

Issue photos
roof-overview.jpg · Otovo agent
roof-overview.jpg
inverter-closeup.jpg · Installer
inverter-closeup.jpg
meter-room.jpg · Otovo agent
meter-room.jpg
completion-report.pdf · Otovo agent
PDF
completion-report.pdf
{% macro issue_tile_footer(file) %}
  {% set is_project_origin = file.id in project_photo_ids %}
  {% call file_gallery_actions_dropdown() %}
    {{ file_gallery_delete_action(
      label=_("Remove file") if is_project_origin else _("Delete file"),
      delete_url=url('issues:detach-photo', args=(issue.pk, file.pk)),
      dialog_title=_("Remove file") if is_project_origin else _("Delete file"),
      confirm_label=_("Remove") if is_project_origin else _("Delete"),
      htmx_target='#issue-photo-gallery-card',
      htmx_swap='outerHTML',
    ) }}
  {% endcall %}
{% endmacro %}

Example 3: Attach dialog selection controls (Issue/Job create pattern)

Use these two includes together for attach flows: controls + selectable gallery.
Select photos to attach: ,
{% set gallery_id = "issue-project-photo-gallery" %}
{% include "rainbow/components/photos/file_gallery_select_controls.html" %}

{% set files = project_photos|map(attribute='photo')|list %}
{% set checkbox_name = "photo_id" %}
{% set selected_ids = selected_photo_ids %}
{% set attached_ids = selected_photo_ids %}
{% set show_attached_badge = true %}
{% include "rainbow/components/photos/selectable_file_gallery.html" %}