defter 0.3.3

Self-hosted Zotero sync and file storage server, with metadata in SQLite and attachments in S3.
{% extends "base.html" %}

{% block title %}Library{% endblock %}

{% block content %}
{#- Rendered alone for htmx's poll (see ui::dashboard), which swaps it in
    place of itself every 30 seconds. -#}
{% block status %}
<div id="status" hx-get="/" hx-trigger="every 30s" hx-swap="outerHTML">
  <section class="space-y-2">
    <h1 class="text-2xl font-semibold tracking-tight">Library</h1>
    <p class="text-sm text-muted-foreground">
      Library version {{ status.version }} · user {{ status.user_id }} ·
      defter {{ status.defter_version }} · commonmeta {{ status.commonmeta_version }}
    </p>
  </section>

  <section class="mt-6 grid grid-cols-2 gap-3 sm:grid-cols-4">
    {%- for stat in status.stats %}
    <div class="rounded-lg border bg-card p-4">
      <div class="text-xs uppercase tracking-wide text-muted-foreground">{{ stat.label }}</div>
      <div class="mt-1 text-2xl font-semibold tabular-nums">{{ stat.value }}</div>
    </div>
    {%- endfor %}
  </section>

  <section class="mt-8 rounded-lg border bg-card p-5 space-y-2">
    <h2 class="font-semibold">Attachment storage</h2>
    <p class="text-sm"><code class="rounded bg-muted px-1.5 py-0.5">{{ status.storage_location }}</code></p>
    <p class="text-sm text-muted-foreground">
      {%- if status.signed_downloads %}
      Clients download files directly from the bucket through pre-signed URLs.
      {%- else %}
      Downloads are streamed through this server.
      {%- endif %}
      Files up to {{ status.max_upload }} are accepted.
    </p>
  </section>
</div>
{% endblock %}

<section class="mt-4 rounded-lg border bg-card p-5 space-y-3">
  <h2 class="font-semibold">Connect Zotero</h2>
  <p class="text-sm text-muted-foreground">
    Requires Zotero 10; only My Library is synced. In Zotero, open Settings → Advanced →
    Config Editor and set (keep the trailing slash):
  </p>
  <pre class="overflow-x-auto rounded-md bg-muted p-3 text-sm"><code>extensions.zotero.api.url = {{ status.api_url }}/
extensions.zotero.streaming.enabled = false</code></pre>
  <p class="text-sm text-muted-foreground">
    Restart Zotero, then log in under Settings → Sync and approve the login on this server with
    your API key.
  </p>
</section>

<section class="mt-4 rounded-lg border bg-card p-5 space-y-3">
  <h2 class="font-semibold">Enrich with commonmeta</h2>
  <p class="text-sm text-muted-foreground">
    commonmeta sync talks to the same API (see <code>docs/commonmeta-rs-changes.md</code> for the
    commonmeta release that supports a remote server):
  </p>
  <pre class="overflow-x-auto rounded-md bg-muted p-3 text-sm"><code>commonmeta sync --zotero-url {{ status.api_url }}</code></pre>
</section>
{% endblock %}