fix: rewrite subtask editing to reuse add form instead of inline table row
Edit button now opens the same "Nuova Misurazione" form pre-filled with existing data, showing "Modifica Misurazione" title and "Aggiorna Misurazione" button. Also adds marker_number to SubtaskUpdate schema so edits persist. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -543,57 +543,34 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<template x-for="subtask in task.subtasks" :key="subtask.id">
|
||||
<!-- ---- View Mode Row ---- -->
|
||||
<tr x-show="editingSubtask !== subtask.id"
|
||||
@dblclick="startEditSubtask(subtask, task.id)"
|
||||
class="cursor-pointer hover:bg-[var(--bg-card-hover)]">
|
||||
|
||||
<!-- Marker Badge -->
|
||||
<tr class="hover:bg-[var(--bg-card-hover)]">
|
||||
<td class="text-center">
|
||||
<span class="marker-badge" x-text="subtask.marker_number"></span>
|
||||
</td>
|
||||
|
||||
<!-- Description -->
|
||||
<td>
|
||||
<span class="text-sm" x-text="subtask.description"></span>
|
||||
</td>
|
||||
|
||||
<!-- Measurement Type -->
|
||||
<td>
|
||||
<span class="text-xs badge badge-neutral" x-text="subtask.measurement_type || '-'"></span>
|
||||
</td>
|
||||
|
||||
<!-- Nominal -->
|
||||
<td class="text-right">
|
||||
<span class="measure-value text-sm" x-text="subtask.nominal != null ? subtask.nominal : '-'"></span>
|
||||
</td>
|
||||
|
||||
<!-- UTL -->
|
||||
<td class="text-right">
|
||||
<span class="measure-value text-sm text-red-500" x-text="subtask.utl != null ? subtask.utl : '-'"></span>
|
||||
</td>
|
||||
|
||||
<!-- UWL -->
|
||||
<td class="text-right">
|
||||
<span class="measure-value text-sm text-amber-500" x-text="subtask.uwl != null ? subtask.uwl : '-'"></span>
|
||||
</td>
|
||||
|
||||
<!-- LWL -->
|
||||
<td class="text-right">
|
||||
<span class="measure-value text-sm text-amber-500" x-text="subtask.lwl != null ? subtask.lwl : '-'"></span>
|
||||
</td>
|
||||
|
||||
<!-- LTL -->
|
||||
<td class="text-right">
|
||||
<span class="measure-value text-sm text-red-500" x-text="subtask.ltl != null ? subtask.ltl : '-'"></span>
|
||||
</td>
|
||||
|
||||
<!-- Unit -->
|
||||
<td class="text-center">
|
||||
<span class="text-xs text-[var(--text-muted)]" x-text="subtask.unit || 'mm'"></span>
|
||||
</td>
|
||||
|
||||
<!-- Tolerance Bar -->
|
||||
<td>
|
||||
<template x-if="subtask.nominal != null && subtask.ltl != null && subtask.utl != null">
|
||||
<div class="tolerance-bar" :title="toleranceTitle(subtask)">
|
||||
@@ -608,8 +585,6 @@
|
||||
<span class="text-xs text-[var(--text-muted)]">-</span>
|
||||
</template>
|
||||
</td>
|
||||
|
||||
<!-- Actions -->
|
||||
<td class="text-center">
|
||||
<div class="flex items-center justify-center gap-1">
|
||||
<button @click.stop="startEditSubtask(subtask, task.id)"
|
||||
@@ -631,120 +606,6 @@
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- ---- Edit Mode Row ---- -->
|
||||
<tr x-show="editingSubtask === subtask.id"
|
||||
class="subtask-edit-row bg-blue-50/50 dark:bg-blue-900/10">
|
||||
|
||||
<!-- Marker -->
|
||||
<td class="text-center">
|
||||
<input type="number"
|
||||
x-model.number="editSubtaskData.marker_number"
|
||||
min="1"
|
||||
class="tmf-input text-center measure-value w-14">
|
||||
</td>
|
||||
|
||||
<!-- Description -->
|
||||
<td>
|
||||
<input type="text"
|
||||
x-model="editSubtaskData.description"
|
||||
class="tmf-input w-full"
|
||||
@keydown.enter.prevent="updateSubtask(subtask.id, task.id)">
|
||||
</td>
|
||||
|
||||
<!-- Measurement Type -->
|
||||
<td>
|
||||
<select x-model="editSubtaskData.measurement_type"
|
||||
class="tmf-input">
|
||||
<option value="">-</option>
|
||||
<option value="linear">{{ _('Lineare') }}</option>
|
||||
<option value="diameter">{{ _('Diametro') }}</option>
|
||||
<option value="radius">{{ _('Raggio') }}</option>
|
||||
<option value="angle">{{ _('Angolo') }}</option>
|
||||
<option value="roughness">{{ _('Rugosita') }}</option>
|
||||
<option value="torque">{{ _('Coppia') }}</option>
|
||||
<option value="force">{{ _('Forza') }}</option>
|
||||
<option value="weight">{{ _('Peso') }}</option>
|
||||
<option value="other">{{ _('Altro') }}</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<!-- Nominal -->
|
||||
<td>
|
||||
<input type="number" step="any"
|
||||
x-model.number="editSubtaskData.nominal"
|
||||
class="tmf-input measure-value text-right w-full">
|
||||
</td>
|
||||
|
||||
<!-- UTL -->
|
||||
<td>
|
||||
<input type="number" step="any"
|
||||
x-model.number="editSubtaskData.utl"
|
||||
class="tmf-input measure-value text-right w-full">
|
||||
</td>
|
||||
|
||||
<!-- UWL -->
|
||||
<td>
|
||||
<input type="number" step="any"
|
||||
x-model.number="editSubtaskData.uwl"
|
||||
class="tmf-input measure-value text-right w-full">
|
||||
</td>
|
||||
|
||||
<!-- LWL -->
|
||||
<td>
|
||||
<input type="number" step="any"
|
||||
x-model.number="editSubtaskData.lwl"
|
||||
class="tmf-input measure-value text-right w-full">
|
||||
</td>
|
||||
|
||||
<!-- LTL -->
|
||||
<td>
|
||||
<input type="number" step="any"
|
||||
x-model.number="editSubtaskData.ltl"
|
||||
class="tmf-input measure-value text-right w-full">
|
||||
</td>
|
||||
|
||||
<!-- Unit -->
|
||||
<td>
|
||||
<select x-model="editSubtaskData.unit"
|
||||
class="tmf-input text-center">
|
||||
<option value="mm">mm</option>
|
||||
<option value="cm">cm</option>
|
||||
<option value="m">m</option>
|
||||
<option value="μm">μm</option>
|
||||
<option value="in">in</option>
|
||||
<option value="°">°</option>
|
||||
<option value="g">g</option>
|
||||
<option value="kg">kg</option>
|
||||
<option value="N">N</option>
|
||||
<option value="Nm">Nm</option>
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<!-- Tolerance (empty in edit) -->
|
||||
<td></td>
|
||||
|
||||
<!-- Actions: Save / Cancel -->
|
||||
<td class="text-center">
|
||||
<div class="flex items-center justify-center gap-1">
|
||||
<button @click="updateSubtask(subtask.id, task.id)"
|
||||
:disabled="!editSubtaskData.description.trim() || saving"
|
||||
class="p-1.5 rounded text-emerald-600 hover:bg-emerald-50 dark:hover:bg-emerald-900/30 transition-colors"
|
||||
title="{{ _('Salva') }}">
|
||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button @click="cancelEditSubtask()"
|
||||
class="p-1.5 rounded text-[var(--text-muted)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-secondary)] transition-colors"
|
||||
title="{{ _('Annulla') }}">
|
||||
<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -772,8 +633,8 @@
|
||||
<div x-show="addingSubtaskForTask === task.id"
|
||||
x-transition
|
||||
class="p-3 rounded-lg bg-[var(--bg-secondary)] border border-[var(--border-color)]">
|
||||
<p class="text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wide mb-3">
|
||||
{{ _('Nuova Misurazione') }}
|
||||
<p class="text-xs font-semibold text-[var(--text-secondary)] uppercase tracking-wide mb-3"
|
||||
x-text="editingSubtaskId ? '{{ _('Modifica Misurazione') }}' : '{{ _('Nuova Misurazione') }}'">
|
||||
</p>
|
||||
<div class="grid grid-cols-2 sm:grid-cols-4 lg:grid-cols-6 gap-3">
|
||||
<!-- Marker Number -->
|
||||
@@ -789,7 +650,7 @@
|
||||
<label class="tmf-label text-xs">{{ _('Descrizione') }} <span class="text-red-500">*</span></label>
|
||||
<input type="text"
|
||||
x-model="newSubtask.description"
|
||||
@keydown.enter.prevent="addSubtask(task.id)"
|
||||
@keydown.enter.prevent="editingSubtaskId ? updateSubtask(editingSubtaskId, task.id) : addSubtask(task.id)"
|
||||
class="tmf-input"
|
||||
placeholder="{{ _('Es. Diametro foro principale') }}">
|
||||
</div>
|
||||
@@ -871,11 +732,11 @@
|
||||
|
||||
<!-- Form Actions -->
|
||||
<div class="flex items-center gap-2 justify-end mt-4">
|
||||
<button @click="addingSubtaskForTask = null; resetNewSubtask(task.id)"
|
||||
<button @click="cancelSubtaskForm(task.id)"
|
||||
class="btn btn-secondary text-xs">
|
||||
{{ _('Annulla') }}
|
||||
</button>
|
||||
<button @click="addSubtask(task.id)"
|
||||
<button @click="editingSubtaskId ? updateSubtask(editingSubtaskId, task.id) : addSubtask(task.id)"
|
||||
:disabled="!newSubtask.description.trim() || saving"
|
||||
class="btn btn-primary text-xs gap-1.5">
|
||||
<svg x-show="!saving" class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
|
||||
@@ -885,7 +746,7 @@
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"/>
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"/>
|
||||
</svg>
|
||||
{{ _('Aggiungi Misurazione') }}
|
||||
<span x-text="editingSubtaskId ? '{{ _('Aggiorna Misurazione') }}' : '{{ _('Aggiungi Misurazione') }}'"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1105,11 +966,7 @@ function taskEditor() {
|
||||
newTask: { title: '', directive: '', description: '' },
|
||||
|
||||
// ---- Subtask CRUD state ----
|
||||
editingSubtask: null,
|
||||
editSubtaskData: {
|
||||
marker_number: 1, description: '', measurement_type: '',
|
||||
nominal: null, utl: null, uwl: null, lwl: null, ltl: null, unit: 'mm'
|
||||
},
|
||||
editingSubtaskId: null,
|
||||
addingSubtaskForTask: null,
|
||||
newSubtask: {
|
||||
marker_number: 1, description: '', measurement_type: '',
|
||||
@@ -1211,7 +1068,7 @@ function taskEditor() {
|
||||
}
|
||||
// Reset inline editors when collapsing
|
||||
if (this.expandedTask !== taskId) {
|
||||
this.editingSubtask = null;
|
||||
this.editingSubtaskId = null;
|
||||
this.addingSubtaskForTask = null;
|
||||
}
|
||||
},
|
||||
@@ -1476,7 +1333,7 @@ function taskEditor() {
|
||||
},
|
||||
|
||||
openAddSubtask(task) {
|
||||
this.editingSubtask = null;
|
||||
this.editingSubtaskId = null;
|
||||
this.addingSubtaskForTask = task.id;
|
||||
this.resetNewSubtask(task.id);
|
||||
},
|
||||
@@ -1530,9 +1387,10 @@ function taskEditor() {
|
||||
},
|
||||
|
||||
startEditSubtask(subtask, taskId) {
|
||||
this.addingSubtaskForTask = null;
|
||||
this.editingSubtask = subtask.id;
|
||||
this.editSubtaskData = {
|
||||
// Open the same form used for adding, but pre-filled with existing data
|
||||
this.editingSubtaskId = subtask.id;
|
||||
this.addingSubtaskForTask = taskId;
|
||||
this.newSubtask = {
|
||||
marker_number: subtask.marker_number,
|
||||
description: subtask.description || '',
|
||||
measurement_type: subtask.measurement_type || '',
|
||||
@@ -1545,29 +1403,27 @@ function taskEditor() {
|
||||
};
|
||||
},
|
||||
|
||||
cancelEditSubtask() {
|
||||
this.editingSubtask = null;
|
||||
this.editSubtaskData = {
|
||||
marker_number: 1, description: '', measurement_type: '',
|
||||
nominal: null, utl: null, uwl: null, lwl: null, ltl: null, unit: 'mm'
|
||||
};
|
||||
cancelSubtaskForm(taskId) {
|
||||
this.editingSubtaskId = null;
|
||||
this.addingSubtaskForTask = null;
|
||||
this.resetNewSubtask(taskId);
|
||||
},
|
||||
|
||||
async updateSubtask(subtaskId, taskId) {
|
||||
if (!this.editSubtaskData.description.trim()) return;
|
||||
if (!this.newSubtask.description.trim()) return;
|
||||
this.saving = true;
|
||||
this.errorMessage = '';
|
||||
|
||||
const payload = {
|
||||
marker_number: this.editSubtaskData.marker_number || 1,
|
||||
description: this.editSubtaskData.description.trim(),
|
||||
measurement_type: this.editSubtaskData.measurement_type || null,
|
||||
nominal: this.editSubtaskData.nominal,
|
||||
utl: this.editSubtaskData.utl,
|
||||
uwl: this.editSubtaskData.uwl,
|
||||
lwl: this.editSubtaskData.lwl,
|
||||
ltl: this.editSubtaskData.ltl,
|
||||
unit: this.editSubtaskData.unit || 'mm'
|
||||
marker_number: this.newSubtask.marker_number || 1,
|
||||
description: this.newSubtask.description.trim(),
|
||||
measurement_type: this.newSubtask.measurement_type || null,
|
||||
nominal: this.newSubtask.nominal,
|
||||
utl: this.newSubtask.utl,
|
||||
uwl: this.newSubtask.uwl,
|
||||
lwl: this.newSubtask.lwl,
|
||||
ltl: this.newSubtask.ltl,
|
||||
unit: this.newSubtask.unit || 'mm'
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -1593,7 +1449,7 @@ function taskEditor() {
|
||||
task.subtasks[idx] = { ...task.subtasks[idx], ...data };
|
||||
}
|
||||
}
|
||||
this.cancelEditSubtask();
|
||||
this.cancelSubtaskForm(taskId);
|
||||
this.successMessage = {{ _("Misurazione aggiornata")|tojson }};
|
||||
}
|
||||
} catch (err) {
|
||||
|
||||
@@ -20,6 +20,7 @@ class SubtaskCreate(BaseModel):
|
||||
|
||||
class SubtaskUpdate(BaseModel):
|
||||
"""Schema for updating a subtask."""
|
||||
marker_number: Optional[int] = Field(None, ge=1)
|
||||
description: Optional[str] = Field(None, min_length=1, max_length=500)
|
||||
measurement_type: Optional[str] = Field(None, max_length=100)
|
||||
nominal: Optional[float] = None
|
||||
|
||||
Reference in New Issue
Block a user