diff --git a/CHANGELOG.md b/CHANGELOG.md index 521ed82c..5f4c84ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,11 @@ All notable changes to MeMesh are documented here. its own **Project** tab. Old `?tab=` deep links and stored tab choices migrate to the surface that absorbed them, so a bookmarked `?tab=Browse` opens Memories instead of nothing. +- **One notice at a time.** The Doctor, Onboarding and Insights banners + could stack three deep above the nav. They now share a priority slot — + Doctor (broken install) > Onboarding (empty library) > Insights + (pending proposals) — showing exactly one; the next in line surfaces + the moment the winner is dismissed or its condition clears. ## [4.6.0] — 2026-08-16 diff --git a/dashboard/dist/index.html b/dashboard/dist/index.html index 1684cbb5..93219d80 100644 --- a/dashboard/dist/index.html +++ b/dashboard/dist/index.html @@ -26,8 +26,8 @@ ${v(F)}`}catch{}}const P=n(co[i]),B=`https://github.com/PCIRCLE-AI/memesh/issues/new?title=${encodeURIComponent(`[${P}] `)}&body=${encodeURIComponent(S)}&labels=${encodeURIComponent(f)}`;window.open(B,"_blank"),u(""),o(!1)}finally{g(!1)}}};return e(Z,{children:[e("button",{ref:b,class:"fb-btn",onClick:()=>o(!s),"aria-haspopup":"dialog","aria-expanded":s,"aria-controls":"fb-panel",children:n("feedback.button")}),s&&e("div",{class:"fb-panel",ref:l,role:"dialog",id:"fb-panel","aria-labelledby":"fb-title",children:[e("h3",{class:"fb-title",id:"fb-title",children:n("feedback.title")}),e("div",{class:"fb-types",children:Yr.map(f=>e("label",{class:`fb-type ${i===f?"selected":""}`,children:[e("input",{type:"radio",name:"fb-type",value:f,checked:i===f,onChange:()=>r(f)}),n(co[f])]},f))}),e("textarea",{ref:y,class:"fb-desc","aria-label":n("feedback.descLabel"),placeholder:n("feedback.placeholder"),value:a,onInput:f=>u(f.target.value)}),e("label",{class:"fb-sys-row",children:[e("input",{type:"checkbox",checked:m,onChange:()=>c(!m)}),n("feedback.includeSys")]}),e("button",{class:"btn btn-primary fb-submit",onClick:w,disabled:d,children:n(d?"feedback.submitting":"feedback.submit")})]})]})}function Jr({currentToken:t,onSubmit:s,rejected:o=!1}){const[i,r]=M(t??""),[a,u]=M(!1);function m(l){l.preventDefault(),u(!0),i.trim()&&s(i.trim())}const c=a&&!i.trim(),d=o&&!c,g=c||d?"auth-prompt-error":void 0;return e("div",{class:"auth-prompt-shell","data-testid":"auth-prompt",children:e("form",{class:"auth-prompt-card",onSubmit:m,children:[e("h1",{children:n("auth.title")}),e("p",{children:n("auth.intro")}),e("label",{children:[e("span",{children:n("auth.tokenLabel")}),e("input",{type:"password",autocomplete:"off",value:i,onInput:l=>r(l.target.value),placeholder:n("auth.tokenPlaceholder"),"aria-invalid":g!==void 0,"aria-describedby":g,autofocus:!0})]}),c&&e("p",{class:"auth-prompt-error",id:g,role:"alert",children:n("auth.empty")}),d&&e("p",{class:"auth-prompt-error",id:g,role:"alert",children:n("auth.invalid")}),e("button",{type:"submit",class:"auth-prompt-submit",children:n("auth.submit")})]})})}const mo="memesh.onboardingDismissed";function Qr({health:t}){const[s,o]=M(()=>{try{return localStorage.getItem(mo)==="true"}catch{return!1}}),[i,r]=M(null),[a,u]=M("");if(ee(()=>{t&&t.entity_count>0&&o(!0)},[t?.entity_count]),!t||t.entity_count>0||s)return null;function m(){o(!0);try{localStorage.setItem(mo,"true")}catch{}}async function c(){u(""),r("seed");try{await Y("POST","/v1/demo/seed"),window.dispatchEvent(new Event("memesh:data-changed"))}catch(g){u(Se(g))}finally{r(null)}}async function d(){if(confirm(n("onboarding.resetConfirm"))){u(""),r("reset");try{await Y("POST","/v1/demo/reset"),window.dispatchEvent(new Event("memesh:data-changed"))}catch(g){u(Se(g))}finally{r(null)}}}return e("div",{role:"region","aria-label":n("onboarding.title"),style:{position:"relative",margin:"12px auto 8px",maxWidth:920,padding:"14px 18px",border:"1px solid rgba(143, 242, 92, 0.28)",borderRadius:"var(--radius)",background:"var(--life-soft)",color:"var(--text-1)"},children:[e("button",{type:"button",onClick:m,"aria-label":n("onboarding.dismiss"),style:{position:"absolute",top:8,right:10,background:"transparent",border:"none",color:"var(--text-3)",fontSize:18,lineHeight:1,cursor:"pointer",padding:4},children:"×"}),e("div",{style:{fontSize:14,fontWeight:600,color:"var(--text-0)",marginBottom:6},children:n("onboarding.title")}),e("div",{style:{fontSize:13,lineHeight:1.55,color:"var(--text-1)"},children:n("onboarding.body")}),e("div",{style:{fontSize:11,lineHeight:1.55,color:"var(--text-3)",marginTop:4},children:n("onboarding.llmHint")}),e("div",{style:{display:"flex",flexWrap:"wrap",gap:10,marginTop:12,alignItems:"center"},children:[e("button",{type:"button",class:"btn btn-primary",onClick:c,disabled:i!==null,style:{minWidth:160},children:n(i==="seed"?"onboarding.seedingButton":"onboarding.seedButton")}),e("span",{style:{fontSize:12,color:"var(--text-3)"},children:n("onboarding.seedHint")})]}),e("details",{style:{marginTop:10,fontSize:12,color:"var(--text-3)"},children:[e("summary",{style:{cursor:"pointer"},children:n("onboarding.cliReference")}),e("div",{style:{display:"flex",flexWrap:"wrap",gap:12,marginTop:8},children:[e("code",{style:{padding:"6px 10px",background:"rgba(0, 0, 0, 0.3)",border:"1px solid rgba(143, 242, 92, 0.20)",borderRadius:"var(--radius-xs)",color:"var(--life)",fontFamily:"var(--mono)",fontSize:12},children:"memesh demo"}),e("span",{style:{fontSize:12,color:"var(--text-3)"},children:n("onboarding.hintDemo")})]}),e("div",{style:{display:"flex",flexWrap:"wrap",gap:12,marginTop:8,alignItems:"center"},children:[e("code",{style:{padding:"6px 10px",background:"rgba(0, 0, 0, 0.3)",border:"1px solid var(--border-subtle)",borderRadius:"var(--radius-xs)",color:"var(--text-2)",fontFamily:"var(--mono)",fontSize:12},children:"memesh demo --reset --yes"}),e("button",{type:"button",class:"btn",onClick:d,disabled:i!==null,style:{fontSize:11,padding:"4px 10px"},children:n(i==="reset"?"onboarding.resettingButton":"onboarding.resetButton")}),e("span",{style:{fontSize:12,color:"var(--text-3)"},children:n("onboarding.hintReset")})]})]}),a&&e("div",{role:"alert",style:{marginTop:10,fontSize:12,color:"var(--danger)"},children:a})]})}const uo="memesh.doctorBanner.dismissedSig";function bs(t,s,o){const i=n(t,o);return i===t?s:i}function Zr(t){return t.code?bs(`doctor.msg.${t.code}.summary`,t.summary,t.params):t.summary}function ea(t){if(t.fix)return t.code?bs(`doctor.msg.${t.code}.fix`,t.fix,t.params):t.fix}function ta(t){return bs(`doctor.label.${t.id}`,t.label)}const sa=new Set(["update-status.no-cache","update-status.stale","update-status.deprecation-unknown","hook-activity.not-wired","shell-cli.not-on-path","skills-manifest.missing-dev","install-channel.unknown","http-probe.no-server","readme-parity.unreadable","readme-parity.drift"]);function oa(t){if(t.status==="fail")return!0;if(t.status!=="warn"||t.code&&sa.has(t.code)||!t.fix)return!1;const s=t.fix.trim().toLowerCase();return!(!s||s==="no action needed"||s.startsWith("no action"))}function na(){const[t,s]=M(null),[o,i]=M(()=>{try{return localStorage.getItem(uo)??""}catch{return""}});if(ee(()=>{let b=!0;const y=()=>{Y("GET","/v1/doctor").then(v=>{b&&s(Array.isArray(v?.checks)?v:null)}).catch(()=>{})};y();const h=()=>y();return window.addEventListener("memesh:data-changed",h),()=>{b=!1,window.removeEventListener("memesh:data-changed",h)}},[]),!t||t.status==="PASS")return null;const r=t.checks.filter(oa);if(r.length===0)return null;const a=r.map(b=>`${b.id}:${b.status}:${b.code??""}:${b.params?.hook??""}`).sort().join("|");if(a===o)return null;function u(){i(a);try{localStorage.setItem(uo,a)}catch{}}function m(){const b=r.map(w=>{const f=w.status==="fail"?"❌":"⚠️",S=w.fix?` _Fix: ${w.fix}_`:"";return`- ${f} **${w.label}**: ${w.summary}${S}`}),y=`${n("doctorBanner.preambleForIssue")} ${b.join(` -`)}`,v=`https://github.com/PCIRCLE-AI/memesh/issues/new?title=${encodeURIComponent("[Bug] memesh doctor reported issues")}&body=${encodeURIComponent(y)}&labels=${encodeURIComponent("feedback,from-dashboard,bug,doctor-warning")}`;window.open(v,"_blank")}const c=t.status==="FAIL",d=c?"var(--danger)":"var(--warning)",g=c?"var(--danger-soft)":"var(--warning-soft)";return e("div",{role:"alert",style:{position:"relative",margin:"12px auto 0",maxWidth:920,padding:"12px 16px",border:`1px solid ${d}`,borderRadius:"var(--radius)",background:g,color:"var(--text-1)"},children:[e("button",{type:"button",onClick:u,"aria-label":n("doctorBanner.dismiss"),style:{position:"absolute",top:6,right:8,background:"transparent",border:"none",color:"var(--text-3)",fontSize:18,lineHeight:1,cursor:"pointer",padding:4},children:"×"}),e("div",{style:{fontSize:13,fontWeight:600,color:d,marginBottom:6},children:n(c?"doctorBanner.failTitle":"doctorBanner.warnTitleSoft")}),e("ul",{style:{margin:"6px 0 10px",paddingLeft:18,fontSize:12,lineHeight:1.5,color:"var(--text-2)"},children:[r.slice(0,3).map(b=>{const y=ea(b);return e("li",{children:[e("strong",{children:[ta(b),":"]})," ",Zr(b),y&&e(Z,{children:[" — ",e("em",{style:{color:"var(--text-3)"},children:y})]})]},b.id)}),r.length>3&&e("li",{style:{color:"var(--text-3)"},children:n("doctorBanner.moreCount",{n:r.length-3})})]}),c&&e("div",{style:{display:"flex",gap:8,alignItems:"center",flexWrap:"wrap"},children:[e("button",{type:"button",class:"btn",onClick:m,style:{fontSize:12,padding:"4px 12px"},children:n("doctorBanner.getHelp")}),e("span",{style:{fontSize:11,color:"var(--text-3)"},children:n("doctorBanner.helpHint")})]})]})}const ho="memesh.insightsBanner.dismissed";function ra({currentTab:t,onNavigateToInsights:s}){const[o,i]=M(0),[r,a]=M(()=>{try{return sessionStorage.getItem(ho)==="true"}catch{return!1}});if(ee(()=>{let c=!0;const d=()=>{Y("GET","/v1/dream/proposals?status=pending").then(l=>{if(!c)return;const b=Array.isArray(l)?l:l?.data??[];i(b.length)}).catch(()=>{})};d();const g=()=>d();return window.addEventListener("memesh:data-changed",g),()=>{c=!1,window.removeEventListener("memesh:data-changed",g)}},[]),t==="Home"||r||o===0)return null;function u(c){c.stopPropagation(),a(!0);try{sessionStorage.setItem(ho,"true")}catch{}}const m=n("banner.pendingInsights",{n:o,s:o===1?"":"s"});return e("div",{role:"button","aria-label":n("banner.viewAll"),onClick:s,onKeyDown:c=>{(c.key==="Enter"||c.key===" ")&&(c.preventDefault(),s())},tabIndex:0,style:{position:"relative",margin:"12px auto 0",maxWidth:920,padding:"10px 40px 10px 16px",border:"1px solid rgba(143, 242, 92, 0.32)",borderRadius:"var(--radius)",background:"var(--life-soft)",color:"var(--text-1)",cursor:"pointer",fontSize:13,lineHeight:1.5,display:"flex",alignItems:"center",justifyContent:"space-between",gap:8},children:[e("span",{style:{flex:1},children:[e("span",{style:{marginRight:6},"aria-hidden":"true",children:"💡"}),m]}),e("button",{type:"button",onClick:u,"aria-label":n("banner.dismiss"),style:{position:"absolute",top:6,right:8,background:"transparent",border:"none",color:"var(--text-3)",fontSize:18,lineHeight:1,cursor:"pointer",padding:4},children:"×"})]})}const Oo=["Home","Memories","Project","Graph","Settings"],aa={Home:"tab.home",Memories:"tab.memories",Project:"tab.project",Graph:"tab.graph",Settings:"tab.settings"},ia={Insights:"Home",Analytics:"Home",Search:"Memories",Browse:"Memories",Manage:"Memories",Lessons:"Memories"},Bo="memesh.tab";function la(){const t=s=>s?Oo.includes(s)?s:ia[s]??null:null;try{const s=new URLSearchParams(window.location.search),o=t(s.get("tab"));if(o)return o;const i=t(localStorage.getItem(Bo));if(i)return i}catch{}return"Home"}function ca(){const[t,s]=M(()=>mn()),[o,i]=M(la),[r,a]=M(()=>new Set);ee(()=>{a(f=>f.has(o)?f:new Set(f).add(o))},[o]);const u=f=>r.has(f)||o===f;ee(()=>{try{localStorage.setItem(Bo,o)}catch{}},[o]);const[m,c]=M(null),[d,g]=M(""),[l,b]=M(!1);ee(()=>{const f=()=>b(!0);return window.addEventListener("memesh:auth-required",f),()=>window.removeEventListener("memesh:auth-required",f)},[]);const[y,h]=M(!1),v=Ce(()=>{Y("GET","/v1/health").then(f=>{c(f),g(""),b(!1)}).catch(f=>{if(f instanceof fs){h(is()!==null),b(!0),g("");return}g(f.message)})},[]);ee(()=>{v();const f=()=>v();return window.addEventListener("memesh:data-changed",f),()=>window.removeEventListener("memesh:data-changed",f)},[v]);const w=Oo.map(f=>({key:f,label:n(aa[f])}));return l?e(Jr,{currentToken:is(),rejected:y,onSubmit:f=>{vn(f),h(!1),b(!1),v()}}):e("div",{class:"shell",children:[e(pn,{health:m,error:d}),e(na,{}),e(ra,{currentTab:o,onNavigateToInsights:()=>i("Home")}),e(Qr,{health:m}),e(fn,{tabs:w,active:o,onSelect:f=>i(f)}),e("div",{class:"main",children:[e("div",{id:"panel-Home",role:"tabpanel","aria-labelledby":"tab-Home",class:`panel ${o==="Home"?"active":""}`,children:o==="Home"&&e(er,{})}),e("div",{id:"panel-Memories",role:"tabpanel","aria-labelledby":"tab-Memories",class:`panel ${o==="Memories"?"active":""}`,children:u("Memories")&&e(vr,{health:m})}),e("div",{id:"panel-Project",role:"tabpanel","aria-labelledby":"tab-Project",class:`panel ${o==="Project"?"active":""}`,children:u("Project")&&e(Lr,{health:m})}),e("div",{id:"panel-Graph",role:"tabpanel","aria-labelledby":"tab-Graph",class:`panel ${o==="Graph"?"active":""}`,children:o==="Graph"&&e(Gr,{})}),e("div",{id:"panel-Settings",role:"tabpanel","aria-labelledby":"tab-Settings",class:`panel ${o==="Settings"?"active":""}`,children:o==="Settings"&&e(Dr,{locale:t,onLocaleChange:s})})]}),e(Xr,{health:m})]})}on(e(ca,{}),document.getElementById("app")); - +`)}`,v=`https://github.com/PCIRCLE-AI/memesh/issues/new?title=${encodeURIComponent("[Bug] memesh doctor reported issues")}&body=${encodeURIComponent(y)}&labels=${encodeURIComponent("feedback,from-dashboard,bug,doctor-warning")}`;window.open(v,"_blank")}const c=t.status==="FAIL",d=c?"var(--danger)":"var(--warning)",g=c?"var(--danger-soft)":"var(--warning-soft)";return e("div",{role:"alert",style:{position:"relative",margin:"12px auto 0",maxWidth:920,padding:"12px 16px",border:`1px solid ${d}`,borderRadius:"var(--radius)",background:g,color:"var(--text-1)"},children:[e("button",{type:"button",onClick:u,"aria-label":n("doctorBanner.dismiss"),style:{position:"absolute",top:6,right:8,background:"transparent",border:"none",color:"var(--text-3)",fontSize:18,lineHeight:1,cursor:"pointer",padding:4},children:"×"}),e("div",{style:{fontSize:13,fontWeight:600,color:d,marginBottom:6},children:n(c?"doctorBanner.failTitle":"doctorBanner.warnTitleSoft")}),e("ul",{style:{margin:"6px 0 10px",paddingLeft:18,fontSize:12,lineHeight:1.5,color:"var(--text-2)"},children:[r.slice(0,3).map(b=>{const y=ea(b);return e("li",{children:[e("strong",{children:[ta(b),":"]})," ",Zr(b),y&&e(Z,{children:[" — ",e("em",{style:{color:"var(--text-3)"},children:y})]})]},b.id)}),r.length>3&&e("li",{style:{color:"var(--text-3)"},children:n("doctorBanner.moreCount",{n:r.length-3})})]}),c&&e("div",{style:{display:"flex",gap:8,alignItems:"center",flexWrap:"wrap"},children:[e("button",{type:"button",class:"btn",onClick:m,style:{fontSize:12,padding:"4px 12px"},children:n("doctorBanner.getHelp")}),e("span",{style:{fontSize:11,color:"var(--text-3)"},children:n("doctorBanner.helpHint")})]})]})}const ho="memesh.insightsBanner.dismissed";function ra({currentTab:t,onNavigateToInsights:s}){const[o,i]=M(0),[r,a]=M(()=>{try{return sessionStorage.getItem(ho)==="true"}catch{return!1}});if(ee(()=>{let c=!0;const d=()=>{Y("GET","/v1/dream/proposals?status=pending").then(l=>{if(!c)return;const b=Array.isArray(l)?l:l?.data??[];i(b.length)}).catch(()=>{})};d();const g=()=>d();return window.addEventListener("memesh:data-changed",g),()=>{c=!1,window.removeEventListener("memesh:data-changed",g)}},[]),t==="Home"||r||o===0)return null;function u(c){c.stopPropagation(),a(!0);try{sessionStorage.setItem(ho,"true")}catch{}}const m=n("banner.pendingInsights",{n:o,s:o===1?"":"s"});return e("div",{role:"button","aria-label":n("banner.viewAll"),onClick:s,onKeyDown:c=>{(c.key==="Enter"||c.key===" ")&&(c.preventDefault(),s())},tabIndex:0,style:{position:"relative",margin:"12px auto 0",maxWidth:920,padding:"10px 40px 10px 16px",border:"1px solid rgba(143, 242, 92, 0.32)",borderRadius:"var(--radius)",background:"var(--life-soft)",color:"var(--text-1)",cursor:"pointer",fontSize:13,lineHeight:1.5,display:"flex",alignItems:"center",justifyContent:"space-between",gap:8},children:[e("span",{style:{flex:1},children:[e("span",{style:{marginRight:6},"aria-hidden":"true",children:"💡"}),m]}),e("button",{type:"button",onClick:u,"aria-label":n("banner.dismiss"),style:{position:"absolute",top:6,right:8,background:"transparent",border:"none",color:"var(--text-3)",fontSize:18,lineHeight:1,cursor:"pointer",padding:4},children:"×"})]})}const Oo=["Home","Memories","Project","Graph","Settings"],aa={Home:"tab.home",Memories:"tab.memories",Project:"tab.project",Graph:"tab.graph",Settings:"tab.settings"},ia={Insights:"Home",Analytics:"Home",Search:"Memories",Browse:"Memories",Manage:"Memories",Lessons:"Memories"},Bo="memesh.tab";function la(){const t=s=>s?Oo.includes(s)?s:ia[s]??null:null;try{const s=new URLSearchParams(window.location.search),o=t(s.get("tab"));if(o)return o;const i=t(localStorage.getItem(Bo));if(i)return i}catch{}return"Home"}function ca(){const[t,s]=M(()=>mn()),[o,i]=M(la),[r,a]=M(()=>new Set);ee(()=>{a(f=>f.has(o)?f:new Set(f).add(o))},[o]);const u=f=>r.has(f)||o===f;ee(()=>{try{localStorage.setItem(Bo,o)}catch{}},[o]);const[m,c]=M(null),[d,g]=M(""),[l,b]=M(!1);ee(()=>{const f=()=>b(!0);return window.addEventListener("memesh:auth-required",f),()=>window.removeEventListener("memesh:auth-required",f)},[]);const[y,h]=M(!1),v=Ce(()=>{Y("GET","/v1/health").then(f=>{c(f),g(""),b(!1)}).catch(f=>{if(f instanceof fs){h(is()!==null),b(!0),g("");return}g(f.message)})},[]);ee(()=>{v();const f=()=>v();return window.addEventListener("memesh:data-changed",f),()=>window.removeEventListener("memesh:data-changed",f)},[v]);const w=Oo.map(f=>({key:f,label:n(aa[f])}));return l?e(Jr,{currentToken:is(),rejected:y,onSubmit:f=>{vn(f),h(!1),b(!1),v()}}):e("div",{class:"shell",children:[e(pn,{health:m,error:d}),e("div",{class:"notice-slot",children:[e(na,{}),e(Qr,{health:m}),e(ra,{currentTab:o,onNavigateToInsights:()=>i("Home")})]}),e(fn,{tabs:w,active:o,onSelect:f=>i(f)}),e("div",{class:"main",children:[e("div",{id:"panel-Home",role:"tabpanel","aria-labelledby":"tab-Home",class:`panel ${o==="Home"?"active":""}`,children:o==="Home"&&e(er,{})}),e("div",{id:"panel-Memories",role:"tabpanel","aria-labelledby":"tab-Memories",class:`panel ${o==="Memories"?"active":""}`,children:u("Memories")&&e(vr,{health:m})}),e("div",{id:"panel-Project",role:"tabpanel","aria-labelledby":"tab-Project",class:`panel ${o==="Project"?"active":""}`,children:u("Project")&&e(Lr,{health:m})}),e("div",{id:"panel-Graph",role:"tabpanel","aria-labelledby":"tab-Graph",class:`panel ${o==="Graph"?"active":""}`,children:o==="Graph"&&e(Gr,{})}),e("div",{id:"panel-Settings",role:"tabpanel","aria-labelledby":"tab-Settings",class:`panel ${o==="Settings"?"active":""}`,children:o==="Settings"&&e(Dr,{locale:t,onLocaleChange:s})})]}),e(Xr,{health:m})]})}on(e(ca,{}),document.getElementById("app")); +
diff --git a/dashboard/src/App.tsx b/dashboard/src/App.tsx index 27948fa7..10a22b5a 100644 --- a/dashboard/src/App.tsx +++ b/dashboard/src/App.tsx @@ -167,9 +167,18 @@ export function App() { return (