UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

79 lines 8 kB
import{n as e}from"./rolldown-runtime-DkW27tQK.js";import{R as t,wr as n,z as r}from"./control-ui-foundation-Cydpkyqa.js";import{Eo as i,Oo as a,Sc as o,b as s,bc as c,k as l}from"./control-ui-core-Rwzhj6nO.js";import{$ as u,K as d,X as f,at as p,q as m,r as h,st as g,t as _}from"./lit-runtime-CV_MH99K.js";import{An as v,_ as y,_n as b,g as x,jn as S}from"./control-ui-core-YphAl4aM.js";import{Yt as C,an as w,en as T,in as E}from"./control-ui-core-vvcQQV2m.js";import{dn as D,un as O}from"./control-ui-boot-shared-DfZ39Yj9.js";import{Is as k,Ls as A}from"./control-ui-boot-shared-CXVvK2AW.js";var j,M;function N(){return(N=e((()=>{w(),j={meetings:{refresh:`Refresh`,loading:`Loading meetings…`,emptyTitle:`Your meeting notes, together`,emptyBody:`Meetings appear here once Discord voice or a meeting plugin captures a transcript.`,docs:`Set up meeting transcripts`,select:`Select a meeting to read its notes.`,inProgress:`In progress`,utterances:`{count} utterances`,participants:`Participants`,notesSource:`Notes: {source}`,noNotes:`No notes have been saved for this meeting yet.`,activeNotes:`Capture is in progress. Refresh to check for notes.`,noSpeech:`No speech captured`,loadingNotes:`Loading notes…`,listLabel:`Meetings by day`}},M=Object.assign(()=>{Object.assign(E,j)},{catalog:j})})))()}function P(e){return new Date(e).toLocaleDateString(void 0,{year:`numeric`,month:`long`,day:`numeric`})}var F,I;function L(){return(L=e((()=>{r(),d(),u(),_(),b(),y(),O(),C(),N(),a(),l(),A(),o(),M(),F=class extends c{constructor(...e){super(...e),this.routeSearch=``,this.sessions=null,this.detail=null,this.listLoading=!1,this.detailLoading=!1,this.listError=null,this.detailError=null,this.detailGeneration=0,this.gateway=new k(this,{getGateway:()=>this.context?.gateway,invalidateRequests:()=>{this.detailGeneration++,this.sessions=null,this.detail=null,this.listLoading=!1,this.detailLoading=!1,this.listError=null,this.detailError=null},ensureInitialData:()=>this.refresh()})}get selector(){return new URLSearchParams(this.routeSearch).get(`selector`)}updated(e){e.has(`routeSearch`)&&(this.detailGeneration++,this.detail=null,this.detailLoading=!1,this.detailError=null,this.loadDetail())}refresh(){this.loadList(),this.loadDetail()}async loadList(){let e=this.gateway.client,t=this.gateway.capture();if(!(!e||!t||this.listLoading)){this.listLoading=!0,this.listError=null;try{let n=await e.request(`transcripts.list`,{limit:200});this.gateway.isCurrent(t)&&(this.sessions=n.sessions)}catch(e){this.gateway.isCurrent(t)&&(this.listError=i(e))}finally{this.gateway.isCurrent(t)&&(this.listLoading=!1)}}}async loadDetail(){let e=this.selector,t=this.gateway.client,n=this.gateway.capture();if(!e||!t||!n)return;let r=++this.detailGeneration,a=()=>this.gateway.isCurrent(n)&&r===this.detailGeneration&&this.selector===e;this.detailLoading=!0,this.detailError=null;try{let n=await t.request(`transcripts.get`,{selector:e});a()&&(this.detail=n)}catch(e){a()&&(this.detailError=i(e))}finally{a()&&(this.detailLoading=!1)}}selectMeeting(e){this.context.navigate(`meetings`,{search:`?${new URLSearchParams({selector:e})}`})}renderRow(e){let t=e.utteranceCount===0,n=e.participants.slice(0,3).join(`, `),r=e.participants.length-3,i=e.stoppedAt?s(Math.max(0,Date.parse(e.stoppedAt)-Date.parse(e.startedAt))):null;return f`<button class="meetings-row ${this.selector===e.selector?`selected`:``} ${t?`meetings-row--silent`:``}" type="button" aria-current=${this.selector===e.selector?`true`:m} @click=${()=>this.selectMeeting(e.selector)} > <span class="meetings-row__title" >${e.title||e.providerName||e.providerId}</span > <span class="meetings-row__meta" >${e.providerName||e.providerId} · ${new Date(e.startedAt).toLocaleTimeString(void 0,{hour:`2-digit`,minute:`2-digit`})} ${e.active?f`<span class="meetings-live">${T(`meetings.inProgress`)}</span>`:i?f` · ${i}`:m} </span> ${n?f`<span class="meetings-row__meta meetings-row__participants" >${n}${r>0?` +${r}`:``}</span >`:m} <span class="meetings-row__meta" >${T(`meetings.utterances`,{count:String(e.utteranceCount)})}</span > ${t||e.overview?f`<span class="meetings-row__overview" >${t?T(`meetings.noSpeech`):e.overview}</span >`:m} </button>`}renderList(){let e=new Map;for(let t of(this.sessions??[]).toSorted((e,t)=>t.startedAt.localeCompare(e.startedAt))){let n=P(t.startedAt),r=e.get(n)??[];r.push(t),e.set(n,r)}return f`<aside class="meetings-list" aria-label=${T(`meetings.listLabel`)}> ${Array.from(e,([e,t])=>f`<section class="meetings-day"> <h2>${e}</h2> ${t.map(e=>this.renderRow(e))} </section>`)} </aside>`}renderDetail(){let e=this.detail;return f`<section class="meetings-detail" aria-busy=${this.detailLoading}> ${this.detailError?f`<div class="callout danger" role="alert">${this.detailError}</div>`:m} ${e?f` <div class="meetings-detail__meta"> ${e.session.summarySource?f`<span >${T(`meetings.notesSource`,{source:e.session.summarySource})}</span >`:m} ${e.session.active?f`<span class="meetings-live">${T(`meetings.inProgress`)}</span>`:m} </div> ${e.summary?.participants.length?f`<p> <strong>${T(`meetings.participants`)}:</strong> ${e.summary.participants.join(`, `)} </p>`:m} ${e.summary?f`<div class="meetings-notes markdown"> ${h(D(e.summary.markdown))} </div>`:f`<h2> ${e.session.title||e.session.providerName||e.session.providerId} </h2> <p>${T(`meetings.noNotes`)}</p> ${e.session.active?f`<p>${T(`meetings.activeNotes`)}</p>`:m}`} `:f`<p class="muted"> ${T(this.detailLoading?`meetings.loadingNotes`:`meetings.select`)} </p>`} </section>`}render(){return f`<section class="content-header content-header--page"> <div> <div class="page-title">${S(`meetings`)}</div> <div class="page-sub">${v(`meetings`)}</div> </div> <button class="btn" type="button" ?disabled=${this.listLoading||!this.gateway.connected} @click=${()=>this.refresh()} > ${T(`meetings.refresh`)} </button> </section> ${this.listError?f`<div class="callout danger" role="alert">${this.listError}</div>`:m} ${this.sessions?.length||this.selector?f`<div class="meetings-layout">${this.renderList()}${this.renderDetail()}</div>`:this.sessions&&!this.listError?f`<section class="meetings-empty" role="status"> <h2>${T(`meetings.emptyTitle`)}</h2> <p>${T(`meetings.emptyBody`)}</p> <a href="https://docs.openclaw.ai/cli/transcripts" target="_blank" rel="noopener noreferrer" >${T(`meetings.docs`)}</a > </section>`:this.listLoading?f`<p role="status">${T(`meetings.loading`)}</p>`:m}`}},n([t({context:x,subscribe:!0})],F.prototype,`context`,void 0),n([g({attribute:!1})],F.prototype,`routeSearch`,void 0),n([p()],F.prototype,`sessions`,void 0),n([p()],F.prototype,`detail`,void 0),n([p()],F.prototype,`listLoading`,void 0),n([p()],F.prototype,`detailLoading`,void 0),n([p()],F.prototype,`listError`,void 0),n([p()],F.prototype,`detailError`,void 0),I={header:!0,render:e=>f`<openclaw-meetings-page .routeSearch=${typeof e==`string`?e:``} ></openclaw-meetings-page>`},customElements.get(`openclaw-meetings-page`)||customElements.define(`openclaw-meetings-page`,F)})))()}L();export{I as meetingsPageComponent}; //# sourceMappingURL=meetings-page-BMcLjmIh.js.map