Session 2: files upload/preview, meetings with action items, decisions
This commit is contained in:
@@ -48,6 +48,18 @@
|
||||
<svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg>
|
||||
Lists
|
||||
</a>
|
||||
<a href="/meetings" class="nav-item {{ 'active' if active_nav == 'meetings' }}">
|
||||
<svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
|
||||
Meetings
|
||||
</a>
|
||||
<a href="/decisions" class="nav-item {{ 'active' if active_nav == 'decisions' }}">
|
||||
<svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10z"/><path d="M9 12l2 2 4-4"/></svg>
|
||||
Decisions
|
||||
</a>
|
||||
<a href="/files" class="nav-item {{ 'active' if active_nav == 'files' }}">
|
||||
<svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"/><polyline points="13 2 13 9 20 9"/></svg>
|
||||
Files
|
||||
</a>
|
||||
<a href="/capture" class="nav-item {{ 'active' if active_nav == 'capture' }}">
|
||||
<svg class="nav-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12"/><path d="M5.45 5.11L2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"/></svg>
|
||||
Capture
|
||||
|
||||
55
templates/decision_detail.html
Normal file
55
templates/decision_detail.html
Normal file
@@ -0,0 +1,55 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="breadcrumb">
|
||||
<a href="/decisions">Decisions</a>
|
||||
<span class="sep">/</span>
|
||||
<span>{{ item.title }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-header">
|
||||
<h1 class="detail-title">{{ item.title }}</h1>
|
||||
<div class="flex gap-2">
|
||||
<a href="/decisions/{{ item.id }}/edit" class="btn btn-secondary btn-sm">Edit</a>
|
||||
<form action="/decisions/{{ item.id }}/delete" method="post" data-confirm="Delete this decision?" style="display:inline">
|
||||
<button type="submit" class="btn btn-danger btn-sm">Delete</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-meta mt-2">
|
||||
<span class="status-badge status-{{ item.status }}">{{ item.status }}</span>
|
||||
<span class="row-tag impact-{{ item.impact }}">{{ item.impact }} impact</span>
|
||||
{% if item.decided_at %}<span class="detail-meta-item">Decided: {{ item.decided_at }}</span>{% endif %}
|
||||
{% if meeting %}<span class="detail-meta-item">Meeting: <a href="/meetings/{{ meeting.id }}">{{ meeting.title }}</a></span>{% endif %}
|
||||
{% if item.tags %}
|
||||
<div class="mt-1">{% for tag in item.tags %}<span class="row-tag">{{ tag }}</span>{% endfor %}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if superseded_by %}
|
||||
<div class="card mt-3" style="border-left: 3px solid var(--amber);">
|
||||
<div style="padding: 12px 16px;">
|
||||
<strong style="color: var(--amber);">Superseded by:</strong>
|
||||
<a href="/decisions/{{ superseded_by.id }}">{{ superseded_by.title }}</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if item.rationale %}
|
||||
<div class="card mt-3">
|
||||
<div class="card-header"><h3 class="card-title">Rationale</h3></div>
|
||||
<div class="detail-body" style="padding: 12px 16px;">{{ item.rationale }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if supersedes %}
|
||||
<div class="card mt-3">
|
||||
<div class="card-header"><h3 class="card-title">Supersedes</h3></div>
|
||||
{% for dec in supersedes %}
|
||||
<div class="list-row">
|
||||
<span class="row-title"><a href="/decisions/{{ dec.id }}">{{ dec.title }}</a></span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
86
templates/decision_form.html
Normal file
86
templates/decision_form.html
Normal file
@@ -0,0 +1,86 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">{{ page_title }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<form method="post" action="{{ '/decisions/' ~ item.id ~ '/edit' if item else '/decisions/create' }}">
|
||||
<div class="form-grid">
|
||||
<div class="form-group full-width">
|
||||
<label class="form-label">Title *</label>
|
||||
<input type="text" name="title" class="form-input" required
|
||||
value="{{ item.title if item else '' }}" placeholder="Summary of the decision...">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Status</label>
|
||||
<select name="status" class="form-select">
|
||||
<option value="proposed" {{ 'selected' if (item and item.status == 'proposed') or not item }}>Proposed</option>
|
||||
<option value="accepted" {{ 'selected' if item and item.status == 'accepted' }}>Accepted</option>
|
||||
<option value="rejected" {{ 'selected' if item and item.status == 'rejected' }}>Rejected</option>
|
||||
<option value="superseded" {{ 'selected' if item and item.status == 'superseded' }}>Superseded</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Impact</label>
|
||||
<select name="impact" class="form-select">
|
||||
<option value="low" {{ 'selected' if item and item.impact == 'low' }}>Low</option>
|
||||
<option value="medium" {{ 'selected' if (item and item.impact == 'medium') or not item }}>Medium</option>
|
||||
<option value="high" {{ 'selected' if item and item.impact == 'high' }}>High</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Decision Date</label>
|
||||
<input type="date" name="decided_at" class="form-input"
|
||||
value="{{ item.decided_at if item and item.decided_at else '' }}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Meeting</label>
|
||||
<select name="meeting_id" class="form-select">
|
||||
<option value="">None</option>
|
||||
{% for m in meetings %}
|
||||
<option value="{{ m.id }}"
|
||||
{{ 'selected' if (item and item.meeting_id and item.meeting_id|string == m.id|string) or (not item and prefill_meeting_id == m.id|string) }}>
|
||||
{{ m.title }} ({{ m.meeting_date }})
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{% if item and other_decisions is defined %}
|
||||
<div class="form-group">
|
||||
<label class="form-label">Superseded By</label>
|
||||
<select name="superseded_by_id" class="form-select">
|
||||
<option value="">None</option>
|
||||
{% for d in other_decisions %}
|
||||
<option value="{{ d.id }}" {{ 'selected' if item.superseded_by_id and item.superseded_by_id|string == d.id|string }}>
|
||||
{{ d.title }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="form-group full-width">
|
||||
<label class="form-label">Rationale</label>
|
||||
<textarea name="rationale" class="form-textarea" rows="6" placeholder="Why was this decided? What alternatives were considered?">{{ item.rationale if item and item.rationale else '' }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Tags</label>
|
||||
<input type="text" name="tags" class="form-input" placeholder="tag1, tag2, ..."
|
||||
value="{{ item.tags|join(', ') if item and item.tags else '' }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn-primary">{{ 'Save Changes' if item else 'Record Decision' }}</button>
|
||||
<a href="{{ '/decisions/' ~ item.id if item else '/decisions' }}" class="btn btn-secondary">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
53
templates/decisions.html
Normal file
53
templates/decisions.html
Normal file
@@ -0,0 +1,53 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">Decisions<span class="page-count">{{ items|length }}</span></h1>
|
||||
<a href="/decisions/create" class="btn btn-primary">+ New Decision</a>
|
||||
</div>
|
||||
|
||||
<form class="filters-bar" method="get" action="/decisions">
|
||||
<select name="status" class="filter-select" onchange="this.form.submit()">
|
||||
<option value="">All Statuses</option>
|
||||
<option value="proposed" {{ 'selected' if current_status == 'proposed' }}>Proposed</option>
|
||||
<option value="accepted" {{ 'selected' if current_status == 'accepted' }}>Accepted</option>
|
||||
<option value="rejected" {{ 'selected' if current_status == 'rejected' }}>Rejected</option>
|
||||
<option value="superseded" {{ 'selected' if current_status == 'superseded' }}>Superseded</option>
|
||||
</select>
|
||||
<select name="impact" class="filter-select" onchange="this.form.submit()">
|
||||
<option value="">All Impact</option>
|
||||
<option value="high" {{ 'selected' if current_impact == 'high' }}>High</option>
|
||||
<option value="medium" {{ 'selected' if current_impact == 'medium' }}>Medium</option>
|
||||
<option value="low" {{ 'selected' if current_impact == 'low' }}>Low</option>
|
||||
</select>
|
||||
</form>
|
||||
|
||||
{% if items %}
|
||||
<div class="card mt-3">
|
||||
{% for item in items %}
|
||||
<div class="list-row">
|
||||
<span class="row-title"><a href="/decisions/{{ item.id }}">{{ item.title }}</a></span>
|
||||
<span class="status-badge status-{{ item.status }}">{{ item.status }}</span>
|
||||
<span class="row-tag impact-{{ item.impact }}">{{ item.impact }}</span>
|
||||
{% if item.decided_at %}
|
||||
<span class="row-meta">{{ item.decided_at }}</span>
|
||||
{% endif %}
|
||||
{% if item.meeting_title %}
|
||||
<span class="row-meta">{{ item.meeting_title }}</span>
|
||||
{% endif %}
|
||||
<div class="row-actions">
|
||||
<a href="/decisions/{{ item.id }}/edit" class="btn btn-ghost btn-xs">Edit</a>
|
||||
<form action="/decisions/{{ item.id }}/delete" method="post" data-confirm="Delete this decision?" style="display:inline">
|
||||
<button type="submit" class="btn btn-ghost btn-xs" style="color: var(--red)">Del</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="empty-state mt-3">
|
||||
<div class="empty-state-icon">⚖</div>
|
||||
<div class="empty-state-text">No decisions recorded yet</div>
|
||||
<a href="/decisions/create" class="btn btn-primary">Record First Decision</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
47
templates/file_preview.html
Normal file
47
templates/file_preview.html
Normal file
@@ -0,0 +1,47 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="breadcrumb">
|
||||
<a href="/files">Files</a>
|
||||
<span class="sep">/</span>
|
||||
<span>{{ item.original_filename }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-header">
|
||||
<h1 class="detail-title">{{ item.original_filename }}</h1>
|
||||
<div class="flex gap-2">
|
||||
<a href="/files/{{ item.id }}/download" class="btn btn-primary btn-sm">Download</a>
|
||||
<form action="/files/{{ item.id }}/delete" method="post" data-confirm="Delete this file?" style="display:inline">
|
||||
<button type="submit" class="btn btn-danger btn-sm">Delete</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-meta mt-2">
|
||||
{% if item.mime_type %}<span class="detail-meta-item">Type: {{ item.mime_type }}</span>{% endif %}
|
||||
{% if item.size_bytes %}<span class="detail-meta-item">Size: {{ "%.1f"|format(item.size_bytes / 1024) }} KB</span>{% endif %}
|
||||
{% if item.description %}<span class="detail-meta-item">{{ item.description }}</span>{% endif %}
|
||||
{% if item.tags %}
|
||||
<div class="mt-1">
|
||||
{% for tag in item.tags %}<span class="row-tag">{{ tag }}</span>{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if can_preview %}
|
||||
<div class="card mt-3" style="padding: 16px;">
|
||||
{% if item.mime_type and item.mime_type.startswith('image/') %}
|
||||
<img src="/files/{{ item.id }}/serve" alt="{{ item.original_filename }}" style="max-width: 100%; height: auto; border-radius: var(--radius);">
|
||||
{% elif item.mime_type == 'application/pdf' %}
|
||||
<iframe src="/files/{{ item.id }}/serve" style="width: 100%; height: 600px; border: none; border-radius: var(--radius);"></iframe>
|
||||
{% elif item.mime_type and item.mime_type.startswith('text/') %}
|
||||
<iframe src="/files/{{ item.id }}/serve" style="width: 100%; height: 400px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface2);"></iframe>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="empty-state mt-3">
|
||||
<div class="empty-state-icon">📄</div>
|
||||
<div class="empty-state-text">Preview not available for this file type</div>
|
||||
<a href="/files/{{ item.id }}/download" class="btn btn-primary">Download Instead</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
37
templates/file_upload.html
Normal file
37
templates/file_upload.html
Normal file
@@ -0,0 +1,37 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">Upload File</h1>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<form method="post" action="/files/upload" enctype="multipart/form-data">
|
||||
{% if context_type %}
|
||||
<input type="hidden" name="context_type" value="{{ context_type }}">
|
||||
<input type="hidden" name="context_id" value="{{ context_id }}">
|
||||
{% endif %}
|
||||
|
||||
<div class="form-grid">
|
||||
<div class="form-group full-width">
|
||||
<label class="form-label">File *</label>
|
||||
<input type="file" name="file" class="form-input" required>
|
||||
</div>
|
||||
|
||||
<div class="form-group full-width">
|
||||
<label class="form-label">Description</label>
|
||||
<input type="text" name="description" class="form-input" placeholder="Optional description...">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Tags</label>
|
||||
<input type="text" name="tags" class="form-input" placeholder="tag1, tag2, ...">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button type="submit" class="btn btn-primary">Upload</button>
|
||||
<a href="/files" class="btn btn-secondary">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
40
templates/files.html
Normal file
40
templates/files.html
Normal file
@@ -0,0 +1,40 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">Files<span class="page-count">{{ items|length }}</span></h1>
|
||||
<a href="/files/upload{{ '?context_type=' ~ context_type ~ '&context_id=' ~ context_id if context_type }}" class="btn btn-primary">+ Upload File</a>
|
||||
</div>
|
||||
|
||||
{% if items %}
|
||||
<div class="card">
|
||||
{% for item in items %}
|
||||
<div class="list-row">
|
||||
<span class="row-title">
|
||||
<a href="/files/{{ item.id }}/preview">{{ item.original_filename }}</a>
|
||||
</span>
|
||||
{% if item.mime_type %}
|
||||
<span class="row-tag">{{ item.mime_type.split('/')|last }}</span>
|
||||
{% endif %}
|
||||
{% if item.size_bytes %}
|
||||
<span class="row-meta">{{ "%.1f"|format(item.size_bytes / 1024) }} KB</span>
|
||||
{% endif %}
|
||||
{% if item.description %}
|
||||
<span class="row-meta">{{ item.description[:50] }}</span>
|
||||
{% endif %}
|
||||
<div class="row-actions">
|
||||
<a href="/files/{{ item.id }}/download" class="btn btn-ghost btn-xs">Download</a>
|
||||
<form action="/files/{{ item.id }}/delete" method="post" data-confirm="Delete this file?" style="display:inline">
|
||||
<button type="submit" class="btn btn-ghost btn-xs" style="color: var(--red)">Del</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="empty-state">
|
||||
<div class="empty-state-icon">📁</div>
|
||||
<div class="empty-state-text">No files uploaded yet</div>
|
||||
<a href="/files/upload" class="btn btn-primary">Upload First File</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
119
templates/meeting_detail.html
Normal file
119
templates/meeting_detail.html
Normal file
@@ -0,0 +1,119 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="breadcrumb">
|
||||
<a href="/meetings">Meetings</a>
|
||||
<span class="sep">/</span>
|
||||
<span>{{ item.title }}</span>
|
||||
</div>
|
||||
|
||||
<div class="detail-header">
|
||||
<h1 class="detail-title">{{ item.title }}</h1>
|
||||
<div class="flex gap-2">
|
||||
<a href="/meetings/{{ item.id }}/edit" class="btn btn-secondary btn-sm">Edit</a>
|
||||
<form action="/meetings/{{ item.id }}/delete" method="post" data-confirm="Delete this meeting?" style="display:inline">
|
||||
<button type="submit" class="btn btn-danger btn-sm">Delete</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-meta mt-2">
|
||||
<span class="detail-meta-item">{{ item.meeting_date }}</span>
|
||||
<span class="status-badge status-{{ item.status }}">{{ item.status }}</span>
|
||||
{% if item.location %}<span class="detail-meta-item">{{ item.location }}</span>{% endif %}
|
||||
{% if item.start_at and item.end_at %}
|
||||
<span class="detail-meta-item">{{ item.start_at.strftime('%H:%M') }} - {{ item.end_at.strftime('%H:%M') }}</span>
|
||||
{% endif %}
|
||||
{% if item.tags %}
|
||||
<div class="mt-1">{% for tag in item.tags %}<span class="row-tag">{{ tag }}</span>{% endfor %}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Agenda -->
|
||||
{% if item.agenda %}
|
||||
<div class="card mt-3">
|
||||
<div class="card-header"><h3 class="card-title">Agenda</h3></div>
|
||||
<div class="detail-body" style="padding: 12px 16px;">{{ item.agenda }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Meeting Notes -->
|
||||
{% if item.notes_body %}
|
||||
<div class="card mt-3">
|
||||
<div class="card-header"><h3 class="card-title">Notes</h3></div>
|
||||
<div class="detail-body" style="padding: 12px 16px;">{{ item.notes_body }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Transcript -->
|
||||
{% if item.transcript %}
|
||||
<div class="card mt-3">
|
||||
<div class="card-header"><h3 class="card-title">Transcript</h3></div>
|
||||
<div class="detail-body" style="padding: 12px 16px; font-family: var(--font-mono); font-size: 0.82rem; white-space: pre-wrap;">{{ item.transcript }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Action Items -->
|
||||
<div class="card mt-3">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Action Items<span class="page-count">{{ action_items|length }}</span></h3>
|
||||
</div>
|
||||
|
||||
<!-- Quick add action item -->
|
||||
<form class="quick-add" action="/meetings/{{ item.id }}/action-item" method="post" style="border-bottom: 1px solid var(--border);">
|
||||
<input type="text" name="title" placeholder="Add action item..." required>
|
||||
<select name="domain_id" class="filter-select" required style="width: auto;">
|
||||
{% for d in domains %}
|
||||
<option value="{{ d.id }}">{{ d.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<button type="submit" class="btn btn-primary btn-sm">Add</button>
|
||||
</form>
|
||||
|
||||
{% for task in action_items %}
|
||||
<div class="list-row {{ 'completed' if task.status == 'done' }}">
|
||||
<div class="row-check">
|
||||
<form action="/tasks/{{ task.id }}/toggle" method="post" style="display:inline">
|
||||
<input type="checkbox" id="mt-{{ task.id }}" {{ 'checked' if task.status == 'done' }}
|
||||
onchange="this.form.submit()">
|
||||
<label for="mt-{{ task.id }}"></label>
|
||||
</form>
|
||||
</div>
|
||||
<span class="priority-dot priority-{{ task.priority }}"></span>
|
||||
<span class="row-title"><a href="/tasks/{{ task.id }}">{{ task.title }}</a></span>
|
||||
{% if task.project_name %}<span class="row-tag">{{ task.project_name }}</span>{% endif %}
|
||||
<span class="status-badge status-{{ task.status }}">{{ task.status|replace('_', ' ') }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% if not action_items %}
|
||||
<div style="padding: 16px; color: var(--muted); font-size: 0.85rem;">No action items yet</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Decisions -->
|
||||
{% if decisions %}
|
||||
<div class="card mt-3">
|
||||
<div class="card-header"><h3 class="card-title">Decisions<span class="page-count">{{ decisions|length }}</span></h3></div>
|
||||
{% for dec in decisions %}
|
||||
<div class="list-row">
|
||||
<span class="row-title"><a href="/decisions/{{ dec.id }}">{{ dec.title }}</a></span>
|
||||
<span class="status-badge status-{{ dec.status }}">{{ dec.status }}</span>
|
||||
<span class="row-tag">{{ dec.impact }}</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Attendees -->
|
||||
{% if attendees %}
|
||||
<div class="card mt-3">
|
||||
<div class="card-header"><h3 class="card-title">Attendees<span class="page-count">{{ attendees|length }}</span></h3></div>
|
||||
{% for att in attendees %}
|
||||
<div class="list-row">
|
||||
<span class="row-title"><a href="/contacts/{{ att.id }}">{{ att.first_name }} {{ att.last_name or '' }}</a></span>
|
||||
{% if att.role %}<span class="row-tag">{{ att.role }}</span>{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
102
templates/meeting_form.html
Normal file
102
templates/meeting_form.html
Normal file
@@ -0,0 +1,102 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">{{ page_title }}</h1>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<form method="post" action="{{ '/meetings/' ~ item.id ~ '/edit' if item else '/meetings/create' }}">
|
||||
<div class="form-grid">
|
||||
<div class="form-group full-width">
|
||||
<label class="form-label">Title *</label>
|
||||
<input type="text" name="title" class="form-input" required
|
||||
value="{{ item.title if item else '' }}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Date *</label>
|
||||
<input type="date" name="meeting_date" class="form-input" required
|
||||
value="{{ item.meeting_date if item else '' }}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Status</label>
|
||||
<select name="status" class="form-select">
|
||||
<option value="scheduled" {{ 'selected' if item and item.status == 'scheduled' }}>Scheduled</option>
|
||||
<option value="completed" {{ 'selected' if item and item.status == 'completed' }}>Completed</option>
|
||||
<option value="cancelled" {{ 'selected' if item and item.status == 'cancelled' }}>Cancelled</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Start Time</label>
|
||||
<input type="datetime-local" name="start_at" class="form-input"
|
||||
value="{{ item.start_at.strftime('%Y-%m-%dT%H:%M') if item and item.start_at else '' }}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">End Time</label>
|
||||
<input type="datetime-local" name="end_at" class="form-input"
|
||||
value="{{ item.end_at.strftime('%Y-%m-%dT%H:%M') if item and item.end_at else '' }}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Location</label>
|
||||
<input type="text" name="location" class="form-input" placeholder="Zoom, Google Meet, Room..."
|
||||
value="{{ item.location if item and item.location else '' }}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Priority</label>
|
||||
<select name="priority" class="form-select">
|
||||
<option value="">None</option>
|
||||
<option value="1" {{ 'selected' if item and item.priority == 1 }}>Critical</option>
|
||||
<option value="2" {{ 'selected' if item and item.priority == 2 }}>High</option>
|
||||
<option value="3" {{ 'selected' if item and item.priority == 3 }}>Normal</option>
|
||||
<option value="4" {{ 'selected' if item and item.priority == 4 }}>Low</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Series (Parent Meeting)</label>
|
||||
<select name="parent_id" class="form-select">
|
||||
<option value="">None</option>
|
||||
{% for m in parent_meetings %}
|
||||
<option value="{{ m.id }}" {{ 'selected' if item and item.parent_id and item.parent_id|string == m.id|string }}>
|
||||
{{ m.title }} ({{ m.meeting_date }})
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group full-width">
|
||||
<label class="form-label">Agenda</label>
|
||||
<textarea name="agenda" class="form-textarea" rows="4">{{ item.agenda if item and item.agenda else '' }}</textarea>
|
||||
</div>
|
||||
|
||||
{% if item %}
|
||||
<div class="form-group full-width">
|
||||
<label class="form-label">Transcript</label>
|
||||
<textarea name="transcript" class="form-textarea" rows="6">{{ item.transcript if item and item.transcript else '' }}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group full-width">
|
||||
<label class="form-label">Meeting Notes</label>
|
||||
<textarea name="notes_body" class="form-textarea" rows="6">{{ item.notes_body if item and item.notes_body else '' }}</textarea>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-label">Tags</label>
|
||||
<input type="text" name="tags" class="form-input" placeholder="tag1, tag2, ..."
|
||||
value="{{ item.tags|join(', ') if item and item.tags else '' }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
46
templates/meetings.html
Normal file
46
templates/meetings.html
Normal file
@@ -0,0 +1,46 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="page-header">
|
||||
<h1 class="page-title">Meetings<span class="page-count">{{ items|length }}</span></h1>
|
||||
<a href="/meetings/create" class="btn btn-primary">+ New Meeting</a>
|
||||
</div>
|
||||
|
||||
<form class="filters-bar" method="get" action="/meetings">
|
||||
<select name="status" class="filter-select" onchange="this.form.submit()">
|
||||
<option value="">All Statuses</option>
|
||||
<option value="scheduled" {{ 'selected' if current_status == 'scheduled' }}>Scheduled</option>
|
||||
<option value="completed" {{ 'selected' if current_status == 'completed' }}>Completed</option>
|
||||
<option value="cancelled" {{ 'selected' if current_status == 'cancelled' }}>Cancelled</option>
|
||||
</select>
|
||||
</form>
|
||||
|
||||
{% if items %}
|
||||
<div class="card mt-3">
|
||||
{% for item in items %}
|
||||
<div class="list-row">
|
||||
<span class="row-title"><a href="/meetings/{{ item.id }}">{{ item.title }}</a></span>
|
||||
<span class="row-meta">{{ item.meeting_date }}</span>
|
||||
{% if item.location %}
|
||||
<span class="row-tag">{{ item.location }}</span>
|
||||
{% endif %}
|
||||
{% if item.action_count %}
|
||||
<span class="row-meta">{{ item.action_count }} action{{ 's' if item.action_count != 1 }}</span>
|
||||
{% endif %}
|
||||
<span class="status-badge status-{{ item.status }}">{{ item.status }}</span>
|
||||
<div class="row-actions">
|
||||
<a href="/meetings/{{ item.id }}/edit" class="btn btn-ghost btn-xs">Edit</a>
|
||||
<form action="/meetings/{{ item.id }}/delete" method="post" data-confirm="Delete this meeting?" style="display:inline">
|
||||
<button type="submit" class="btn btn-ghost btn-xs" style="color: var(--red)">Del</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="empty-state mt-3">
|
||||
<div class="empty-state-icon">📅</div>
|
||||
<div class="empty-state-text">No meetings yet</div>
|
||||
<a href="/meetings/create" class="btn btn-primary">Schedule First Meeting</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user