Files
ThinkStorm/thinkstorm/templates/ideas.html
T
xAdmin 41e08611c9 Implement optional single-image intake, Signal ingestion, and multimodal vision analysis
- Add image intake service with format validation (JPEG, PNG, WebP) and EXIF/GPS stripping
- Enforce strict single-image rule across Web and Signal attachment channels
- Implement token-optimized vision downscaling and JPEG compression
- Add IMAGE_CONTEXT pipeline stage with OmniRoute vision routing and resilient failover
- Seed and manage versioned idea-image-interpreter prompt in catalog
- Update Web UI with responsive image picker, preview chip, and Visual Context tab
- Add comprehensive automated test suite in test_image_intake.py
- Update README and Labyricorn devlog
2026-08-23 01:40:22 -07:00

142 lines
7.6 KiB
HTML

{% extends "base.html" %}
{% block title %}{% if current_state == 'TRASHED' %}Trash Bin - ThinkStorm{% else %}Browse Incubating Ideas - ThinkStorm{% endif %}{% endblock %}
{% block content %}
<div style="margin-bottom: 2rem;">
<h1 style="font-size: 2.2rem; margin-bottom: 0.5rem;">{% if current_state == 'TRASHED' %}🗑️ Trash Bin{% else %}Incubation Catalog{% endif %}</h1>
<p style="color: var(--text-secondary);">
{% if current_state == 'TRASHED' %}
Discarded submissions and unpromising ideas. Items in trash are retrievable at any time until permanently emptied.
{% else %}
Explore anonymous submissions, source-backed research dossiers, and claimed work tracks.
{% endif %}
</p>
</div>
<!-- Toolbar -->
<div class="ideas-toolbar">
<div class="filter-pills">
<a href="/ideas" class="filter-pill {% if not current_state %}active{% endif %}">Available & Active</a>
<a href="/ideas?state=AVAILABLE" class="filter-pill {% if current_state == 'AVAILABLE' %}active{% endif %}">Available</a>
<a href="/ideas?state=CLAIMED" class="filter-pill {% if current_state == 'CLAIMED' %}active{% endif %}">Claimed</a>
<a href="/ideas?state=ACTIVE" class="filter-pill {% if current_state == 'ACTIVE' %}active{% endif %}">Active</a>
<a href="/ideas?state=COMPLETED" class="filter-pill {% if current_state == 'COMPLETED' %}active{% endif %}">Completed</a>
<a href="/ideas?state=ALL" class="filter-pill {% if current_state == 'ALL' %}active{% endif %}">All Ideas</a>
<a href="/ideas?state=TRASHED" class="filter-pill filter-pill-trash {% if current_state == 'TRASHED' %}active{% endif %}">
🗑️ Trash {% if trashed_count and trashed_count > 0 %}<span class="badge badge-trashed" style="font-size:0.7rem; margin-left:0.25rem; padding:0.1rem 0.4rem;">{{ trashed_count }}</span>{% endif %}
</a>
</div>
<form method="GET" action="/ideas" style="display:flex; gap:0.5rem; flex:1; max-width:380px;">
{% if current_state %}<input type="hidden" name="state" value="{{ current_state }}">{% endif %}
<input type="text" name="q" value="{{ search_query or '' }}" class="form-input" placeholder="Search ideas or keywords..." style="padding:0.45rem 0.85rem; font-size:0.9rem;">
<button type="submit" class="btn btn-secondary btn-sm">Search</button>
</form>
</div>
<!-- Trash Banner when in Trash view -->
{% if current_state == 'TRASHED' %}
<div class="glass-card" style="padding:1.25rem 1.5rem; margin-bottom:1.5rem; border-color:rgba(239,68,68,0.3); background:rgba(239,68,68,0.06); display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:1rem;">
<div>
<h3 style="font-size:1.1rem; color:#f87171; margin-bottom:0.25rem; display:flex; align-items:center; gap:0.5rem;">
<span>🗑️ Trash Management</span>
<span class="badge badge-trashed">{{ ideas|length }} item(s)</span>
</h3>
<p style="color:var(--text-secondary); font-size:0.85rem; margin:0;">
Items in the trash are withheld from active incubation. You can restore ideas back to their previous state, or permanently empty the trash.
</p>
</div>
{% if ideas and ideas|length > 0 %}
<button onclick="emptyTrash()" class="btn btn-danger" style="display:flex; align-items:center; gap:0.4rem;">
<span>🗑️ Empty Trash</span>
</button>
{% endif %}
</div>
{% endif %}
<!-- Grid -->
{% if ideas and ideas|length > 0 %}
<div class="ideas-grid">
{% for idea in ideas %}
<div class="glass-card idea-card interactive {% if idea.lifecycle_state == 'TRASHED' %}card-trashed{% endif %}">
<div class="idea-card-header">
<a href="/ideas/{{ idea.id }}" class="idea-id-link">{{ idea.id }}</a>
<div style="display:flex; align-items:center; gap:0.5rem;">
{% if idea.lifecycle_state != 'TRASHED' %}
<div class="maturity-meter" title="Enrichment Level {{ idea.enrichment_level }}/5">
<span style="font-size:0.7rem;">L{{ idea.enrichment_level }}</span>
<div class="dots">
{% for i in range(1, 6) %}
<div class="dot {% if idea.enrichment_level >= i %}active{% endif %}"></div>
{% endfor %}
</div>
</div>
{% endif %}
<span class="badge badge-{{ idea.lifecycle_state|lower }}">{{ idea.lifecycle_state }}</span>
</div>
</div>
<h2 class="idea-card-title">
<a href="/ideas/{{ idea.id }}" style="color:var(--text-primary);">{{ idea.title }}</a>
</h2>
<p class="idea-card-summary">{{ idea.summary }}</p>
{% if idea.tags and idea.tags|length > 0 %}
<div class="tag-list">
{% for t in idea.tags %}
<span class="tag-item">#{{ t }}</span>
{% endfor %}
</div>
{% endif %}
<div class="idea-card-footer">
{% if idea.lifecycle_state == 'TRASHED' %}
<div style="display:flex; gap:0.5rem; width:100%; justify-content:space-between; align-items:center;">
<div style="display:flex; gap:0.4rem;">
<button onclick="restoreIdea('{{ idea.id }}')" class="btn btn-secondary btn-sm" style="color:#34d399;" title="Restore this idea">
♻️ Restore
</button>
<button onclick="deleteIdeaPermanently('{{ idea.id }}')" class="btn btn-danger btn-sm" title="Permanently delete from database">
❌ Delete
</button>
</div>
<a href="/ideas/{{ idea.id }}" style="font-weight:600; font-size:0.85rem;">View Dossier →</a>
</div>
{% else %}
<div>
{% if idea.claimed_by %}
<span>Claimed by <strong>{{ idea.claimed_by }}</strong></span>
{% else %}
<span style="color:var(--color-success);">Ready to claim</span>
{% endif %}
</div>
<div style="display:flex; align-items:center; gap:0.6rem;">
{% if idea.enrichment_level < 4 or idea.lifecycle_state in ['SUBMITTED', 'DUPLICATE', 'QUARANTINED'] %}
<button onclick="event.stopPropagation(); event.preventDefault(); reprocessIdea('{{ idea.id }}');" class="btn btn-warning btn-sm" style="padding:0.25rem 0.6rem; font-size:0.8rem; font-weight:700;" title="Trigger research and feasibility processing">⚡ Process</button>
{% endif %}
<button onclick="event.stopPropagation(); event.preventDefault(); trashIdea('{{ idea.id }}');" class="btn btn-secondary btn-sm" style="padding:0.25rem 0.6rem; color:#f87171; font-size:0.8rem;" title="Move to Trash">🗑️ Trash</button>
<a href="/ideas/{{ idea.id }}" style="font-weight:600; font-size:0.85rem;">View Dossier →</a>
</div>
{% endif %}
</div>
</div>
{% endfor %}
</div>
{% else %}
<div class="glass-card" style="padding: 3rem; text-align: center; margin-top: 1rem;">
{% if current_state == 'TRASHED' %}
<h3 style="margin-bottom: 0.5rem;">Trash is Empty</h3>
<p style="color: var(--text-secondary); margin-bottom: 1.5rem;">There are currently no discarded or trashed ideas.</p>
<a href="/ideas" class="btn btn-secondary">Browse Active Ideas</a>
{% else %}
<h3 style="margin-bottom: 0.5rem;">No ideas found</h3>
<p style="color: var(--text-secondary); margin-bottom: 1.5rem;">There are currently no ideas matching the selected filters.</p>
<a href="/" class="btn btn-primary">⚡ Submit an Idea</a>
{% endif %}
</div>
{% endif %}
{% endblock %}