| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566 |
- {% extends "layout.twig" %}
- {% set errorMessages = {
- 'no_file': 'No file was uploaded.',
- 'too_big': 'The file is larger than 5 MB.',
- 'partial': 'The upload was interrupted. Try again.',
- 'upload_invalid': 'Upload validation failed.',
- 'not_xlsx': 'That doesn’t look like an .xlsx file.',
- 'parse_failed': 'Could not parse the workbook. Open it in Excel to confirm it’s not corrupted.',
- 'too_large_payload': 'The parsed workbook is too large for a preview session (limit: 2 MB). Split sheets or shorten task lists and try again.',
- 'expired': 'Your previous import session expired. Please upload again.',
- 'nothing_selected': 'No sheets were selected to import.',
- 'server': 'Server upload error.',
- 'size': 'File size is invalid.',
- 'unknown': 'Upload failed.',
- } %}
- {% block content %}
- <section class="max-w-2xl">
- <h1 class="text-2xl font-semibold tracking-tight">Import sprints from XLSX</h1>
- <p class="text-slate-600 mt-1 text-sm dark:text-slate-400">
- Upload the team’s <em>Tool_Sprint Planning</em> workbook. Each tab is parsed
- as one sprint; the next step lets you confirm targets, names, dates,
- and review the diff before committing.
- </p>
- {% if error != '' and errorMessages[error] is defined %}
- <div class="mt-4 rounded-md border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-800 dark:bg-red-900 dark:border-red-800 dark:text-red-200">
- {{ errorMessages[error] }}
- </div>
- {% endif %}
- <form method="post" action="/sprints/import" enctype="multipart/form-data"
- class="mt-6 space-y-4 rounded-lg border bg-white p-5 dark:bg-slate-800 dark:border-slate-700">
- <input type="hidden" name="_csrf" value="{{ csrfToken }}">
- <label class="block">
- <span class="text-sm text-slate-700 dark:text-slate-300">Workbook (.xlsx, max 5 MB)</span>
- <input type="file" name="xlsx" accept=".xlsx,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" required
- class="mt-1 block w-full text-sm text-slate-700 file:mr-3 file:rounded-md file:border-0 file:bg-slate-900 file:text-white file:px-3 file:py-2 dark:text-slate-200 dark:file:bg-slate-700">
- </label>
- <details class="text-sm text-slate-600 dark:text-slate-400">
- <summary class="cursor-pointer select-none">How are cell colours mapped to status?</summary>
- <ul class="mt-2 ml-5 list-disc space-y-1">
- <li>Greens (e.g. Excel “Green”, light pastel green) → <strong>abgeschlossen</strong>.</li>
- <li>Yellows and oranges → <strong>gestartet</strong>.</li>
- <li>Reds → <strong>abgebrochen</strong>.</li>
- <li>White, blue, or no fill → <strong>zugewiesen</strong> (default).</li>
- </ul>
- <p class="mt-2">Workers and tasks are matched to existing rows by name (case-insensitive).
- Anything not yet in the database is created.</p>
- </details>
- <div class="flex gap-3 pt-2">
- <button type="submit"
- class="rounded-md bg-slate-900 text-white px-4 py-2 text-sm font-medium hover:bg-slate-800 dark:bg-slate-700 dark:hover:bg-slate-600">
- Upload & preview
- </button>
- <a href="/" class="inline-flex items-center rounded-md border border-slate-300 bg-white text-slate-700 px-4 py-2 text-sm hover:bg-slate-100 dark:bg-slate-800 dark:border-slate-600 dark:text-slate-200 dark:hover:bg-slate-700">
- Cancel
- </a>
- </div>
- </form>
- </section>
- {% endblock %}
|