{% extends "utilities/_base.html" %} {% from "components/job_section.html" import job_section with context %} {% from "components/run_history.html" import run_history_list with context %} {% from "components/page_header.html" import page_header %} {% from "components/issue_card.html" import issue_card %} {% block title %}{{ _("Library Health - Library - Yaffo") }}{% endblock %} {% block utility_content %}
{% set header_actions %} {# Always available: unlike the status fixes, this re-runs indexing on files already indexed — a rebuild, not a reconcile. It re-detects faces, so it confirms the loss of person assignments first. #} {% endset %} {{ page_header( _('Library Health'), _('Compare photos on the file system with the database'), actions=header_actions, ) }} {% if warnings|length > 0 %}
{% for warning in warnings %}
{{ warning.message }} {% if warning.type == 'error' %} {{ _("Go to Settings") }} {% endif %}
{% endfor %}
{% endif %} {# The latest import and index runs while in progress. One that finishes while the page is open keeps its card until reload, then it's in the run history, so no Dismiss (it deletes the job). #} {{ job_section(in_progress_jobs, show_cancel=true, show_dismiss=false) }} {% if media_dirs|length > 0 %}
{{ _("Total on Filesystem") }}
—
{{ _("Imported in Database") }}
—
{{ _("Indexed in Database") }}
—
{{ _("Not Indexed") }}
—
{{ _("Orphaned in DB") }}
—
{{ _("Missing Thumbnails") }}
—
{% endif %} {# What needs attention, one card per problem with its own fix. The scan fills the first three; files that couldn't be indexed are known up front. "Everything is in sync" shows only once the scan found nothing and nothing failed. #} {% if media_dirs|length > 0 or failed_count %}

{{ _("Library status") }}

{{ issue_card('unindexed', description=_("New files in your media folders that aren't in the library yet."), action_id='index-new-button', action_label=_("Index them"), has_files=true) }} {{ issue_card('orphaned', description=_("Library entries whose file was deleted, or whose media folder was removed from Settings. Removing them also removes their faces."), action_id='remove-orphaned-button', action_label=_("Remove them"), has_files=true) }} {{ issue_card('missing-thumbnails', description=_("Face crops and video posters are gone from the thumbnail folder, so they show as broken images. Regenerating writes them again from your photos and videos; faces keep their people."), action_id='regenerate-thumbnails-button', action_label=_("Regenerate thumbnails")) }} {% call issue_card('failed', title=ngettext("%(num)d file couldn't be indexed", "%(num)d files couldn't be indexed", failed_count), description=_("They still show in your library, but without the date, location, faces or labels that indexing reads. Yaffo leaves them alone until a file changes; retry after fixing a file or updating Yaffo."), action_id='retry-failed-button', action_label=_("Retry all"), has_files=true, shown=failed_count > 0) %}
    {% for item in failed_media %}
  • {{ item.file_name }} {{ item.folder }} {{ item.reason }}
  • {% endfor %}
{% if failed_count > failed_media|length %}

{{ ngettext("and %(num)d more", "and %(num)d more", failed_count - failed_media|length) }}

{% endif %} {% endcall %}
{% endif %} {% if media_dirs|length == 0 %}

{{ _("No Media Directories Configured") }}

{% trans settings_url=url_for('settings_index') %} Please configure media directories in Settings to start indexing photos. {% endtrans %}

{% endif %} {% if run_history %}

{{ _("Run history") }}

{{ run_history_list(run_history, url_for('utilities_index_photos'), show_label=true) }}
{% endif %}
{% endblock %} {% block scripts %} {% endblock %}