feat: return-to-project redirects from create/edit forms

When creating or editing items from a project detail tab, users now
return to that project's tab instead of the entity's own page.
Edit links pass from_project param; forms include hidden field.
Reassigning to a different project redirects to the new project.
Decisions/meetings create from project context inserts junction rows.
File uploads from project context redirect back to project files tab.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-06 18:28:15 +00:00
parent ba9c36e691
commit c7a07ed280
18 changed files with 125 additions and 27 deletions

View File

@@ -46,7 +46,8 @@
</datalist>
</div>
<div class="form-actions"><button type="submit" class="btn btn-primary">{{ 'Save' if item else 'Create' }}</button><a href="{{ '/contacts/' ~ item.id if item else '/contacts' }}" class="btn btn-secondary">Cancel</a></div>
{% if from_project is defined and from_project %}<input type="hidden" name="from_project" value="{{ from_project }}">{% endif %}
<div class="form-actions"><button type="submit" class="btn btn-primary">{{ 'Save' if item else 'Create' }}</button><a href="{{ '/projects/' ~ from_project ~ '?tab=contacts' if from_project is defined and from_project else ('/contacts/' ~ item.id if item else '/contacts') }}" class="btn btn-secondary">Cancel</a></div>
</div>
</form></div>

View File

@@ -78,9 +78,11 @@
</div>
{% if prefill_task_id is defined and prefill_task_id %}<input type="hidden" name="task_id" value="{{ prefill_task_id }}">{% endif %}
{% if prefill_project_id is defined and prefill_project_id %}<input type="hidden" name="project_id" value="{{ prefill_project_id }}">{% endif %}
{% if from_project is defined and from_project %}<input type="hidden" name="from_project" value="{{ from_project }}">{% endif %}
<div class="form-actions">
<button type="submit" class="btn btn-primary">{{ 'Save Changes' if item else 'Record Decision' }}</button>
<a href="{{ '/tasks/' ~ prefill_task_id ~ '?tab=decisions' if prefill_task_id is defined and prefill_task_id else ('/decisions/' ~ item.id if item else '/decisions') }}" class="btn btn-secondary">Cancel</a>
<a href="{{ '/projects/' ~ from_project ~ '?tab=decisions' if from_project is defined and from_project else ('/projects/' ~ prefill_project_id ~ '?tab=decisions' if prefill_project_id is defined and prefill_project_id else ('/tasks/' ~ prefill_task_id ~ '?tab=decisions' if prefill_task_id is defined and prefill_task_id else ('/decisions/' ~ item.id if item else '/decisions'))) }}" class="btn btn-secondary">Cancel</a>
</div>
</form>
</div>

View File

@@ -45,9 +45,10 @@
</select>
</div>
{% if from_project is defined and from_project %}<input type="hidden" name="from_project" value="{{ from_project }}">{% endif %}
<div class="form-actions">
<button type="submit" class="btn btn-primary">Save Changes</button>
<a href="/focus/{{ item.id }}" class="btn btn-secondary">Cancel</a>
<a href="{{ '/projects/' ~ from_project ~ '?tab=focus' if from_project is defined and from_project else '/focus/' ~ item.id }}" class="btn btn-secondary">Cancel</a>
</div>
</div>
</form>

View File

@@ -16,7 +16,8 @@
{% if prefill_task_id is defined and prefill_task_id %}<input type="hidden" name="task_id" value="{{ prefill_task_id }}">{% endif %}
{% if prefill_meeting_id is defined and prefill_meeting_id %}<input type="hidden" name="meeting_id" value="{{ prefill_meeting_id }}">{% endif %}
{% if prefill_contact_id is defined and prefill_contact_id %}<input type="hidden" name="contact_id" value="{{ prefill_contact_id }}">{% endif %}
<div class="form-actions"><button type="submit" class="btn btn-primary">{{ 'Save' if item else 'Create' }}</button><a href="{{ '/contacts/' ~ prefill_contact_id if prefill_contact_id is defined and prefill_contact_id else ('/projects/' ~ prefill_project_id ~ '?tab=links' if prefill_project_id is defined and prefill_project_id else ('/tasks/' ~ prefill_task_id ~ '?tab=links' if prefill_task_id is defined and prefill_task_id else '/links')) }}" class="btn btn-secondary">Cancel</a></div>
{% if from_project is defined and from_project %}<input type="hidden" name="from_project" value="{{ from_project }}">{% endif %}
<div class="form-actions"><button type="submit" class="btn btn-primary">{{ 'Save' if item else 'Create' }}</button><a href="{{ '/projects/' ~ from_project ~ '?tab=links' if from_project is defined and from_project else ('/contacts/' ~ prefill_contact_id if prefill_contact_id is defined and prefill_contact_id else ('/projects/' ~ prefill_project_id ~ '?tab=links' if prefill_project_id is defined and prefill_project_id else ('/tasks/' ~ prefill_task_id ~ '?tab=links' if prefill_task_id is defined and prefill_task_id else '/links'))) }}" class="btn btn-secondary">Cancel</a></div>
</div>
</form></div>
{% endblock %}

View File

@@ -76,9 +76,10 @@
{% if prefill_task_id is defined and prefill_task_id %}<input type="hidden" name="task_id" value="{{ prefill_task_id }}">{% endif %}
{% if prefill_meeting_id is defined and prefill_meeting_id %}<input type="hidden" name="meeting_id" value="{{ prefill_meeting_id }}">{% endif %}
{% if prefill_focus_id is defined and prefill_focus_id %}<input type="hidden" name="focus_id" value="{{ prefill_focus_id }}">{% endif %}
{% if from_project is defined and from_project %}<input type="hidden" name="from_project" value="{{ from_project }}">{% endif %}
<div class="form-actions">
<button type="submit" class="btn btn-primary">{{ 'Save Changes' if item else 'Create List' }}</button>
<a href="{{ '/focus/' ~ prefill_focus_id ~ '?tab=lists' if prefill_focus_id is defined and prefill_focus_id else ('/tasks/' ~ prefill_task_id ~ '?tab=lists' if prefill_task_id is defined and prefill_task_id else ('/lists/' ~ item.id if item else '/lists')) }}" class="btn btn-secondary">Cancel</a>
<a href="{{ '/projects/' ~ from_project ~ '?tab=lists' if from_project is defined and from_project else ('/focus/' ~ prefill_focus_id ~ '?tab=lists' if prefill_focus_id is defined and prefill_focus_id else ('/tasks/' ~ prefill_task_id ~ '?tab=lists' if prefill_task_id is defined and prefill_task_id else ('/projects/' ~ prefill_project_id ~ '?tab=lists' if prefill_project_id is defined and prefill_project_id and not item else ('/lists/' ~ item.id if item else '/lists')))) }}" class="btn btn-secondary">Cancel</a>
</div>
</form>
</div>

View File

@@ -93,9 +93,11 @@
</div>
</div>
{% if prefill_project_id is defined and prefill_project_id %}<input type="hidden" name="project_id" value="{{ prefill_project_id }}">{% endif %}
{% if from_project is defined and from_project %}<input type="hidden" name="from_project" value="{{ from_project }}">{% endif %}
<div class="form-actions">
<button type="submit" class="btn btn-primary">{{ 'Save Changes' if item else 'Create Meeting' }}</button>
<a href="{{ '/meetings/' ~ item.id if item else '/meetings' }}" class="btn btn-secondary">Cancel</a>
<a href="{{ '/projects/' ~ from_project ~ '?tab=meetings' if from_project is defined and from_project else ('/projects/' ~ prefill_project_id ~ '?tab=meetings' if prefill_project_id is defined and prefill_project_id else ('/meetings/' ~ item.id if item else '/meetings')) }}" class="btn btn-secondary">Cancel</a>
</div>
</form>
</div>

View File

@@ -16,7 +16,8 @@
{% if prefill_task_id is defined and prefill_task_id %}<input type="hidden" name="task_id" value="{{ prefill_task_id }}">{% endif %}
{% if prefill_meeting_id is defined and prefill_meeting_id %}<input type="hidden" name="meeting_id" value="{{ prefill_meeting_id }}">{% endif %}
{% if prefill_focus_id is defined and prefill_focus_id %}<input type="hidden" name="focus_id" value="{{ prefill_focus_id }}">{% endif %}
<div class="form-actions"><button type="submit" class="btn btn-primary">{{ 'Save' if item else 'Create' }}</button><a href="{{ '/focus/' ~ prefill_focus_id ~ '?tab=notes' if prefill_focus_id is defined and prefill_focus_id else ('/notes/' ~ item.id if item else '/notes') }}" class="btn btn-secondary">Cancel</a></div>
{% if from_project is defined and from_project %}<input type="hidden" name="from_project" value="{{ from_project }}">{% endif %}
<div class="form-actions"><button type="submit" class="btn btn-primary">{{ 'Save' if item else 'Create' }}</button><a href="{{ '/projects/' ~ from_project ~ '?tab=notes' if from_project is defined and from_project else ('/focus/' ~ prefill_focus_id ~ '?tab=notes' if prefill_focus_id is defined and prefill_focus_id else ('/projects/' ~ prefill_project_id ~ '?tab=notes' if prefill_project_id is defined and prefill_project_id and not item else ('/notes/' ~ item.id if item else '/notes'))) }}" class="btn btn-secondary">Cancel</a></div>
</div>
</form></div>
{% endblock %}

View File

@@ -67,7 +67,7 @@
{% if t.due_date %}<span class="row-meta">{{ t.due_date }}</span>{% endif %}
<span class="status-badge status-{{ t.status }}">{{ t.status|replace('_', ' ') }}</span>
<div class="row-actions">
<a href="/tasks/{{ t.id }}/edit" class="btn btn-ghost btn-xs">Edit</a>
<a href="/tasks/{{ t.id }}/edit?from_project={{ item.id }}" class="btn btn-ghost btn-xs">Edit</a>
<form action="/projects/{{ item.id }}/tasks/{{ t.id }}/unlink" method="post" style="display:inline">
<button class="btn btn-ghost btn-xs">Unlink</button>
</form>
@@ -87,7 +87,7 @@
<span class="row-title"><a href="/notes/{{ n.id }}">{{ n.title }}</a></span>
<span class="row-meta">{{ n.updated_at.strftime('%Y-%m-%d') if n.updated_at else '' }}</span>
<div class="row-actions">
<a href="/notes/{{ n.id }}/edit" class="btn btn-ghost btn-xs">Edit</a>
<a href="/notes/{{ n.id }}/edit?from_project={{ item.id }}" class="btn btn-ghost btn-xs">Edit</a>
<form action="/projects/{{ item.id }}/notes/{{ n.id }}/unlink" method="post" style="display:inline">
<button class="btn btn-ghost btn-xs">Unlink</button>
</form>
@@ -107,7 +107,7 @@
<span class="row-title"><a href="{{ l.url }}" target="_blank">{{ l.label }}</a></span>
<span class="row-meta">{{ l.url[:50] }}{% if l.url|length > 50 %}...{% endif %}</span>
<div class="row-actions">
<a href="/links/{{ l.id }}/edit" class="btn btn-ghost btn-xs">Edit</a>
<a href="/links/{{ l.id }}/edit?from_project={{ item.id }}" class="btn btn-ghost btn-xs">Edit</a>
<form action="/projects/{{ item.id }}/links/{{ l.id }}/unlink" method="post" style="display:inline">
<button class="btn btn-ghost btn-xs" title="Unlink from project">Unlink</button>
</form>
@@ -146,7 +146,7 @@
<span class="row-title"><a href="/lists/{{ l.id }}">{{ l.name }}</a></span>
<span class="row-meta">{{ l.item_count }} items</span>
<div class="row-actions">
<a href="/lists/{{ l.id }}/edit" class="btn btn-ghost btn-xs">Edit</a>
<a href="/lists/{{ l.id }}/edit?from_project={{ item.id }}" class="btn btn-ghost btn-xs">Edit</a>
<form action="/projects/{{ item.id }}/lists/{{ l.id }}/unlink" method="post" style="display:inline">
<button class="btn btn-ghost btn-xs">Unlink</button>
</form>
@@ -166,7 +166,7 @@
<span class="row-title"><a href="/decisions/{{ d.id }}">{{ d.title }}</a></span>
<span class="status-badge status-{{ d.status }}">{{ d.status }}</span>
<div class="row-actions">
<a href="/decisions/{{ d.id }}/edit" class="btn btn-ghost btn-xs">Edit</a>
<a href="/decisions/{{ d.id }}/edit?from_project={{ item.id }}" class="btn btn-ghost btn-xs">Edit</a>
<form action="/projects/{{ item.id }}/decisions/{{ d.id }}/unlink" method="post" style="display:inline">
<button class="btn btn-ghost btn-xs">Unlink</button>
</form>
@@ -180,7 +180,7 @@
{% endfor %}
{% elif tab == 'meetings' %}
<a href="/meetings/create" class="btn btn-ghost btn-sm mb-3">+ New Meeting</a>
<a href="/meetings/create?project_id={{ item.id }}" class="btn btn-ghost btn-sm mb-3">+ New Meeting</a>
<div class="card mb-4">
<form action="/projects/{{ item.id }}/meetings/add" method="post" class="flex gap-2 items-end" style="padding: 12px;">
<div class="form-group" style="flex:1; margin:0;">
@@ -201,7 +201,7 @@
<span class="row-meta">{{ m.meeting_date }}</span>
<span class="status-badge status-{{ m.status }}">{{ m.status }}</span>
<div class="row-actions">
<a href="/meetings/{{ m.id }}/edit" class="btn btn-ghost btn-xs">Edit</a>
<a href="/meetings/{{ m.id }}/edit?from_project={{ item.id }}" class="btn btn-ghost btn-xs">Edit</a>
<form action="/projects/{{ item.id }}/meetings/{{ m.id }}/remove" method="post" style="display:inline">
<button class="btn btn-ghost btn-xs">Unlink</button>
</form>
@@ -221,7 +221,7 @@
{% if f.domain_name %}<span class="row-tag" style="{% if f.domain_color %}border-color:{{ f.domain_color }};color:{{ f.domain_color }}{% endif %}">{{ f.domain_name }}</span>{% endif %}
<span class="row-meta">{{ f.created_at.strftime('%Y-%m-%d') if f.created_at else '' }}</span>
<div class="row-actions">
<a href="/focus/{{ f.id }}/edit" class="btn btn-ghost btn-xs">Edit</a>
<a href="/focus/{{ f.id }}/edit?from_project={{ item.id }}" class="btn btn-ghost btn-xs">Edit</a>
<form action="/projects/{{ item.id }}/focus/{{ f.id }}/unlink" method="post" style="display:inline">
<button class="btn btn-ghost btn-xs">Unlink</button>
</form>
@@ -262,7 +262,7 @@
{% if c.role %}<span class="row-tag">{{ c.role }}</span>{% endif %}
<span class="row-meta">{{ c.linked_at.strftime('%Y-%m-%d') if c.linked_at else '' }}</span>
<div class="row-actions">
<a href="/contacts/{{ c.id }}/edit" class="btn btn-ghost btn-xs">Edit</a>
<a href="/contacts/{{ c.id }}/edit?from_project={{ item.id }}" class="btn btn-ghost btn-xs">Edit</a>
<form action="/projects/{{ item.id }}/contacts/{{ c.id }}/remove" method="post" style="display:inline">
<button class="btn btn-ghost btn-xs">Unlink</button>
</form>

View File

@@ -108,10 +108,11 @@
{% if prefill_parent_id %}
<input type="hidden" name="parent_id" value="{{ prefill_parent_id }}">
{% endif %}
{% if from_project is defined and from_project %}<input type="hidden" name="from_project" value="{{ from_project }}">{% endif %}
<div class="form-actions">
<button type="submit" class="btn btn-primary">{{ 'Save Changes' if item else 'Create Task' }}</button>
<a href="{{ '/tasks/' ~ item.id if item else '/tasks' }}" class="btn btn-secondary">Cancel</a>
<a href="{{ '/projects/' ~ from_project ~ '?tab=tasks' if from_project is defined and from_project else ('/tasks/' ~ item.id if item else '/tasks') }}" class="btn btn-secondary">Cancel</a>
</div>
</div>
</form>