feat: add archive/delete/restore sessions with header preview
This commit is contained in:
@@ -30,10 +30,16 @@
|
||||
<!-- Active Sessions -->
|
||||
{% if sessions %}
|
||||
<div class="section-card">
|
||||
<h2 class="section-title">📋 My Active Sessions</h2>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-md);">
|
||||
<h2 class="section-title">📋 My Sessions</h2>
|
||||
<label class="checkbox-toggle">
|
||||
<input type="checkbox" id="showArchivedToggle" {% if show_archived %}checked{% endif %} onchange="toggleArchived(this.checked)">
|
||||
<span>Show archived/deleted</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="sessions-list">
|
||||
{% for s in sessions %}
|
||||
<div class="session-list-item-container">
|
||||
<div class="session-list-item-container session-status-{{ s.status }}">
|
||||
<a href="{{ url_for('conssheets.scan_session', session_id=s.id) }}" class="session-list-item">
|
||||
<div class="session-list-info">
|
||||
<h3 class="session-list-name">{{ s.process_name }}</h3>
|
||||
@@ -42,14 +48,52 @@
|
||||
<span>•</span>
|
||||
<span>{{ s.scan_count or 0 }} lots scanned</span>
|
||||
</div>
|
||||
{% if s.header_preview %}
|
||||
<div class="session-list-meta" style="margin-top: var(--space-xs); font-size: 0.8rem;">
|
||||
{% for hf in s.header_preview %}
|
||||
<span><strong>{{ hf.field_label }}:</strong> {{ hf.field_value or '—' }}</span>
|
||||
{% if not loop.last %}<span>•</span>{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if s.status == 'archived' %}
|
||||
<div class="session-list-meta" style="margin-top: var(--space-xs);">
|
||||
<span style="color: var(--color-warning);">📦 Archived</span>
|
||||
</div>
|
||||
{% elif s.status == 'deleted' %}
|
||||
<div class="session-list-meta" style="margin-top: var(--space-xs);">
|
||||
<span style="color: var(--color-danger);">🗑️ Deleted</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="session-list-action">
|
||||
<span class="arrow-icon">→</span>
|
||||
</div>
|
||||
</a>
|
||||
<button class="btn-archive" onclick="archiveSession({{ s.id }}, '{{ s.process_name }}')" title="Archive this session">
|
||||
🗑️
|
||||
</button>
|
||||
|
||||
{% if s.status == 'active' %}
|
||||
<button class="btn-session-action btn-archive" onclick="archiveSession({{ s.id }}, '{{ s.process_name }}')" title="Archive this session">
|
||||
📦
|
||||
</button>
|
||||
{% if session.role in ['owner', 'admin'] %}
|
||||
<button class="btn-session-action btn-delete" onclick="deleteSession({{ s.id }}, '{{ s.process_name }}')" title="Delete this session">
|
||||
❌
|
||||
</button>
|
||||
{% endif %}
|
||||
{% elif s.status == 'archived' %}
|
||||
<button class="btn-session-action btn-unarchive" onclick="unarchiveSession({{ s.id }}, '{{ s.process_name }}')" title="Restore to active">
|
||||
↩️
|
||||
</button>
|
||||
{% if session.role in ['owner', 'admin'] %}
|
||||
<button class="btn-session-action btn-delete" onclick="deleteSession({{ s.id }}, '{{ s.process_name }}')" title="Delete this session">
|
||||
❌
|
||||
</button>
|
||||
{% endif %}
|
||||
{% elif s.status == 'deleted' and session.role in ['owner', 'admin'] %}
|
||||
<button class="btn-session-action btn-restore" onclick="restoreSession({{ s.id }}, '{{ s.process_name }}')" title="Restore from deleted">
|
||||
🔄
|
||||
</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
@@ -63,89 +107,20 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.new-session-section {
|
||||
background: var(--color-surface);
|
||||
border: 2px solid var(--color-border);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: var(--space-xl);
|
||||
margin-bottom: var(--space-xl);
|
||||
}
|
||||
|
||||
.process-buttons {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--space-md);
|
||||
margin-top: var(--space-md);
|
||||
}
|
||||
|
||||
.section-card {
|
||||
margin-top: var(--space-xl);
|
||||
}
|
||||
|
||||
.session-list-item-container {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: var(--space-sm);
|
||||
margin-bottom: var(--space-sm);
|
||||
}
|
||||
|
||||
.session-list-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: var(--color-surface);
|
||||
border: 2px solid var(--color-border);
|
||||
border-radius: var(--radius-md);
|
||||
padding: var(--space-lg);
|
||||
text-decoration: none;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.session-list-item:hover {
|
||||
border-color: var(--color-primary);
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.session-list-name {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
color: var(--color-text);
|
||||
margin: 0 0 var(--space-xs) 0;
|
||||
}
|
||||
|
||||
.session-list-meta {
|
||||
display: flex;
|
||||
gap: var(--space-sm);
|
||||
font-size: 0.875rem;
|
||||
color: var(--color-text-muted);
|
||||
}
|
||||
|
||||
.arrow-icon {
|
||||
font-size: 1.5rem;
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
.btn-archive {
|
||||
background: var(--color-surface);
|
||||
border: 2px solid var(--color-border);
|
||||
border-radius: var(--radius-md);
|
||||
padding: var(--space-md);
|
||||
cursor: pointer;
|
||||
font-size: 1.25rem;
|
||||
transition: var(--transition);
|
||||
}
|
||||
|
||||
.btn-archive:hover {
|
||||
border-color: var(--color-danger);
|
||||
background: rgba(255, 51, 102, 0.1);
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Styles moved to static/css/style.css for maintainability -->
|
||||
<script>
|
||||
function toggleArchived(checked) {
|
||||
const url = new URL(window.location.href);
|
||||
if (checked) {
|
||||
url.searchParams.set('show_archived', '1');
|
||||
} else {
|
||||
url.searchParams.delete('show_archived');
|
||||
}
|
||||
window.location.href = url.toString();
|
||||
}
|
||||
|
||||
function archiveSession(sessionId, processName) {
|
||||
if (!confirm(`Archive this ${processName} session?\n\nYou can still view it later from the admin panel.`)) {
|
||||
if (!confirm(`Archive this ${processName} session?\n\nYou can restore it later.`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -162,5 +137,62 @@ function archiveSession(sessionId, processName) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function unarchiveSession(sessionId, processName) {
|
||||
if (!confirm(`Restore ${processName} session to active?`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(`/conssheets/session/${sessionId}/unarchive`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'}
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
location.reload();
|
||||
} else {
|
||||
alert(data.message || 'Error restoring session');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function deleteSession(sessionId, processName) {
|
||||
if (!confirm(`⚠️ DELETE ${processName} session?\n\nThis will mark all scanned data as deleted.\nThis action cannot be undone easily.\n\nAre you absolutely sure?`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(`/conssheets/session/${sessionId}/delete`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'}
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
location.reload();
|
||||
} else {
|
||||
alert(data.message || 'Error deleting session');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function restoreSession(sessionId, processName) {
|
||||
if (!confirm(`Restore ${processName} from deleted?\n\nThis will reactivate the session and all its data.`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fetch(`/conssheets/session/${sessionId}/restore`, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'}
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
location.reload();
|
||||
} else {
|
||||
alert(data.message || 'Error restoring session');
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user