| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- {% extends "layout.twig" %}
- {% set errorMessages = {
- 'commit': 'A sheet failed to import; see the message below. Earlier sheets in the run did commit.',
- 'expired': 'Your previous import session expired. Please upload again.',
- 'nothing_selected': 'No sheets were selected to import.',
- } %}
- {% block content %}
- <section class="space-y-6">
- <header class="flex items-baseline gap-4 flex-wrap">
- <h1 class="text-2xl font-semibold tracking-tight">Import preview</h1>
- <span class="text-sm text-slate-500 dark:text-slate-400">{{ fileName }}</span>
- <span class="text-sm text-slate-500 dark:text-slate-400">{{ sheets|length }} sheet(s) found</span>
- </header>
- {% if error != '' and errorMessages[error] is defined %}
- <div class="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/{{ token }}" class="space-y-6">
- <input type="hidden" name="_csrf" value="{{ csrfToken }}">
- {% for sheet in sheets %}
- {% set s = summaries[loop.index0] %}
- {% set idx = loop.index0 %}
- <section class="rounded-lg border bg-white p-5 dark:bg-slate-800 dark:border-slate-700">
- <header class="flex items-baseline gap-3 flex-wrap">
- <h2 class="text-lg font-semibold">{{ sheet.sheetName }}</h2>
- <span class="text-xs text-slate-500 dark:text-slate-400">
- {{ s.weekCount }} weeks · {{ s.workerCount }} workers · {{ s.taskCount }} tasks · {{ s.cellCount }} day cells
- </span>
- </header>
- {% if sheet.warnings is not empty %}
- <ul class="mt-3 space-y-1 text-xs text-amber-700 dark:text-amber-300">
- {% for w in sheet.warnings %}<li>· {{ w }}</li>{% endfor %}
- </ul>
- {% endif %}
- <div class="mt-4 grid grid-cols-1 sm:grid-cols-2 gap-4">
- <label class="block">
- <span class="text-sm text-slate-700 dark:text-slate-300">Sprint name</span>
- <input type="text" name="name_{{ idx }}" value="{{ sheet.sheetName }}"
- class="mt-1 block w-full rounded-md border-slate-300 border shadow-sm px-3 py-2 focus:outline-none focus:ring-2 focus:ring-slate-400 dark:bg-slate-800 dark:border-slate-600 dark:text-slate-100 dark:focus:ring-slate-500">
- </label>
- <label class="block">
- <span class="text-sm text-slate-700 dark:text-slate-300">Reserve fraction (read-only — taken from sheet)</span>
- <input type="text" disabled value="{{ (sheet.reserveFraction * 100)|round(0) }}%"
- class="mt-1 block w-full rounded-md border-slate-300 border bg-slate-50 px-3 py-2 text-slate-500 dark:bg-slate-900 dark:border-slate-700 dark:text-slate-400">
- </label>
- <label class="block">
- <span class="text-sm text-slate-700 dark:text-slate-300">Start date</span>
- <input type="date" name="start_{{ idx }}" value="{{ sheet.inferredStartDate }}"
- class="mt-1 block w-full rounded-md border-slate-300 border shadow-sm px-3 py-2 focus:outline-none focus:ring-2 focus:ring-slate-400 dark:bg-slate-800 dark:border-slate-600 dark:text-slate-100 dark:focus:ring-slate-500">
- <span class="text-xs text-slate-500 dark:text-slate-400">Inferred from KW {{ sheet.weeks[0].kw }}; check the year.</span>
- </label>
- <label class="block">
- <span class="text-sm text-slate-700 dark:text-slate-300">End date</span>
- <input type="date" name="end_{{ idx }}" value="{{ sheet.inferredEndDate }}"
- class="mt-1 block w-full rounded-md border-slate-300 border shadow-sm px-3 py-2 focus:outline-none focus:ring-2 focus:ring-slate-400 dark:bg-slate-800 dark:border-slate-600 dark:text-slate-100 dark:focus:ring-slate-500">
- </label>
- </div>
- <fieldset class="mt-5">
- <legend class="text-sm font-medium text-slate-700 dark:text-slate-300">Target sprint</legend>
- <div class="mt-2 space-y-1 text-sm">
- <label class="flex items-center gap-2">
- <input type="radio" name="target_{{ idx }}" value="new" checked>
- <span>Create new sprint</span>
- </label>
- <label class="flex items-center gap-2 {% if emptySprints is empty %}text-slate-400 dark:text-slate-600{% endif %}">
- <input type="radio" name="target_{{ idx }}" value="existing"
- {% if emptySprints is empty %}disabled{% endif %}>
- <span>Merge into empty existing sprint:</span>
- <select name="existing_{{ idx }}"
- {% if emptySprints is empty %}disabled{% endif %}
- class="rounded-md border-slate-300 border px-2 py-1 text-sm dark:bg-slate-800 dark:border-slate-600 dark:text-slate-100">
- <option value="">— pick —</option>
- {% for sp in emptySprints %}
- <option value="{{ sp.id }}">{{ sp.name }} ({{ sp.startDate }} → {{ sp.endDate }})</option>
- {% endfor %}
- </select>
- </label>
- </div>
- {% if emptySprints is empty %}
- <p class="mt-1 text-xs text-slate-500 dark:text-slate-400">
- No empty sprints exist. Only sprints with no weeks, workers, or tasks can be merge targets.
- </p>
- {% endif %}
- </fieldset>
- <div class="mt-5 grid grid-cols-1 md:grid-cols-2 gap-4 text-sm">
- <div class="rounded-md border border-slate-200 p-3 dark:border-slate-700">
- <div class="font-medium text-slate-700 dark:text-slate-300">Workers</div>
- {% if s.newWorkers is empty %}
- <p class="mt-1 text-slate-500 dark:text-slate-400">All {{ s.workerCount }} workers already exist.</p>
- {% else %}
- <p class="mt-1 text-slate-600 dark:text-slate-400">
- Will create {{ s.newWorkers|length }} new worker(s):
- <span class="text-slate-800 dark:text-slate-100">{{ s.newWorkers|join(', ') }}</span>
- </p>
- {% endif %}
- </div>
- <div class="rounded-md border border-slate-200 p-3 dark:border-slate-700">
- <div class="font-medium text-slate-700 dark:text-slate-300">Status colours</div>
- <ul class="mt-1 space-y-0.5 text-slate-600 dark:text-slate-400">
- <li><span class="inline-block w-3 h-3 align-middle rounded-sm bg-slate-300 dark:bg-slate-600 mr-1"></span> zugewiesen: {{ s.statusCounts.zugewiesen }}</li>
- <li><span class="inline-block w-3 h-3 align-middle rounded-sm bg-yellow-300 mr-1"></span> gestartet: {{ s.statusCounts.gestartet }}</li>
- <li><span class="inline-block w-3 h-3 align-middle rounded-sm bg-green-500 mr-1"></span> abgeschlossen: {{ s.statusCounts.abgeschlossen }}</li>
- <li><span class="inline-block w-3 h-3 align-middle rounded-sm bg-red-500 mr-1"></span> abgebrochen: {{ s.statusCounts.abgebrochen }}</li>
- </ul>
- </div>
- </div>
- <label class="mt-4 flex items-center gap-2 text-sm">
- <input type="checkbox" name="skip_{{ idx }}" value="1">
- <span>Skip this sheet</span>
- </label>
- </section>
- {% endfor %}
- <div class="flex gap-3">
- <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">
- Commit import
- </button>
- <a href="/sprints/import" 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 %}
|