5.12 (livrat): editare in modal a randurilor de preview, cont obligatoriu inainte de import, formular editare extras (_form_editare, _editare_preview_modal), plus suita de teste aferenta (preview edit/compact, mapare op, form editare, signup, admin panel). Design + planificare: - docs/design.md: sistem de design (tokeni, breakpoints, scara control, componente, a11y). - docs/prd/prd-5.12-* si prd-5.13-* (5.13 cu raport /autoplan: CEO+Design+Eng, audit trail). Curatare: sterse PNG-urile de test/mockup temporare din radacina. Nota: implementarea CSS 5.13 (responsive compact + sistem butoane) NU e inca facuta — planul revizuit cere refactorul testelor fragile din test_web_responsive.py INAINTE de CSS. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
151 lines
6.1 KiB
HTML
151 lines
6.1 KiB
HTML
<div id="import-section">
|
|
{% set pas = 2 %}{% include '_stepper.html' %}
|
|
{% from '_eroare.html' import card_erori %}
|
|
{# prima_inregistrare poate veni din context (web_upload_import) sau derivat din sample_rows #}
|
|
{%- set prima_inreg = prima_inregistrare if prima_inregistrare is defined else (sample_rows[0] if sample_rows else none) -%}
|
|
<div class="card">
|
|
<h2 style="font-size:15px; margin:0 0 12px;">
|
|
Mapare coloane —
|
|
<span class="muted" style="font-weight:400;">{{ filename or ("import #" ~ import_id) }}</span>
|
|
</h2>
|
|
|
|
{% if eroare_mapare %}
|
|
<div style="margin-bottom:12px;">
|
|
{{ card_erori([eroare_mapare]) }}
|
|
</div>
|
|
{% elif message %}
|
|
<div class="flash" style="{% if error %}border-color:var(--err); background:color-mix(in srgb, var(--err) 12%, var(--card));{% endif %} margin-bottom:12px;"
|
|
{% if error %}role="alert"{% endif %}>
|
|
{{ message }}
|
|
</div>
|
|
{% endif %}
|
|
|
|
<p class="muted" style="margin:0 0 12px; font-size:13px;">
|
|
Asociaza fiecare coloana din fisier cu campul canonic corespunzator.
|
|
Maparea se retine automat pentru fisiere cu acelasi antet.
|
|
</p>
|
|
|
|
{# Tabel orizontal preview: antet + prima inregistrare (US-003) #}
|
|
<div class="tablewrap" style="margin-bottom:16px;">
|
|
<table class="preview-antet" style="border-collapse:collapse; font-size:12px; width:100%; min-width:max-content;">
|
|
<thead>
|
|
<tr>
|
|
{% for col in columns %}
|
|
<th style="padding:4px 10px; text-align:left; background:var(--card); border:1px solid var(--line);
|
|
white-space:nowrap; font-weight:600; font-size:12px; color:var(--ink);">
|
|
{{ col }}
|
|
</th>
|
|
{% endfor %}
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% if prima_inreg %}
|
|
<tr>
|
|
{% for col in columns %}
|
|
{%- set val = prima_inreg.get(col, '') | string -%}
|
|
<td style="padding:4px 10px; border:1px solid var(--line); white-space:nowrap;
|
|
font-size:11px; color:var(--muted); max-width:160px; overflow:hidden; text-overflow:ellipsis;"
|
|
title="{{ val }}">
|
|
{{ val[:40] }}{% if val | length > 40 %}…{% endif %}
|
|
</td>
|
|
{% endfor %}
|
|
</tr>
|
|
{% else %}
|
|
<tr>
|
|
<td colspan="{{ columns | length }}"
|
|
style="padding:6px 10px; border:1px solid var(--line); font-size:12px;
|
|
color:var(--muted); font-style:italic; text-align:center;">
|
|
Antet fara randuri de date
|
|
</td>
|
|
</tr>
|
|
{% endif %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<form hx-post="/_import/{{ import_id }}/mapare-coloane"
|
|
hx-target="#import-section"
|
|
hx-swap="outerHTML">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token or '' }}">
|
|
|
|
<div style="margin-bottom:8px; display:flex; align-items:center; gap:10px; flex-wrap:wrap;">
|
|
<label for="format-data" style="font-size:13px; color:var(--muted);">
|
|
Format data
|
|
</label>
|
|
<input type="text" id="format-data" name="format_data"
|
|
value="{{ format_data or 'DD.MM.YYYY' }}"
|
|
placeholder="ex: DD.MM.YYYY"
|
|
style="max-width:160px;"
|
|
aria-describedby="format-data-hint">
|
|
<span id="format-data-hint" class="muted" style="font-size:12px;">
|
|
sau YYYY-MM-DD, MM/DD/YYYY etc.
|
|
</span>
|
|
</div>
|
|
|
|
{% for col in columns %}
|
|
{%- set sugg = fuzzy_suggestions.get(col, []) -%}
|
|
{%- set best = sugg[0].camp_canonic if sugg else '' -%}
|
|
<input type="hidden" name="colname" value="{{ col }}">
|
|
<div class="maprow">
|
|
<div class="mapcol grow">
|
|
<div><strong>{{ col }}</strong></div>
|
|
{% if sugg %}
|
|
<div class="muted" style="font-size:12px; margin-top:2px;">
|
|
sugestie: <span class="sugg">{{ sugg[0].camp_canonic }}
|
|
({{ sugg[0].score | round | int }}%)</span>
|
|
</div>
|
|
{% endif %}
|
|
{%- set ns = namespace(samples=[]) -%}
|
|
{%- for row in sample_rows -%}
|
|
{%- if row.get(col) is not none and row.get(col) != '' -%}
|
|
{%- set ns.samples = ns.samples + [row[col] | string] -%}
|
|
{%- endif -%}
|
|
{%- endfor -%}
|
|
{% if ns.samples %}
|
|
<div class="muted" style="font-size:11px; margin-top:2px;">
|
|
ex: {{ ns.samples[:2] | join(", ") }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="mapcol" style="min-width:200px;">
|
|
<label for="canon-{{ loop.index }}"
|
|
style="display:block; font-size:12px; color:var(--muted); margin-bottom:2px;">
|
|
Camp canonic
|
|
</label>
|
|
<select id="canon-{{ loop.index }}" name="canon">
|
|
<option value="">— ignorat —</option>
|
|
{% for field_key, field_label in canonical_fields %}
|
|
<option value="{{ field_key }}"
|
|
{% if field_key == best %}selected{% endif %}>
|
|
{{ field_key }} — {{ field_label }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
|
|
<div style="margin-top:16px; display:flex; align-items:center; gap:12px; flex-wrap:wrap;">
|
|
<button type="submit"
|
|
{% if not prima_inreg %}disabled aria-disabled="true"{% endif %}
|
|
style="min-height:44px; padding:10px 24px; font-size:14px;{% if not prima_inreg %} opacity:0.5; cursor:not-allowed;{% endif %}">
|
|
Salveaza si continua la preview
|
|
</button>
|
|
{% if not prima_inreg %}
|
|
<span style="font-size:12px; color:var(--err);">
|
|
Fisierul nu contine randuri de date — incarca un fisier cu cel putin o inregistrare.
|
|
</span>
|
|
{% else %}
|
|
<span class="muted" style="font-size:12px;">
|
|
maparea se retine pentru fisiere cu acelasi antet
|
|
</span>
|
|
{% endif %}
|
|
</div>
|
|
</form>
|
|
|
|
<div style="margin-top:12px;">
|
|
<a href="/" class="muted" style="font-size:13px;">Incarca alt fisier</a>
|
|
</div>
|
|
</div>
|
|
</div>
|