* feat(web): Curated Memory restructure + per-user Dismiss + filter-state utility
Squashed from cvrysanek/zsrotyr's 4-commit PR branch + rebased onto
current main + CHANGELOG bullets spliced into [Unreleased] (preserves
existing #316/#320/#322 entries that landed on main since the branch
was authored).
Routes + access:
- /corporate-memory now user-facing (get_current_user), in primary
nav next to "Data Packages" — same gate as /api/memory/*.
- /admin/corporate-memory is the new admin review queue location
(was /corporate-memory/admin); reached via Admin dropdown. Template
renamed: corporate_memory_admin.html → admin_corporate_memory.html.
Visual chrome:
- Both pages migrate to shared _page_hero.html blue hero band.
Per-user Dismiss (new feature, schema v46):
- knowledge_item_user_dismissed(user_id, item_id, dismissed_at) + index.
- POST /api/memory/{id}/dismiss + DELETE (idempotent).
- Mandatory items can never be dismissed — enforced at 2 layers.
- GET /api/memory: hide_dismissed=false default + dismissed_by_me flag.
- GET /api/memory/bundle: always excludes dismissed for the caller.
- UI: Dismiss/Undismiss button per item (hidden for mandatory),
gray-out + line-through for dismissed rows, Hide-dismissed toggle.
Admin edit modal:
- Category as <select> + "Add new category…" reveal.
- Audience as <select> with (unset)/all/group:<name> from RBAC.
- Tags: full tag-input widget (pills, ×-remove, Backspace pop,
Enter/comma to add, ↑/↓ typeahead from EXISTING_TAGS).
Bulk-edit modal pickers (closes #128):
- Move-to-category / Add-tag: <select> + add-new.
- Set-audience: <select> (no more typo-able 'gourp:eng').
- Remove-tag: closed-set picker.
FilterState utility:
- app/web/static/js/filter-state.js — save/load/clear/bindInputs
for per-page localStorage filter state. Adopted on /corporate-memory.
E2E verified live on a real VM through the API + browser flow.
* release: 0.54.18 — Curated Memory restructure + 4 adversarial-review fixes
Bundles together:
- #316 fix(store): surface review failures + harden publish gate
(BREAKING fail-CLOSED guardrail, override v2+ promote, restore guard,
retry/rescan staged-bundle, banner widening, LLM truncation retry)
- #320 fix(store): C2 bundle export RBAC + H2 per-entity write lock +
H3 update_status compare-and-swap with bg_verdict_skipped audit
- #322 fix(store): M1 prompt sentinel filename escape + M2 atomic
promote_to_version helper + L1 admin forensic download per-version
- #324 Curated Memory restructure + per-user Dismiss + FilterState utility
Bump from 0.54.17 → 0.54.18 (patch — pre-1.0 policy: every cycle is patch).
150 lines
4.6 KiB
HTML
150 lines
4.6 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Home — {{ instance_name or "AI Data Analyst" }}{% endblock %}
|
|
|
|
{% block content %}
|
|
{% include "_page_chrome.html" %}
|
|
<style>
|
|
.home-mock {
|
|
--hp-primary: #0073D1;
|
|
--hp-primary-dark: #0056A3;
|
|
--hp-primary-light: #E6F3FC;
|
|
--hp-border: #E5E7EB;
|
|
--hp-border-light: #F3F4F6;
|
|
--hp-text-primary: #111827;
|
|
--hp-text-secondary: #6B7280;
|
|
color: var(--hp-text-primary);
|
|
font-size: 14px;
|
|
line-height: 1.5;
|
|
}
|
|
.home-mock * { box-sizing: border-box; }
|
|
|
|
.home-mock .hero {
|
|
background: linear-gradient(135deg, #0073D1 0%, #0056A3 100%);
|
|
color: white;
|
|
border-radius: 16px;
|
|
padding: 38px 40px;
|
|
margin-bottom: 22px;
|
|
box-shadow: 0 8px 24px rgba(0, 86, 163, 0.18);
|
|
}
|
|
.home-mock .hero .eyebrow {
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.8px;
|
|
opacity: 0.85;
|
|
margin-bottom: 10px;
|
|
}
|
|
.home-mock .hero h1 {
|
|
font-size: 30px;
|
|
font-weight: 600;
|
|
letter-spacing: -0.4px;
|
|
margin-bottom: 12px;
|
|
line-height: 1.2;
|
|
color: white;
|
|
}
|
|
.home-mock .hero p {
|
|
font-size: 15px;
|
|
opacity: 0.94;
|
|
max-width: 680px;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.home-mock .section-label {
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.6px;
|
|
color: var(--hp-text-secondary);
|
|
margin: 30px 0 12px;
|
|
}
|
|
|
|
.home-mock .quick-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
|
gap: 18px;
|
|
margin-bottom: 18px;
|
|
}
|
|
.home-mock .quick-card {
|
|
background: white;
|
|
border: 1px solid var(--hp-border);
|
|
border-radius: 12px;
|
|
padding: 22px;
|
|
text-decoration: none;
|
|
color: inherit;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
transition: border-color .15s, box-shadow .15s;
|
|
}
|
|
.home-mock .quick-card:hover {
|
|
border-color: var(--hp-primary);
|
|
box-shadow: 0 4px 12px rgba(0, 115, 209, 0.10);
|
|
}
|
|
.home-mock .quick-card .ico {
|
|
font-size: 22px;
|
|
margin-bottom: 8px;
|
|
}
|
|
.home-mock .quick-card .ttl {
|
|
font-size: 15px;
|
|
font-weight: 600;
|
|
color: var(--hp-text-primary);
|
|
}
|
|
.home-mock .quick-card .desc {
|
|
font-size: 13px;
|
|
color: var(--hp-text-secondary);
|
|
line-height: 1.55;
|
|
}
|
|
</style>
|
|
|
|
<div class="home-mock">
|
|
{% set display_name = (user.name or (user.email or "").split("@")[0] or "back") %}
|
|
|
|
<div class="hero">
|
|
<div class="eyebrow">Welcome back, {{ display_name }}</div>
|
|
<h1>You're all set up</h1>
|
|
<p>
|
|
Open Claude Code in any project under <code style="background: rgba(255,255,255,0.12); padding: 1px 6px; border-radius: 4px; font-family: ui-monospace, 'SF Mono', Consolas, monospace; font-size: 12.5px;">~/{{ workspace_dir }}/Projects/</code>
|
|
and start a session — your data and plugins are already synced. Use the cards below to jump into the parts of {{ instance_brand }} you need.
|
|
</p>
|
|
</div>
|
|
|
|
<div class="section-label">Quick links</div>
|
|
|
|
<div class="quick-grid">
|
|
<a class="quick-card" href="/dashboard">
|
|
<span class="ico">📊</span>
|
|
<div class="ttl">Dashboard</div>
|
|
<div class="desc">Sync state, table inventory, recent activity.</div>
|
|
</a>
|
|
<a class="quick-card" href="/catalog">
|
|
<span class="ico">📚</span>
|
|
<div class="ttl">Catalog</div>
|
|
<div class="desc">Browse tables, schema, and metric definitions.</div>
|
|
</a>
|
|
{# Curated Memory is user-facing — the /corporate-memory route runs
|
|
on get_current_user, so the card shows for everyone, matching
|
|
its primary-nav placement next to Data Packages. #}
|
|
<a class="quick-card" href="/corporate-memory">
|
|
<span class="ico">🧠</span>
|
|
<div class="ttl">Curated Memory</div>
|
|
<div class="desc">Shared analyst knowledge and prior solutions.</div>
|
|
</a>
|
|
{# Activity Center admin-only — parity with the top-nav gating. #}
|
|
{% if is_admin %}
|
|
<a class="quick-card" href="/activity-center">
|
|
<span class="ico">📈</span>
|
|
<div class="ttl">Activity Center</div>
|
|
<div class="desc">Per-user analytics on {{ instance_brand }} adoption.</div>
|
|
</a>
|
|
{% endif %}
|
|
{% if is_admin %}
|
|
<a class="quick-card" href="/admin/server-config">
|
|
<span class="ico">⚙️</span>
|
|
<div class="ttl">Admin</div>
|
|
<div class="desc">Server configuration, RBAC, marketplaces.</div>
|
|
</a>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|