@augmentd-labs/canvas-web 2.26.43 → 2.26.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/CalendarApplet-CsyUmI2B.js +2 -0
- package/dist/assets/{DocumentBodyEditor-CVO5KPCs.js → DocumentBodyEditor-C8AEpqX3.js} +1 -1
- package/dist/assets/{DocumentIcon-9i1uCMQa.js → DocumentIcon-0ya9gycp.js} +1 -1
- package/dist/assets/{EditorOverlay-D5t3xg4w.js → EditorOverlay-DglJkHo3.js} +1 -1
- package/dist/assets/{FiltersApplet-gQ6jhX7q.js → FiltersApplet-CVnCAs-P.js} +1 -1
- package/dist/assets/HomeFab-iC5BF7LV.js +3 -0
- package/dist/assets/{IdentityFields-D-NCTUaE.js → IdentityFields-CB3Ap0bl.js} +1 -1
- package/dist/assets/{LensApplet-WFygUZx1.js → LensApplet-DA0ZWS1k.js} +1 -1
- package/dist/assets/LinkToCard-oi3wGP0a.js +1 -0
- package/dist/assets/{MarkdownEditor-DbpRWbO6.js → MarkdownEditor-bDoyR7l2.js} +2 -2
- package/dist/assets/{MessageComposerDialog-CdPp-3GR.js → MessageComposerDialog-CLrwtB76.js} +1 -1
- package/dist/assets/{NextShell-ull6WmMg.js → NextShell-DCWxD5TR.js} +1 -1
- package/dist/assets/{NotesApplet-D8cseekh.js → NotesApplet-BSJ-9RKl.js} +1 -1
- package/dist/assets/ObjectPropertiesCard-DesXRw-_.js +8 -0
- package/dist/assets/{PathPickerField-CW2yG2Yg.js → PathPickerField-CSIa7jSl.js} +1 -1
- package/dist/assets/PickDocumentsCard-DVdBxx3s.js +1 -0
- package/dist/assets/{SketchApplet-BKnhzTBA.js → SketchApplet--3uyqpmo.js} +1 -1
- package/dist/assets/{SketchEditor-DmGMcbU0.js → SketchEditor-CSA7dTyq.js} +2 -2
- package/dist/assets/{TerminalApplet-D7YxftqM.js → TerminalApplet-BZJx2ztD.js} +1 -1
- package/dist/assets/{TextDocumentEditor-BQnVD0dd.js → TextDocumentEditor-VYIF2XCX.js} +1 -1
- package/dist/assets/{TodosApplet-DU5VWc5i.js → TodosApplet-DY7JzeZS.js} +1 -1
- package/dist/assets/{TodosWidget-CNnfNk4L.js → TodosWidget-DGftEAbs.js} +1 -1
- package/dist/assets/{_agentId_-DVR-2m5A.js → _agentId_-BrzFDu8r.js} +0 -0
- package/dist/assets/{_contextId_-BofzZDP6.js → _contextId_-DS6b9Uml.js} +1 -1
- package/dist/assets/_workspaceName_-XRqfa4c6.js +1 -0
- package/dist/assets/{about-lxN3BXmR.js → about-hcdKJNm5.js} +1 -1
- package/dist/assets/{add-LFFQQgj3.js → add-CEBusWuu.js} +1 -1
- package/dist/assets/{agents-DxqAi3vk.js → agents-BfSFdg41.js} +1 -1
- package/dist/assets/{agents-DHexvztp.js → agents-wFp7Vh3p.js} +1 -1
- package/dist/assets/{alert-dialog-CFeuDt0T.js → alert-dialog-BKtaX1_a.js} +1 -1
- package/dist/assets/{api-tokens-drrVuCYc.js → api-tokens-Biqt5TnG.js} +1 -1
- package/dist/assets/{appearance-0-j0SAoe.js → appearance-D5BUjZm8.js} +1 -1
- package/dist/assets/{applet-target-pLdP-R76.js → applet-target-LvhUEvE5.js} +1 -1
- package/dist/assets/{apps-ylUU3K5c.js → apps-65YXCnzH.js} +1 -1
- package/dist/assets/{auth-PqttD05H.js → auth-BwxT5xRB.js} +1 -1
- package/dist/assets/{button-SeUZ_Pvi.js → button--VYZekMF.js} +1 -1
- package/dist/assets/{context-t3rdtGUB.js → context-DY40EDc6.js} +1 -1
- package/dist/assets/{contexts-DDJagU4j.js → contexts-BPO_Wb9W.js} +1 -1
- package/dist/assets/{contexts-Bq8LHUTK2.js → contexts-DBJ0_-AO2.js} +1 -1
- package/dist/assets/{date-time-picker-DCikruos.js → date-time-picker-p3vy4nst.js} +1 -1
- package/dist/assets/{devices-BwU9M8-W.js → devices-DZbbaWYU.js} +1 -1
- package/dist/assets/{document-Cr7GhnVd.js → document-Dv8NCUoM.js} +1 -1
- package/dist/assets/document-list-Bbbx-pTZ.js +3 -0
- package/dist/assets/document-paste-BuTC6S7_.js +1 -0
- package/dist/assets/{embedding-D-I_ygUZ.js → embedding-B9vSy_a9.js} +1 -1
- package/dist/assets/{embedding-BvXcVfij.js → embedding-M2hUmnk0.js} +1 -1
- package/dist/assets/{form-panel-3p-ncEVK.js → form-panel-CEbNKttr.js} +1 -1
- package/dist/assets/{home-CfYR15C5.js → home-vr8b8oR-.js} +1 -1
- package/dist/assets/index-CTvqbEB8.js +16 -0
- package/dist/assets/index-CoVFQpP3.css +2 -0
- package/dist/assets/{inferd-config-editor-B8x_XPOt.js → inferd-config-editor-Dpdj90iN.js} +1 -1
- package/dist/assets/{key-bindings-DAIw70SC.js → key-bindings-DmqvYSaF.js} +1 -1
- package/dist/assets/{label-BSTdjCWU.js → label-RuOXXC8t.js} +1 -1
- package/dist/assets/{lazy-editor-BUFAkTGl.js → lazy-editor-CShGeIep.js} +2 -2
- package/dist/assets/{logs-DjG8_wJ2.js → logs-7eSz9yjc.js} +1 -1
- package/dist/assets/{offline-ByoT6JJX.js → offline-C-Yvb6LA.js} +1 -1
- package/dist/assets/{page-header-DrDt1sQ2.js → page-header-NyYSXjfY.js} +1 -1
- package/dist/assets/{public-share-CXR25Q1X.js → public-share-0DqS7L2Q.js} +1 -1
- package/dist/assets/{query-debug-lD5vbJGi.js → query-debug-PEWbZsOP.js} +1 -1
- package/dist/assets/registry-g1SKt_fD.js +2 -0
- package/dist/assets/{remotes-RPGcw6fH.js → remotes-DqCLds8Q.js} +1 -1
- package/dist/assets/{roles-sb8vgjV_.js → roles-BwVDE1aQ.js} +1 -1
- package/dist/assets/{roles-p2cRajz-.js → roles-W7oJ5WMg.js} +1 -1
- package/dist/assets/rule-builder-CziPqpNe.js +6 -0
- package/dist/assets/settings-BIoSwdXv.js +16 -0
- package/dist/assets/{settings-C5cS_cw0.js → settings-BWCMmkjr.js} +1 -1
- package/dist/assets/{settings-Bojeuvgh.js → settings-CbMkpipO.js} +1 -1
- package/dist/assets/settings-XMhqrvTu.js +1 -0
- package/dist/assets/{share-target-PgtwhQo-.js → share-target-hDXdgW6o.js} +1 -1
- package/dist/assets/{shared-BLOuO2Is.js → shared-CLjTxih0.js} +1 -1
- package/dist/assets/{shared-fdwDs5-g.js → shared-DVlDThVA.js} +1 -1
- package/dist/assets/sketch-lazy-CtjOUfVz.js +2 -0
- package/dist/assets/{subtree-transfer-dialog-DQM5zfx2.js → subtree-transfer-dialog-DtE6JSUr.js} +1 -1
- package/dist/assets/{text-documents-Cdb3U63i.js → text-documents-wu6fzOuw.js} +2 -2
- package/dist/assets/tree-folders-IDoobsGN.js +1 -0
- package/dist/assets/ui-DEgHnkQu.js +41 -0
- package/dist/assets/{use-applet-docs-rimRHjID.js → use-applet-docs-C08GAUm3.js} +1 -1
- package/dist/assets/{use-applet-target-BygCSj5n.js → use-applet-target-BlpVWlnA.js} +1 -1
- package/dist/assets/{use-canvas-pins-Bmj8upH3.js → use-canvas-pins-q5Tncavk.js} +2 -2
- package/dist/assets/{use-menu-DIP1zh7I.js → use-menu-CKSpS96u.js} +1 -1
- package/dist/assets/use-settings-back-D_MM9diy.js +1 -0
- package/dist/assets/{use-sortable-data-BBKmqs79.js → use-sortable-data-D7zS2qCC.js} +1 -1
- package/dist/assets/{use-workspace-identity-CSkRwVyo.js → use-workspace-identity-XSv3dATQ.js} +1 -1
- package/dist/assets/{useAddTarget-DeRZWtGg.js → useAddTarget-BvuFR5pN.js} +1 -1
- package/dist/assets/{useAgentModels-DLjVm0T8.js → useAgentModels-CI9XT6yc.js} +1 -1
- package/dist/assets/{useDocumentThumbnail-Cj4UYyhC.js → useDocumentThumbnail-CZIaXkIi.js} +1 -1
- package/dist/assets/{useEditNoteFields-BT1ASu_q.js → useEditNoteFields-DsVKIHWm.js} +1 -1
- package/dist/assets/{users-DuVk-TEd.js → users-DzlbKZp6.js} +1 -1
- package/dist/assets/workspace-4hWrSEku.js +1 -0
- package/dist/assets/{workspace-content-gate-C54J9Man.js → workspace-content-gate-BlFdbi67.js} +1 -1
- package/dist/assets/{workspace-import-form-DTvV9jYt.js → workspace-import-form-CWs9ZTts.js} +1 -1
- package/dist/assets/{workspaces-CqHYstZv.js → workspaces-67v2hWrl.js} +1 -1
- package/dist/assets/workspaces-ByYQ6L3I.js +1 -0
- package/dist/index.html +36 -38
- package/dist/sw.js +1 -1
- package/package.json +2 -2
- package/dist/assets/CalendarApplet-JRMqt67k.js +0 -2
- package/dist/assets/FileForm-CDiVKvxq.js +0 -1
- package/dist/assets/HomeFab-Bp9cpmps.js +0 -3
- package/dist/assets/LinkToCard-CKVi4Nrg.js +0 -1
- package/dist/assets/ObjectPropertiesCard-D2lrTQqT.js +0 -8
- package/dist/assets/PickDocumentsCard-BWgc-A02.js +0 -1
- package/dist/assets/UploadProgressList-D2wEpa7t.js +0 -1
- package/dist/assets/_workspaceName_-Ds__P3h9.js +0 -1
- package/dist/assets/backend-sync-progress-Dp12uN4y.js +0 -6
- package/dist/assets/document-list-BLu9S0zR.js +0 -3
- package/dist/assets/index-BNP_llN_.js +0 -16
- package/dist/assets/index-CYvpxvg6.css +0 -2
- package/dist/assets/registry-H_3ckTyM.js +0 -2
- package/dist/assets/settings-COqQc1hP.js +0 -16
- package/dist/assets/settings-DziSEdYH.js +0 -1
- package/dist/assets/sketch-lazy-BY_ka1hw.js +0 -2
- package/dist/assets/tree-folders-Da9k9cbV.js +0 -1
- package/dist/assets/ui-CDoK3F3U.js +0 -41
- package/dist/assets/use-settings-back-DGmLAD63.js +0 -1
- package/dist/assets/workspace-C5V-ZCOE.js +0 -1
- package/dist/assets/workspace-area-menu-LLSySOlH.js +0 -1
- package/dist/assets/workspaces-DxvxX0wQ.js +0 -1
- /package/dist/assets/{backend-sync-progress-DU-e9TWi.css → rule-builder-DU-e9TWi.css} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{It as r,
|
|
1
|
+
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{It as r,Si as i,Ut as a,X as o,wt as s}from"./ui-DEgHnkQu.js";import{t as c}from"./button--VYZekMF.js";import{t as l}from"./input-BOtCd4HP.js";import{t as u}from"./label-RuOXXC8t.js";import{i as d}from"./auth-Bx9fAZmz.js";import{n as f}from"./use-toast-BlLDqSUO.js";import{n as p}from"./page-header-NyYSXjfY.js";import{t as m}from"./use-settings-back-D_MM9diy.js";import{t as h}from"./admin-Bhg9QBHL.js";var g=e(n(),1),_=t(),v={tail:200,level:``,module:``};function y(e){return e.slice(-1e3)}function b(e){switch(e.levelLabel){case`fatal`:return`text-destructive`;case`error`:return`text-destructive`;case`warn`:return`text-warning`;case`info`:return`text-info`;case`debug`:return`text-muted-foreground`;case`trace`:return`text-muted-foreground`;default:return`text-success`}}function x(){let e=m(),t=d()?.userType===`admin`,{showToast:n}=f(),x=(0,g.useRef)(null),[S,C]=(0,g.useState)(v),[w,T]=(0,g.useState)(v),[E,D]=(0,g.useState)([]),[O,k]=(0,g.useState)(t),[A,j]=(0,g.useState)(!1),[M,N]=(0,g.useState)(!1),[P,F]=(0,g.useState)(t?null:`Access denied. Admin privileges required.`),I=(0,g.useCallback)(async e=>{try{k(!0);let t=await h.logs.getLogs(e);D(y(t)),F(null)}catch(e){let t=e instanceof Error?e.message:`Failed to load server logs`;F(t),n({title:`Error`,description:t,variant:`destructive`})}finally{k(!1)}},[n]);(0,g.useEffect)(()=>{t&&I(S)},[S,t,I]),(0,g.useEffect)(()=>{if(!t||M)return;let e=new AbortController;return j(!0),h.logs.streamLogs(S,{signal:e.signal,onEntry:e=>{D(t=>y([...t,e]))},onError:e=>{F(e.message)}}).catch(e=>{let t=e instanceof Error?e.message:`Log stream stopped`;F(t),n({title:`Stream error`,description:t,variant:`destructive`})}).finally(()=>{j(!1)}),()=>{e.abort()}},[S,t,M,n]),(0,g.useEffect)(()=>{!x.current||M||(x.current.scrollTop=x.current.scrollHeight)},[E,M]);let L=()=>{C({tail:Math.min(Math.max(Number(w.tail)||v.tail,1),500),level:w.level||``,module:w.module.trim()})},R=(0,g.useMemo)(()=>[{value:``,label:`All levels`},{value:`trace`,label:`Trace`},{value:`debug`,label:`Debug`},{value:`info`,label:`Info`},{value:`warn`,label:`Warn`},{value:`error`,label:`Error`},{value:`fatal`,label:`Fatal`}],[]);return t?(0,_.jsxs)(`div`,{className:`space-y-6`,children:[(0,_.jsx)(p,{onBack:e,title:`Server Logs`,description:`Live tail for the unified canvas-server logger`,actions:(0,_.jsxs)(`div`,{className:`flex items-center gap-2 text-sm`,children:[(0,_.jsx)(i,{className:`w-4 h-4 ${A?`text-success`:`text-muted-foreground`}`}),(0,_.jsx)(`span`,{className:`text-muted-foreground`,children:M?`Paused`:A?`Streaming`:`Disconnected`})]})}),(0,_.jsxs)(`div`,{className:`grid gap-4 md:grid-cols-[140px_180px_1fr_auto]`,children:[(0,_.jsxs)(`div`,{children:[(0,_.jsx)(u,{htmlFor:`tail`,children:`Tail`}),(0,_.jsx)(l,{id:`tail`,type:`number`,min:1,max:500,value:w.tail,onChange:e=>T(t=>({...t,tail:Number(e.target.value)}))})]}),(0,_.jsxs)(`div`,{children:[(0,_.jsx)(u,{htmlFor:`level`,children:`Level`}),(0,_.jsx)(`select`,{id:`level`,className:`w-full px-3 py-2 border rounded-md bg-background`,value:w.level,onChange:e=>T(t=>({...t,level:e.target.value})),children:R.map(e=>(0,_.jsx)(`option`,{value:e.value,children:e.label},e.value||`all`))})]}),(0,_.jsxs)(`div`,{children:[(0,_.jsx)(u,{htmlFor:`module`,children:`Module filter`}),(0,_.jsx)(l,{id:`module`,placeholder:`auth, http, workspace...`,value:w.module,onChange:e=>T(t=>({...t,module:e.target.value}))})]}),(0,_.jsx)(`div`,{className:`flex items-end`,children:(0,_.jsx)(c,{onClick:L,className:`w-full`,children:`Apply`})})]}),(0,_.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,_.jsxs)(c,{variant:`outline`,onClick:()=>N(e=>!e),children:[M?(0,_.jsx)(r,{className:`w-4 h-4 mr-2`}):(0,_.jsx)(a,{className:`w-4 h-4 mr-2`}),M?`Resume`:`Pause`]}),(0,_.jsxs)(c,{variant:`outline`,onClick:()=>I(S),children:[(0,_.jsx)(s,{className:`w-4 h-4 mr-2`}),`Refresh`]}),(0,_.jsxs)(c,{variant:`outline`,onClick:()=>D([]),children:[(0,_.jsx)(o,{className:`w-4 h-4 mr-2`}),`Clear buffer`]}),(0,_.jsxs)(`span`,{className:`text-sm text-muted-foreground ml-auto`,children:[`Showing `,E.length,` lines`]})]}),P&&(0,_.jsx)(`div`,{className:`rounded-md border border-destructive/30 bg-destructive/5 px-4 py-3 text-sm text-destructive`,children:P}),(0,_.jsx)(`div`,{className:`border rounded-lg overflow-hidden`,children:(0,_.jsx)(`div`,{ref:x,"data-scheme":`dark`,className:`bg-background text-success font-mono text-xs h-viewport-pane overflow-auto p-4 rounded-md`,children:O?(0,_.jsx)(`div`,{className:`text-muted-foreground`,children:`Loading logs...`}):E.length===0?(0,_.jsx)(`div`,{className:`text-muted-foreground`,children:`No logs available`}):(0,_.jsx)(`div`,{className:`whitespace-pre-wrap break-words`,children:E.map((e,t)=>(0,_.jsx)(`div`,{className:b(e),children:e.line},`${e.time||`log`}-${t}`))})})})]}):(0,_.jsx)(`div`,{className:`text-center space-y-4`,children:(0,_.jsx)(`div`,{className:`text-destructive`,children:`Access denied. Admin privileges required.`})})}export{x as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{L as r,Lt as i,Vn as a,Wr as o,X as s,kt as c,oi as l,pn as u}from"./ui-CDoK3F3U.js";import{t as d}from"./utils-2pl1SbIp.js";import{t as f}from"./button-SeUZ_Pvi.js";import{c as p}from"./api-CA6WiiYM.js";import{t as m}from"./LinkToCard-CKVi4Nrg.js";import{L as h,R as g,jt as _,nt as v}from"./workspace-C5V-ZCOE.js";import{t as y}from"./useToastHelpers-CRrpIIdY.js";import{n as b}from"./LinkToSidePanel-eCy3nW4R.js";import{n as x}from"./page-header-DrDt1sQ2.js";import{t as S}from"./use-settings-back-DGmLAD63.js";var C=e(n(),1),w=`offline-content-v1`,T=`offline-api-v1`,E=1073741824,D={enabled:!1,budgetBytes:4*E,excludedWorkspaces:[]},O=1e3;function k(e){return(e.startsWith(`/`)?e:`/${e}`).replace(/\/+$/,``)||`/`}function A(e,t,n){return`${e}:${t}:${k(n)}`}var j=`canvas-offline`,M=2,N=null;function P(){return N||(N=new Promise((e,t)=>{let n=indexedDB.open(j,M);n.onupgradeneeded=e=>{let t=n.result;if(t.objectStoreNames.contains(`config`)||t.createObjectStore(`config`),t.objectStoreNames.contains(`entries`)||t.createObjectStore(`entries`,{keyPath:`url`}),e.oldVersion>=1&&t.objectStoreNames.contains(`pins`)){t.deleteObjectStore(`pins`);let e=n.transaction.objectStore(`entries`).openCursor();e.onsuccess=()=>{let t=e.result;if(!t)return;let n=t.value;n.pinned&&t.update({...n,pinned:!1}),t.continue()}}t.objectStoreNames.contains(`scopes`)||t.createObjectStore(`scopes`,{keyPath:`id`})},n.onsuccess=()=>{n.result.onversionchange=()=>{n.result.close(),N=null},e(n.result)},n.onerror=()=>{N=null,t(n.error)}}),N)}function F(e){return new Promise((t,n)=>{e.oncomplete=()=>t(),e.onerror=()=>n(e.error),e.onabort=()=>n(e.error)})}function I(e){return new Promise((t,n)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>n(e.error)})}async function L(e,t){return I((await P()).transaction(e).objectStore(e).get(t))}async function R(e){return I((await P()).transaction(e).objectStore(e).getAll())}async function z(e,t,n){let r=(await P()).transaction(e,`readwrite`);return r.objectStore(e).put(t,n),F(r)}async function B(e,t){let n=(await P()).transaction(e,`readwrite`);return n.objectStore(e).delete(t),F(n)}async function V(e){let t=(await P()).transaction(e,`readwrite`);return t.objectStore(e).clear(),F(t)}async function H(){try{let e=await L(`config`,`settings`);return e?{...D,...e}:D}catch{return D}}async function U(e){await z(`config`,e,`settings`)}async function W(e,t){let n=(await P()).transaction(`entries`,`readwrite`),r=n.objectStore(`entries`);for(let n of e){let e=r.get(n);e.onsuccess=()=>{let i=e.result;i?r.put({...i,pinned:t}):t&&r.put({url:n,kind:`content`,size:0,lastAccess:Date.now(),pinned:t})}}return F(n)}async function ee(e){let t=await R(`entries`),n=t.filter(e=>e.kind===`api`).sort((e,t)=>e.lastAccess-t.lastAccess),r=n.slice(0,Math.max(0,n.length-O)),i=t.filter(e=>e.kind===`content`),a=i.reduce((e,t)=>e+t.size,0),o=i.filter(e=>!e.pinned).sort((e,t)=>e.lastAccess-t.lastAccess),s=[];for(let t of o){if(a<=e)break;s.push(t),a-=t.size}if(!r.length&&!s.length)return;let[c,l]=await Promise.all([caches.open(T),caches.open(w)]);await Promise.all([...r.map(async e=>{await c.delete(e.url),await B(`entries`,e.url)}),...s.map(async e=>{await l.delete(e.url),await B(`entries`,e.url)})])}async function te(){let e=await R(`entries`),t=e.filter(e=>e.kind===`content`);return{contentBytes:t.reduce((e,t)=>e+t.size,0),contentCount:t.length,pinnedBytes:t.filter(e=>e.pinned).reduce((e,t)=>e+t.size,0),apiCount:e.length-t.length}}async function ne(){await Promise.all([caches.delete(w),caches.delete(T)]),await V(`entries`),await V(`scopes`)}async function re(){return R(`scopes`)}async function ie(e){return L(`scopes`,e)}async function G(e){await z(`scopes`,e)}async function K(e){let t=await L(`scopes`,e);await B(`scopes`,e),t?.urls.length&&await q(t.urls)}async function q(e){let t=await R(`scopes`),n=new Set(t.flatMap(e=>e.urls)),r=e.filter(e=>!n.has(e));r.length&&await W(r,!1)}var J=3,ae=`data/schema/file`,Y=128;async function oe({workspaceRef:e,path:t,treeName:n,treeType:r},i){let a=await H();if(!a.enabled)throw Error(`Enable the offline cache first`);if(a.excludedWorkspaces.includes(e))throw Error(`Workspace "${e}" is excluded from offline caching`);let o=A(e,n,t),s=k(t),c=await ie(o),l=((await v(e,s,[],{limit:1e4,treeName:n,treeType:r})).payload??[]).filter(e=>e.schema===ae),u=[],d=0,f=0,m=!1,_=l.length;i?.({done:f,total:_,bytes:d});let y=0;await Promise.all(Array.from({length:Math.min(J,l.length)},async()=>{for(;y<l.length;){let t=l[y++];if(d>=a.budgetBytes*.9){m=!0;return}try{let{blob:n}=await h(e,t.id);d+=n.size,u.push(`${p.workspaces}/${e}/documents/${t.id}/content`);try{await g(e,t.id,Y),u.push(`${p.workspaces}/${e}/documents/${t.id}/thumbnail?size=${Y}`)}catch{}}catch{}f+=1,i?.({done:f,total:_,bytes:d})}})),await W(u,!0);let b={id:o,workspaceRef:e,treeName:n,treeType:r,path:s,urls:u,bytes:d,warmedAt:Date.now(),...m?{truncated:!0}:{}};if(await G(b),c){let e=new Set(u),t=c.urls.filter(t=>!e.has(t));t.length&&await q(t)}return b}var X=t(),Z=[{label:`1 GB`,bytes:1*E},{label:`2 GB`,bytes:2*E},{label:`4 GB`,bytes:4*E},{label:`8 GB`,bytes:8*E}];function Q(e){return e<1048576?`${(e/1024).toFixed(0)} KB`:e<1073741824?`${(e/1048576).toFixed(1)} MB`:`${(e/E).toFixed(2)} GB`}function se(){navigator.serviceWorker?.controller?.postMessage({type:`OFFLINE_SETTINGS_CHANGED`})}function ce(){let{showSuccessToast:e,showErrorToast:t}=y(),[n,p]=(0,C.useState)(null),[h,g]=(0,C.useState)(null),[v,x]=(0,C.useState)(null),[S,w]=(0,C.useState)([]),[T,E]=(0,C.useState)([]),[D,O]=(0,C.useState)({}),[k,j]=(0,C.useState)(!1),[M,N]=(0,C.useState)(!1),P=(0,C.useCallback)(()=>{H().then(p).catch(()=>{}),te().then(g).catch(()=>{}),re().then(e=>E(e.sort((e,t)=>e.id.localeCompare(t.id)))).catch(()=>{}),navigator.storage?.persisted?.().then(x).catch(()=>{})},[]);(0,C.useEffect)(()=>{P(),_().then(e=>w(e.map(e=>e.name).filter(Boolean).sort())).catch(()=>{})},[P]);let F=async e=>{p(e),await U(e),se(),e.enabled&&navigator.storage?.persist?.().then(x).catch(()=>{}),ee(e.budgetBytes).then(P).catch(()=>{})},I=e=>{if(!n)return;let t=n.excludedWorkspaces.includes(e)?n.excludedWorkspaces.filter(t=>t!==e):[...n.excludedWorkspaces,e];F({...n,excludedWorkspaces:t})},L=async()=>{j(!0);try{await ne(),e(`Offline cache cleared`),P()}catch(e){t(e instanceof Error?e.message:`Failed to clear cache`)}finally{j(!1)}},R=async n=>{let r=A(n.workspaceRef,n.treeName,n.path);O(e=>({...e,[r]:{done:0,total:0,bytes:0}}));try{let t=await oe(n,e=>O(t=>({...t,[r]:e})));e(t.truncated?`Pinned ${Q(t.bytes)} — stopped at the size budget`:`Pinned ${t.workspaceRef}:/${t.path} (${Q(t.bytes)})`)}catch(e){t(e instanceof Error?e.message:`Failed to pin`)}finally{O(e=>{let{[r]:t,...n}=e;return n}),P()}},z=(e,t)=>{N(!1);for(let n of e)R({workspaceRef:t.workspaceName,path:n,treeName:t.treeName,treeType:t.treeType})},B=e=>({workspaceRef:e.workspaceRef,path:e.path,treeName:e.treeName||`context`,treeType:e.treeType||`context`}),V=async e=>{await K(e),P()};return n?(0,X.jsxs)(`div`,{className:`space-y-8`,children:[(0,X.jsxs)(`section`,{children:[(0,X.jsx)($,{title:`Offline cache`,description:`Keep documents you open (and scopes you pin) readable without a connection. Cached on this device only; least-recently-used files are evicted when the size budget fills. Video streaming is not cached.`}),(0,X.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,X.jsxs)(`button`,{type:`button`,onClick:()=>F({...n,enabled:!n.enabled}),"aria-pressed":n.enabled,className:d(`focus-ring flex items-center gap-3 rounded-lg border p-4 text-left transition-colors`,n.enabled?`border-primary bg-accent`:`border-input hover:bg-muted/40`),children:[(0,X.jsx)(a,{className:`h-5 w-5 shrink-0 text-muted-foreground`}),(0,X.jsxs)(`span`,{className:`flex-1`,children:[(0,X.jsx)(`span`,{className:`block text-sm font-medium`,children:n.enabled?`Enabled`:`Disabled`}),(0,X.jsx)(`span`,{className:`block text-xs text-muted-foreground`,children:n.enabled?v===!1?`Storage is not persistent — the browser may still evict the cache under disk pressure`:`Documents are cached as you browse`:`Nothing is cached for offline use`})]}),n.enabled&&(0,X.jsx)(o,{className:`h-4 w-4 shrink-0 text-primary`})]}),n.enabled&&(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`p`,{className:`mb-2 text-sm font-medium`,children:`Size budget`}),(0,X.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:Z.map(e=>(0,X.jsx)(f,{variant:n.budgetBytes===e.bytes?`default`:`outline`,size:`sm`,onClick:()=>F({...n,budgetBytes:e.bytes}),children:e.label},e.bytes))})]}),h&&(0,X.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,X.jsxs)(`div`,{className:`flex items-baseline justify-between text-sm`,children:[(0,X.jsxs)(`span`,{children:[Q(h.contentBytes),` of `,Q(n.budgetBytes),` used`]}),(0,X.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[h.contentCount,` file(s)`,h.pinnedBytes>0?`, ${Q(h.pinnedBytes)} pinned`:``]})]}),(0,X.jsx)(`div`,{className:`h-2 w-full overflow-hidden rounded-full bg-muted`,children:(0,X.jsx)(`div`,{className:`h-full rounded-full bg-primary`,style:{width:`${Math.min(100,h.contentBytes/n.budgetBytes*100)}%`}})})]}),(0,X.jsx)(`div`,{children:(0,X.jsxs)(f,{variant:`outline`,size:`sm`,onClick:L,disabled:k,children:[k?(0,X.jsx)(u,{className:`mr-1.5 h-3.5 w-3.5 animate-spin`}):(0,X.jsx)(s,{className:`mr-1.5 h-3.5 w-3.5`}),`Clear offline cache`]})})]})]})]}),n.enabled&&(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`section`,{children:[(0,X.jsx)($,{title:`Pinned scopes`,description:`A pinned scope — a workspace, or one of its tree paths — is downloaded up front and never evicted. Scopes resolve fresh on every re-warm, so moved contexts and reorganized trees are picked up; documents that left a scope return to normal eviction.`}),(0,X.jsx)(`div`,{className:`mb-3`,children:(0,X.jsxs)(f,{size:`sm`,onClick:()=>N(!0),disabled:!!Object.keys(D).length,children:[(0,X.jsx)(i,{className:`mr-1.5 h-3.5 w-3.5`}),`Pin a path…`]})}),(0,X.jsxs)(`ul`,{className:`space-y-1`,children:[T.map(e=>{let t=D[e.id];return(0,X.jsxs)(`li`,{className:`flex items-center gap-3 rounded-md border border-input px-3 py-2 text-sm`,children:[(0,X.jsxs)(`span`,{className:`flex-1 truncate font-mono text-xs sm:text-sm`,children:[e.workspaceRef,`://`,e.path.replace(/^\//,``),e.treeName&&e.treeName!==`context`&&(0,X.jsx)(`span`,{className:`ml-1.5 rounded bg-muted px-1 py-0.5 font-sans text-[10px] text-muted-foreground`,children:e.treeName})]}),t?(0,X.jsxs)(`span`,{className:`flex items-center gap-2 text-xs text-muted-foreground`,children:[(0,X.jsx)(u,{className:`h-3.5 w-3.5 animate-spin`}),t.total>0?`${t.done}/${t.total} · ${Q(t.bytes)}`:`listing…`]}):(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[Q(e.bytes),e.truncated?` (partial)`:``]}),(0,X.jsx)(f,{variant:`ghost`,size:`sm`,onClick:()=>R(B(e)),"aria-label":`Re-warm ${e.id}`,title:`Re-warm: re-resolve the scope and download anything new`,children:(0,X.jsx)(c,{className:`h-3.5 w-3.5`})}),(0,X.jsx)(f,{variant:`ghost`,size:`sm`,onClick:()=>V(e.id),"aria-label":`Unpin ${e.id}`,children:(0,X.jsx)(r,{className:`h-3.5 w-3.5`})})]})]},e.id)}),T.length===0&&(0,X.jsx)(`li`,{className:`rounded-md border border-dashed border-input px-3 py-4 text-center text-sm text-muted-foreground`,children:`Nothing pinned — everything relies on browse-caching and LRU`})]})]}),(0,X.jsxs)(`section`,{children:[(0,X.jsx)($,{title:`Workspace caching`,description:`Excluded workspaces are never cached — not even as you browse — and are not served from cache.`}),(0,X.jsx)(`ul`,{className:`space-y-1`,children:S.map(e=>{let t=n.excludedWorkspaces.includes(e);return(0,X.jsxs)(`li`,{className:`flex items-center gap-3 rounded-md border border-input px-3 py-2 text-sm`,children:[(0,X.jsx)(`span`,{className:d(`flex-1 truncate`,t&&`text-muted-foreground line-through`),children:e}),t&&(0,X.jsx)(l,{className:`h-3.5 w-3.5 text-muted-foreground`}),(0,X.jsx)(f,{variant:t?`outline`:`ghost`,size:`sm`,onClick:()=>I(e),children:t?`Include`:`Exclude`})]},e)})})]})]}),M&&(0,X.jsx)(b,{onClose:()=>N(!1),children:(0,X.jsx)(m,{sizeClassName:`h-full w-[380px] max-w-[90vw] max-md:w-full`,multiple:!1,tabs:[`context`,`directory`],title:`Pin for offline…`,confirmLabel:`Pin path`,onConfirm:z,onClose:()=>N(!1)})})]}):null}function $({title:e,description:t}){return(0,X.jsxs)(`div`,{className:`mb-4`,children:[(0,X.jsx)(`h2`,{className:`text-base font-semibold`,children:e}),(0,X.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:t})]})}function le(){return(0,X.jsxs)(`div`,{className:`mx-auto max-w-4xl`,children:[(0,X.jsx)(x,{className:`mb-6`,title:`Offline`,onBack:S(),description:`Per-device offline cache: browse notes, files, photos and saved websites without a connection.`}),(0,X.jsx)(ce,{})]})}export{le as default};
|
|
1
|
+
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{Kr as r,L as i,Lt as a,Vn as o,X as s,ci as c,kt as l,pn as u}from"./ui-DEgHnkQu.js";import{t as d}from"./utils-2pl1SbIp.js";import{t as f}from"./button--VYZekMF.js";import{c as p}from"./api-CA6WiiYM.js";import{t as m}from"./LinkToCard-oi3wGP0a.js";import{L as h,R as g,jt as _,nt as v}from"./workspace-4hWrSEku.js";import{t as y}from"./useToastHelpers-CRrpIIdY.js";import{n as b}from"./LinkToSidePanel-eCy3nW4R.js";import{n as x}from"./page-header-NyYSXjfY.js";import{t as S}from"./use-settings-back-D_MM9diy.js";var C=e(n(),1),w=`offline-content-v1`,T=`offline-api-v1`,E=1073741824,D={enabled:!1,budgetBytes:4*E,excludedWorkspaces:[]},O=1e3;function k(e){return(e.startsWith(`/`)?e:`/${e}`).replace(/\/+$/,``)||`/`}function A(e,t,n){return`${e}:${t}:${k(n)}`}var j=`canvas-offline`,M=2,N=null;function P(){return N||(N=new Promise((e,t)=>{let n=indexedDB.open(j,M);n.onupgradeneeded=e=>{let t=n.result;if(t.objectStoreNames.contains(`config`)||t.createObjectStore(`config`),t.objectStoreNames.contains(`entries`)||t.createObjectStore(`entries`,{keyPath:`url`}),e.oldVersion>=1&&t.objectStoreNames.contains(`pins`)){t.deleteObjectStore(`pins`);let e=n.transaction.objectStore(`entries`).openCursor();e.onsuccess=()=>{let t=e.result;if(!t)return;let n=t.value;n.pinned&&t.update({...n,pinned:!1}),t.continue()}}t.objectStoreNames.contains(`scopes`)||t.createObjectStore(`scopes`,{keyPath:`id`})},n.onsuccess=()=>{n.result.onversionchange=()=>{n.result.close(),N=null},e(n.result)},n.onerror=()=>{N=null,t(n.error)}}),N)}function F(e){return new Promise((t,n)=>{e.oncomplete=()=>t(),e.onerror=()=>n(e.error),e.onabort=()=>n(e.error)})}function I(e){return new Promise((t,n)=>{e.onsuccess=()=>t(e.result),e.onerror=()=>n(e.error)})}async function L(e,t){return I((await P()).transaction(e).objectStore(e).get(t))}async function R(e){return I((await P()).transaction(e).objectStore(e).getAll())}async function z(e,t,n){let r=(await P()).transaction(e,`readwrite`);return r.objectStore(e).put(t,n),F(r)}async function B(e,t){let n=(await P()).transaction(e,`readwrite`);return n.objectStore(e).delete(t),F(n)}async function V(e){let t=(await P()).transaction(e,`readwrite`);return t.objectStore(e).clear(),F(t)}async function H(){try{let e=await L(`config`,`settings`);return e?{...D,...e}:D}catch{return D}}async function U(e){await z(`config`,e,`settings`)}async function W(e,t){let n=(await P()).transaction(`entries`,`readwrite`),r=n.objectStore(`entries`);for(let n of e){let e=r.get(n);e.onsuccess=()=>{let i=e.result;i?r.put({...i,pinned:t}):t&&r.put({url:n,kind:`content`,size:0,lastAccess:Date.now(),pinned:t})}}return F(n)}async function ee(e){let t=await R(`entries`),n=t.filter(e=>e.kind===`api`).sort((e,t)=>e.lastAccess-t.lastAccess),r=n.slice(0,Math.max(0,n.length-O)),i=t.filter(e=>e.kind===`content`),a=i.reduce((e,t)=>e+t.size,0),o=i.filter(e=>!e.pinned).sort((e,t)=>e.lastAccess-t.lastAccess),s=[];for(let t of o){if(a<=e)break;s.push(t),a-=t.size}if(!r.length&&!s.length)return;let[c,l]=await Promise.all([caches.open(T),caches.open(w)]);await Promise.all([...r.map(async e=>{await c.delete(e.url),await B(`entries`,e.url)}),...s.map(async e=>{await l.delete(e.url),await B(`entries`,e.url)})])}async function te(){let e=await R(`entries`),t=e.filter(e=>e.kind===`content`);return{contentBytes:t.reduce((e,t)=>e+t.size,0),contentCount:t.length,pinnedBytes:t.filter(e=>e.pinned).reduce((e,t)=>e+t.size,0),apiCount:e.length-t.length}}async function ne(){await Promise.all([caches.delete(w),caches.delete(T)]),await V(`entries`),await V(`scopes`)}async function re(){return R(`scopes`)}async function ie(e){return L(`scopes`,e)}async function G(e){await z(`scopes`,e)}async function K(e){let t=await L(`scopes`,e);await B(`scopes`,e),t?.urls.length&&await q(t.urls)}async function q(e){let t=await R(`scopes`),n=new Set(t.flatMap(e=>e.urls)),r=e.filter(e=>!n.has(e));r.length&&await W(r,!1)}var J=3,ae=`data/schema/file`,Y=128;async function oe({workspaceRef:e,path:t,treeName:n,treeType:r},i){let a=await H();if(!a.enabled)throw Error(`Enable the offline cache first`);if(a.excludedWorkspaces.includes(e))throw Error(`Workspace "${e}" is excluded from offline caching`);let o=A(e,n,t),s=k(t),c=await ie(o),l=((await v(e,s,[],{limit:1e4,treeName:n,treeType:r})).payload??[]).filter(e=>e.schema===ae),u=[],d=0,f=0,m=!1,_=l.length;i?.({done:f,total:_,bytes:d});let y=0;await Promise.all(Array.from({length:Math.min(J,l.length)},async()=>{for(;y<l.length;){let t=l[y++];if(d>=a.budgetBytes*.9){m=!0;return}try{let{blob:n}=await h(e,t.id);d+=n.size,u.push(`${p.workspaces}/${e}/documents/${t.id}/content`);try{await g(e,t.id,Y),u.push(`${p.workspaces}/${e}/documents/${t.id}/thumbnail?size=${Y}`)}catch{}}catch{}f+=1,i?.({done:f,total:_,bytes:d})}})),await W(u,!0);let b={id:o,workspaceRef:e,treeName:n,treeType:r,path:s,urls:u,bytes:d,warmedAt:Date.now(),...m?{truncated:!0}:{}};if(await G(b),c){let e=new Set(u),t=c.urls.filter(t=>!e.has(t));t.length&&await q(t)}return b}var X=t(),Z=[{label:`1 GB`,bytes:1*E},{label:`2 GB`,bytes:2*E},{label:`4 GB`,bytes:4*E},{label:`8 GB`,bytes:8*E}];function Q(e){return e<1048576?`${(e/1024).toFixed(0)} KB`:e<1073741824?`${(e/1048576).toFixed(1)} MB`:`${(e/E).toFixed(2)} GB`}function se(){navigator.serviceWorker?.controller?.postMessage({type:`OFFLINE_SETTINGS_CHANGED`})}function ce(){let{showSuccessToast:e,showErrorToast:t}=y(),[n,p]=(0,C.useState)(null),[h,g]=(0,C.useState)(null),[v,x]=(0,C.useState)(null),[S,w]=(0,C.useState)([]),[T,E]=(0,C.useState)([]),[D,O]=(0,C.useState)({}),[k,j]=(0,C.useState)(!1),[M,N]=(0,C.useState)(!1),P=(0,C.useCallback)(()=>{H().then(p).catch(()=>{}),te().then(g).catch(()=>{}),re().then(e=>E(e.sort((e,t)=>e.id.localeCompare(t.id)))).catch(()=>{}),navigator.storage?.persisted?.().then(x).catch(()=>{})},[]);(0,C.useEffect)(()=>{P(),_().then(e=>w(e.map(e=>e.name).filter(Boolean).sort())).catch(()=>{})},[P]);let F=async e=>{p(e),await U(e),se(),e.enabled&&navigator.storage?.persist?.().then(x).catch(()=>{}),ee(e.budgetBytes).then(P).catch(()=>{})},I=e=>{if(!n)return;let t=n.excludedWorkspaces.includes(e)?n.excludedWorkspaces.filter(t=>t!==e):[...n.excludedWorkspaces,e];F({...n,excludedWorkspaces:t})},L=async()=>{j(!0);try{await ne(),e(`Offline cache cleared`),P()}catch(e){t(e instanceof Error?e.message:`Failed to clear cache`)}finally{j(!1)}},R=async n=>{let r=A(n.workspaceRef,n.treeName,n.path);O(e=>({...e,[r]:{done:0,total:0,bytes:0}}));try{let t=await oe(n,e=>O(t=>({...t,[r]:e})));e(t.truncated?`Pinned ${Q(t.bytes)} — stopped at the size budget`:`Pinned ${t.workspaceRef}:/${t.path} (${Q(t.bytes)})`)}catch(e){t(e instanceof Error?e.message:`Failed to pin`)}finally{O(e=>{let{[r]:t,...n}=e;return n}),P()}},z=(e,t)=>{N(!1);for(let n of e)R({workspaceRef:t.workspaceName,path:n,treeName:t.treeName,treeType:t.treeType})},B=e=>({workspaceRef:e.workspaceRef,path:e.path,treeName:e.treeName||`context`,treeType:e.treeType||`context`}),V=async e=>{await K(e),P()};return n?(0,X.jsxs)(`div`,{className:`space-y-8`,children:[(0,X.jsxs)(`section`,{children:[(0,X.jsx)($,{title:`Offline cache`,description:`Keep documents you open (and scopes you pin) readable without a connection. Cached on this device only; least-recently-used files are evicted when the size budget fills. Video streaming is not cached.`}),(0,X.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[(0,X.jsxs)(`button`,{type:`button`,onClick:()=>F({...n,enabled:!n.enabled}),"aria-pressed":n.enabled,className:d(`focus-ring flex items-center gap-3 rounded-lg border p-4 text-left transition-colors`,n.enabled?`border-primary bg-accent`:`border-input hover:bg-muted/40`),children:[(0,X.jsx)(o,{className:`h-5 w-5 shrink-0 text-muted-foreground`}),(0,X.jsxs)(`span`,{className:`flex-1`,children:[(0,X.jsx)(`span`,{className:`block text-sm font-medium`,children:n.enabled?`Enabled`:`Disabled`}),(0,X.jsx)(`span`,{className:`block text-xs text-muted-foreground`,children:n.enabled?v===!1?`Storage is not persistent — the browser may still evict the cache under disk pressure`:`Documents are cached as you browse`:`Nothing is cached for offline use`})]}),n.enabled&&(0,X.jsx)(r,{className:`h-4 w-4 shrink-0 text-primary`})]}),n.enabled&&(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`p`,{className:`mb-2 text-sm font-medium`,children:`Size budget`}),(0,X.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:Z.map(e=>(0,X.jsx)(f,{variant:n.budgetBytes===e.bytes?`default`:`outline`,size:`sm`,onClick:()=>F({...n,budgetBytes:e.bytes}),children:e.label},e.bytes))})]}),h&&(0,X.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,X.jsxs)(`div`,{className:`flex items-baseline justify-between text-sm`,children:[(0,X.jsxs)(`span`,{children:[Q(h.contentBytes),` of `,Q(n.budgetBytes),` used`]}),(0,X.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[h.contentCount,` file(s)`,h.pinnedBytes>0?`, ${Q(h.pinnedBytes)} pinned`:``]})]}),(0,X.jsx)(`div`,{className:`h-2 w-full overflow-hidden rounded-full bg-muted`,children:(0,X.jsx)(`div`,{className:`h-full rounded-full bg-primary`,style:{width:`${Math.min(100,h.contentBytes/n.budgetBytes*100)}%`}})})]}),(0,X.jsx)(`div`,{children:(0,X.jsxs)(f,{variant:`outline`,size:`sm`,onClick:L,disabled:k,children:[k?(0,X.jsx)(u,{className:`mr-1.5 h-3.5 w-3.5 animate-spin`}):(0,X.jsx)(s,{className:`mr-1.5 h-3.5 w-3.5`}),`Clear offline cache`]})})]})]})]}),n.enabled&&(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`section`,{children:[(0,X.jsx)($,{title:`Pinned scopes`,description:`A pinned scope — a workspace, or one of its tree paths — is downloaded up front and never evicted. Scopes resolve fresh on every re-warm, so moved contexts and reorganized trees are picked up; documents that left a scope return to normal eviction.`}),(0,X.jsx)(`div`,{className:`mb-3`,children:(0,X.jsxs)(f,{size:`sm`,onClick:()=>N(!0),disabled:!!Object.keys(D).length,children:[(0,X.jsx)(a,{className:`mr-1.5 h-3.5 w-3.5`}),`Pin a path…`]})}),(0,X.jsxs)(`ul`,{className:`space-y-1`,children:[T.map(e=>{let t=D[e.id];return(0,X.jsxs)(`li`,{className:`flex items-center gap-3 rounded-md border border-input px-3 py-2 text-sm`,children:[(0,X.jsxs)(`span`,{className:`flex-1 truncate font-mono text-xs sm:text-sm`,children:[e.workspaceRef,`://`,e.path.replace(/^\//,``),e.treeName&&e.treeName!==`context`&&(0,X.jsx)(`span`,{className:`ml-1.5 rounded bg-muted px-1 py-0.5 font-sans text-[10px] text-muted-foreground`,children:e.treeName})]}),t?(0,X.jsxs)(`span`,{className:`flex items-center gap-2 text-xs text-muted-foreground`,children:[(0,X.jsx)(u,{className:`h-3.5 w-3.5 animate-spin`}),t.total>0?`${t.done}/${t.total} · ${Q(t.bytes)}`:`listing…`]}):(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[Q(e.bytes),e.truncated?` (partial)`:``]}),(0,X.jsx)(f,{variant:`ghost`,size:`sm`,onClick:()=>R(B(e)),"aria-label":`Re-warm ${e.id}`,title:`Re-warm: re-resolve the scope and download anything new`,children:(0,X.jsx)(l,{className:`h-3.5 w-3.5`})}),(0,X.jsx)(f,{variant:`ghost`,size:`sm`,onClick:()=>V(e.id),"aria-label":`Unpin ${e.id}`,children:(0,X.jsx)(i,{className:`h-3.5 w-3.5`})})]})]},e.id)}),T.length===0&&(0,X.jsx)(`li`,{className:`rounded-md border border-dashed border-input px-3 py-4 text-center text-sm text-muted-foreground`,children:`Nothing pinned — everything relies on browse-caching and LRU`})]})]}),(0,X.jsxs)(`section`,{children:[(0,X.jsx)($,{title:`Workspace caching`,description:`Excluded workspaces are never cached — not even as you browse — and are not served from cache.`}),(0,X.jsx)(`ul`,{className:`space-y-1`,children:S.map(e=>{let t=n.excludedWorkspaces.includes(e);return(0,X.jsxs)(`li`,{className:`flex items-center gap-3 rounded-md border border-input px-3 py-2 text-sm`,children:[(0,X.jsx)(`span`,{className:d(`flex-1 truncate`,t&&`text-muted-foreground line-through`),children:e}),t&&(0,X.jsx)(c,{className:`h-3.5 w-3.5 text-muted-foreground`}),(0,X.jsx)(f,{variant:t?`outline`:`ghost`,size:`sm`,onClick:()=>I(e),children:t?`Include`:`Exclude`})]},e)})})]})]}),M&&(0,X.jsx)(b,{onClose:()=>N(!1),children:(0,X.jsx)(m,{sizeClassName:`h-full w-[380px] max-w-[90vw] max-md:w-full`,multiple:!1,tabs:[`context`,`directory`],title:`Pin for offline…`,confirmLabel:`Pin path`,onConfirm:z,onClose:()=>N(!1)})})]}):null}function $({title:e,description:t}){return(0,X.jsxs)(`div`,{className:`mb-4`,children:[(0,X.jsx)(`h2`,{className:`text-base font-semibold`,children:e}),(0,X.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:t})]})}function le(){return(0,X.jsxs)(`div`,{className:`mx-auto max-w-4xl`,children:[(0,X.jsx)(x,{className:`mb-6`,title:`Offline`,onBack:S(),description:`Per-device offline cache: browse notes, files, photos and saved websites without a connection.`}),(0,X.jsx)(ce,{})]})}export{le as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{l as e}from"./code-editor-BOIngd5F.js";import{g as t}from"./chunk-62JRHF6Z-vspAGgtK.js";import{L as n,
|
|
1
|
+
import{l as e}from"./code-editor-BOIngd5F.js";import{g as t}from"./chunk-62JRHF6Z-vspAGgtK.js";import{L as n,hi as r}from"./ui-DEgHnkQu.js";import{t as i}from"./utils-2pl1SbIp.js";var a=e();function o({title:e,description:o,actions:s,backTo:c,onBack:l,className:u,compact:d}){let f=t();return(0,a.jsxs)(`div`,{className:i(`flex flex-wrap items-start gap-x-3 gap-y-2`,!d&&`border-b pb-4`,u),children:[(0,a.jsxs)(`div`,{className:`flex min-w-[14rem] flex-1 items-start gap-3`,children:[(l||c)&&(0,a.jsx)(`button`,{type:`button`,onClick:()=>l?l():f(c),"aria-label":`Back`,title:`Back`,className:`mt-1 shrink-0 text-muted-foreground transition-colors hover:text-foreground touch-target`,children:(0,a.jsx)(r,{className:`h-5 w-5`})}),(0,a.jsxs)(`div`,{className:`min-w-0`,children:[(0,a.jsx)(`h1`,{className:i(`truncate font-bold tracking-tight`,d?`text-xl`:`text-3xl`),children:e}),o&&(0,a.jsx)(`p`,{className:i(`break-words text-muted-foreground`,d?`mt-1 text-xs`:`mt-2`),children:o})]})]}),(0,a.jsx)(`button`,{type:`button`,onClick:()=>f(`/`),"aria-label":`Close`,title:`Close`,className:`order-2 flex h-9 w-9 shrink-0 items-center justify-center rounded-md border text-muted-foreground transition-colors hover:bg-muted hover:text-foreground touch-target`,children:(0,a.jsx)(n,{className:`h-4 w-4`})}),s&&(0,a.jsx)(`div`,{className:`order-3 flex w-full items-center gap-2 max-sm:flex-wrap sm:order-1 sm:w-auto`,children:s})]})}function s({className:e}){let r=t();return(0,a.jsx)(`button`,{type:`button`,onClick:()=>r(`/`),"aria-label":`Close`,title:`Close`,className:i(`flex h-7 w-7 shrink-0 items-center justify-center rounded-md border text-muted-foreground transition-colors hover:bg-accent hover:text-foreground touch-target`,e),children:(0,a.jsx)(n,{className:`h-3.5 w-3.5`})})}function c({onBack:e,title:t=`Back`,className:n}){return(0,a.jsx)(`button`,{type:`button`,onClick:e,"aria-label":t,title:t,className:i(`flex h-7 w-7 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-foreground touch-target`,n),children:(0,a.jsx)(r,{className:`h-4 w-4`})})}export{o as n,c as r,s as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{u as t}from"./code-editor-BOIngd5F.js";import{l as n}from"./api-CA6WiiYM.js";import{L as r,M as i,R as a,Xt as o,j as s}from"./workspace-
|
|
1
|
+
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{u as t}from"./code-editor-BOIngd5F.js";import{l as n}from"./api-CA6WiiYM.js";import{L as r,M as i,R as a,Xt as o,j as s}from"./workspace-4hWrSEku.js";var c=e(t(),1),l=(0,c.createContext)(null);function u(){return(0,c.useContext)(l)}function d(e,t,r={}){let i=new URLSearchParams;r.download&&i.set(`download`,`1`),r.url&&i.set(`url`,r.url),r.format&&i.set(`format`,r.format),r.version&&i.set(`v`,r.version);let a=i.toString();return`${n}/pub/c/${encodeURIComponent(e)}/documents/${t}/content${a?`?${a}`:``}`}async function f(e,t,r=256){let i=await fetch(`${n}/pub/c/${encodeURIComponent(e)}/documents/${t}/thumbnail?size=${r}`);if(!i.ok)throw Error(`HTTP ${i.status}`);let a=i.headers.get(`content-type`)||`image/webp`;return{blob:await i.blob(),mime:a}}async function p(e,t,n={}){let r=await fetch(d(e,t,n),{signal:n.signal});if(!r.ok)throw Error(`HTTP ${r.status}`);let i=r.headers.get(`content-type`)||`application/octet-stream`;return{blob:await r.blob(),mime:i}}async function m(e,t,n,r={}){let{blob:i}=await p(e,t,{...r}),a=URL.createObjectURL(i),o=document.createElement(`a`);o.href=a,o.download=n,document.body.appendChild(o),o.click(),o.remove(),setTimeout(()=>URL.revokeObjectURL(a),3e4)}function h(e){let t=u();return(0,c.useMemo)(()=>({isPublic:t!=null,fetchBlob:(n,i={})=>t?p(t,n,i):r(e,n,i),fetchThumbnail:(n,r=256,i)=>t?f(t,n,r):a(e,n,r,i),download:(n,r,a={})=>t?m(t,n,r,a):i(e,n,r,a),streamUrl:(n,r={})=>t?d(t,n,r):s(e,n,r),mintTicket:n=>t?Promise.resolve(!0):o(e,n)}),[e,t])}export{u as i,d as n,h as r,l as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{Kn as r,Tt as i,X as a,ar as o,kt as s,or as c}from"./ui-CDoK3F3U.js";import{t as l}from"./button-SeUZ_Pvi.js";import{t as u}from"./input-BOtCd4HP.js";import{t as d}from"./api-CA6WiiYM.js";import{Z as f,mt as p,pn as m,vt as h}from"./workspace-C5V-ZCOE.js";import{t as g}from"./workspace-access-C9nZlBBZ.js";var _=e(n(),1),v={membership:`keep`,propagation:`never`,targets:[],acceptPropagatedDeletions:!1},y=e=>`/workspaces/${encodeURIComponent(e)}/trash/operations`,b=(e,t)=>d.get(`${y(e)}?${new URLSearchParams(Object.entries(t).map(([e,t])=>[e,String(t)]))}`),x=(e,t,n,r={})=>d.post(`${y(e)}/${n}`,{ids:t,...r}),S=(e,t,n,r)=>d.patch(`/workspaces/${encodeURIComponent(e)}/backends/imap/${encodeURIComponent(t)}/containers/${encodeURIComponent(n)}`,{removalPolicy:r}),C=e=>`/workspaces/${encodeURIComponent(e)}/trash/items`,w=(e,t={})=>d.get(`${C(e)}?${new URLSearchParams(Object.entries(t).filter(([,e])=>e!==void 0&&e!==``).map(([e,t])=>[e,String(t)]))}`);async function T(e,t,n){let r=[];for(let i=0;i<n.length;i+=200)r.push(...(await d.post(`${C(e)}/${t}`,{ids:n.slice(i,i+200)})).results);return r}var E=(e,t)=>T(e,`restore`,t),D=(e,t)=>T(e,`discard`,t),O=t(),k=200,A=864e5;function j(e,t){return e.expiresAt?Math.max(0,Math.ceil((Date.parse(e.expiresAt)-t)/A)):null}function M(e,t){if(!e.deletedAt)return`Earlier`;let n=new Date(t).setHours(0,0,0,0),r=Date.parse(e.deletedAt);return r>=n?`Today`:r>=n-A?`Yesterday`:r>=n-6*A?`Last 7 days`:`Earlier`}function N(e){return e==null?``:e<1024?`${e} B`:e<1024**2?`${(e/1024).toFixed(0)} KB`:e<1024**3?`${(e/1024**2).toFixed(1)} MB`:`${(e/1024**3).toFixed(1)} GB`}var P={document:c,file:o,folder:r};function F({workspaceName:e,canWrite:t}){let[n,r]=(0,_.useState)([]),[o,c]=(0,_.useState)(0),[d,f]=(0,_.useState)(null),[m,h]=(0,_.useState)(``),[g,v]=(0,_.useState)(!0),[y,b]=(0,_.useState)(!1),[x,S]=(0,_.useState)(``),[C,T]=(0,_.useState)(new Set),[A,F]=(0,_.useState)(null),[I]=(0,_.useState)(()=>Date.now()),L=(0,_.useCallback)(async(t=0)=>{v(!0);try{let n=await w(e,{search:m.trim(),limit:k,offset:t});r(e=>t?[...e,...n.items]:n.items),c(n.total),f(n.retentionDays),S(``)}catch(e){S(e instanceof Error?e.message:`Could not load deleted items`)}finally{v(!1)}},[e,m]);(0,_.useEffect)(()=>{let e=setTimeout(()=>{T(new Set),L()},m?250:0);return()=>clearTimeout(e)},[L,m]);let R=(0,_.useMemo)(()=>{let e=[];for(let t of n){let n=M(t,I),r=e[e.length-1];r?.label===n?r.items.push(t):e.push({label:n,items:[t]})}return e},[n,I]),z=async(t,r)=>{if(!(!r.length||y)){b(!0),S(``),F(null);try{let i=(t===`restore`?await E(e,r):await D(e,r)).filter(e=>!e.ok);if(i.length){let e=new Map(n.map(e=>[e.id,e.name]));S(`${i.length} of ${r.length} could not be ${t===`restore`?`restored`:`deleted`}: ${i.slice(0,3).map(t=>`${e.get(t.id)||t.id} (${t.message||`failed`})`).join(`, `)}`)}p(e),window.dispatchEvent(new CustomEvent(`workspace:tree:refresh`,{detail:{workspaceName:e}})),T(new Set),await L()}catch(e){S(e instanceof Error?e.message:`Action failed`)}finally{b(!1)}}},B=(e,t)=>T(n=>{let r=new Set(n);return t?r.add(e):r.delete(e),r}),V=[...C],H=n.map(e=>e.id);return(0,O.jsxs)(`div`,{className:`space-y-3`,children:[(0,O.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,O.jsx)(u,{"aria-label":`Search deleted items`,placeholder:`Search by name or folder`,className:`max-w-xs`,value:m,onChange:e=>h(e.target.value)}),(0,O.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[o,` item`,o===1?``:`s`,d?`, kept for ${d} days`:``]}),(0,O.jsxs)(`div`,{className:`ml-auto flex items-center gap-2`,children:[(0,O.jsx)(l,{size:`sm`,variant:`ghost`,onClick:()=>void L(),disabled:g||y,"aria-label":`Refresh`,children:(0,O.jsx)(s,{className:`h-3.5 w-3.5 ${g?`animate-spin`:``}`})}),V.length>0?(0,O.jsxs)(O.Fragment,{children:[(0,O.jsxs)(l,{size:`sm`,variant:`outline`,disabled:!t||y,onClick:()=>void z(`restore`,V),children:[(0,O.jsx)(i,{className:`mr-2 h-3.5 w-3.5`}),`Restore `,V.length]}),(0,O.jsxs)(l,{size:`sm`,variant:`destructive`,disabled:!t||y,onClick:()=>F({ids:V,label:`${V.length} selected item${V.length===1?``:`s`}`}),children:[(0,O.jsx)(a,{className:`mr-2 h-3.5 w-3.5`}),`Delete forever`]})]}):(0,O.jsxs)(l,{size:`sm`,variant:`outline`,disabled:!t||y||!n.length,onClick:()=>F({ids:H,label:m.trim()?`all ${H.length} listed items`:`all ${H.length} items`}),children:[(0,O.jsx)(a,{className:`mr-2 h-3.5 w-3.5`}),`Empty trash`]})]})]}),A&&(0,O.jsxs)(`div`,{role:`alertdialog`,className:`flex flex-wrap items-center gap-3 rounded border border-destructive/50 bg-destructive/5 px-3 py-2 text-sm`,children:[(0,O.jsxs)(`span`,{children:[`Delete `,A.label,` forever? This cannot be undone.`]}),(0,O.jsx)(l,{size:`sm`,variant:`destructive`,disabled:y,onClick:()=>void z(`discard`,A.ids),children:`Delete forever`}),(0,O.jsx)(l,{size:`sm`,variant:`ghost`,onClick:()=>F(null),children:`Cancel`})]}),x&&(0,O.jsx)(`p`,{role:`alert`,className:`text-sm text-destructive`,children:x}),!n.length&&(0,O.jsx)(`p`,{className:`py-10 text-center text-sm text-muted-foreground`,children:g?`Loading…`:m.trim()?`Nothing deleted matches that search.`:`Nothing was deleted recently.`}),R.map(e=>(0,O.jsxs)(`section`,{children:[(0,O.jsx)(`h3`,{className:`mb-1 text-xs font-medium uppercase tracking-wide text-muted-foreground`,children:e.label}),(0,O.jsx)(`ul`,{className:`divide-y rounded-md border`,children:e.items.map(e=>{let n=P[e.kind],r=j(e,I);return(0,O.jsxs)(`li`,{className:`flex items-center gap-3 px-3 py-2`,children:[(0,O.jsx)(`input`,{type:`checkbox`,"aria-label":`Select ${e.name}`,disabled:!t||y,checked:C.has(e.id),onChange:t=>B(e.id,t.target.checked)}),(0,O.jsx)(n,{className:`h-4 w-4 shrink-0 text-muted-foreground`}),(0,O.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,O.jsx)(`div`,{className:`truncate text-sm`,children:e.name}),(0,O.jsxs)(`div`,{className:`truncate text-xs text-muted-foreground`,children:[e.from.length?e.from.join(`, `):`No folder recorded`,e.reason===`source-missing`?` · disappeared from its source`:``]})]}),(0,O.jsxs)(`div`,{className:`hidden shrink-0 text-right text-xs text-muted-foreground sm:block`,children:[(0,O.jsx)(`div`,{children:e.deletedAt?new Date(e.deletedAt).toLocaleString(void 0,{dateStyle:`medium`,timeStyle:`short`}):``}),(0,O.jsx)(`div`,{children:[N(e.size),r==null?``:r===0?`expires today`:`${r} day${r===1?``:`s`} left`].filter(Boolean).join(` · `)})]}),(0,O.jsxs)(l,{size:`sm`,variant:`outline`,disabled:!t||y,onClick:()=>void z(`restore`,[e.id]),title:`Put it back where it was`,children:[(0,O.jsx)(i,{className:`h-3.5 w-3.5 sm:mr-2`}),(0,O.jsx)(`span`,{className:`hidden sm:inline`,children:`Restore`})]}),(0,O.jsx)(l,{size:`sm`,variant:`ghost`,disabled:!t||y,onClick:()=>F({ids:[e.id],label:`"${e.name}"`}),"aria-label":`Delete ${e.name} forever`,children:(0,O.jsx)(a,{className:`h-3.5 w-3.5`})})]},e.id)})})]},e.label)),n.length<o&&(0,O.jsx)(`div`,{className:`text-center`,children:(0,O.jsx)(l,{size:`sm`,variant:`outline`,disabled:g,onClick:()=>void L(n.length),children:`Show more`})})]})}function I({value:e,backends:t,source:n,onSave:r,destination:i=!0}){let[a,o]=(0,_.useState)({...v,...e}),[s,c]=(0,_.useState)(!1),[u,d]=(0,_.useState)(``),f=`rounded border bg-background px-2 py-1.5 text-xs w-full`,p=async()=>{c(!0),d(``);try{await r(a),d(`Removal policy saved.`)}catch(e){d(e instanceof Error?e.message:`Could not save policy`)}finally{c(!1)}};return(0,O.jsxs)(`details`,{className:`border-t pt-3 text-xs`,children:[(0,O.jsx)(`summary`,{className:`cursor-pointer font-medium`,children:`Source removals and Trash`}),(0,O.jsxs)(`div`,{className:`mt-3 space-y-3`,children:[(0,O.jsx)(`p`,{className:`text-muted-foreground`,children:`A completed scan removes missing locations from the backend tree. Items with no remaining locations go to Trash until you purge them.`}),(0,O.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,O.jsxs)(`label`,{className:`space-y-1 block`,children:[`When an item disappears from this source`,(0,O.jsxs)(`select`,{className:f,value:a.membership,disabled:s,onChange:e=>o({...a,membership:e.target.value}),children:[(0,O.jsx)(`option`,{value:`keep`,children:`Keep in managed trees`}),(0,O.jsx)(`option`,{value:`review`,children:`Review removal in Trash`}),(0,O.jsx)(`option`,{value:`trash`,children:`Move to Trash automatically`})]})]}),(0,O.jsxs)(`label`,{className:`space-y-1 block`,children:[`Remove tracked copies from other backends`,(0,O.jsxs)(`select`,{className:f,value:a.propagation,disabled:s,onChange:e=>o({...a,propagation:e.target.value}),children:[(0,O.jsx)(`option`,{value:`never`,children:`Never`}),(0,O.jsx)(`option`,{value:`review`,children:`Review in Trash`}),(0,O.jsx)(`option`,{value:`automatic`,children:`Automatically, retaining recovery copies`})]})]})]}),a.propagation!==`never`&&(0,O.jsxs)(`fieldset`,{className:`space-y-2`,children:[(0,O.jsx)(`legend`,{className:`mb-1 font-medium`,children:`Destinations`}),(0,O.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(`input`,{type:`checkbox`,checked:a.targets===`all`,disabled:s,onChange:e=>o({...a,targets:e.target.checked?`all`:[]})}),`All eligible backends`]}),a.targets!==`all`&&t.filter(e=>e.address!==n&&e.kind===`storage`).map(e=>(0,O.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(`input`,{type:`checkbox`,disabled:s||e.config?.propagatedRemovalSupported!==!0,checked:a.targets.includes(e.address),onChange:t=>o({...a,targets:t.target.checked?[...a.targets,e.address]:a.targets.filter(t=>t!==e.address)})}),String(e.config?.label||e.address),e.config?.propagatedRemovalSupported===!0?!e.config?.removalPolicy?.acceptPropagatedDeletions&&` · protected`:` · recovery removal unavailable`]},e.address)),(0,O.jsx)(`p`,{className:`text-muted-foreground`,children:`Only tracked, Canvas-owned copies are eligible. Protected destinations refuse propagated deletion. Recovery removal currently supports filesystem and workspace blob storage; remote destinations remain protected.`})]}),i&&(0,O.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(`input`,{type:`checkbox`,disabled:s,checked:a.acceptPropagatedDeletions,onChange:e=>o({...a,acceptPropagatedDeletions:e.target.checked})}),`Accept propagated deletions on this backend`]}),(0,O.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,O.jsx)(l,{size:`sm`,variant:`outline`,disabled:s,onClick:()=>void p(),children:s?`Saving…`:`Save removal policy`}),(0,O.jsx)(`span`,{role:`status`,children:u})]})]})]})}function L({workspaceName:e}){return(0,O.jsx)(R,{workspaceName:e},e)}function R({workspaceName:e}){let[t,n]=(0,_.useState)(`deleted`),[r,i]=(0,_.useState)(0),[a,o]=(0,_.useState)({write:!1,admin:!1});return(0,_.useEffect)(()=>{let t=!0;return f(e).then(e=>{let n=e.remote?.permissions||e.access?.permissions||(typeof e.sharedVia==`object`?e.sharedVia?.permissions:[])||[],r=g(e);t&&o({admin:r,write:r||n.includes(`write`)})}).catch(()=>{}),b(e,{view:`pending`,offset:0}).then(e=>{t&&i(e.total)}).catch(()=>{}),()=>{t=!1}},[e]),(0,O.jsxs)(`div`,{className:`space-y-4`,children:[(0,O.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,role:`tablist`,"aria-label":`Trash`,children:[(0,O.jsx)(l,{role:`tab`,"aria-selected":t===`deleted`,size:`sm`,variant:t===`deleted`?`default`:`outline`,onClick:()=>n(`deleted`),children:`Recently deleted`}),(0,O.jsxs)(l,{role:`tab`,"aria-selected":t===`removals`,size:`sm`,variant:t===`removals`?`default`:`outline`,onClick:()=>n(`removals`),children:[`Source removals`,r>0?` (${r} to review)`:``]})]}),t===`deleted`?(0,O.jsx)(F,{workspaceName:e,canWrite:a.write}):(0,O.jsx)(z,{workspaceName:e,access:a,onPending:i})]})}function z({workspaceName:e,access:t,onPending:n}){let[r,i]=(0,_.useState)(`pending`),[a,o]=(0,_.useState)(``),[c,d]=(0,_.useState)(``),[f,g]=(0,_.useState)(0),[y,C]=(0,_.useState)(0),[w,T]=(0,_.useState)(null),[E,D]=(0,_.useState)(``),[k,A]=(0,_.useState)(!1),[j,M]=(0,_.useState)(new Set),[N,P]=(0,_.useState)({}),[F,L]=(0,_.useState)([]),[R,z]=(0,_.useState)(null);(0,_.useEffect)(()=>{let t=!0;return h(e).then(e=>{t&&L(e)}).catch(()=>{}),()=>{t=!1}},[e]),(0,_.useEffect)(()=>{let t=!1,i=()=>b(e,{view:r,search:a,...c?{backend:c}:{},offset:f}).then(e=>{t||(T(e),D(``),r===`pending`&&!a&&!c&&n(e.total))}).catch(e=>{t||D(e instanceof Error?e.message:`Could not load Trash`)});i();let o=setInterval(()=>{k||i()},5e3);return()=>{t=!0,clearInterval(o)}},[e,r,a,c,f,y,k,n]);let B=w?.operations||[],V=()=>{M(new Set),C(e=>e+1)},H=()=>{p(e),window.dispatchEvent(new CustomEvent(`workspace:tree:refresh`,{detail:{workspaceName:e}})),window.dispatchEvent(new CustomEvent(`workspace:trash:refresh`,{detail:{workspaceName:e}}))},U=async(t,n=[...j])=>{if(!(!n.length||k)&&!(t===`purge`&&!window.confirm(`Permanently delete retained recovery copies for ${n.length} operation(s)?`))){A(!0),D(``);try{let r=(t===`approve`?(await Promise.all(n.map(n=>x(e,[n],t,N[n])))).flatMap(e=>e.results):(await x(e,n,t)).results).filter(e=>!e.ok||e.operation?.state===`failed`);r.length&&D(r.map(e=>e.error||e.operation?.error||`A destination could not be changed. Expand the item for details.`).join(` `)),H(),V()}catch(e){D(e instanceof Error?e.message:`Trash action failed`)}finally{A(!1)}}},W=e=>{i(e),g(0),T(null),M(new Set),P({})};return(0,O.jsxs)(`div`,{className:`space-y-4`,children:[(0,O.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Files that disappeared from a backend or mailbox. Decide what happens to the copies Canvas still holds, and see what the removal policies did.`}),(0,O.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,role:`tablist`,"aria-label":`Trash views`,children:[[[`pending`,`To review`],[`trashed`,`Recovery copies`],[`activity`,`Activity`]].map(([e,t])=>(0,O.jsx)(l,{role:`tab`,"aria-selected":r===e,size:`sm`,variant:r===e?`default`:`outline`,onClick:()=>W(e),children:t},e)),(0,O.jsxs)(l,{size:`sm`,variant:`ghost`,className:`ml-auto`,onClick:V,disabled:k,children:[(0,O.jsx)(s,{className:`mr-2 h-3.5 w-3.5`}),`Refresh`]})]}),(0,O.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,O.jsx)(u,{"aria-label":`Filter Trash items`,placeholder:`Filter by item or path…`,className:`max-w-xs`,value:a,onChange:e=>{o(e.target.value),T(null),g(0),M(new Set)}}),(0,O.jsx)(u,{"aria-label":`Filter by backend`,placeholder:`Backend name…`,className:`max-w-56`,value:c,onChange:e=>{d(e.target.value),T(null),g(0),M(new Set)}}),j.size>0&&(0,O.jsxs)(`div`,{className:`flex items-center gap-2 text-xs`,children:[(0,O.jsxs)(`span`,{children:[j.size,` selected`]}),r===`pending`&&(0,O.jsxs)(O.Fragment,{children:[(0,O.jsx)(l,{size:`sm`,disabled:k,onClick:()=>void U(`approve`),children:`Approve selected`}),(0,O.jsx)(l,{size:`sm`,variant:`outline`,disabled:k,onClick:()=>void U(`keep`),children:`Keep selected`}),(0,O.jsx)(l,{size:`sm`,variant:`outline`,disabled:k,onClick:()=>void U(`retry`),children:`Retry`})]}),r===`trashed`&&(0,O.jsxs)(O.Fragment,{children:[(0,O.jsx)(l,{size:`sm`,variant:`outline`,disabled:k,onClick:()=>void U(`restore`),children:`Restore copies`}),(0,O.jsx)(l,{size:`sm`,variant:`destructive`,disabled:k,onClick:()=>void U(`purge`),children:`Purge copies`})]})]})]}),R&&(0,O.jsxs)(`div`,{className:`rounded border p-3 space-y-2`,children:[(0,O.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,O.jsxs)(`p`,{className:`text-sm font-medium`,children:[`Removal policy · `,R.source.account||R.source.backend,R.source.folder?` / ${R.source.folder}`:``]}),(0,O.jsx)(l,{size:`sm`,variant:`ghost`,onClick:()=>z(null),children:`Close`})]}),(0,O.jsx)(I,{source:R.source.backend,backends:F,destination:!1,value:{...v,...F.find(e=>e.address===R.source.backend)?.config?.removalPolicy,membership:N[R.id]?.membership??R.membership!==`keep`?`review`:`keep`,propagation:R.targets.length?`review`:`never`,targets:[...new Set(R.targets.filter(e=>!N[R.id]||N[R.id].targets.includes(JSON.stringify([e.backend,e.key]))).map(e=>e.backend))]},onSave:async t=>{R.source.driver===`imap`?await S(e,R.source.account,R.source.folder,t):await m(e,R.source.driver,R.source.backend,{removalPolicy:t}),L(await h(e))}},R.id)]}),E&&(0,O.jsx)(`p`,{role:`alert`,className:`text-sm text-destructive`,children:E}),(0,O.jsxs)(`div`,{className:`overflow-x-auto rounded border`,children:[(0,O.jsxs)(`table`,{className:`w-full text-left text-xs`,children:[(0,O.jsx)(`thead`,{className:`bg-muted`,children:(0,O.jsxs)(`tr`,{children:[(0,O.jsx)(`th`,{className:`p-3 w-8`,children:(0,O.jsx)(`input`,{type:`checkbox`,"aria-label":`Select visible operations`,disabled:!t.write||k||!B.length||r===`activity`,checked:B.length>0&&B.every(e=>j.has(e.id)),onChange:e=>M(e.target.checked?new Set(B.map(e=>e.id)):new Set)})}),(0,O.jsx)(`th`,{className:`p-3`,children:`Item and affected copies`}),(0,O.jsx)(`th`,{className:`p-3`,children:`Source`}),(0,O.jsx)(`th`,{className:`p-3`,children:`Status`}),(0,O.jsx)(`th`,{className:`p-3`,children:`Detected`})]})}),(0,O.jsx)(`tbody`,{children:B.map(e=>{let n=N[e.id]||{targets:e.targets.filter(e=>e.state!==`kept`).map(e=>JSON.stringify([e.backend,e.key])),membership:e.membership!==`keep`};return(0,O.jsxs)(`tr`,{className:`border-t align-top`,children:[(0,O.jsx)(`td`,{className:`p-3`,children:(0,O.jsx)(`input`,{type:`checkbox`,"aria-label":`Select ${e.title}`,disabled:!t.write||k||r===`activity`,checked:j.has(e.id),onChange:t=>M(n=>{let r=new Set(n);return t.target.checked?r.add(e.id):r.delete(e.id),r})})}),(0,O.jsx)(`td`,{className:`p-3 min-w-64`,children:(0,O.jsxs)(`details`,{children:[(0,O.jsx)(`summary`,{className:`cursor-pointer font-medium`,children:e.title}),(0,O.jsxs)(`div`,{className:`mt-2 space-y-2 text-muted-foreground`,children:[(0,O.jsx)(`p`,{children:e.orphan?`No remaining byte locations. Restore placements only unless recovery bytes are available.`:`${e.remainingLocations.length} remaining location(s) when detected.`}),e.placements.map(e=>(0,O.jsxs)(`p`,{children:[e.tree,`: `,e.paths.join(`, `)]},e.tree)),e.membership!==`keep`&&(0,O.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(`input`,{type:`checkbox`,checked:n.membership,disabled:k||r!==`pending`||e.membershipApplied,onChange:t=>P({...N,[e.id]:{...n,membership:t.target.checked}})}),e.membershipApplied?`Managed placements moved to Trash`:`Move managed placements to Trash`]}),e.targets.map(t=>{let i=JSON.stringify([t.backend,t.key]);return(0,O.jsxs)(`label`,{className:`flex items-start gap-2`,children:[(0,O.jsx)(`input`,{type:`checkbox`,disabled:k||r!==`pending`||!!t.trashId,checked:n.targets.includes(i),onChange:t=>P({...N,[e.id]:{...n,targets:t.target.checked?[...n.targets,i]:n.targets.filter(e=>e!==i)}})}),(0,O.jsxs)(`span`,{className:`break-all`,children:[t.backend,`:`,t.key,` · `,t.state,t.error&&(0,O.jsx)(`span`,{className:`block text-destructive`,children:t.error})]})]},i)}),(0,O.jsx)(l,{size:`sm`,variant:`outline`,disabled:!t.admin,onClick:()=>z(e),children:`Use these choices as a source policy`}),e.remainingLocations.map(e=>(0,O.jsx)(`p`,{className:`break-all`,children:e.url},e.url))]})]})}),(0,O.jsxs)(`td`,{className:`p-3 break-all`,children:[e.source.account||e.source.backend,e.source.folder&&(0,O.jsx)(`span`,{className:`block text-muted-foreground`,children:e.source.folder})]}),(0,O.jsxs)(`td`,{className:`p-3`,children:[e.state,e.error&&(0,O.jsx)(`p`,{className:`mt-1 max-w-xs text-destructive`,children:e.error})]}),(0,O.jsx)(`td`,{className:`p-3 whitespace-nowrap text-muted-foreground`,children:new Date(e.createdAt).toLocaleString()})]},e.id)})})]}),!B.length&&(0,O.jsx)(`p`,{className:`p-5 text-center text-sm text-muted-foreground`,children:w?`No matching operations.`:`Loading…`})]}),(0,O.jsxs)(`div`,{className:`flex items-center justify-between text-xs text-muted-foreground`,children:[(0,O.jsxs)(`span`,{children:[w?.total??0,` operation(s)`]}),(0,O.jsxs)(`div`,{className:`flex gap-2`,children:[(0,O.jsx)(l,{size:`sm`,variant:`outline`,disabled:!f||k,onClick:()=>{g(Math.max(0,f-200)),M(new Set)},children:`Previous`}),(0,O.jsx)(l,{size:`sm`,variant:`outline`,disabled:f+B.length>=(w?.total??0)||k,onClick:()=>{g(f+200),M(new Set)},children:`Next`})]})]})]})}var B=`canvas:query-debug`,V=`canvas:query-debug-changed`;function H(){try{return localStorage.getItem(B)===`1`}catch{return!1}}function U(e){try{e?localStorage.setItem(B,`1`):localStorage.removeItem(B)}catch{}window.dispatchEvent(new CustomEvent(V,{detail:e}))}function W(){let[e,t]=(0,_.useState)(H);return(0,_.useEffect)(()=>{let e=()=>t(H());return window.addEventListener(V,e),window.addEventListener(`storage`,e),()=>{window.removeEventListener(V,e),window.removeEventListener(`storage`,e)}},[]),e}export{I as a,L as i,U as n,S as o,W as r,H as t};
|
|
1
|
+
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{Kn as r,Tt as i,X as a,ar as o,kt as s,or as c}from"./ui-DEgHnkQu.js";import{t as l}from"./button--VYZekMF.js";import{t as u}from"./input-BOtCd4HP.js";import{t as d}from"./api-CA6WiiYM.js";import{Z as f,mt as p,pn as m,vt as h}from"./workspace-4hWrSEku.js";import{t as g}from"./workspace-access-C9nZlBBZ.js";var _=e(n(),1),v={membership:`keep`,propagation:`never`,targets:[],acceptPropagatedDeletions:!1},y=e=>`/workspaces/${encodeURIComponent(e)}/trash/operations`,b=(e,t)=>d.get(`${y(e)}?${new URLSearchParams(Object.entries(t).map(([e,t])=>[e,String(t)]))}`),x=(e,t,n,r={})=>d.post(`${y(e)}/${n}`,{ids:t,...r}),S=(e,t,n,r)=>d.patch(`/workspaces/${encodeURIComponent(e)}/backends/imap/${encodeURIComponent(t)}/containers/${encodeURIComponent(n)}`,{removalPolicy:r}),C=e=>`/workspaces/${encodeURIComponent(e)}/trash/items`,w=(e,t={})=>d.get(`${C(e)}?${new URLSearchParams(Object.entries(t).filter(([,e])=>e!==void 0&&e!==``).map(([e,t])=>[e,String(t)]))}`);async function T(e,t,n){let r=[];for(let i=0;i<n.length;i+=200)r.push(...(await d.post(`${C(e)}/${t}`,{ids:n.slice(i,i+200)})).results);return r}var E=(e,t)=>T(e,`restore`,t),D=(e,t)=>T(e,`discard`,t),O=t(),k=200,A=864e5;function j(e,t){return e.expiresAt?Math.max(0,Math.ceil((Date.parse(e.expiresAt)-t)/A)):null}function M(e,t){if(!e.deletedAt)return`Earlier`;let n=new Date(t).setHours(0,0,0,0),r=Date.parse(e.deletedAt);return r>=n?`Today`:r>=n-A?`Yesterday`:r>=n-6*A?`Last 7 days`:`Earlier`}function N(e){return e==null?``:e<1024?`${e} B`:e<1024**2?`${(e/1024).toFixed(0)} KB`:e<1024**3?`${(e/1024**2).toFixed(1)} MB`:`${(e/1024**3).toFixed(1)} GB`}var P={document:c,file:o,folder:r};function F({workspaceName:e,canWrite:t}){let[n,r]=(0,_.useState)([]),[o,c]=(0,_.useState)(0),[d,f]=(0,_.useState)(null),[m,h]=(0,_.useState)(``),[g,v]=(0,_.useState)(!0),[y,b]=(0,_.useState)(!1),[x,S]=(0,_.useState)(``),[C,T]=(0,_.useState)(new Set),[A,F]=(0,_.useState)(null),[I]=(0,_.useState)(()=>Date.now()),L=(0,_.useCallback)(async(t=0)=>{v(!0);try{let n=await w(e,{search:m.trim(),limit:k,offset:t});r(e=>t?[...e,...n.items]:n.items),c(n.total),f(n.retentionDays),S(``)}catch(e){S(e instanceof Error?e.message:`Could not load deleted items`)}finally{v(!1)}},[e,m]);(0,_.useEffect)(()=>{let e=setTimeout(()=>{T(new Set),L()},m?250:0);return()=>clearTimeout(e)},[L,m]);let R=(0,_.useMemo)(()=>{let e=[];for(let t of n){let n=M(t,I),r=e[e.length-1];r?.label===n?r.items.push(t):e.push({label:n,items:[t]})}return e},[n,I]),z=async(t,r)=>{if(!(!r.length||y)){b(!0),S(``),F(null);try{let i=(t===`restore`?await E(e,r):await D(e,r)).filter(e=>!e.ok);if(i.length){let e=new Map(n.map(e=>[e.id,e.name]));S(`${i.length} of ${r.length} could not be ${t===`restore`?`restored`:`deleted`}: ${i.slice(0,3).map(t=>`${e.get(t.id)||t.id} (${t.message||`failed`})`).join(`, `)}`)}p(e),window.dispatchEvent(new CustomEvent(`workspace:tree:refresh`,{detail:{workspaceName:e}})),T(new Set),await L()}catch(e){S(e instanceof Error?e.message:`Action failed`)}finally{b(!1)}}},B=(e,t)=>T(n=>{let r=new Set(n);return t?r.add(e):r.delete(e),r}),V=[...C],H=n.map(e=>e.id);return(0,O.jsxs)(`div`,{className:`space-y-3`,children:[(0,O.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,children:[(0,O.jsx)(u,{"aria-label":`Search deleted items`,placeholder:`Search by name or folder`,className:`max-w-xs`,value:m,onChange:e=>h(e.target.value)}),(0,O.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[o,` item`,o===1?``:`s`,d?`, kept for ${d} days`:``]}),(0,O.jsxs)(`div`,{className:`ml-auto flex items-center gap-2`,children:[(0,O.jsx)(l,{size:`sm`,variant:`ghost`,onClick:()=>void L(),disabled:g||y,"aria-label":`Refresh`,children:(0,O.jsx)(s,{className:`h-3.5 w-3.5 ${g?`animate-spin`:``}`})}),V.length>0?(0,O.jsxs)(O.Fragment,{children:[(0,O.jsxs)(l,{size:`sm`,variant:`outline`,disabled:!t||y,onClick:()=>void z(`restore`,V),children:[(0,O.jsx)(i,{className:`mr-2 h-3.5 w-3.5`}),`Restore `,V.length]}),(0,O.jsxs)(l,{size:`sm`,variant:`destructive`,disabled:!t||y,onClick:()=>F({ids:V,label:`${V.length} selected item${V.length===1?``:`s`}`}),children:[(0,O.jsx)(a,{className:`mr-2 h-3.5 w-3.5`}),`Delete forever`]})]}):(0,O.jsxs)(l,{size:`sm`,variant:`outline`,disabled:!t||y||!n.length,onClick:()=>F({ids:H,label:m.trim()?`all ${H.length} listed items`:`all ${H.length} items`}),children:[(0,O.jsx)(a,{className:`mr-2 h-3.5 w-3.5`}),`Empty trash`]})]})]}),A&&(0,O.jsxs)(`div`,{role:`alertdialog`,className:`flex flex-wrap items-center gap-3 rounded border border-destructive/50 bg-destructive/5 px-3 py-2 text-sm`,children:[(0,O.jsxs)(`span`,{children:[`Delete `,A.label,` forever? This cannot be undone.`]}),(0,O.jsx)(l,{size:`sm`,variant:`destructive`,disabled:y,onClick:()=>void z(`discard`,A.ids),children:`Delete forever`}),(0,O.jsx)(l,{size:`sm`,variant:`ghost`,onClick:()=>F(null),children:`Cancel`})]}),x&&(0,O.jsx)(`p`,{role:`alert`,className:`text-sm text-destructive`,children:x}),!n.length&&(0,O.jsx)(`p`,{className:`py-10 text-center text-sm text-muted-foreground`,children:g?`Loading…`:m.trim()?`Nothing deleted matches that search.`:`Nothing was deleted recently.`}),R.map(e=>(0,O.jsxs)(`section`,{children:[(0,O.jsx)(`h3`,{className:`mb-1 text-xs font-medium uppercase tracking-wide text-muted-foreground`,children:e.label}),(0,O.jsx)(`ul`,{className:`divide-y rounded-md border`,children:e.items.map(e=>{let n=P[e.kind],r=j(e,I);return(0,O.jsxs)(`li`,{className:`flex items-center gap-3 px-3 py-2`,children:[(0,O.jsx)(`input`,{type:`checkbox`,"aria-label":`Select ${e.name}`,disabled:!t||y,checked:C.has(e.id),onChange:t=>B(e.id,t.target.checked)}),(0,O.jsx)(n,{className:`h-4 w-4 shrink-0 text-muted-foreground`}),(0,O.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,O.jsx)(`div`,{className:`truncate text-sm`,children:e.name}),(0,O.jsxs)(`div`,{className:`truncate text-xs text-muted-foreground`,children:[e.from.length?e.from.join(`, `):`No folder recorded`,e.reason===`source-missing`?` · disappeared from its source`:``]})]}),(0,O.jsxs)(`div`,{className:`hidden shrink-0 text-right text-xs text-muted-foreground sm:block`,children:[(0,O.jsx)(`div`,{children:e.deletedAt?new Date(e.deletedAt).toLocaleString(void 0,{dateStyle:`medium`,timeStyle:`short`}):``}),(0,O.jsx)(`div`,{children:[N(e.size),r==null?``:r===0?`expires today`:`${r} day${r===1?``:`s`} left`].filter(Boolean).join(` · `)})]}),(0,O.jsxs)(l,{size:`sm`,variant:`outline`,disabled:!t||y,onClick:()=>void z(`restore`,[e.id]),title:`Put it back where it was`,children:[(0,O.jsx)(i,{className:`h-3.5 w-3.5 sm:mr-2`}),(0,O.jsx)(`span`,{className:`hidden sm:inline`,children:`Restore`})]}),(0,O.jsx)(l,{size:`sm`,variant:`ghost`,disabled:!t||y,onClick:()=>F({ids:[e.id],label:`"${e.name}"`}),"aria-label":`Delete ${e.name} forever`,children:(0,O.jsx)(a,{className:`h-3.5 w-3.5`})})]},e.id)})})]},e.label)),n.length<o&&(0,O.jsx)(`div`,{className:`text-center`,children:(0,O.jsx)(l,{size:`sm`,variant:`outline`,disabled:g,onClick:()=>void L(n.length),children:`Show more`})})]})}function I({value:e,backends:t,source:n,onSave:r,destination:i=!0}){let[a,o]=(0,_.useState)({...v,...e}),[s,c]=(0,_.useState)(!1),[u,d]=(0,_.useState)(``),f=`rounded border bg-background px-2 py-1.5 text-xs w-full`,p=async()=>{c(!0),d(``);try{await r(a),d(`Removal policy saved.`)}catch(e){d(e instanceof Error?e.message:`Could not save policy`)}finally{c(!1)}};return(0,O.jsxs)(`details`,{className:`border-t pt-3 text-xs`,children:[(0,O.jsx)(`summary`,{className:`cursor-pointer font-medium`,children:`Source removals and Trash`}),(0,O.jsxs)(`div`,{className:`mt-3 space-y-3`,children:[(0,O.jsx)(`p`,{className:`text-muted-foreground`,children:`A completed scan removes missing locations from the backend tree. Items with no remaining locations go to Trash until you purge them.`}),(0,O.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,O.jsxs)(`label`,{className:`space-y-1 block`,children:[`When an item disappears from this source`,(0,O.jsxs)(`select`,{className:f,value:a.membership,disabled:s,onChange:e=>o({...a,membership:e.target.value}),children:[(0,O.jsx)(`option`,{value:`keep`,children:`Keep in managed trees`}),(0,O.jsx)(`option`,{value:`review`,children:`Review removal in Trash`}),(0,O.jsx)(`option`,{value:`trash`,children:`Move to Trash automatically`})]})]}),(0,O.jsxs)(`label`,{className:`space-y-1 block`,children:[`Remove tracked copies from other backends`,(0,O.jsxs)(`select`,{className:f,value:a.propagation,disabled:s,onChange:e=>o({...a,propagation:e.target.value}),children:[(0,O.jsx)(`option`,{value:`never`,children:`Never`}),(0,O.jsx)(`option`,{value:`review`,children:`Review in Trash`}),(0,O.jsx)(`option`,{value:`automatic`,children:`Automatically, retaining recovery copies`})]})]})]}),a.propagation!==`never`&&(0,O.jsxs)(`fieldset`,{className:`space-y-2`,children:[(0,O.jsx)(`legend`,{className:`mb-1 font-medium`,children:`Destinations`}),(0,O.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(`input`,{type:`checkbox`,checked:a.targets===`all`,disabled:s,onChange:e=>o({...a,targets:e.target.checked?`all`:[]})}),`All eligible backends`]}),a.targets!==`all`&&t.filter(e=>e.address!==n&&e.kind===`storage`).map(e=>(0,O.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(`input`,{type:`checkbox`,disabled:s||e.config?.propagatedRemovalSupported!==!0,checked:a.targets.includes(e.address),onChange:t=>o({...a,targets:t.target.checked?[...a.targets,e.address]:a.targets.filter(t=>t!==e.address)})}),String(e.config?.label||e.address),e.config?.propagatedRemovalSupported===!0?!e.config?.removalPolicy?.acceptPropagatedDeletions&&` · protected`:` · recovery removal unavailable`]},e.address)),(0,O.jsx)(`p`,{className:`text-muted-foreground`,children:`Only tracked, Canvas-owned copies are eligible. Protected destinations refuse propagated deletion. Recovery removal currently supports filesystem and workspace blob storage; remote destinations remain protected.`})]}),i&&(0,O.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(`input`,{type:`checkbox`,disabled:s,checked:a.acceptPropagatedDeletions,onChange:e=>o({...a,acceptPropagatedDeletions:e.target.checked})}),`Accept propagated deletions on this backend`]}),(0,O.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,O.jsx)(l,{size:`sm`,variant:`outline`,disabled:s,onClick:()=>void p(),children:s?`Saving…`:`Save removal policy`}),(0,O.jsx)(`span`,{role:`status`,children:u})]})]})]})}function L({workspaceName:e}){return(0,O.jsx)(R,{workspaceName:e},e)}function R({workspaceName:e}){let[t,n]=(0,_.useState)(`deleted`),[r,i]=(0,_.useState)(0),[a,o]=(0,_.useState)({write:!1,admin:!1});return(0,_.useEffect)(()=>{let t=!0;return f(e).then(e=>{let n=e.remote?.permissions||e.access?.permissions||(typeof e.sharedVia==`object`?e.sharedVia?.permissions:[])||[],r=g(e);t&&o({admin:r,write:r||n.includes(`write`)})}).catch(()=>{}),b(e,{view:`pending`,offset:0}).then(e=>{t&&i(e.total)}).catch(()=>{}),()=>{t=!1}},[e]),(0,O.jsxs)(`div`,{className:`space-y-4`,children:[(0,O.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,role:`tablist`,"aria-label":`Trash`,children:[(0,O.jsx)(l,{role:`tab`,"aria-selected":t===`deleted`,size:`sm`,variant:t===`deleted`?`default`:`outline`,onClick:()=>n(`deleted`),children:`Recently deleted`}),(0,O.jsxs)(l,{role:`tab`,"aria-selected":t===`removals`,size:`sm`,variant:t===`removals`?`default`:`outline`,onClick:()=>n(`removals`),children:[`Source removals`,r>0?` (${r} to review)`:``]})]}),t===`deleted`?(0,O.jsx)(F,{workspaceName:e,canWrite:a.write}):(0,O.jsx)(z,{workspaceName:e,access:a,onPending:i})]})}function z({workspaceName:e,access:t,onPending:n}){let[r,i]=(0,_.useState)(`pending`),[a,o]=(0,_.useState)(``),[c,d]=(0,_.useState)(``),[f,g]=(0,_.useState)(0),[y,C]=(0,_.useState)(0),[w,T]=(0,_.useState)(null),[E,D]=(0,_.useState)(``),[k,A]=(0,_.useState)(!1),[j,M]=(0,_.useState)(new Set),[N,P]=(0,_.useState)({}),[F,L]=(0,_.useState)([]),[R,z]=(0,_.useState)(null);(0,_.useEffect)(()=>{let t=!0;return h(e).then(e=>{t&&L(e)}).catch(()=>{}),()=>{t=!1}},[e]),(0,_.useEffect)(()=>{let t=!1,i=()=>b(e,{view:r,search:a,...c?{backend:c}:{},offset:f}).then(e=>{t||(T(e),D(``),r===`pending`&&!a&&!c&&n(e.total))}).catch(e=>{t||D(e instanceof Error?e.message:`Could not load Trash`)});i();let o=setInterval(()=>{k||i()},5e3);return()=>{t=!0,clearInterval(o)}},[e,r,a,c,f,y,k,n]);let B=w?.operations||[],V=()=>{M(new Set),C(e=>e+1)},H=()=>{p(e),window.dispatchEvent(new CustomEvent(`workspace:tree:refresh`,{detail:{workspaceName:e}})),window.dispatchEvent(new CustomEvent(`workspace:trash:refresh`,{detail:{workspaceName:e}}))},U=async(t,n=[...j])=>{if(!(!n.length||k)&&!(t===`purge`&&!window.confirm(`Permanently delete retained recovery copies for ${n.length} operation(s)?`))){A(!0),D(``);try{let r=(t===`approve`?(await Promise.all(n.map(n=>x(e,[n],t,N[n])))).flatMap(e=>e.results):(await x(e,n,t)).results).filter(e=>!e.ok||e.operation?.state===`failed`);r.length&&D(r.map(e=>e.error||e.operation?.error||`A destination could not be changed. Expand the item for details.`).join(` `)),H(),V()}catch(e){D(e instanceof Error?e.message:`Trash action failed`)}finally{A(!1)}}},W=e=>{i(e),g(0),T(null),M(new Set),P({})};return(0,O.jsxs)(`div`,{className:`space-y-4`,children:[(0,O.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Files that disappeared from a backend or mailbox. Decide what happens to the copies Canvas still holds, and see what the removal policies did.`}),(0,O.jsxs)(`div`,{className:`flex flex-wrap items-center gap-2`,role:`tablist`,"aria-label":`Trash views`,children:[[[`pending`,`To review`],[`trashed`,`Recovery copies`],[`activity`,`Activity`]].map(([e,t])=>(0,O.jsx)(l,{role:`tab`,"aria-selected":r===e,size:`sm`,variant:r===e?`default`:`outline`,onClick:()=>W(e),children:t},e)),(0,O.jsxs)(l,{size:`sm`,variant:`ghost`,className:`ml-auto`,onClick:V,disabled:k,children:[(0,O.jsx)(s,{className:`mr-2 h-3.5 w-3.5`}),`Refresh`]})]}),(0,O.jsxs)(`div`,{className:`flex flex-wrap gap-2`,children:[(0,O.jsx)(u,{"aria-label":`Filter Trash items`,placeholder:`Filter by item or path…`,className:`max-w-xs`,value:a,onChange:e=>{o(e.target.value),T(null),g(0),M(new Set)}}),(0,O.jsx)(u,{"aria-label":`Filter by backend`,placeholder:`Backend name…`,className:`max-w-56`,value:c,onChange:e=>{d(e.target.value),T(null),g(0),M(new Set)}}),j.size>0&&(0,O.jsxs)(`div`,{className:`flex items-center gap-2 text-xs`,children:[(0,O.jsxs)(`span`,{children:[j.size,` selected`]}),r===`pending`&&(0,O.jsxs)(O.Fragment,{children:[(0,O.jsx)(l,{size:`sm`,disabled:k,onClick:()=>void U(`approve`),children:`Approve selected`}),(0,O.jsx)(l,{size:`sm`,variant:`outline`,disabled:k,onClick:()=>void U(`keep`),children:`Keep selected`}),(0,O.jsx)(l,{size:`sm`,variant:`outline`,disabled:k,onClick:()=>void U(`retry`),children:`Retry`})]}),r===`trashed`&&(0,O.jsxs)(O.Fragment,{children:[(0,O.jsx)(l,{size:`sm`,variant:`outline`,disabled:k,onClick:()=>void U(`restore`),children:`Restore copies`}),(0,O.jsx)(l,{size:`sm`,variant:`destructive`,disabled:k,onClick:()=>void U(`purge`),children:`Purge copies`})]})]})]}),R&&(0,O.jsxs)(`div`,{className:`rounded border p-3 space-y-2`,children:[(0,O.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,O.jsxs)(`p`,{className:`text-sm font-medium`,children:[`Removal policy · `,R.source.account||R.source.backend,R.source.folder?` / ${R.source.folder}`:``]}),(0,O.jsx)(l,{size:`sm`,variant:`ghost`,onClick:()=>z(null),children:`Close`})]}),(0,O.jsx)(I,{source:R.source.backend,backends:F,destination:!1,value:{...v,...F.find(e=>e.address===R.source.backend)?.config?.removalPolicy,membership:N[R.id]?.membership??R.membership!==`keep`?`review`:`keep`,propagation:R.targets.length?`review`:`never`,targets:[...new Set(R.targets.filter(e=>!N[R.id]||N[R.id].targets.includes(JSON.stringify([e.backend,e.key]))).map(e=>e.backend))]},onSave:async t=>{R.source.driver===`imap`?await S(e,R.source.account,R.source.folder,t):await m(e,R.source.driver,R.source.backend,{removalPolicy:t}),L(await h(e))}},R.id)]}),E&&(0,O.jsx)(`p`,{role:`alert`,className:`text-sm text-destructive`,children:E}),(0,O.jsxs)(`div`,{className:`overflow-x-auto rounded border`,children:[(0,O.jsxs)(`table`,{className:`w-full text-left text-xs`,children:[(0,O.jsx)(`thead`,{className:`bg-muted`,children:(0,O.jsxs)(`tr`,{children:[(0,O.jsx)(`th`,{className:`p-3 w-8`,children:(0,O.jsx)(`input`,{type:`checkbox`,"aria-label":`Select visible operations`,disabled:!t.write||k||!B.length||r===`activity`,checked:B.length>0&&B.every(e=>j.has(e.id)),onChange:e=>M(e.target.checked?new Set(B.map(e=>e.id)):new Set)})}),(0,O.jsx)(`th`,{className:`p-3`,children:`Item and affected copies`}),(0,O.jsx)(`th`,{className:`p-3`,children:`Source`}),(0,O.jsx)(`th`,{className:`p-3`,children:`Status`}),(0,O.jsx)(`th`,{className:`p-3`,children:`Detected`})]})}),(0,O.jsx)(`tbody`,{children:B.map(e=>{let n=N[e.id]||{targets:e.targets.filter(e=>e.state!==`kept`).map(e=>JSON.stringify([e.backend,e.key])),membership:e.membership!==`keep`};return(0,O.jsxs)(`tr`,{className:`border-t align-top`,children:[(0,O.jsx)(`td`,{className:`p-3`,children:(0,O.jsx)(`input`,{type:`checkbox`,"aria-label":`Select ${e.title}`,disabled:!t.write||k||r===`activity`,checked:j.has(e.id),onChange:t=>M(n=>{let r=new Set(n);return t.target.checked?r.add(e.id):r.delete(e.id),r})})}),(0,O.jsx)(`td`,{className:`p-3 min-w-64`,children:(0,O.jsxs)(`details`,{children:[(0,O.jsx)(`summary`,{className:`cursor-pointer font-medium`,children:e.title}),(0,O.jsxs)(`div`,{className:`mt-2 space-y-2 text-muted-foreground`,children:[(0,O.jsx)(`p`,{children:e.orphan?`No remaining byte locations. Restore placements only unless recovery bytes are available.`:`${e.remainingLocations.length} remaining location(s) when detected.`}),e.placements.map(e=>(0,O.jsxs)(`p`,{children:[e.tree,`: `,e.paths.join(`, `)]},e.tree)),e.membership!==`keep`&&(0,O.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,O.jsx)(`input`,{type:`checkbox`,checked:n.membership,disabled:k||r!==`pending`||e.membershipApplied,onChange:t=>P({...N,[e.id]:{...n,membership:t.target.checked}})}),e.membershipApplied?`Managed placements moved to Trash`:`Move managed placements to Trash`]}),e.targets.map(t=>{let i=JSON.stringify([t.backend,t.key]);return(0,O.jsxs)(`label`,{className:`flex items-start gap-2`,children:[(0,O.jsx)(`input`,{type:`checkbox`,disabled:k||r!==`pending`||!!t.trashId,checked:n.targets.includes(i),onChange:t=>P({...N,[e.id]:{...n,targets:t.target.checked?[...n.targets,i]:n.targets.filter(e=>e!==i)}})}),(0,O.jsxs)(`span`,{className:`break-all`,children:[t.backend,`:`,t.key,` · `,t.state,t.error&&(0,O.jsx)(`span`,{className:`block text-destructive`,children:t.error})]})]},i)}),(0,O.jsx)(l,{size:`sm`,variant:`outline`,disabled:!t.admin,onClick:()=>z(e),children:`Use these choices as a source policy`}),e.remainingLocations.map(e=>(0,O.jsx)(`p`,{className:`break-all`,children:e.url},e.url))]})]})}),(0,O.jsxs)(`td`,{className:`p-3 break-all`,children:[e.source.account||e.source.backend,e.source.folder&&(0,O.jsx)(`span`,{className:`block text-muted-foreground`,children:e.source.folder})]}),(0,O.jsxs)(`td`,{className:`p-3`,children:[e.state,e.error&&(0,O.jsx)(`p`,{className:`mt-1 max-w-xs text-destructive`,children:e.error})]}),(0,O.jsx)(`td`,{className:`p-3 whitespace-nowrap text-muted-foreground`,children:new Date(e.createdAt).toLocaleString()})]},e.id)})})]}),!B.length&&(0,O.jsx)(`p`,{className:`p-5 text-center text-sm text-muted-foreground`,children:w?`No matching operations.`:`Loading…`})]}),(0,O.jsxs)(`div`,{className:`flex items-center justify-between text-xs text-muted-foreground`,children:[(0,O.jsxs)(`span`,{children:[w?.total??0,` operation(s)`]}),(0,O.jsxs)(`div`,{className:`flex gap-2`,children:[(0,O.jsx)(l,{size:`sm`,variant:`outline`,disabled:!f||k,onClick:()=>{g(Math.max(0,f-200)),M(new Set)},children:`Previous`}),(0,O.jsx)(l,{size:`sm`,variant:`outline`,disabled:f+B.length>=(w?.total??0)||k,onClick:()=>{g(f+200),M(new Set)},children:`Next`})]})]})]})}var B=`canvas:query-debug`,V=`canvas:query-debug-changed`;function H(){try{return localStorage.getItem(B)===`1`}catch{return!1}}function U(e){try{e?localStorage.setItem(B,`1`):localStorage.removeItem(B)}catch{}window.dispatchEvent(new CustomEvent(V,{detail:e}))}function W(){let[e,t]=(0,_.useState)(H);return(0,_.useEffect)(()=>{let e=()=>t(H());return window.addEventListener(V,e),window.addEventListener(`storage`,e),()=>{window.removeEventListener(V,e),window.removeEventListener(`storage`,e)}},[]),e}export{I as a,L as i,U as n,S as o,W as r,H as t};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/TerminalApplet-BZJx2ztD.js","assets/rolldown-runtime-C0FnF6B9.js","assets/code-editor-BOIngd5F.js","assets/ui-DEgHnkQu.js","assets/react-BHzhHVTZ.js","assets/use-applet-target-BlpVWlnA.js","assets/workspace-4hWrSEku.js","assets/button--VYZekMF.js","assets/utils-BxVxyehK.js","assets/utils-2pl1SbIp.js","assets/input-BOtCd4HP.js","assets/api-CA6WiiYM.js","assets/alert-dialog-BKtaX1_a.js","assets/use-toolbox-Ck_cLGgf.js","assets/TerminalApplet-BrP-ENHg.css","assets/NotesApplet-BSJ-9RKl.js","assets/useAddTarget-BvuFR5pN.js","assets/context-DY40EDc6.js","assets/note-save-status-DPz4VzL6.js","assets/useEditNoteFields-DsVKIHWm.js","assets/tags-YamdPoBK.js","assets/index-CTvqbEB8.js","assets/preload-helper-Czpn1I53.js","assets/chunk-62JRHF6Z-vspAGgtK.js","assets/label-RuOXXC8t.js","assets/socket-hM4c-ZSl.js","assets/socket-CtH3EU9m.js","assets/auth-Bx9fAZmz.js","assets/use-toast-BlLDqSUO.js","assets/LinkToCard-oi3wGP0a.js","assets/useEscapeClose-DR_xKT_k.js","assets/useToastHelpers-CRrpIIdY.js","assets/layer-style-Byl5LNFR.js","assets/color-DFEH4BfK.js","assets/DocumentIcon-0ya9gycp.js","assets/use-canvas-pins-q5Tncavk.js","assets/TodosWidget-DGftEAbs.js","assets/ObjectPropertiesCard-DesXRw-_.js","assets/use-mobile-Db-vWu9Y.js","assets/IdentityFields-CB3Ap0bl.js","assets/date-time-picker-p3vy4nst.js","assets/relation-events-CKio19hE.js","assets/map-BxCwdK0d.js","assets/map-BcsP_QXj.css","assets/public-share-0DqS7L2Q.js","assets/text-documents-wu6fzOuw.js","assets/blobs-WiXP9QRi.js","assets/useDocumentThumbnail-CZIaXkIi.js","assets/markdown-view-BBBZtNSR.js","assets/sanitize-DrVcFY1Q.js","assets/MessageComposerDialog-CLrwtB76.js","assets/markdown-it-DRESbtwK.js","assets/punycode.es6-ZbLrB_Dn.js","assets/lazy-editor-CShGeIep.js","assets/LinkToSidePanel-eCy3nW4R.js","assets/DocumentBodyEditor-C8AEpqX3.js","assets/use-document-modal-PG8bQyIB.js","assets/sketch-lazy-CtjOUfVz.js","assets/geo-CZfs0E-x.js","assets/ObjectPropertiesCard-Docu7O5V.css","assets/document-list-Bbbx-pTZ.js","assets/document-open-mode-DoImW-xs.js","assets/PickDocumentsCard-DVdBxx3s.js","assets/sha256-65KIjGvZ.js","assets/rule-builder-CziPqpNe.js","assets/PathPickerField-CSIa7jSl.js","assets/rule-builder-DU-e9TWi.css","assets/workspace-access-C9nZlBBZ.js","assets/search-COMZIxA7.js","assets/use-sortable-data-D7zS2qCC.js","assets/workspace-BydSRtST.js","assets/document-list-DAYdk5vh.css","assets/url-params-n7kU_WZ-.js","assets/use-canvas-pins-C57Vbkrq.css","assets/use-menu-CKSpS96u.js","assets/last-path-BbXWC3b3.js","assets/document-paste-BuTC6S7_.js","assets/workspace-content-gate-BlFdbi67.js","assets/use-theme-DaxpiICf.js","assets/index-CoVFQpP3.css","assets/shared-CLjTxih0.js","assets/use-applet-docs-C08GAUm3.js","assets/TodosApplet-DY7JzeZS.js","assets/LensApplet-DA0ZWS1k.js","assets/FiltersApplet-CVnCAs-P.js","assets/SketchApplet--3uyqpmo.js","assets/CalendarApplet-CsyUmI2B.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{t as r}from"./preload-helper-Czpn1I53.js";import{$r as i,St as a,Xr as o,ct as s,hn as c,it as l,tt as u}from"./ui-DEgHnkQu.js";var d=e(n(),1),f=t();function p(e){let t=(0,d.lazy)(e);return function(e){return(0,f.jsx)(d.Suspense,{fallback:(0,f.jsx)(`p`,{className:`p-4 text-sm text-muted-foreground`,role:`status`,children:`Opening app…`}),children:(0,f.jsx)(t,{...e})})}}var m=p(()=>r(()=>import(`./TerminalApplet-BZJx2ztD.js`).then(e=>({default:e.TerminalApplet})),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]))),h=p(()=>r(()=>import(`./NotesApplet-BSJ-9RKl.js`).then(e=>({default:e.NotesApplet})),__vite__mapDeps([15,1,2,3,4,9,8,6,7,10,11,12,16,13,17,18,19,20,5,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81]))),g=p(()=>r(()=>import(`./TodosApplet-DY7JzeZS.js`).then(e=>({default:e.TodosApplet})),__vite__mapDeps([82,1,2,3,4,9,8,6,7,10,11,12,16,13,17,40,20,41,5,80,29,30,31,28,32,33,34,54,81]))),_=p(()=>r(()=>import(`./LensApplet-DA0ZWS1k.js`).then(e=>({default:e.LensApplet})),__vite__mapDeps([83,1,2,3,4,9,8,6,7,10,11,12,47,44,34,56,5,13,21,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37,38,39,20,16,17,40,41,42,43,45,46,48,49,50,51,52,53,54,18,19,55,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79]))),v=p(()=>r(()=>import(`./FiltersApplet-CVnCAs-P.js`).then(e=>({default:e.FiltersApplet})),__vite__mapDeps([84,1,2,26,11,25,13,5,6,4,7,3,8,9,10,12,21,22,23,24,27,28,29,30,31,32,33,34,35,36,37,38,39,20,16,17,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,18,19,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79]))),y=p(()=>r(()=>import(`./SketchApplet--3uyqpmo.js`).then(e=>({default:e.SketchApplet})),__vite__mapDeps([85,1,2,3,4,7,8,9,6,10,11,12,47,44,31,28,57,22,5,13,81,17]))),b=p(()=>r(()=>import(`./CalendarApplet-CsyUmI2B.js`).then(e=>({default:e.CalendarApplet})),__vite__mapDeps([86,1,2,23,22,3,4,9,8,29,7,6,10,11,12,30,31,28,32,33,34,16,13,17,40,20,41,5,21,24,25,26,27,35,36,37,38,39,42,43,44,45,46,47,48,49,50,51,52,53,54,18,19,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80]))),x=[{id:`terminal`,category:`utilities`,label:`Terminal`,icon:l,modes:[`context`],description:`Shell sessions for this context`,Component:m},{id:`filters`,category:`utilities`,label:`Filters`,icon:s,modes:[`context`,`global`],description:`Search and filter a workspace or a live context`,Component:v},{id:`notes`,category:`productivity`,label:`Notes`,icon:u,modes:[`context`],description:`All notes in the current context, editable in place`,Component:h},{id:`todo`,category:`productivity`,label:`Todos`,icon:c,modes:[`context`],description:`Todos in the current context, done items hidden by default`,Component:g},{id:`calendar`,category:`productivity`,label:`Calendar`,icon:o,modes:[`context`],description:`Day, week, month, year and schedule views of the events and due tasks in the current context`,Component:b},{id:`sketch`,category:`creative`,label:`Sketch`,icon:i,modes:[`context`],description:`Quick-sketch into the current context; tap a sketch to keep editing`,Component:y},{id:`lens`,category:`media`,label:`Lens`,icon:a,modes:[`context`],description:`Point a camera at things; matching documents surface live`,Component:_}];function S(e){return x.filter(t=>t.modes.includes(e))}export{S as n,x as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{l as e}from"./code-editor-BOIngd5F.js";import{n as t}from"./page-header-
|
|
1
|
+
import{l as e}from"./code-editor-BOIngd5F.js";import{n as t}from"./page-header-NyYSXjfY.js";var n=e();function r(){return(0,n.jsxs)(`div`,{className:`space-y-6`,children:[(0,n.jsx)(t,{title:`Remotes`,description:`Connect to remote Canvas instances`}),(0,n.jsx)(`div`,{className:`flex flex-col items-center justify-center py-12 space-y-4`,children:(0,n.jsxs)(`div`,{className:`text-center`,children:[(0,n.jsx)(`h2`,{className:`text-2xl font-semibold mb-2`,children:`Coming Soon`}),(0,n.jsx)(`p`,{className:`text-muted-foreground max-w-md`,children:`Remote connection management is currently under development. Check back later for updates.`})]})})]})}export{r as default};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{
|
|
1
|
+
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{Ar as r,It as i,Lr as a,Nr as o,Pt as s,Rr as c,Si as l,_t as u,or as d,rt as f,wt as p}from"./ui-DEgHnkQu.js";import{t as m}from"./button--VYZekMF.js";import{t as h}from"./input-BOtCd4HP.js";import{i as g}from"./auth-Bx9fAZmz.js";import{n as _}from"./use-toast-BlLDqSUO.js";import{jt as v}from"./workspace-4hWrSEku.js";import{t as y}from"./useEscapeClose-DR_xKT_k.js";import{n as b}from"./page-header-NyYSXjfY.js";import{t as x}from"./role-C5I0Plgn.js";import{t as S}from"./form-panel-CEbNKttr.js";import{t as C}from"./use-create-panel-DhSNIGtr.js";var w=e(n(),1),T=t();function E({status:e}){let t={running:{icon:a,color:`text-success`,bg:`bg-success-subtle`,label:`Running`},stopped:{icon:o,color:`text-muted-foreground`,bg:`bg-muted`,label:`Stopped`},starting:{icon:r,color:`text-info`,bg:`bg-info-subtle`,label:`Starting`},stopping:{icon:r,color:`text-warning`,bg:`bg-warning-subtle`,label:`Stopping`},error:{icon:c,color:`text-destructive`,bg:`bg-destructive-subtle`,label:`Error`},created:{icon:l,color:`text-muted-foreground`,bg:`bg-muted`,label:`Created`},configured:{icon:l,color:`text-info`,bg:`bg-info-subtle`,label:`Configured`},removed:{icon:o,color:`text-destructive`,bg:`bg-destructive-subtle`,label:`Removed`}},n=t[e]||t.created,i=n.icon;return(0,T.jsxs)(`span`,{className:`inline-flex items-center gap-1 px-2 py-1 rounded text-xs font-medium ${n.bg} ${n.color}`,children:[(0,T.jsx)(i,{className:`w-3 h-3`}),n.label]})}function D(){let[e,t]=(0,w.useState)([]),[n,a]=(0,w.useState)(!0),[o,c]=(0,w.useState)(null),[l,D]=(0,w.useState)(null);y(()=>D(null),l!==null);let[O,k]=C(),[A,j]=(0,w.useState)([]),[M,N]=(0,w.useState)([]),[P,F]=(0,w.useState)(``),[I,L]=(0,w.useState)(``),[R,z]=(0,w.useState)(``),[B,V]=(0,w.useState)(!1),{showToast:H}=_(),U=g(),W=(0,w.useCallback)(async()=>{try{a(!0);let e=await x.listRoles({type:`workspace`,userId:U?.id});t(e),c(null)}catch(e){let t=e instanceof Error?e.message:`Failed to fetch roles`;c(t)}finally{a(!1)}},[U?.id]);(0,w.useEffect)(()=>{let e=()=>W();e();let t=setInterval(e,3e4);return()=>clearInterval(t)},[W]),(0,w.useEffect)(()=>{O&&(x.listTemplates().then(e=>{let t=e.filter(e=>e.type===`workspace`);j(t),F(e=>e||t[0]?.id||``)}).catch(()=>j([])),v().then(e=>{N(e),z(t=>t||e[0]?.id||``)}).catch(()=>N([])))},[O]);let G=async e=>{if(e.preventDefault(),!(!P||!I.trim()||!R)){V(!0);try{let e=await x.createRole({template:P,name:I.trim(),type:`workspace`,userId:U?.id,workspaceId:R});L(``),k(!1),await W(),H({title:`Created`,description:`Role "${e.name}" created`})}catch(e){H({title:`Error`,description:e instanceof Error?e.message:`Failed to create role`,variant:`destructive`})}finally{V(!1)}}},K=async e=>{try{await x.startRole(e.id),H({title:`Success`,description:`Role "${e.name}" started successfully`}),W()}catch(e){let t=e instanceof Error?e.message:`Failed to start role`;H({title:`Error`,description:t,variant:`destructive`})}},q=async e=>{try{await x.stopRole(e.id),H({title:`Success`,description:`Role "${e.name}" stopped successfully`}),W()}catch(e){let t=e instanceof Error?e.message:`Failed to stop role`;H({title:`Error`,description:t,variant:`destructive`})}},J=async e=>{try{await x.restartRole(e.id),H({title:`Success`,description:`Role "${e.name}" restarted successfully`}),W()}catch(e){let t=e instanceof Error?e.message:`Failed to restart role`;H({title:`Error`,description:t,variant:`destructive`})}},Y=async e=>{try{let t=await x.getRoleLogs(e.id,100);D({role:e,logs:t})}catch(e){let t=e instanceof Error?e.message:`Failed to fetch logs`;H({title:`Error`,description:t,variant:`destructive`})}};return(0,T.jsxs)(`div`,{className:`space-y-6`,children:[(0,T.jsx)(b,{title:`My Roles`,description:`Manage your workspace roles and services`,actions:(0,T.jsxs)(T.Fragment,{children:[!O&&(0,T.jsxs)(m,{onClick:()=>k(!0),children:[(0,T.jsx)(s,{className:`mr-2 h-4 w-4`}),`Create Role`]}),(0,T.jsxs)(m,{onClick:W,variant:`outline`,children:[(0,T.jsx)(p,{className:`mr-2 h-4 w-4`}),`Refresh`]})]})}),O&&(0,T.jsx)(S,{title:`Create New Role`,onClose:()=>k(!1),children:(0,T.jsxs)(`form`,{onSubmit:G,className:`space-y-4`,children:[(0,T.jsxs)(`div`,{className:`grid gap-4 md:grid-cols-2`,children:[(0,T.jsxs)(`div`,{children:[(0,T.jsx)(`label`,{htmlFor:`role-template`,className:`mb-1 block text-sm font-medium`,children:`Template`}),(0,T.jsxs)(`select`,{id:`role-template`,className:`w-full rounded-md border border-border bg-background px-3 py-2`,value:P,onChange:e=>F(e.target.value),disabled:B||A.length===0,children:[A.length===0&&(0,T.jsx)(`option`,{value:``,children:`No workspace templates available`}),A.map(e=>(0,T.jsxs)(`option`,{value:e.id,children:[e.name,` - `,e.description]},e.id))]})]}),(0,T.jsxs)(`div`,{children:[(0,T.jsx)(`label`,{htmlFor:`role-name`,className:`mb-1 block text-sm font-medium`,children:`Role Name`}),(0,T.jsx)(h,{id:`role-name`,value:I,onChange:e=>L(e.target.value),placeholder:`e.g., canvas-sshd`,disabled:B})]})]}),(0,T.jsxs)(`div`,{children:[(0,T.jsx)(`label`,{htmlFor:`role-workspace`,className:`mb-1 block text-sm font-medium`,children:`Workspace`}),(0,T.jsxs)(`select`,{id:`role-workspace`,className:`w-full rounded-md border border-border bg-background px-3 py-2`,value:R,onChange:e=>z(e.target.value),disabled:B||M.length===0,children:[M.length===0&&(0,T.jsx)(`option`,{value:``,children:`No workspaces available. Create one first.`}),M.map(e=>(0,T.jsx)(`option`,{value:e.id,children:e.label||e.name},e.id))]})]}),(0,T.jsxs)(m,{type:`submit`,disabled:B||!P||!I.trim()||!R,children:[(0,T.jsx)(s,{className:`mr-2 h-4 w-4`}),B?`Creating…`:`Create Role`]})]})}),n?(0,T.jsx)(`div`,{className:`text-center py-8`,children:`Loading roles...`}):o?(0,T.jsx)(`div`,{className:`text-center py-8 text-destructive`,children:o}):e.length===0?(0,T.jsxs)(`div`,{className:`text-center py-12 border rounded-lg`,children:[(0,T.jsx)(u,{className:`w-12 h-12 mx-auto text-muted-foreground mb-4`}),(0,T.jsx)(`p`,{className:`text-muted-foreground`,children:`You don't have any workspace roles yet`}),(0,T.jsx)(`p`,{className:`text-sm text-muted-foreground mt-2`,children:`Contact your administrator to set up roles for your workspaces`})]}):(0,T.jsx)(`div`,{className:`grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4`,children:e.map(e=>(0,T.jsxs)(`div`,{className:`border rounded-lg p-6 space-y-4 hover:shadow-elevation-2 transition-shadow`,children:[(0,T.jsxs)(`div`,{className:`flex items-start justify-between`,children:[(0,T.jsxs)(`div`,{className:`flex-1`,children:[(0,T.jsx)(`h3`,{className:`font-semibold text-lg`,children:e.name}),(0,T.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:e.template})]}),(0,T.jsx)(E,{status:e.status})]}),e.container&&(0,T.jsx)(`div`,{className:`text-xs text-muted-foreground`,children:(0,T.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,T.jsx)(u,{className:`w-3 h-3`}),(0,T.jsx)(`span`,{className:`truncate`,children:e.container.name})]})}),(0,T.jsxs)(`div`,{className:`flex gap-2 pt-2`,children:[e.status===`stopped`||e.status===`created`?(0,T.jsxs)(m,{size:`sm`,variant:`outline`,onClick:()=>K(e),className:`flex-1`,children:[(0,T.jsx)(i,{className:`w-4 h-4 mr-2`}),`Start`]}):e.status===`running`?(0,T.jsxs)(T.Fragment,{children:[(0,T.jsxs)(m,{size:`sm`,variant:`outline`,onClick:()=>q(e),className:`flex-1`,children:[(0,T.jsx)(f,{className:`w-4 h-4 mr-2`}),`Stop`]}),(0,T.jsxs)(m,{size:`sm`,variant:`outline`,onClick:()=>J(e),className:`flex-1`,children:[(0,T.jsx)(p,{className:`w-4 h-4 mr-2`}),`Restart`]})]}):(0,T.jsxs)(m,{size:`sm`,variant:`outline`,disabled:!0,className:`flex-1`,children:[(0,T.jsx)(r,{className:`w-4 h-4 mr-2`}),e.status]}),(0,T.jsx)(m,{size:`sm`,variant:`outline`,onClick:()=>Y(e),title:`View Logs`,children:(0,T.jsx)(d,{className:`w-4 h-4`})})]})]},e.id))}),(0,T.jsxs)(`div`,{className:`border-t pt-6`,children:[(0,T.jsx)(`h2`,{className:`text-lg font-semibold mb-4`,children:`Global Services`}),(0,T.jsxs)(`div`,{className:`text-sm text-muted-foreground space-y-2`,children:[(0,T.jsx)(`p`,{children:`Global roles are server-wide services managed by your administrator. These include services like SSH access, storage, and other shared infrastructure.`}),(0,T.jsx)(`p`,{children:`To check the status of global services, contact your system administrator.`})]})]}),l&&(0,T.jsx)(`div`,{className:`fixed inset-0 bg-scrim flex items-center justify-center z-50`,children:(0,T.jsxs)(`div`,{className:`bg-background rounded-lg shadow-elevation-3 max-w-4xl w-full mx-4 max-h-viewport-modal flex flex-col`,children:[(0,T.jsxs)(`div`,{className:`p-6 border-b`,children:[(0,T.jsxs)(`h2`,{className:`text-xl font-bold`,children:[l.role.name,` - Logs`]}),(0,T.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:l.role.template})]}),(0,T.jsx)(`div`,{className:`flex-1 overflow-y-auto p-6`,children:(0,T.jsx)(`div`,{"data-scheme":`dark`,className:`bg-background text-success p-4 rounded font-mono text-xs overflow-x-auto`,children:l.logs.length===0?(0,T.jsx)(`div`,{className:`text-muted-foreground`,children:`No logs available`}):(0,T.jsx)(`pre`,{children:l.logs.join(`
|
|
2
2
|
`)})})}),(0,T.jsx)(`div`,{className:`p-4 border-t flex justify-end`,children:(0,T.jsx)(m,{onClick:()=>D(null),children:`Close`})})]})})]})}export{D as default};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{Ir as r,It as i,L as a,Lr as o,Mr as s,Pt as c,Y as l,_t as u,bi as d,kr as f,or as p,rt as m,wt as h}from"./ui-CDoK3F3U.js";import{t as g}from"./button-SeUZ_Pvi.js";import{t as _}from"./input-BOtCd4HP.js";import{t as v}from"./label-BSTdjCWU.js";import{i as y}from"./auth-Bx9fAZmz.js";import{n as ee}from"./use-toast-BlLDqSUO.js";import{t as b}from"./useEscapeClose-DR_xKT_k.js";import{n as x}from"./page-header-DrDt1sQ2.js";import{t as S}from"./use-settings-back-DGmLAD63.js";import{t as C}from"./role-C5I0Plgn.js";var w=e(n(),1),T=t();function E({status:e}){let t={running:{icon:r,color:`text-success`,bg:`bg-success-subtle`,label:`Running`},stopped:{icon:s,color:`text-muted-foreground`,bg:`bg-muted`,label:`Stopped`},starting:{icon:f,color:`text-info`,bg:`bg-info-subtle`,label:`Starting`},stopping:{icon:f,color:`text-warning`,bg:`bg-warning-subtle`,label:`Stopping`},error:{icon:o,color:`text-destructive`,bg:`bg-destructive-subtle`,label:`Error`},created:{icon:d,color:`text-muted-foreground`,bg:`bg-muted`,label:`Created`},configured:{icon:d,color:`text-info`,bg:`bg-info-subtle`,label:`Configured`},removed:{icon:s,color:`text-destructive`,bg:`bg-destructive-subtle`,label:`Removed`}},n=t[e]||t.created,i=n.icon;return(0,T.jsxs)(`span`,{className:`inline-flex items-center gap-1 px-2 py-1 rounded text-xs font-medium ${n.bg} ${n.color}`,children:[(0,T.jsx)(i,{className:`w-3 h-3`}),n.label]})}function te({type:e}){return(0,T.jsxs)(`span`,{className:`inline-flex items-center gap-1 px-2 py-1 rounded text-xs font-medium ${e===`global`?`bg-accent text-primary`:`bg-info-subtle text-info`}`,children:[(0,T.jsx)(u,{className:`w-3 h-3`}),e===`global`?`Global`:`Workspace`]})}function D(){let e=S(),t=y()?.userType===`admin`,[n,r]=(0,w.useState)([]),[o,s]=(0,w.useState)([]),[d,f]=(0,w.useState)(t),[D,O]=(0,w.useState)(t?null:`Access denied. Admin privileges required.`),[k,A]=(0,w.useState)(!1);b(()=>A(!1),k);let[j,M]=(0,w.useState)(null),[N,P]=(0,w.useState)(!1);b(()=>P(!1),N);let[F,ne]=(0,w.useState)([]),[I,L]=(0,w.useState)({type:``,status:``,search:``}),[R,z]=(0,w.useState)({template:``,name:``,type:`global`}),{showToast:B}=ee(),V=(0,w.useRef)(I);(0,w.useEffect)(()=>{V.current=I},[I]);let H=(0,w.useCallback)(async()=>{try{f(!0);let{type:e,status:t}=V.current,n=await C.listRoles({type:e||void 0,status:t||void 0});r(n),O(null)}catch(e){let t=e instanceof Error?e.message:`Failed to fetch roles`;O(t)}finally{f(!1)}},[]),U=(0,w.useCallback)(async()=>{try{let e=await C.listTemplates();s(e)}catch(e){console.error(`Failed to fetch templates:`,e)}},[]);(0,w.useEffect)(()=>{t&&(H(),U())},[t,H,U]);let W=async()=>{if(!R.template||!R.name){B({title:`Validation Error`,description:`Template and name are required`,variant:`destructive`});return}try{await C.createRole(R),B({title:`Success`,description:`Role "${R.name}" created successfully`}),A(!1),X(),H()}catch(e){let t=e instanceof Error?e.message:`Failed to create role`;B({title:`Error`,description:t,variant:`destructive`})}},G=async e=>{try{await C.startRole(e.id),B({title:`Success`,description:`Role "${e.name}" started successfully`}),H()}catch(e){let t=e instanceof Error?e.message:`Failed to start role`;B({title:`Error`,description:t,variant:`destructive`})}},K=async e=>{try{await C.stopRole(e.id),B({title:`Success`,description:`Role "${e.name}" stopped successfully`}),H()}catch(e){let t=e instanceof Error?e.message:`Failed to stop role`;B({title:`Error`,description:t,variant:`destructive`})}},q=async e=>{try{await C.restartRole(e.id),B({title:`Success`,description:`Role "${e.name}" restarted successfully`}),H()}catch(e){let t=e instanceof Error?e.message:`Failed to restart role`;B({title:`Error`,description:t,variant:`destructive`})}},J=async e=>{if(confirm(`Are you sure you want to delete role "${e.name}"?`))try{await C.deleteRole(e.id,e.status===`running`),B({title:`Success`,description:`Role "${e.name}" deleted successfully`}),H()}catch(e){let t=e instanceof Error?e.message:`Failed to delete role`;B({title:`Error`,description:t,variant:`destructive`})}},Y=async e=>{try{let t=await C.getRoleLogs(e.id,100);ne(t),M(e),P(!0)}catch(e){let t=e instanceof Error?e.message:`Failed to fetch logs`;B({title:`Error`,description:t,variant:`destructive`})}},X=()=>{z({template:``,name:``,type:`global`})},Z=()=>{X(),A(!0)},Q=()=>{A(!1),X()},$=n.filter(e=>!I.search||e.name.toLowerCase().includes(I.search.toLowerCase())||e.template.toLowerCase().includes(I.search.toLowerCase()));return t?D&&!t?(0,T.jsx)(`div`,{className:`text-center space-y-4`,children:(0,T.jsx)(`div`,{className:`text-destructive`,children:D})}):(0,T.jsxs)(`div`,{className:`space-y-6`,children:[(0,T.jsx)(x,{onBack:e,title:`Role Management`,description:`Manage global and workspace roles for Canvas services`,actions:(0,T.jsxs)(g,{onClick:Z,className:`gap-2`,children:[(0,T.jsx)(c,{className:`w-4 h-4`}),`Create Role`]})}),(0,T.jsxs)(`div`,{className:`flex gap-4 items-end`,children:[(0,T.jsxs)(`div`,{className:`flex-1`,children:[(0,T.jsx)(v,{htmlFor:`search`,children:`Search`}),(0,T.jsx)(_,{id:`search`,placeholder:`Search by name or template...`,value:I.search,onChange:e=>L({...I,search:e.target.value})})]}),(0,T.jsxs)(`div`,{className:`w-48`,children:[(0,T.jsx)(v,{htmlFor:`type`,children:`Type`}),(0,T.jsxs)(`select`,{id:`type`,className:`w-full px-3 py-2 border rounded-md bg-background`,value:I.type,onChange:e=>L({...I,type:e.target.value}),children:[(0,T.jsx)(`option`,{value:``,children:`All Types`}),(0,T.jsx)(`option`,{value:`global`,children:`Global`}),(0,T.jsx)(`option`,{value:`workspace`,children:`Workspace`})]})]}),(0,T.jsxs)(`div`,{className:`w-48`,children:[(0,T.jsx)(v,{htmlFor:`status`,children:`Status`}),(0,T.jsxs)(`select`,{id:`status`,className:`w-full px-3 py-2 border rounded-md bg-background`,value:I.status,onChange:e=>L({...I,status:e.target.value}),children:[(0,T.jsx)(`option`,{value:``,children:`All Statuses`}),(0,T.jsx)(`option`,{value:`running`,children:`Running`}),(0,T.jsx)(`option`,{value:`stopped`,children:`Stopped`}),(0,T.jsx)(`option`,{value:`starting`,children:`Starting`}),(0,T.jsx)(`option`,{value:`error`,children:`Error`})]})]}),(0,T.jsxs)(g,{onClick:H,variant:`outline`,children:[(0,T.jsx)(h,{className:`w-4 h-4 mr-2`}),`Refresh`]})]}),d?(0,T.jsx)(`div`,{className:`text-center py-8`,children:`Loading roles...`}):$.length===0?(0,T.jsxs)(`div`,{className:`text-center py-8 border rounded-lg`,children:[(0,T.jsx)(u,{className:`w-12 h-12 mx-auto text-muted-foreground mb-4`}),(0,T.jsx)(`p`,{className:`text-muted-foreground`,children:I.search||I.type||I.status?`No roles match your filters`:`No roles created yet`}),!I.search&&!I.type&&!I.status&&(0,T.jsxs)(g,{onClick:Z,variant:`outline`,className:`mt-4`,children:[(0,T.jsx)(c,{className:`w-4 h-4 mr-2`}),`Create Your First Role`]})]}):(0,T.jsx)(`div`,{className:`border rounded-lg`,children:(0,T.jsxs)(`table`,{className:`w-full`,children:[(0,T.jsx)(`thead`,{className:`bg-muted/50`,children:(0,T.jsxs)(`tr`,{children:[(0,T.jsx)(`th`,{className:`text-left p-4 font-medium`,children:`Name`}),(0,T.jsx)(`th`,{className:`text-left p-4 font-medium`,children:`Template`}),(0,T.jsx)(`th`,{className:`text-left p-4 font-medium`,children:`Type`}),(0,T.jsx)(`th`,{className:`text-left p-4 font-medium`,children:`Status`}),(0,T.jsx)(`th`,{className:`text-left p-4 font-medium`,children:`Container`}),(0,T.jsx)(`th`,{className:`text-left p-4 font-medium`,children:`Created`}),(0,T.jsx)(`th`,{className:`text-right p-4 font-medium`,children:`Actions`})]})}),(0,T.jsx)(`tbody`,{className:`divide-y`,children:$.map(e=>(0,T.jsxs)(`tr`,{className:`hover:bg-muted/50`,children:[(0,T.jsx)(`td`,{className:`p-4 font-medium`,children:e.name}),(0,T.jsx)(`td`,{className:`p-4 text-sm text-muted-foreground`,children:e.template}),(0,T.jsx)(`td`,{className:`p-4`,children:(0,T.jsx)(te,{type:e.type})}),(0,T.jsx)(`td`,{className:`p-4`,children:(0,T.jsx)(E,{status:e.status})}),(0,T.jsx)(`td`,{className:`p-4 text-sm text-muted-foreground`,children:e.container?.name||`-`}),(0,T.jsx)(`td`,{className:`p-4 text-sm text-muted-foreground`,children:new Date(e.createdAt).toLocaleDateString()}),(0,T.jsx)(`td`,{className:`p-4`,children:(0,T.jsxs)(`div`,{className:`flex justify-end gap-2`,children:[e.status===`stopped`||e.status===`created`?(0,T.jsx)(g,{size:`sm`,variant:`outline`,onClick:()=>G(e),title:`Start`,children:(0,T.jsx)(i,{className:`w-4 h-4`})}):e.status===`running`?(0,T.jsx)(g,{size:`sm`,variant:`outline`,onClick:()=>K(e),title:`Stop`,children:(0,T.jsx)(m,{className:`w-4 h-4`})}):null,e.status===`running`&&(0,T.jsx)(g,{size:`sm`,variant:`outline`,onClick:()=>q(e),title:`Restart`,children:(0,T.jsx)(h,{className:`w-4 h-4`})}),(0,T.jsx)(g,{size:`sm`,variant:`outline`,onClick:()=>Y(e),title:`View Logs`,children:(0,T.jsx)(p,{className:`w-4 h-4`})}),(0,T.jsx)(g,{size:`sm`,variant:`outline`,onClick:()=>J(e),title:`Delete`,className:`text-destructive hover:text-destructive`,children:(0,T.jsx)(l,{className:`w-4 h-4`})})]})})]},e.id))})]})}),k&&(0,T.jsx)(`div`,{className:`fixed inset-0 bg-scrim flex items-center justify-center z-50`,children:(0,T.jsx)(`div`,{className:`bg-background rounded-lg shadow-elevation-3 max-w-lg w-full mx-4 max-h-viewport-modal overflow-y-auto`,children:(0,T.jsxs)(`div`,{className:`p-6 space-y-4`,children:[(0,T.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,T.jsx)(`h2`,{className:`text-xl font-bold`,children:`Create New Role`}),(0,T.jsx)(g,{size:`sm`,variant:`ghost`,onClick:Q,children:(0,T.jsx)(a,{className:`w-4 h-4`})})]}),(0,T.jsxs)(`div`,{className:`space-y-4`,children:[(0,T.jsxs)(`div`,{children:[(0,T.jsx)(v,{htmlFor:`template`,children:`Template *`}),(0,T.jsxs)(`select`,{id:`template`,className:`w-full px-3 py-2 border rounded-md bg-background mt-1`,value:R.template,onChange:e=>z({...R,template:e.target.value}),children:[(0,T.jsx)(`option`,{value:``,children:`Select a template...`}),o.map(e=>(0,T.jsxs)(`option`,{value:e.id,children:[e.name,` - `,e.description]},e.id))]})]}),(0,T.jsxs)(`div`,{children:[(0,T.jsx)(v,{htmlFor:`name`,children:`Role Name *`}),(0,T.jsx)(_,{id:`name`,placeholder:`e.g., canvas-sshd`,value:R.name,onChange:e=>z({...R,name:e.target.value})})]}),(0,T.jsxs)(`div`,{children:[(0,T.jsx)(v,{htmlFor:`roleType`,children:`Type *`}),(0,T.jsxs)(`select`,{id:`roleType`,className:`w-full px-3 py-2 border rounded-md bg-background mt-1`,value:R.type,onChange:e=>z({...R,type:e.target.value}),children:[(0,T.jsx)(`option`,{value:`global`,children:`Global (Server-wide)`}),(0,T.jsx)(`option`,{value:`workspace`,children:`Workspace (User-scoped)`})]})]}),R.template&&(0,T.jsxs)(`div`,{className:`p-4 bg-muted rounded-lg`,children:[(0,T.jsx)(`h3`,{className:`font-medium mb-2`,children:`Template Info`}),o.find(e=>e.id===R.template)&&(0,T.jsxs)(`div`,{className:`text-sm space-y-1 text-muted-foreground`,children:[(0,T.jsxs)(`p`,{children:[(0,T.jsx)(`strong`,{children:`Image:`}),` `,o.find(e=>e.id===R.template)?.container.image]}),(0,T.jsxs)(`p`,{children:[(0,T.jsx)(`strong`,{children:`Category:`}),` `,o.find(e=>e.id===R.template)?.category]}),o.find(e=>e.id===R.template)?.documentation?.readme&&(0,T.jsx)(`p`,{className:`mt-2`,children:o.find(e=>e.id===R.template)?.documentation?.readme})]})]})]}),(0,T.jsxs)(`div`,{className:`flex justify-end gap-2 pt-4 border-t`,children:[(0,T.jsx)(g,{variant:`outline`,onClick:Q,children:`Cancel`}),(0,T.jsx)(g,{onClick:W,children:`Create Role`})]})]})})}),N&&j&&(0,T.jsx)(`div`,{className:`fixed inset-0 bg-scrim flex items-center justify-center z-50`,children:(0,T.jsxs)(`div`,{className:`bg-background rounded-lg shadow-elevation-3 max-w-4xl w-full mx-4 max-h-viewport-modal flex flex-col`,children:[(0,T.jsxs)(`div`,{className:`p-6 border-b flex items-center justify-between`,children:[(0,T.jsxs)(`div`,{children:[(0,T.jsx)(`h2`,{className:`text-xl font-bold`,children:`Role Logs`}),(0,T.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:j.name})]}),(0,T.jsx)(g,{size:`sm`,variant:`ghost`,onClick:()=>P(!1),children:(0,T.jsx)(a,{className:`w-4 h-4`})})]}),(0,T.jsx)(`div`,{className:`flex-1 overflow-y-auto p-6`,children:(0,T.jsx)(`div`,{"data-scheme":`dark`,className:`bg-background text-success p-4 rounded font-mono text-xs overflow-x-auto`,children:F.length===0?(0,T.jsx)(`div`,{className:`text-muted-foreground`,children:`No logs available`}):(0,T.jsx)(`pre`,{children:F.join(`
|
|
1
|
+
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{Ar as r,It as i,L as a,Lr as o,Nr as s,Pt as c,Rr as l,Si as u,Y as d,_t as f,or as p,rt as m,wt as h}from"./ui-DEgHnkQu.js";import{t as g}from"./button--VYZekMF.js";import{t as _}from"./input-BOtCd4HP.js";import{t as v}from"./label-RuOXXC8t.js";import{i as y}from"./auth-Bx9fAZmz.js";import{n as ee}from"./use-toast-BlLDqSUO.js";import{t as b}from"./useEscapeClose-DR_xKT_k.js";import{n as x}from"./page-header-NyYSXjfY.js";import{t as S}from"./use-settings-back-D_MM9diy.js";import{t as C}from"./role-C5I0Plgn.js";var w=e(n(),1),T=t();function E({status:e}){let t={running:{icon:o,color:`text-success`,bg:`bg-success-subtle`,label:`Running`},stopped:{icon:s,color:`text-muted-foreground`,bg:`bg-muted`,label:`Stopped`},starting:{icon:r,color:`text-info`,bg:`bg-info-subtle`,label:`Starting`},stopping:{icon:r,color:`text-warning`,bg:`bg-warning-subtle`,label:`Stopping`},error:{icon:l,color:`text-destructive`,bg:`bg-destructive-subtle`,label:`Error`},created:{icon:u,color:`text-muted-foreground`,bg:`bg-muted`,label:`Created`},configured:{icon:u,color:`text-info`,bg:`bg-info-subtle`,label:`Configured`},removed:{icon:s,color:`text-destructive`,bg:`bg-destructive-subtle`,label:`Removed`}},n=t[e]||t.created,i=n.icon;return(0,T.jsxs)(`span`,{className:`inline-flex items-center gap-1 px-2 py-1 rounded text-xs font-medium ${n.bg} ${n.color}`,children:[(0,T.jsx)(i,{className:`w-3 h-3`}),n.label]})}function te({type:e}){return(0,T.jsxs)(`span`,{className:`inline-flex items-center gap-1 px-2 py-1 rounded text-xs font-medium ${e===`global`?`bg-accent text-primary`:`bg-info-subtle text-info`}`,children:[(0,T.jsx)(f,{className:`w-3 h-3`}),e===`global`?`Global`:`Workspace`]})}function D(){let e=S(),t=y()?.userType===`admin`,[n,r]=(0,w.useState)([]),[o,s]=(0,w.useState)([]),[l,u]=(0,w.useState)(t),[D,O]=(0,w.useState)(t?null:`Access denied. Admin privileges required.`),[k,A]=(0,w.useState)(!1);b(()=>A(!1),k);let[j,M]=(0,w.useState)(null),[N,P]=(0,w.useState)(!1);b(()=>P(!1),N);let[F,ne]=(0,w.useState)([]),[I,L]=(0,w.useState)({type:``,status:``,search:``}),[R,z]=(0,w.useState)({template:``,name:``,type:`global`}),{showToast:B}=ee(),V=(0,w.useRef)(I);(0,w.useEffect)(()=>{V.current=I},[I]);let H=(0,w.useCallback)(async()=>{try{u(!0);let{type:e,status:t}=V.current,n=await C.listRoles({type:e||void 0,status:t||void 0});r(n),O(null)}catch(e){let t=e instanceof Error?e.message:`Failed to fetch roles`;O(t)}finally{u(!1)}},[]),U=(0,w.useCallback)(async()=>{try{let e=await C.listTemplates();s(e)}catch(e){console.error(`Failed to fetch templates:`,e)}},[]);(0,w.useEffect)(()=>{t&&(H(),U())},[t,H,U]);let W=async()=>{if(!R.template||!R.name){B({title:`Validation Error`,description:`Template and name are required`,variant:`destructive`});return}try{await C.createRole(R),B({title:`Success`,description:`Role "${R.name}" created successfully`}),A(!1),X(),H()}catch(e){let t=e instanceof Error?e.message:`Failed to create role`;B({title:`Error`,description:t,variant:`destructive`})}},G=async e=>{try{await C.startRole(e.id),B({title:`Success`,description:`Role "${e.name}" started successfully`}),H()}catch(e){let t=e instanceof Error?e.message:`Failed to start role`;B({title:`Error`,description:t,variant:`destructive`})}},K=async e=>{try{await C.stopRole(e.id),B({title:`Success`,description:`Role "${e.name}" stopped successfully`}),H()}catch(e){let t=e instanceof Error?e.message:`Failed to stop role`;B({title:`Error`,description:t,variant:`destructive`})}},q=async e=>{try{await C.restartRole(e.id),B({title:`Success`,description:`Role "${e.name}" restarted successfully`}),H()}catch(e){let t=e instanceof Error?e.message:`Failed to restart role`;B({title:`Error`,description:t,variant:`destructive`})}},J=async e=>{if(confirm(`Are you sure you want to delete role "${e.name}"?`))try{await C.deleteRole(e.id,e.status===`running`),B({title:`Success`,description:`Role "${e.name}" deleted successfully`}),H()}catch(e){let t=e instanceof Error?e.message:`Failed to delete role`;B({title:`Error`,description:t,variant:`destructive`})}},Y=async e=>{try{let t=await C.getRoleLogs(e.id,100);ne(t),M(e),P(!0)}catch(e){let t=e instanceof Error?e.message:`Failed to fetch logs`;B({title:`Error`,description:t,variant:`destructive`})}},X=()=>{z({template:``,name:``,type:`global`})},Z=()=>{X(),A(!0)},Q=()=>{A(!1),X()},$=n.filter(e=>!I.search||e.name.toLowerCase().includes(I.search.toLowerCase())||e.template.toLowerCase().includes(I.search.toLowerCase()));return t?D&&!t?(0,T.jsx)(`div`,{className:`text-center space-y-4`,children:(0,T.jsx)(`div`,{className:`text-destructive`,children:D})}):(0,T.jsxs)(`div`,{className:`space-y-6`,children:[(0,T.jsx)(x,{onBack:e,title:`Role Management`,description:`Manage global and workspace roles for Canvas services`,actions:(0,T.jsxs)(g,{onClick:Z,className:`gap-2`,children:[(0,T.jsx)(c,{className:`w-4 h-4`}),`Create Role`]})}),(0,T.jsxs)(`div`,{className:`flex gap-4 items-end`,children:[(0,T.jsxs)(`div`,{className:`flex-1`,children:[(0,T.jsx)(v,{htmlFor:`search`,children:`Search`}),(0,T.jsx)(_,{id:`search`,placeholder:`Search by name or template...`,value:I.search,onChange:e=>L({...I,search:e.target.value})})]}),(0,T.jsxs)(`div`,{className:`w-48`,children:[(0,T.jsx)(v,{htmlFor:`type`,children:`Type`}),(0,T.jsxs)(`select`,{id:`type`,className:`w-full px-3 py-2 border rounded-md bg-background`,value:I.type,onChange:e=>L({...I,type:e.target.value}),children:[(0,T.jsx)(`option`,{value:``,children:`All Types`}),(0,T.jsx)(`option`,{value:`global`,children:`Global`}),(0,T.jsx)(`option`,{value:`workspace`,children:`Workspace`})]})]}),(0,T.jsxs)(`div`,{className:`w-48`,children:[(0,T.jsx)(v,{htmlFor:`status`,children:`Status`}),(0,T.jsxs)(`select`,{id:`status`,className:`w-full px-3 py-2 border rounded-md bg-background`,value:I.status,onChange:e=>L({...I,status:e.target.value}),children:[(0,T.jsx)(`option`,{value:``,children:`All Statuses`}),(0,T.jsx)(`option`,{value:`running`,children:`Running`}),(0,T.jsx)(`option`,{value:`stopped`,children:`Stopped`}),(0,T.jsx)(`option`,{value:`starting`,children:`Starting`}),(0,T.jsx)(`option`,{value:`error`,children:`Error`})]})]}),(0,T.jsxs)(g,{onClick:H,variant:`outline`,children:[(0,T.jsx)(h,{className:`w-4 h-4 mr-2`}),`Refresh`]})]}),l?(0,T.jsx)(`div`,{className:`text-center py-8`,children:`Loading roles...`}):$.length===0?(0,T.jsxs)(`div`,{className:`text-center py-8 border rounded-lg`,children:[(0,T.jsx)(f,{className:`w-12 h-12 mx-auto text-muted-foreground mb-4`}),(0,T.jsx)(`p`,{className:`text-muted-foreground`,children:I.search||I.type||I.status?`No roles match your filters`:`No roles created yet`}),!I.search&&!I.type&&!I.status&&(0,T.jsxs)(g,{onClick:Z,variant:`outline`,className:`mt-4`,children:[(0,T.jsx)(c,{className:`w-4 h-4 mr-2`}),`Create Your First Role`]})]}):(0,T.jsx)(`div`,{className:`border rounded-lg`,children:(0,T.jsxs)(`table`,{className:`w-full`,children:[(0,T.jsx)(`thead`,{className:`bg-muted/50`,children:(0,T.jsxs)(`tr`,{children:[(0,T.jsx)(`th`,{className:`text-left p-4 font-medium`,children:`Name`}),(0,T.jsx)(`th`,{className:`text-left p-4 font-medium`,children:`Template`}),(0,T.jsx)(`th`,{className:`text-left p-4 font-medium`,children:`Type`}),(0,T.jsx)(`th`,{className:`text-left p-4 font-medium`,children:`Status`}),(0,T.jsx)(`th`,{className:`text-left p-4 font-medium`,children:`Container`}),(0,T.jsx)(`th`,{className:`text-left p-4 font-medium`,children:`Created`}),(0,T.jsx)(`th`,{className:`text-right p-4 font-medium`,children:`Actions`})]})}),(0,T.jsx)(`tbody`,{className:`divide-y`,children:$.map(e=>(0,T.jsxs)(`tr`,{className:`hover:bg-muted/50`,children:[(0,T.jsx)(`td`,{className:`p-4 font-medium`,children:e.name}),(0,T.jsx)(`td`,{className:`p-4 text-sm text-muted-foreground`,children:e.template}),(0,T.jsx)(`td`,{className:`p-4`,children:(0,T.jsx)(te,{type:e.type})}),(0,T.jsx)(`td`,{className:`p-4`,children:(0,T.jsx)(E,{status:e.status})}),(0,T.jsx)(`td`,{className:`p-4 text-sm text-muted-foreground`,children:e.container?.name||`-`}),(0,T.jsx)(`td`,{className:`p-4 text-sm text-muted-foreground`,children:new Date(e.createdAt).toLocaleDateString()}),(0,T.jsx)(`td`,{className:`p-4`,children:(0,T.jsxs)(`div`,{className:`flex justify-end gap-2`,children:[e.status===`stopped`||e.status===`created`?(0,T.jsx)(g,{size:`sm`,variant:`outline`,onClick:()=>G(e),title:`Start`,children:(0,T.jsx)(i,{className:`w-4 h-4`})}):e.status===`running`?(0,T.jsx)(g,{size:`sm`,variant:`outline`,onClick:()=>K(e),title:`Stop`,children:(0,T.jsx)(m,{className:`w-4 h-4`})}):null,e.status===`running`&&(0,T.jsx)(g,{size:`sm`,variant:`outline`,onClick:()=>q(e),title:`Restart`,children:(0,T.jsx)(h,{className:`w-4 h-4`})}),(0,T.jsx)(g,{size:`sm`,variant:`outline`,onClick:()=>Y(e),title:`View Logs`,children:(0,T.jsx)(p,{className:`w-4 h-4`})}),(0,T.jsx)(g,{size:`sm`,variant:`outline`,onClick:()=>J(e),title:`Delete`,className:`text-destructive hover:text-destructive`,children:(0,T.jsx)(d,{className:`w-4 h-4`})})]})})]},e.id))})]})}),k&&(0,T.jsx)(`div`,{className:`fixed inset-0 bg-scrim flex items-center justify-center z-50`,children:(0,T.jsx)(`div`,{className:`bg-background rounded-lg shadow-elevation-3 max-w-lg w-full mx-4 max-h-viewport-modal overflow-y-auto`,children:(0,T.jsxs)(`div`,{className:`p-6 space-y-4`,children:[(0,T.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,T.jsx)(`h2`,{className:`text-xl font-bold`,children:`Create New Role`}),(0,T.jsx)(g,{size:`sm`,variant:`ghost`,onClick:Q,children:(0,T.jsx)(a,{className:`w-4 h-4`})})]}),(0,T.jsxs)(`div`,{className:`space-y-4`,children:[(0,T.jsxs)(`div`,{children:[(0,T.jsx)(v,{htmlFor:`template`,children:`Template *`}),(0,T.jsxs)(`select`,{id:`template`,className:`w-full px-3 py-2 border rounded-md bg-background mt-1`,value:R.template,onChange:e=>z({...R,template:e.target.value}),children:[(0,T.jsx)(`option`,{value:``,children:`Select a template...`}),o.map(e=>(0,T.jsxs)(`option`,{value:e.id,children:[e.name,` - `,e.description]},e.id))]})]}),(0,T.jsxs)(`div`,{children:[(0,T.jsx)(v,{htmlFor:`name`,children:`Role Name *`}),(0,T.jsx)(_,{id:`name`,placeholder:`e.g., canvas-sshd`,value:R.name,onChange:e=>z({...R,name:e.target.value})})]}),(0,T.jsxs)(`div`,{children:[(0,T.jsx)(v,{htmlFor:`roleType`,children:`Type *`}),(0,T.jsxs)(`select`,{id:`roleType`,className:`w-full px-3 py-2 border rounded-md bg-background mt-1`,value:R.type,onChange:e=>z({...R,type:e.target.value}),children:[(0,T.jsx)(`option`,{value:`global`,children:`Global (Server-wide)`}),(0,T.jsx)(`option`,{value:`workspace`,children:`Workspace (User-scoped)`})]})]}),R.template&&(0,T.jsxs)(`div`,{className:`p-4 bg-muted rounded-lg`,children:[(0,T.jsx)(`h3`,{className:`font-medium mb-2`,children:`Template Info`}),o.find(e=>e.id===R.template)&&(0,T.jsxs)(`div`,{className:`text-sm space-y-1 text-muted-foreground`,children:[(0,T.jsxs)(`p`,{children:[(0,T.jsx)(`strong`,{children:`Image:`}),` `,o.find(e=>e.id===R.template)?.container.image]}),(0,T.jsxs)(`p`,{children:[(0,T.jsx)(`strong`,{children:`Category:`}),` `,o.find(e=>e.id===R.template)?.category]}),o.find(e=>e.id===R.template)?.documentation?.readme&&(0,T.jsx)(`p`,{className:`mt-2`,children:o.find(e=>e.id===R.template)?.documentation?.readme})]})]})]}),(0,T.jsxs)(`div`,{className:`flex justify-end gap-2 pt-4 border-t`,children:[(0,T.jsx)(g,{variant:`outline`,onClick:Q,children:`Cancel`}),(0,T.jsx)(g,{onClick:W,children:`Create Role`})]})]})})}),N&&j&&(0,T.jsx)(`div`,{className:`fixed inset-0 bg-scrim flex items-center justify-center z-50`,children:(0,T.jsxs)(`div`,{className:`bg-background rounded-lg shadow-elevation-3 max-w-4xl w-full mx-4 max-h-viewport-modal flex flex-col`,children:[(0,T.jsxs)(`div`,{className:`p-6 border-b flex items-center justify-between`,children:[(0,T.jsxs)(`div`,{children:[(0,T.jsx)(`h2`,{className:`text-xl font-bold`,children:`Role Logs`}),(0,T.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:j.name})]}),(0,T.jsx)(g,{size:`sm`,variant:`ghost`,onClick:()=>P(!1),children:(0,T.jsx)(a,{className:`w-4 h-4`})})]}),(0,T.jsx)(`div`,{className:`flex-1 overflow-y-auto p-6`,children:(0,T.jsx)(`div`,{"data-scheme":`dark`,className:`bg-background text-success p-4 rounded font-mono text-xs overflow-x-auto`,children:F.length===0?(0,T.jsx)(`div`,{className:`text-muted-foreground`,children:`No logs available`}):(0,T.jsx)(`pre`,{children:F.join(`
|
|
2
2
|
`)})})}),(0,T.jsx)(`div`,{className:`p-4 border-t flex justify-end`,children:(0,T.jsx)(g,{onClick:()=>P(!1),children:`Close`})})]})})]}):(0,T.jsx)(`div`,{className:`text-center space-y-4`,children:(0,T.jsx)(`div`,{className:`text-destructive`,children:`Access denied. Admin privileges required.`})})}export{D as default};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{l as t,u as n}from"./code-editor-BOIngd5F.js";import{Bn as r,Bt as i,Ct as a,Fr as o,Gr as s,L as c,Mn as l,Pt as u,Q as d,X as f,Y as p,Yn as m,Z as h,cn as g,pi as ee,pn as _,qn as v,ri as y,si as te,st as b,ti as ne,yr as x}from"./ui-DEgHnkQu.js";import{t as S}from"./utils-2pl1SbIp.js";import{t as C}from"./button--VYZekMF.js";import{t as w}from"./input-BOtCd4HP.js";import{t as T}from"./api-CA6WiiYM.js";import{t as E}from"./socket-CtH3EU9m.js";import{n as re}from"./use-toast-BlLDqSUO.js";import{t as ie}from"./LinkToCard-oi3wGP0a.js";import{H as ae,cn as oe,sn as se,vt as ce}from"./workspace-4hWrSEku.js";import{i as le}from"./MessageComposerDialog-CLrwtB76.js";import{n as ue}from"./LinkToSidePanel-eCy3nW4R.js";import{t as de}from"./PathPickerField-CSIa7jSl.js";var D=e(n(),1);function O(e){return`/workspaces/${e}/hooks`}async function k(e){return await T.get(O(e))||[]}async function A(e,t){return(await T.get(`${O(e)}/${t}`))?.content??``}async function j(e,t,n){await T.put(`${O(e)}/${t}`,{content:n})}async function M(e,t){await T.delete(`${O(e)}/${t}`)}var N=[`example-`,`disabled-`,`_`];function P(e){let t=e.lastIndexOf(`/`);return{dir:t===-1?``:e.slice(0,t+1),base:t===-1?e:e.slice(t+1)}}function fe(e){return N.find(t=>e.startsWith(t))??null}function pe(e){return fe(P(e).base)===null}function F(e){return P(e).base.startsWith(`example-`)}function me(e){let{dir:t,base:n}=P(e),r=fe(n);return t+(r?n.slice(r.length):`disabled-${n}`)}async function he(e,t,n){if(pe(t)===n)return t;let r=me(t);return await j(e,r,await A(e,t)),await M(e,t),r}function ge(e){let t={};for(let n of e){let e;e=n.path.includes(`/`)?n.path.split(`/`)[0]:/^(?:example-|disabled-|_)?rules\.json$/.test(n.path)?`rules`:n.path.replace(/\.js$/,``),(t[e]||=[]).push(n)}return t}function _e(e){let t=e.when?.event;return Array.isArray(t)?t.map(String):t?[String(t)]:[]}function ve(e){let t=e.when?.eventPathExact??e.when?.pathExact??e.when?.path;return Array.isArray(t)?t.map(String):typeof t==`string`?[t]:[]}function ye(e){let t=String(e||``).split(`/`).filter(Boolean);return t[0]===`workspace`&&t.length>=2?{backend:`workspace:${t[1]}`,rel:t.slice(2).join(`/`)}:t[0]===`device`?t.length>=3?{backend:t[2],rel:t.slice(3).join(`/`)}:null:t.length>=2?{backend:t[1],rel:t.slice(2).join(`/`)}:null}function be(e){let t=new URLSearchParams;return e.kind&&e.kind!==`mirror`&&t.set(`addRuleKind`,e.kind),e.path&&t.set(`addRulePath`,e.path),e.target&&t.set(`addRuleTarget`,e.target),e.storeTo&&t.set(`addRuleStoreTo`,e.storeTo),e.storeFolder&&t.set(`addRuleStoreFolder`,e.storeFolder),t}function xe(e){return String(e||``).replace(/^[a-z]+:/i,``).split(`/`).filter(Boolean).join(`/`)}var Se=`rules.json`;async function Ce(e){try{let t=await A(e,Se),n=JSON.parse(t||`{}`);return Array.isArray(n.rules)?n.rules:[]}catch{return[]}}async function we(e,t){await j(e,Se,JSON.stringify({$schema:`canvas.hook-rules/v1`,rules:t},null,2)+`
|
|
2
|
+
`)}async function Te(e,t={}){let n=new URLSearchParams;t.status&&n.set(`status`,t.status),t.handler&&n.set(`handler`,t.handler),t.limit&&n.set(`limit`,String(t.limit));let r=n.toString(),i=await T.getEnvelope(`${O(e)}/pending${r?`?${r}`:``}`),a=i.payload||[];return{actions:a,total:i.totalCount??a.length}}async function Ee(e,t){return await T.post(`${O(e)}/pending/decisions`,t)}async function De(e,t){return T.post(`${O(e)}/pending/decisions/all`,t)}async function Oe(e){return await T.get(`${O(e)}/pending/decisions/all`)??null}async function ke(e,t){return await T.get(`${O(e)}/runs/${encodeURIComponent(t)}`)}async function Ae(e,t={}){let n=new URLSearchParams;t.limit&&n.set(`limit`,String(t.limit)),t.handler&&n.set(`handler`,t.handler),t.event&&n.set(`event`,t.event),t.failed&&n.set(`failed`,`true`);let r=n.toString();return await T.get(`${O(e)}/runs${r?`?${r}`:``}`)||[]}var I=1e4,je=`canvas.hooks.backfillLimit`;function Me(e){let t=Math.floor(Number(e));return!Number.isFinite(t)||t<1?500:Math.min(t,I)}function Ne(){try{let e=localStorage.getItem(je);return e?Me(e):500}catch{return 500}}function Pe(e){let t=Me(e);try{localStorage.setItem(je,String(t))}catch{}return t}function Fe(e){if(e.includes(`/`)){let t=e.split(`/`)[0];return t===`lib`||t===`rules`?null:t}return e.endsWith(`.js`)?e.replace(/\.js$/,``).replace(/^(?:example-|disabled-|_)/,``):null}async function Ie(e,t){return await T.post(`${O(e)}/backfill`,t)}function Le(e,t){return T.post(`${O(e)}/backfill/jobs`,t)}function L(e,t){return T.get(`${O(e)}/backfill/jobs/${t}`)}function Re(e,t){return T.delete(`${O(e)}/backfill/jobs/${t}`)}function ze(e){return T.get(`${O(e)}/backfill/jobs`)}async function R(e,t){return await T.post(`${O(e)}/run`,t)}async function z(e,t){return await T.post(`${O(e)}/runs/${t}/replay`,{})}async function Be(e){return await T.get(`${O(e)}/meta`)}async function Ve(e,t){return await T.post(`${O(e)}/generate`,t)}async function He(e,t){let n=await A(e,Se),r=JSON.parse(n),i=Array.isArray(r)?r:r?.rules;if(!Array.isArray(i))throw Error(`The workspace rules file is invalid. Fix it in Rules before adding a rule.`);let a=(Array.isArray(t)?t:[t]).filter(e=>!i.some(t=>t.id===e.id));if(!a.length)return;let o=Array.isArray(r)?[...i,...a]:{...r,rules:[...i,...a]};await j(e,Se,JSON.stringify(o,null,2)+`
|
|
3
|
+
`)}var Ue=He,B=new Map;function We(e,t,n,r,i,a){let o=JSON.stringify([t,n,r,a]),s=B.get(o);if(s)return s;let c=(async()=>{let o=e({title:`Resyncing…`,description:r});try{for(a?await oe(t,n,r,a):await se(t,n,r);;){let e=await ae(t,n,r);i?.(e);let s=a?e.containers?.find(e=>e.name===a):void 0;if(a?s?.status!==`syncing`:!e.resyncing&&e.status!==`syncing`){let i=s?s.lastError:e.lastError;if(i)throw Error(i);o.done({title:e.resyncCancelledAt?`Resync stopped`:`Resync complete`,description:`${r}${n!==`imap`&&e.progress?` · ${e.progress.scanned} files scanned`:``}`}),window.dispatchEvent(new CustomEvent(`workspace:documents:refresh`,{detail:{workspaceName:t,treeName:`backends`}}));return}let c=n===`imap`?void 0:e.progress;o.update({title:`Resyncing…`,description:`${r}${c?` · ${c.scanned}${c.total==null?``:` / ${c.total}`} files scanned`:``}`}),await new Promise(e=>setTimeout(e,2e3))}}catch(e){throw o.fail({title:`Resync needs attention`,description:`${r}: ${e instanceof Error?e.message:String(e)}`,variant:`destructive`}),e}})();return B.set(o,c),c.finally(()=>{B.get(o)===c&&B.delete(o)}).catch(()=>{}),c}function Ge(e,t,n,r=new Date){let i=e=>String(e).padStart(2,`0`),a={YYYY:String(r.getFullYear()),YY:i(r.getFullYear()%100),MM:i(r.getMonth()+1),DD:i(r.getDate()),HH:i(r.getHours()),mm:i(r.getMinutes()),ss:i(r.getSeconds())},o=e=>e.replace(/\{\{\s*([A-Za-z]+)\s*\}\}/g,(e,t)=>a[t]??e),s=e=>e.split(/[\\/]+/).filter(e=>e&&e!==`.`&&e!==`..`).join(`/`),c=[e,s(o(t.trim()))].filter(Boolean).join(`/`),l=s(o(n.trim()));return{root:c,added:l,result:[c,l,`<attachment filename>`].filter(Boolean).join(`/`),date:`${a.YYYY}-${a.MM}-${a.DD}`}}var V=`Applying rules to existing documents…`,Ke=new Map;function H(e){return`${e.ruleIds.length>1?`Rule ${e.ruleIndex+1}/${e.ruleIds.length}: `:``}${e.processed}${e.total===null?``:` / ${e.total}`} documents · ${e.applied} applied`}function qe(e,t){let n=`${t.checked} checked, ${t.applied} applied${t.skipped?`, ${t.skipped} already there`:``}`;t.status===`cancelled`?e.done({title:`Cancelled`,description:n}):t.status===`failed`?e.fail({title:`Stopped before finishing`,description:`${n}: ${t.error}. The rule stays enabled; rerun it from Rules to finish.`,variant:`destructive`}):t.failed?e.done({title:`Finished with errors`,description:`${n}, ${t.failed} failed. Details in the rule’s run log.`,variant:`destructive`}):e.done({title:`Rule applied`,description:n})}function Je(e,t,n){let r=Ke.get(n.id);if(r)return r;let i=new Promise(r=>{let i={channel:`workspace:${t}`},a=e({title:V,description:H(n),action:{label:`Cancel`,onClick:()=>{a.update({title:`Cancelling…`,description:H(n)}),Re(t,n.id).catch(()=>a.update({title:V,description:`Could not cancel. Try again.`}))}}}),o=()=>{u?.(),E.off(`job.progress`,c),E.off(`job.finished`,c),r()},s=e=>{if(e.status===`running`)return a.update({title:V,description:H(e)});qe(a,e),window.dispatchEvent(new CustomEvent(`workspace:documents:refresh`)),window.dispatchEvent(new CustomEvent(`workspace:tree:refresh`)),o()},c=e=>{let t=e?.job;t?.id===n.id&&s(t)},l=()=>{E.emit(`subscribe`,i),L(t,n.id).then(s,()=>{})},u=E.on(`connect`,l);E.on(`job.progress`,c),E.on(`job.finished`,c),l()});return Ke.set(n.id,i),i.finally(()=>Ke.delete(n.id)),i}async function Ye(e,t,n){let r;try{r=await Le(t,{ruleIds:n,limit:Ne()})}catch(t){e({title:V}).fail({title:`Could not start`,description:`${t instanceof Error?t.message:String(t)}. The rule stays enabled; rerun it from Rules.`,variant:`destructive`});return}return Je(e,t,r)}async function Xe(e,t){let n=await ze(t).catch(()=>[]);for(let r of n)r.status===`running`&&Je(e,t,r)}function U(e){return`/workspaces/${e}/scripts`}async function Ze(e){return await T.get(U(e))||[]}async function Qe(e,t){return(await T.get(`${U(e)}/${t}`))?.content??``}async function $e(e,t,n){await T.put(`${U(e)}/${t}`,{content:n})}async function et(e,t){await T.delete(`${U(e)}/${t}`)}var W=t(),tt=[{value:``,label:`any item`},{value:`email`,label:`an email`},{value:`message`,label:`a message`},{value:`tab`,label:`a browser tab / link`},{value:`note`,label:`a note`},{value:`file`,label:`a file`},{value:`todo`,label:`a todo / task`}],nt=[{value:`document.inserted`,label:`is added`,hint:`Fires when the item is created or uploaded.`},{value:`document.updated`,label:`is updated`,hint:`Fires on every edit of the item.`},{value:`document.moved`,label:`is moved or renamed`,hint:`Fires when the file behind the item changes its path. Its content and modified date stay the same.`},{value:`document.linked`,label:`is filed into a folder`,hint:`Fires when the item is (re)filed into a tree path — the usual pair with "is added" for folder rules.`},{value:`document.unlinked`,label:`is removed from a folder`,hint:`Fires when the item leaves a tree path.`}],rt=[{key:`toExact`,label:`recipient (To/Cc) is`,hint:`accounting@example.com`},{key:`fromExact`,label:`email sender is`,hint:`person@example.com`},{key:`senderExact`,label:`message sender is`,hint:`Sender ID`},{key:`sender`,label:`message sender contains`,hint:`Sender ID or name`},{key:`senderRegex`,label:`message sender matches regex`,hint:`Sender ID or name pattern`},{key:`body`,label:`body / text contains`,hint:`Words in the email preview or message text`},{key:`bodyRegex`,label:`body / text matches regex`,hint:`invoice\\s+\\d+`},{key:`threadExact`,label:`thread is`,hint:`Thread ID`},{key:`channelExact`,label:`channel / conversation is`,hint:`Channel or conversation ID`},{key:`platformExact`,label:`platform is`,hint:`slack, whatsapp, teams`},{key:`pathExact`,label:`is directly in the folder`,hint:`Current folder membership`},{key:`eventPathExact`,label:`is inserted / linked directly into`,hint:`Exact event destination, e.g. ctx:/foo/bar/baz. Descendant inserts do not match.`},{key:`path`,label:`is under the folder`,hint:`/projects/canvas/UI or backends:/workspace/home/foo`},{key:`mime`,label:`file type is`,hint:`image/*, application/pdf`},{key:`from`,label:`sender contains`,hint:`boss@company.tld`},{key:`to`,label:`recipient (To/Cc) contains`,hint:`invoice@my-company.tld`},{key:`subject`,label:`subject contains`,hint:`invoice`},{key:`fromRegex`,label:`sender matches regex`,hint:`@(acme|example)\\.com$`},{key:`toRegex`,label:`recipient (To/Cc) matches regex`,hint:`^(billing|accounts)@`},{key:`subjectRegex`,label:`subject matches regex`,hint:`^invoice\\s+\\d+`},{key:`urlRegex`,label:`URL matches regex`,hint:`/(invoice|receipt)/`},{key:`urlHost`,label:`website is`,hint:`youtube.com`},{key:`urlContains`,label:`URL contains`,hint:`/watch?v=`},{key:`attachment`,label:`has an attachment of type`,hint:`application/pdf, or * for any`}],it=new Set([`toExact`,`fromExact`,`senderExact`,`threadExact`,`channelExact`,`platformExact`]),at=e=>it.has(e)?e.replace(/Exact$/,``):e.replace(/Regex$/,``),ot=[{key:`sendFile`,label:`Send file(s) via a channel`,icon:g,tone:`text-blue-600 dark:text-blue-400 bg-blue-500/10`},{key:`extractAttachments`,label:`Extract email attachments to a folder`,icon:g,tone:`text-amber-600 dark:text-amber-400 bg-amber-500/10`},{key:`moveMessage`,label:`Move the email to a mail folder`,icon:g,tone:`text-teal-600 dark:text-teal-400 bg-teal-500/10`},{key:`store`,label:`Copy/Move file(s) to a storage backend`,icon:r,tone:`text-sky-600 dark:text-sky-400 bg-sky-500/10`},{key:`download`,label:`download what the link points at`,icon:x,tone:`text-rose-600 dark:text-rose-400 bg-rose-500/10`},{key:`link`,label:`file it into a folder`,icon:m,tone:`text-emerald-600 dark:text-emerald-400 bg-emerald-500/10`},{key:`unlink`,label:`remove it from a folder`,icon:m,tone:`text-amber-600 dark:text-amber-400 bg-amber-500/10`},{key:`tag`,label:`add tags`,icon:d,tone:`text-violet-600 dark:text-violet-400 bg-violet-500/10`},{key:`unstore`,label:`delete the file from a storage backend`,icon:p,tone:`text-amber-600 dark:text-amber-400 bg-amber-500/10`},{key:`notify`,label:`Send me a notification`,icon:te,tone:`text-pink-600 dark:text-pink-400 bg-pink-500/10`},{key:`agent`,label:`ask an agent`,icon:y,tone:`text-indigo-600 dark:text-indigo-400 bg-indigo-500/10`},{key:`script`,label:`run a script`,icon:h,tone:`text-slate-600 dark:text-slate-300 bg-slate-500/10`},{key:`delete`,label:`delete it from Canvas`,icon:f,tone:`text-destructive bg-destructive/10`},{key:`destroy`,label:`delete it everywhere`,icon:f,tone:`text-destructive bg-destructive/10`}],st=e=>ot.find(t=>t.key===e)||ot[1],ct=`{{title}}{{ext}}`,G=`{{YYYY}}/{{MM}}/{{YYYY}}{{MM}}{{DD}}_{{HH}}{{mm}}{{ss}}{{ext}}`,lt=[{value:`auto`,label:`whatever it is (auto)`,hint:`arXiv → the PDF · YouTube, Vimeo, TikTok… → the video · image / video / PDF links → the file · anything else → the page.`},{value:`image`,label:`the file itself (image, PDF, …)`,hint:`Fetches the bytes the URL serves.`},{value:`video`,label:`the video (yt-dlp)`,hint:`Best video + audio, merged. Needs yt-dlp on the server.`},{value:`arxiv`,label:`the arXiv paper (PDF)`,hint:`Works for abs/ and pdf/ links.`},{value:`page`,label:`the page with its images & styles`,hint:`One page, offline-readable (wget --page-requisites).`},{value:`website`,label:`the whole website (mirror)`,hint:`Follows links on the same site up to the chosen depth.`}],ut=[{value:`keep`,label:`keep the original file name`},{value:`title`,label:`use the item title as file name`},{value:`dated`,label:`photo style: 2024/07/20240714_183012.jpg`},{value:`custom`,label:`custom template…`}],K=e=>({sendDriver:`imap`,sendSource:`document`,sendSubject:`{{file.name}}`,sendMessage:``,kind:e,a:``,b:``,recursive:!1,storeFrom:``,storeFolder:``,storeName:`keep`,storeMode:`copy`,storeConflict:`rename`,attachmentMime:`application/pdf`,attachmentName:``,attachmentPath:`{{YYYY}}/{{MM}}`,includeInline:!1,deleteSource:!1,dlKind:`auto`,dlDepth:`2`,dlTags:``,keepLast:!0,notePath:``,noteTitle:``,filePath:``,fileBackend:`home`,fileInsert:``,notifyReply:!1}),q={id:null,description:``,events:[`document.inserted`],schema:``,cascade:!1,approval:!1,conditions:[],actions:[K(`link`)]},dt=e=>e.split(`|`).map(e=>e.trim()).filter(Boolean);function ft(e){return e.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``)||`rule-${Math.random().toString(36).slice(2,7)}`}var J=e=>e.split(`,`).map(e=>e.trim()).filter(Boolean),pt=[{id:`send-invoices`,title:`Send invoice PDFs to accounting`,icon:g,tone:`text-blue-600 dark:text-blue-400 bg-blue-500/10`,blurb:`Send matching PDF attachments to your accounting firm’s ingestion email, or to a Slack / WhatsApp conversation. Keep the original email and files.`,build:()=>({...q,description:`Send invoice PDFs to accounting`,schema:`email`,conditions:[{field:`toExact`,value:``}],actions:[{...K(`sendFile`),sendSource:`attachments`,sendSubject:`Invoice: {{file.name}}`}]})},{id:`attachments`,title:`File PDF email attachments by month`,icon:g,tone:`text-amber-600 dark:text-amber-400 bg-amber-500/10`,blurb:`Choose a recipient and extract PDF attachments into Accounting / year / month, using the email date. Add a subject or filename filter to narrow it to invoices.`,build:()=>({...q,description:`File accounting PDF attachments by month`,schema:`email`,conditions:[{field:`toExact`,value:``}],actions:[{...K(`extractAttachments`),a:`workspace:home`,storeFolder:`Accounting`}]})},{id:`store`,title:`Copy/Move file(s) to a storage backend`,icon:r,tone:`text-sky-600 dark:text-sky-400 bg-sky-500/10`,blurb:`Uploads land in the managed blob store. Pick a folder in Canvas and a folder on a storage backend — copy or move matching files and optionally recreate their sub-folder paths.`,build:({backend:e})=>({...q,description:`Copy/Move file(s) to a storage backend`,schema:`file`,events:[`document.inserted`,`document.linked`],conditions:[{field:`path`,value:``}],actions:[{...K(`store`),a:e,recursive:!0}]})},{id:`photos`,title:`Sort photos by date`,icon:l,tone:`text-emerald-600 dark:text-emerald-400 bg-emerald-500/10`,blurb:`Images filed into a folder are stored as Photos / 2024 / 07 / 20240714_183012.jpg — by the time the photo was taken (EXIF), not uploaded.`,build:({backend:e})=>({...q,description:`Sort photos by date`,schema:`file`,events:[`document.inserted`,`document.linked`],conditions:[{field:`path`,value:``},{field:`mime`,value:`image/*`}],actions:[{...K(`store`),a:e,storeFolder:`Photos`,storeName:`dated`}]})},{id:`mirror`,title:`Mirror a storage folder`,icon:m,tone:`text-violet-600 dark:text-violet-400 bg-violet-500/10`,blurb:`Everything that appears under a folder of a storage backend shows up 1:1 in the Directory tree.`,build:()=>({...q,description:`Mirror a storage folder`,events:[`document.inserted`,`document.linked`],conditions:[{field:`path`,value:`backends:/workspace/home/`}],actions:[{...K(`link`),a:`dir:/`,recursive:!0}]})},{id:`mail`,title:`File mail from a sender`,icon:g,tone:`text-amber-600 dark:text-amber-400 bg-amber-500/10`,blurb:`Emails from a person or domain are filed into a folder and you get a notification.`,build:()=>({...q,description:`Mail from …`,schema:`email`,conditions:[{field:`from`,value:``}],actions:[{...K(`link`),a:`/work/urgent`},{...K(`notify`),a:`New mail from {{doc.data.from}}: {{doc.data.subject}}`}]})},{id:`download`,title:`Download what links point at`,icon:x,tone:`text-rose-600 dark:text-rose-400 bg-rose-500/10`,blurb:`Bookmarks filed into a folder are fetched for real — images, videos (yt-dlp), arXiv papers, a page or a whole website — saved to a folder and filed next to the link.`,build:({backend:e})=>({...q,description:`Download what links point at`,schema:`tab`,events:[`document.inserted`,`document.linked`],conditions:[{field:`path`,value:``}],actions:[{...K(`download`),a:e,storeFolder:`Downloads`,recursive:!0}]})},{id:`agent`,title:`Ask an agent`,icon:y,tone:`text-indigo-600 dark:text-indigo-400 bg-indigo-500/10`,blurb:`Hand new items to an agent with a prompt; save its reply as a note or get it as a notification.`,build:()=>({...q,description:`Summarize new items`,actions:[{...K(`agent`),b:`Read document #{{doc.id}} in full with canvas_doc_get_by_id, then summarize it in three bullet points.`,notifyReply:!0}]})},{id:`blank`,title:`Start from scratch`,icon:b,tone:`text-muted-foreground bg-muted`,blurb:`An empty rule: choose what it reacts to, add conditions and actions.`,build:()=>({...q})}];function Y(e){let t=e.filter(e=>[`path`,`pathExact`,`eventPathExact`].includes(e.field));if(t.length!==1||t[0].field!==`eventPathExact`)return null;let n=dt(t[0].value);return n.length===1&&/^(ctx|context):\//.test(n[0])?n[0].replace(/^(ctx|context):/,``).replace(/\/+$/,``)||`/`:null}function mt(e){if(Y(e)!==null)return!0;let t=e.filter(e=>[`path`,`pathExact`,`eventPathExact`].includes(e.field)).flatMap(e=>dt(e.value));return t.length>0&&t.every(e=>/^(ctx|context|dir|directory|backends):\//.test(e))}function ht(e,t,n){let r=e=>e.replace(/\\/g,`/`).split(`/`).filter(e=>e&&e!==`.`&&e!==`..`).join(`/`),i=`${n?.treePath?`backends:${n.treePath}`:e.a}/${r(e.storeFolder.trim())}`.replace(/\/+$/,``),a=Y(t),o=e.recursive?a===null?`<sub-folders>`:r(a):``;return{root:i,recreated:o,result:[i,o,e.storeName===`keep`?`<original filename>`:e.storeName===`title`?`<title>.<ext>`:e.storeName===`dated`?G:e.b||`<filename>`].filter(Boolean).join(`/`)}}function gt(e,t=[]){let n={event:e.events.length===1?e.events[0]:e.events};e.schema&&(n.schema=e.schema);let r={},i={};for(let t of e.conditions){let e=t.field.endsWith(`Regex`),n=it.has(t.field),a=n&&![`fromExact`,`toExact`].includes(t.field),o=e||a?t.value.trim()?[t.value]:[]:dt(t.value);if(e&&o.length)try{new RegExp(t.value,`i`)}catch{throw Error(`Invalid regular expression for ${rt.find(e=>e.key===t.field)?.label}: ${t.value}`)}if(!o.length)throw Error(`Enter a value for ${rt.find(e=>e.key===t.field)?.label||t.field}, or remove that condition.`);if(t.field===`urlHost`||t.field===`urlContains`||t.field===`urlRegex`){let e=t.field===`urlHost`?`host`:t.field===`urlRegex`?`regex`:`contains`,n=i[e],r=[...Array.isArray(n)?n:n==null?[]:[n],...o];i[e]=r.length===1?r[0]:r}else(r[at(t.field)]||=[]).push(...e?o.map(e=>({regex:e})):n?o.map(e=>({equals:e})):o)}for(let[e,t]of Object.entries(r))t?.length&&(n[e]=t.length===1?t[0]:t);Object.keys(i).length&&(n.url=i);let a=e=>{let t={};return e.notePath.trim()&&(t.note={path:e.notePath.trim(),...e.noteTitle.trim()?{title:e.noteTitle.trim()}:{}}),e.filePath.trim()&&(t.file={path:e.filePath.trim(),...e.fileBackend===`data`?{backend:`data`}:{},...e.fileInsert.trim()?{insert:e.fileInsert.trim()}:{}}),e.notifyReply&&(t.notify=!0),Object.keys(t).length?t:null},o=[];for(let n of e.actions){let r=n.a.trim(),i=n.b.trim(),s=n.recursive?{recursive:!0}:{};if(n.kind===`sendFile`){if(!r)throw Error(`Choose a sending account for the file.`);if(!i)throw Error(n.sendDriver===`imap`?`Enter the destination email address.`:`Enter a configured destination conversation.`);if(![`imap`,`slack`,`whatsapp`].includes(n.sendDriver))throw Error(`Choose email, Slack or WhatsApp.`);if(![`document`,`attachments`,`download`].includes(n.sendSource))throw Error(`Choose which files to send.`);if(n.sendSource===`download`&&!o.some(e=>e.action===`download`))throw Error(`Add a Download action before sending its files.`);let e=J(n.attachmentMime);if(n.sendSource===`attachments`&&(!e.length||e.some(e=>!/^(\*|[a-z0-9!#$&^_.+-]+\/(\*|[a-z0-9!#$&^_.+-]+)|\*\/\*)$/i.test(e))))throw Error(`Enter attachment MIME types, such as application/pdf.`);if(n.sendDriver===`whatsapp`&&n.sendMessage.length>1024)throw Error(`WhatsApp file captions must be at most 1,024 characters.`);o.push({action:`sendFile`,source:n.sendSource,driver:n.sendDriver,address:r,...n.sendDriver===`imap`?{to:J(i),subject:n.sendSubject}:{target:i},...n.sendMessage?{message:n.sendMessage}:{},...n.sendSource===`attachments`?{mime:e.length===1?e[0]:e,...n.attachmentName.trim()?{filename:n.attachmentName.trim()}:{},...n.includeInline?{includeInline:!0}:{}}:{}})}if(n.kind===`link`&&r&&o.push({action:`link`,paths:J(r),...s,...i?{tags:J(i)}:{}}),n.kind===`unlink`&&r&&o.push({action:`unlink`,paths:J(r),...s}),n.kind===`tag`&&r&&o.push({action:`tag`,tags:J(r)}),n.kind===`moveMessage`){if(!r)throw Error(`Enter the mail folder to move the email to, such as INBOX/Accounting/{{YYYY}}/Expenses.`);o.push({action:`moveMessage`,folder:r})}if(n.kind===`store`&&r){if(n.storeMode===`move`&&!n.storeFrom.trim())throw Error(`Choose the source backend whose copy should be moved.`);if(n.recursive&&!mt(e.conditions))throw Error(`Choose a Context, Directory or Backends source path to recreate the path.`);if(n.recursive&&t.find(e=>e.address===r)?.capabilities?.paths!==!0)throw Error(`This destination has not reported support for folder paths. Choose a supported backend or turn off path recreation.`);let a=n.storeFolder.trim().replace(/^\/+|\/+$/g,``),c=n.storeName===`title`?ct:n.storeName===`dated`?G:n.storeName===`custom`?i:``;o.push({action:`store`,to:r,...n.storeFrom.trim()?{from:n.storeFrom.trim()}:{},mode:n.storeMode,...a?{folder:a}:{},...s,...n.deleteSource?{deleteSource:!0}:{},...n.recursive&&Y(e.conditions)!==null?{pathMode:`full`}:{},...c?{key:c}:{},onConflict:n.storeConflict})}if(n.kind===`extractAttachments`){if(!r)throw Error(`Choose a destination backend for the attachments.`);if(t.find(e=>e.address===r)?.capabilities?.paths!==!0)throw Error(`Choose an attachment destination with support for folder paths.`);let e=J(n.attachmentMime);if(!e.length||e.some(e=>!/^(\*|[a-z0-9!#$&^_.+-]+\/(\*|[a-z0-9!#$&^_.+-]+)|\*\/\*)$/i.test(e)))throw Error(`Enter attachment MIME types, such as application/pdf or image/*. Use * for all attachments.`);if(![`rename`,`error`].includes(n.storeConflict))throw Error(`Choose rename or skip for attachment filename conflicts.`);o.push({action:`extractAttachments`,to:r,mime:e.length===1?e[0]:e,...n.storeFolder.trim()?{folder:n.storeFolder.trim()}:{},...n.attachmentPath.trim()?{subfolder:n.attachmentPath.trim()}:{},...n.attachmentName.trim()?{filename:n.attachmentName.trim()}:{},...n.includeInline?{includeInline:!0}:{},onConflict:n.storeConflict})}if(n.kind===`download`){let e=n.storeFolder.trim().replace(/^\/+|\/+$/g,``),t=Number(n.dlDepth);o.push({action:`download`,to:r||`workspace:home`,...e?{folder:e}:{},...s,...n.deleteSource?{deleteSource:!0}:{},...n.dlKind===`auto`?{}:{kind:n.dlKind},...i?{insert:J(i)}:{},...n.dlTags.trim()?{tags:J(n.dlTags)}:{},...n.dlKind===`website`&&Number.isFinite(t)&&t>0&&t!==2?{depth:t}:{}})}if(n.kind===`unstore`&&r&&o.push({action:`unstore`,from:r,...i?{ifOn:i}:{},...n.keepLast?{}:{keepLast:!1}}),n.kind===`notify`&&r&&o.push({action:`notify`,message:r}),n.kind===`delete`&&o.push({action:`delete`}),n.kind===`destroy`&&o.push({action:`destroy`}),n.kind===`agent`&&r&&i){let e=a(n);o.push({action:`agent`,slug:r,prompt:i,...e?{output:e}:{}})}if(n.kind===`script`&&r){let e=a(n);o.push({action:`script`,path:r,...e?{output:e}:{}})}}return{id:e.id||ft(e.description),enabled:!0,...e.description?{description:e.description}:{},...e.cascade?{cascade:!0}:{},...e.approval?{approval:!0}:{},...e.editable?.length?{editable:e.editable}:{},...e.ttl===void 0?{}:{ttl:e.ttl},when:n,then:o}}function _t(e){let{event:t,schema:n,from:r,to:i,subject:a,body:o,sender:s,thread:c,channel:l,platform:u,path:d,pathExact:f,eventPathExact:p,mime:m,url:h,attachment:g,...ee}=e.when;if(Object.keys(ee).length>0)return null;let _=Array.isArray(t)?t:[t];if(!_.length||!_.every(e=>typeof e==`string`&&nt.some(t=>t.value===e))||n!==void 0&&typeof n!=`string`)return null;let v=[],y=(e,t)=>{let n=Array.isArray(t)?t:[t];if(e.endsWith(`Regex`)){if(!n.every(e=>typeof e==`string`))return!1;for(let t of n)v.push({field:e,value:t})}else if(it.has(e))for(let t of n){if(!t||typeof t!=`object`||Object.keys(t).length!==1||typeof t.equals!=`string`)return!1;v.push({field:e,value:t.equals})}else if([`from`,`to`,`subject`,`body`,`sender`].includes(e))for(let t of n)if(typeof t==`string`)v.push({field:e,value:t});else if([`from`,`to`,`sender`].includes(e)&&t&&typeof t==`object`&&Object.keys(t).length===1&&typeof t.equals==`string`)v.push({field:`${e}Exact`,value:t.equals});else if(t&&typeof t==`object`&&Object.keys(t).length===1&&typeof t.regex==`string`)v.push({field:`${e}Regex`,value:t.regex});else return!1;else{if(!n.every(e=>typeof e==`string`))return!1;v.push({field:e,value:n.join(` | `)})}return!0};if(d!==void 0&&!y(`path`,d)||f!==void 0&&!y(`pathExact`,f)||p!==void 0&&!y(`eventPathExact`,p)||m!==void 0&&!y(`mime`,m)||r!==void 0&&!y(`from`,r)||i!==void 0&&!y(`to`,i)||a!==void 0&&!y(`subject`,a)||o!==void 0&&!y(`body`,o)||s!==void 0&&!y(`sender`,s)||c!==void 0&&!y(`threadExact`,c)||l!==void 0&&!y(`channelExact`,l)||u!==void 0&&!y(`platformExact`,u)||g!==void 0&&!y(`attachment`,g))return null;if(h!==void 0){if(typeof h==`string`)v.push({field:`urlContains`,value:h});else if(h&&typeof h==`object`){let e=h;if(Object.keys(e).filter(e=>e!==`host`&&e!==`contains`&&e!==`regex`).length||e.host!==void 0&&!y(`urlHost`,e.host)||e.contains!==void 0&&!y(`urlContains`,e.contains)||e.regex!==void 0&&!y(`urlRegex`,e.regex))return null}else return null}let te=e=>{let t=e.output&&typeof e.output==`object`?e.output:{};if(Object.keys(t).filter(e=>e!==`note`&&e!==`file`&&e!==`notify`).length)return null;let n=t.note&&typeof t.note==`object`?t.note:{},r=t.file&&typeof t.file==`object`?t.file:{};return Object.keys(r).filter(e=>e!==`path`&&e!==`backend`&&e!==`insert`).length?null:{notePath:typeof n.path==`string`?n.path:``,noteTitle:typeof n.title==`string`?n.title:``,filePath:typeof r.path==`string`?r.path:``,fileBackend:r.backend===`data`?`data`:`home`,fileInsert:typeof r.insert==`string`?r.insert:``,notifyReply:t.notify===!0}},b=[];for(let t of e.then||[]){if(t.approval!==void 0)return null;if(t.action===`link`&&Array.isArray(t.paths))b.push({...K(`link`),a:t.paths.join(`, `),b:Array.isArray(t.tags)?t.tags.join(`, `):``,recursive:t.recursive===!0});else if(t.action===`unlink`&&Array.isArray(t.paths))b.push({...K(`unlink`),a:t.paths.join(`, `),recursive:t.recursive===!0});else if(t.action===`tag`&&Array.isArray(t.tags))b.push({...K(`tag`),a:t.tags.join(`, `)});else if(t.action===`moveMessage`){if(Object.keys(t).some(e=>e!==`action`&&e!==`folder`)||typeof t.folder!=`string`)return null;b.push({...K(`moveMessage`),a:t.folder})}else if(t.action===`notify`&&typeof t.message==`string`)b.push({...K(`notify`),a:t.message});else if(t.action===`store`&&typeof t.to==`string`){if(t.pathMode!==void 0&&(t.pathMode!==`full`||t.recursive!==!0||Y(v)===null)||t.recursive===!0&&Y(v)!==null&&t.pathMode!==`full`||t.folder!==void 0&&typeof t.folder!=`string`||t.key!==void 0&&typeof t.key!=`string`)return null;let e=typeof t.key==`string`?t.key:``;b.push({...K(`store`),a:t.to,b:e===ct||e===G?``:e,storeFolder:typeof t.folder==`string`?t.folder:``,recursive:t.recursive===!0,deleteSource:t.deleteSource===!0,storeName:e?e===ct?`title`:e===G?`dated`:`custom`:`keep`,storeFrom:typeof t.from==`string`?t.from:Array.isArray(t.from)?String(t.from[0]??``):``,storeMode:t.mode===`move`?`move`:`copy`,storeConflict:t.onConflict===`error`||t.onConflict===`overwrite`?t.onConflict:`rename`})}else if(t.action===`sendFile`){let e=new Set([`action`,`source`,`driver`,`address`,`to`,`target`,`subject`,`message`,`mime`,`filename`,`includeInline`]);if(Object.keys(t).some(t=>!e.has(t))||![`imap`,`slack`,`whatsapp`].includes(String(t.driver))||typeof t.address!=`string`||t.source!==void 0&&![`document`,`attachments`,`download`].includes(String(t.source))||[`target`,`subject`,`message`,`filename`].some(e=>t[e]!==void 0&&typeof t[e]!=`string`)||t.includeInline!==void 0&&typeof t.includeInline!=`boolean`)return null;let n=Array.isArray(t.to)?t.to:t.to===void 0?[]:[t.to],r=Array.isArray(t.mime)?t.mime:[t.mime??`*`];if(!n.every(e=>typeof e==`string`)||!r.every(e=>typeof e==`string`)||(t.driver===`imap`?t.target!==void 0:t.to!==void 0||t.subject!==void 0))return null;b.push({...K(`sendFile`),a:t.address,b:t.driver===`imap`?n.join(`, `):String(t.target||``),sendDriver:t.driver,sendSource:t.source||`document`,sendSubject:String(t.subject??`{{file.name}}`),sendMessage:String(t.message||``),attachmentMime:r.join(`, `),attachmentName:String(t.filename||``),includeInline:t.includeInline===!0})}else if(t.action===`extractAttachments`){let e=new Set([`action`,`to`,`folder`,`subfolder`,`mime`,`filename`,`includeInline`,`onConflict`]);if(Object.keys(t).some(t=>!e.has(t))||typeof t.to!=`string`||[`folder`,`subfolder`,`filename`].some(e=>t[e]!==void 0&&typeof t[e]!=`string`)||t.includeInline!==void 0&&typeof t.includeInline!=`boolean`||t.onConflict!==void 0&&t.onConflict!==`rename`&&t.onConflict!==`error`)return null;let n=Array.isArray(t.mime)?t.mime:[t.mime??`*`];if(!n.every(e=>typeof e==`string`))return null;b.push({...K(`extractAttachments`),a:t.to,storeFolder:typeof t.folder==`string`?t.folder:``,attachmentPath:typeof t.subfolder==`string`?t.subfolder:``,attachmentMime:n.join(`, `),attachmentName:typeof t.filename==`string`?t.filename:``,includeInline:t.includeInline===!0,storeConflict:t.onConflict===`error`?`error`:`rename`})}else if(t.action===`download`){let e=new Set([`action`,`to`,`folder`,`recursive`,`kind`,`insert`,`tags`,`depth`,`deleteSource`]);if(Object.keys(t).some(t=>!e.has(t)))return null;let n=typeof t.kind==`string`?t.kind:`auto`;if(!lt.some(e=>e.value===n))return null;let r=Array.isArray(t.insert)?t.insert:typeof t.insert==`string`?[t.insert]:[];if(!r.every(e=>typeof e==`string`))return null;b.push({...K(`download`),a:typeof t.to==`string`?t.to:`workspace:home`,b:r.join(`, `),storeFolder:typeof t.folder==`string`?t.folder:``,recursive:t.recursive===!0,deleteSource:t.deleteSource===!0,dlKind:n,dlDepth:typeof t.depth==`number`?String(t.depth):`2`,dlTags:Array.isArray(t.tags)?t.tags.join(`, `):``})}else if(t.action===`unstore`&&(typeof t.from==`string`||Array.isArray(t.from))){let e=e=>Array.isArray(e)?String(e[0]??``):typeof e==`string`?e:``;b.push({...K(`unstore`),a:e(t.from),b:e(t.ifOn),keepLast:t.keepLast!==!1})}else if(t.action===`delete`)b.push(K(`delete`));else if(t.action===`destroy`)b.push(K(`destroy`));else if(t.action===`agent`&&typeof t.slug==`string`&&typeof t.prompt==`string`){let e=te(t);if(!e)return null;b.push({...K(`agent`),a:t.slug,b:t.prompt,...e})}else if(t.action===`script`&&typeof t.path==`string`){let e=te(t);if(!e)return null;b.push({...K(`script`),a:t.path,...e})}else return null}return{id:e.id,description:e.description||``,events:_,schema:typeof n==`string`?n:``,cascade:e.cascade===!0,approval:e.approval===!0,...e.editable?.length?{editable:e.editable}:{},...e.ttl===void 0?{}:{ttl:e.ttl},conditions:v,actions:b.length?b:[K(`link`)]}}var vt=(e,t)=>t.find(t=>t.value===e)?.label?.replace(/\s\(\d+\)$/,``)||(e?String(e).replace(/^data\/schema\//,``):`any item`);function yt(e,t=tt){let n=e.when,r=_e(e).map(e=>nt.find(t=>t.value===e)?.label||e).join(` or `),i=[`When ${vt(n.schema,t)} ${r}`],a=e=>Array.isArray(e)?e.join(` or `):typeof e==`object`&&e?JSON.stringify(e):String(e),o={path:`under`,pathExact:`directly in`,eventPathExact:`inserted / linked directly into`,mime:`type`,from:`from`,to:`to`,subject:`subject`,body:`body / text`,sender:`sender`,thread:`thread`,channel:`conversation`,platform:`platform`,url:`url`,attachment:`attachment`};for(let e of Object.keys(o))n[e]!==void 0&&i.push(`${o[e]} ${a(n[e])}`);return i.join(` · `)}function bt(e){let t=e.output||{},n=t.note||{},r=t.file||{};return[n.path?`reply → note ${n.path}`:``,r.path?`reply → file ${r.backend===`data`?`data:`:`home/`}${r.path}${r.insert?` (indexed at ${r.insert})`:``}`:``,t.notify?`reply → notify`:``].filter(Boolean).join(`, `)}function xt(e){if(e.action===`link`)return`file into ${e.paths?.join(`, `)}${e.recursive===!0?` (sub-folders kept)`:``}`;if(e.action===`unlink`)return`remove from ${e.paths?.join(`, `)}${e.recursive===!0?` (sub-folders kept)`:``}`;if(e.action===`tag`)return`tag ${e.tags?.join(`, `)}`;if(e.action===`store`){let t=typeof e.folder==`string`&&e.folder?`/${e.folder}`:``,n=e.key===ct?`, named by title`:e.key===G?`, by date`:typeof e.key==`string`&&e.key?`, as ${e.key}`:``;return`${e.mode===`move`?`move`:`copy`} the file to ${e.to}${t}${e.recursive===!0?e.pathMode===`full`?` (full directory path recreated)`:` (sub-folder path recreated)`:``}${n}`}if(e.action===`extractAttachments`){let t=[e.to,e.folder,e.subfolder].filter(Boolean).join(`/`);return`extract ${Array.isArray(e.mime)?e.mime.join(`, `):e.mime||`all`} attachments to ${t}${e.filename?` (filename contains ${e.filename})`:``}`}if(e.action===`moveMessage`)return`move the email to mail folder ${e.folder}`;if(e.action===`download`){let t=lt.find(t=>t.value===(e.kind||`auto`)),n=typeof e.folder==`string`&&e.folder?`/${e.folder}`:``,r=Array.isArray(e.insert)&&e.insert.length?`, filed at ${e.insert.join(`, `)}`:`, filed next to the link`;return`download ${t?.value===`auto`?`the link (auto-detected)`:t?.label||e.kind} to ${e.to||`workspace:home`}${n}${e.recursive===!0?` (sub-folders kept)`:``}${r}`}if(e.action===`unstore`)return`delete the file from ${Array.isArray(e.from)?e.from.join(`, `):e.from}${e.ifOn?` once it is on ${Array.isArray(e.ifOn)?e.ifOn.join(`, `):e.ifOn}`:``}`;if(e.action===`sendFile`)return`send ${e.source===`attachments`?`matching attachments`:e.source===`download`?`downloaded files`:`the file`} via ${e.driver===`imap`?`email`:e.driver} to ${Array.isArray(e.to)?e.to.join(`, `):e.to||e.target||`…`}`;if(e.action===`notify`)return`send me a notification`;if(e.action===`delete`)return`delete from Canvas (keeps stored files/mail)`;if(e.action===`destroy`)return`⚠ delete everywhere (index + storage)`;if(e.action===`agent`){let t=bt(e);return`ask agent "${e.slug}"${t?` (${t})`:``}`}if(e.action===`script`){let t=bt(e);return`run ${e.path}${t?` (${t})`:``}`}return e.action}function St(e){return(e.then||[]).map(xt).join(` · `)||`(no actions)`}function Ct(e){return ve(e).length>0&&(e.then||[]).length>0&&(e.then||[]).every(e=>e.action===`link`||e.action===`unlink`||e.action===`store`||e.action===`unstore`)}function wt(e){let t={};for(let n of e){if(n.handlerType!==`rule`)continue;let e=t[n.handler]||={count:0,errors:0,last:n};e.count++,n.status===`error`&&e.errors++,n.ts>e.last.ts&&(e.last=n)}return t}function Tt(e){let t=Date.now()-new Date(e).getTime();if(!Number.isFinite(t)||t<0)return``;let n=Math.floor(t/6e4);if(n<1)return`just now`;if(n<60)return`${n}m ago`;let r=Math.floor(n/60);return r<48?`${r}h ago`:`${Math.floor(r/24)}d ago`}function Et(e){return e.some(e=>e.address===`workspace:home`)?`workspace:home`:e.find(e=>e.address!==`workspace:data`)?.address||e[0]?.address||``}function Dt(e){if(e.kind===`document`&&e.rule)return{..._t(e.rule)||q,id:null};if(e.kind===`download`){let t=e.path?` filed under ${e.path.replace(/^(ctx|dir):/,``)}`:``;return{...q,description:`Download links${t}`,schema:`tab`,events:[`document.inserted`,`document.linked`],conditions:[{field:`path`,value:e.path||``}],actions:[{...K(`download`),a:e.storeTo||``,storeFolder:e.storeFolder||`Downloads`,recursive:!0}]}}if(e.kind===`store`){let t=e.path||``,n=/^(?:(?:ctx|context):)?\//.test(t),r=[{field:n?`eventPathExact`:`path`,value:n&&t.startsWith(`/`)?`ctx:${t}`:t}],i=e.path?`${n?` inserted / linked directly into`:` filed under`} ${e.path.replace(/^(ctx|context|dir|directory):/,``)}`:``;return{...q,description:e.storeTo?`Copy files${i} to ${e.storeTo}${e.storeFolder?`/${e.storeFolder}`:``}`:`Copy files${i} to a storage backend`,schema:`file`,events:[`document.inserted`,`document.linked`],conditions:r,actions:[{...K(`store`),a:e.storeTo||``,storeFolder:e.storeFolder||``,recursive:mt(r)}]}}return{...q,description:`Mirror ${e.path} into ${e.target}`,events:[`document.inserted`,`document.linked`],conditions:[{field:`path`,value:e.path||``}],actions:[{...K(`link`),a:e.target||`dir:/`,recursive:!0}]}}var X=`h-10 w-full rounded-md border bg-background px-3 text-sm outline-none focus:ring-2 focus:ring-ring disabled:opacity-50`,Z=`h-10 text-sm`;function Q({label:e,hint:t,children:n,className:r}){return(0,W.jsxs)(`label`,{className:S(`flex min-w-0 flex-col gap-1.5`,r),children:[(0,W.jsx)(`span`,{className:`text-sm font-medium`,children:e}),n,t&&(0,W.jsx)(`span`,{className:`text-xs leading-relaxed text-muted-foreground`,children:t})]})}function $({checked:e,onChange:t,label:n,hint:r,disabled:i}){return(0,W.jsxs)(`button`,{type:`button`,role:`switch`,"aria-checked":e,disabled:i,onClick:()=>t(!e),className:S(`flex w-full items-start gap-3 rounded-lg border p-3 text-left transition-colors hover:bg-accent/40 disabled:cursor-not-allowed disabled:opacity-50`,e&&`border-primary/40 bg-primary/5`),children:[(0,W.jsx)(`span`,{className:S(`mt-0.5 inline-flex h-5 w-9 shrink-0 items-center rounded-full p-0.5 transition-colors`,e?`bg-primary`:`bg-muted-foreground/30`),children:(0,W.jsx)(`span`,{className:S(`h-4 w-4 rounded-full bg-background shadow transition-transform`,e&&`translate-x-4`)})}),(0,W.jsxs)(`span`,{className:`min-w-0`,children:[(0,W.jsx)(`span`,{className:`block text-sm font-medium`,children:n}),r&&(0,W.jsx)(`span`,{className:`block text-xs leading-relaxed text-muted-foreground`,children:r})]})]})}function Ot({value:e,options:t,onChange:n}){return(0,W.jsx)(`div`,{className:`inline-flex h-10 rounded-md border bg-background p-1`,children:t.map(t=>(0,W.jsx)(`button`,{type:`button`,onClick:()=>n(t.value),className:S(`rounded px-3 text-sm transition-colors`,e===t.value?`bg-primary text-primary-foreground shadow-sm`:`text-muted-foreground hover:text-foreground`),children:t.label},t.value))})}function kt({active:e,onClick:t,children:n,title:r}){return(0,W.jsx)(`button`,{type:`button`,title:r,onClick:t,"aria-pressed":e,className:S(`h-9 rounded-full border px-3.5 text-sm transition-colors`,e?`border-primary bg-primary/10 font-medium text-foreground`:`text-muted-foreground hover:bg-accent hover:text-foreground`),children:n})}function At({step:e,title:t,hint:n}){return(0,W.jsxs)(`div`,{className:`flex items-start gap-3`,children:[(0,W.jsx)(`span`,{className:`mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-primary/10 text-sm font-semibold text-primary`,children:e}),(0,W.jsxs)(`div`,{children:[(0,W.jsx)(`h3`,{className:`text-base font-semibold leading-7`,children:t}),n&&(0,W.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:n})]})]})}function jt({icon:e,tone:t,size:n=`md`}){return(0,W.jsx)(`span`,{className:S(`inline-flex shrink-0 items-center justify-center rounded-xl`,n===`lg`?`h-12 w-12`:`h-10 w-10`,t),children:(0,W.jsx)(e,{className:n===`lg`?`h-6 w-6`:`h-5 w-5`})})}function Mt({workspaceId:e,onOpenJson:t,onShowRuns:n,backfillLimit:r,prefill:l,onPrefillConsumed:d,createOnly:p=!1,onCreated:h,onCancel:g}){let{showToast:y,showProgress:te}=re(),[x,T]=(0,D.useState)([]),[E,ae]=(0,D.useState)({}),oe=e=>{Ae(e,{limit:500}).then(e=>ae(wt(e))).catch(()=>ae({}))},[se,O]=(0,D.useState)(!0),[k,A]=(0,D.useState)(null),[j,M]=(0,D.useState)(!1),[N,P]=(0,D.useState)(!1),[fe,pe]=(0,D.useState)([]),[F,me]=(0,D.useState)([]),[he,ge]=(0,D.useState)([]),[_e,be]=(0,D.useState)(``),xe=(0,D.useRef)(null),[Se,Te]=(0,D.useState)(e);e!==Se&&(Te(e),O(!0)),(0,D.useEffect)(()=>{Ce(e).then(e=>T(e)).finally(()=>O(!1)),oe(e)},[e]);let[Ee,De]=(0,D.useState)(null);l!==Ee&&(De(l),l&&(A(Dt(l)),M(!1))),(0,D.useEffect)(()=>{l&&d?.()},[l,d]),(0,D.useEffect)(()=>{Ze(e).then(e=>pe(e.map(e=>e.path))).catch(()=>pe([]))},[e]),(0,D.useEffect)(()=>{let t=!1;return le(e).then(e=>{t||(ge([...new Map(e.map(e=>[`${e.driver}:${e.address}`,e])).values()]),be(``))}).catch(()=>{t||(ge([]),be(`Sending accounts could not be loaded.`))}),()=>{t=!0}},[e]),(0,D.useEffect)(()=>{ce(e).then(e=>{let t=e.filter(e=>e.kind===`storage`&&e.enabled!==!1&&e.config?.supported!==!1&&e.config?.readOnly!==!0&&e.capabilities?.write!==!1);me(t);let n=Et(t);n&&A(e=>e&&e.actions.some(e=>(e.kind===`store`||e.kind===`download`)&&!e.a)?{...e,actions:e.actions.map(e=>(e.kind===`store`||e.kind===`download`)&&!e.a?{...e,a:n}:e)}:e)}).catch(()=>me([]))},[e]);let[Oe,ke]=(0,D.useState)(tt);(0,D.useEffect)(()=>{Be(e).then(e=>{e.schemas?.length&&ke([{value:``,label:`any item`},...e.schemas.map(e=>({value:e.id,label:`${e.name} (${e.count})`}))])}).catch(()=>{})},[e]);let I=async(t,n)=>{P(!0);try{return await we(e,t),T(t),y({title:n,description:`rules.json updated (committed to workspace git)`}),!0}catch(e){return y({title:`Error`,description:e instanceof Error?e.message:`Failed to save rules`,variant:`destructive`}),!1}finally{P(!1)}},je=async()=>{if(!k||se||N)return;let t;try{t=gt(k,F)}catch(e){y({title:`Invalid rule`,description:e instanceof Error?e.message:`Check the rule conditions and actions`,variant:`destructive`});return}if(!t.then.length){y({title:`Add an action`,description:`Pick at least one "then" action and fill in its fields.`,variant:`destructive`});return}if(p){t.id=`${t.id}-${Math.random().toString(36).slice(2,10)}`,P(!0);try{await He(e,t),y({title:`Rule created`,description:`The rule will run for matching new items.`}),h?.()}catch(e){y({title:`Could not create rule`,description:e instanceof Error?e.message:`Failed to save rule`,variant:`destructive`})}finally{P(!1)}return}!k.id&&x.some(e=>e.id===t.id)&&(t.id=`${t.id}-${Math.random().toString(36).slice(2,10)}`);let n=k.id?x.map(e=>e.id===k.id?{...t,enabled:e.enabled!==!1}:e):[...x,t];await I(n,k.id?`Rule updated`:`Rule created`)&&(A(null),h?.())},Me=e=>I(x.map(t=>t.id===e?{...t,enabled:t.enabled===!1}:t),`Rule toggled`),Ne=e=>{confirm(`Delete rule "${e}"?`)&&I(x.filter(t=>t.id!==e),`Rule deleted`)},[Pe,Fe]=(0,D.useState)(null),Le=async t=>{Fe(t);try{let n=await Ie(e,{ruleId:t,dryRun:!0,limit:r}),i=n.results.filter(e=>e.matched).length;if(!i){y({title:`Apply to existing items`,description:`No matches among ${n.processed} existing documents (conditions evaluate against each document's current tree placements). Raise the batch size in the toolbar to cover more.`});return}if(!confirm(`Rule "${t}" matches ${i} of the first ${n.processed} of ${n.total??n.processed} existing documents. Run its actions on all of them now?`))return;await Ye(te,e,[t])}catch(e){y({title:`Backfill failed`,description:e instanceof Error?e.message:`Unknown error`,variant:`destructive`})}finally{Fe(null),oe(e)}},L=(e,t)=>A(n=>n&&{...n,[e]:t}),Re=e=>{A(e.build({backend:Et(F)})),M(!1),requestAnimationFrame(()=>xe.current?.scrollIntoView({behavior:`smooth`,block:`start`}))},ze=e=>{let n=_t(e);n?(A(n),M(!1),requestAnimationFrame(()=>xe.current?.scrollIntoView({behavior:`smooth`,block:`start`}))):t?.()},[R,z]=(0,D.useState)(null),Ve=(e,t)=>t.treeType===`context`?e:t.treeName===`directory`?`dir:${e}`:`${t.treeName}:${e}`,Ue=(e,t)=>{if(!R||!k||!e.length){z(null);return}if(R.target===`storeFolder`){let t=ye(e[0]);L(`actions`,k.actions.map((e,n)=>n===R.index?{...e,storeFolder:t?.rel||``,...t?.backend&&F.some(e=>e.address===t.backend)?{a:t.backend}:{}}:e))}else if(R.target===`condition`){let n=e.map(e=>Ve(e,t)),r=t.treeType===`context`&&k.actions.some(e=>e.kind===`store`);L(`conditions`,k.conditions.map((e,t)=>t===R.index?{...e,...r?{field:`eventPathExact`}:{},value:n.join(` | `)}:e))}else{let n=e.map(e=>Ve(e,t));L(`actions`,k.actions.map((e,t)=>t===R.index?e.kind===`download`?{...e,b:n.join(`, `)}:{...e,a:n.join(`, `)}:e))}z(null)},B=(e,t,n=`Browse…`)=>(0,W.jsxs)(C,{type:`button`,size:`sm`,variant:`outline`,className:`h-10 shrink-0 px-3`,title:n,onClick:()=>z({target:e,index:t}),children:[(0,W.jsx)(v,{className:`h-4 w-4 sm:mr-1.5`}),(0,W.jsx)(`span`,{className:`hidden sm:inline`,children:`Browse`})]}),We=mt(k?.conditions||[]),V=!!k?.conditions.some(e=>[`path`,`pathExact`,`eventPathExact`].includes(e.field)&&e.value.trim()),Ke=e=>`${e.address}${e.address===`workspace:data`?` — managed blob store (default)`:e.address===`workspace:home`?` — workspace home folder`:e.driver?` — ${e.driver}`:``}`,H=(e,t,n,r=`workspace:home`)=>F.length?(0,W.jsxs)(`select`,{className:X,value:e,onChange:e=>t(e.target.value),children:[(0,W.jsx)(`option`,{value:``,children:n}),F.map(e=>(0,W.jsx)(`option`,{value:e.address,children:Ke(e)},e.address)),e&&!F.some(t=>t.address===e)&&(0,W.jsx)(`option`,{value:e,children:e})]}):(0,W.jsx)(w,{className:S(Z,`font-mono`),placeholder:r,value:e,onChange:e=>t(e.target.value)}),qe=x.filter(Ct),Je=x.filter(e=>!Ct(e)),Xe=({rule:e})=>{let t=e.enabled!==!1,r=_t(e)!==null,a=E[e.id],s=st(e.then?.[0]?.action||`link`),c=ve(e),l=e.when.eventPathExact===void 0?Pe===null?null:`Apply is busy checking or starting another rule. Please wait.`:`Apply is unavailable: “is inserted / linked directly into” requires an original filing event. To process existing items, edit the condition to “is directly in the folder” or “is under the folder” to match current membership instead.`;return(0,W.jsxs)(`div`,{className:S(`rule-card rounded-xl border bg-card p-4 transition-opacity`,!t&&`opacity-60`),children:[(0,W.jsx)(jt,{icon:s.icon,tone:s.tone}),(0,W.jsxs)(`div`,{className:`rule-card-content min-w-0 space-y-1.5`,children:[(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-x-2 gap-y-1`,children:[(0,W.jsx)(`h3`,{className:`text-base font-semibold leading-6`,children:e.description||e.id}),e.approval===!0&&(0,W.jsx)(`span`,{className:`rounded-full bg-warning/15 px-2 py-0.5 text-xs font-medium text-warning`,children:`needs approval`}),e.cascade===!0&&(0,W.jsx)(`span`,{className:`rounded-full bg-muted px-2 py-0.5 text-xs text-muted-foreground`,children:`incl. automation-created`}),!r&&(0,W.jsx)(`span`,{className:`rounded-full bg-muted px-2 py-0.5 text-xs text-muted-foreground`,title:`This rule uses matchers the builder cannot show; edit it as JSON.`,children:`JSON only`})]}),(0,W.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:yt(e,Oe)}),l&&(0,W.jsx)(`p`,{id:`apply-reason-${e.id}`,className:`text-sm text-muted-foreground`,children:l}),(0,W.jsxs)(`p`,{className:`flex items-start gap-1.5 text-sm`,children:[(0,W.jsx)(ee,{className:`mt-1 h-3.5 w-3.5 shrink-0 text-muted-foreground`}),(0,W.jsx)(`span`,{children:St(e)})]}),c.length>0&&(0,W.jsx)(`p`,{className:`truncate font-mono text-xs text-muted-foreground`,title:c.join(` | `),children:c.join(` | `)}),(0,W.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:a?(0,W.jsxs)(`button`,{type:`button`,className:S(`text-left underline-offset-2 hover:underline`,a.last.status===`error`&&`text-destructive`,!n&&`cursor-default hover:no-underline`),title:n?`Show this rule's run log`:a.last.error||a.last.skipReason||``,onClick:()=>n?.(e.id),children:[`ran `,a.count,`×`,a.errors?` (${a.errors} failed)`:``,` · last `,a.last.status,` `,Tt(a.last.ts)]}):`not run yet`})]}),(0,W.jsxs)(`div`,{className:`rule-card-actions`,children:[(0,W.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":t,disabled:N,title:t?`Enabled — click to pause`:`Paused — click to enable`,onClick:()=>Me(e.id),className:S(`mr-1 inline-flex h-6 w-11 items-center rounded-full p-0.5 transition-colors`,t?`bg-primary`:`bg-muted-foreground/30`),children:(0,W.jsx)(`span`,{className:S(`h-5 w-5 rounded-full bg-background shadow transition-transform`,t&&`translate-x-5`)})}),(0,W.jsxs)(C,{size:`sm`,variant:`ghost`,className:`h-9 px-2.5`,title:l||`Apply this rule to existing items (dry-run first)`,"aria-describedby":l?`apply-reason-${e.id}`:void 0,disabled:l!==null,onClick:()=>Le(e.id),children:[Pe===e.id?(0,W.jsx)(_,{className:`h-4 w-4 animate-spin`}):(0,W.jsx)(o,{className:`h-4 w-4`}),(0,W.jsx)(`span`,{className:`rule-card-action-label ml-1.5`,children:`Apply`})]}),(0,W.jsxs)(C,{size:`sm`,variant:`ghost`,className:`h-9 px-2.5`,title:r?`Edit rule`:`Edit as JSON`,onClick:()=>ze(e),children:[r?(0,W.jsx)(i,{className:`h-4 w-4`}):(0,W.jsx)(ne,{className:`h-4 w-4`}),(0,W.jsx)(`span`,{className:`rule-card-action-label ml-1.5`,children:`Edit`})]}),(0,W.jsx)(C,{size:`sm`,variant:`ghost`,className:`h-9 px-2.5 text-destructive hover:text-destructive`,title:`Delete rule`,onClick:()=>Ne(e.id),children:(0,W.jsx)(f,{className:`h-4 w-4`})})]})]})},U=(0,W.jsxs)(`div`,{className:`space-y-3`,children:[(0,W.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,W.jsx)(`h3`,{className:`text-base font-semibold`,children:`What should happen automatically?`}),j&&(0,W.jsxs)(C,{size:`sm`,variant:`ghost`,onClick:()=>M(!1),children:[(0,W.jsx)(c,{className:`mr-1 h-4 w-4`}),` Close`]})]}),(0,W.jsx)(`div`,{className:`grid min-w-0 grid-cols-[repeat(auto-fill,minmax(min(100%,17rem),1fr))] gap-3`,children:pt.map(e=>(0,W.jsxs)(`button`,{type:`button`,onClick:()=>Re(e),className:`flex min-w-0 items-start gap-3 rounded-xl border bg-card p-4 text-left transition-colors hover:border-primary/50 hover:bg-accent/40`,children:[(0,W.jsx)(jt,{icon:e.icon,tone:e.tone,size:`lg`}),(0,W.jsxs)(`span`,{className:`min-w-0`,children:[(0,W.jsx)(`span`,{className:`block text-base font-semibold leading-6`,children:e.title}),(0,W.jsx)(`span`,{className:`mt-1 block break-words text-sm leading-relaxed text-muted-foreground`,children:e.blurb})]})]},e.id))})]});return(0,W.jsxs)(`div`,{className:`rule-builder min-w-0 space-y-5`,children:[!p&&(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center justify-between gap-3`,children:[(0,W.jsxs)(`div`,{className:`min-w-0 flex-[1_1_20rem]`,children:[(0,W.jsx)(`h2`,{className:`text-lg font-semibold`,children:`Rules`}),(0,W.jsxs)(`p`,{className:`text-sm text-muted-foreground`,children:[`Rules run automatically as items arrive or get filed — no code needed. Stored in`,` `,(0,W.jsx)(`span`,{className:`font-mono`,children:`rules.json`}),` in the workspace git.`]})]}),(0,W.jsxs)(`div`,{className:`flex shrink-0 gap-2`,children:[t&&(0,W.jsxs)(C,{variant:`ghost`,onClick:t,title:`Edit rules.json directly`,children:[(0,W.jsx)(ne,{className:`mr-1.5 h-4 w-4`}),` JSON`]}),(0,W.jsxs)(C,{onClick:()=>{A(null),M(!0)},disabled:j,children:[(0,W.jsx)(u,{className:`mr-1.5 h-4 w-4`}),` New rule`]})]})]}),j&&!k&&U,k&&(0,W.jsxs)(`div`,{ref:xe,className:`scroll-mt-4 space-y-6 rounded-xl border bg-card p-4 sm:p-6`,children:[(0,W.jsxs)(`div`,{className:`flex items-center justify-between gap-3`,children:[(0,W.jsx)(`h3`,{className:`text-lg font-semibold`,children:k.id?`Edit rule`:`New rule`}),(0,W.jsxs)(C,{variant:`ghost`,size:`sm`,onClick:()=>A(null),children:[(0,W.jsx)(c,{className:`mr-1 h-4 w-4`}),` Cancel`]})]}),(0,W.jsx)(Q,{label:`Name`,hint:`Shown in the list and the run log.`,children:(0,W.jsx)(w,{className:`h-11 text-base`,placeholder:`Keep UI designs in Projects/Canvas/UI`,value:k.description,onChange:e=>L(`description`,e.target.value)})}),(0,W.jsxs)(`section`,{className:`space-y-4`,children:[(0,W.jsx)(At,{step:1,title:`When…`,hint:`What the rule reacts to. All conditions must match; repeat a condition for either/or.`}),(0,W.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-[minmax(0,220px)_1fr]`,children:[(0,W.jsx)(Q,{label:`Item`,children:(0,W.jsxs)(`select`,{className:X,value:k.schema,onChange:e=>L(`schema`,e.target.value),children:[Oe.map(e=>(0,W.jsx)(`option`,{value:e.value,children:e.label},e.value)),k.schema&&!Oe.some(e=>e.value===k.schema)&&(0,W.jsx)(`option`,{value:k.schema,children:k.schema.replace(/^data\/schema\//,``)})]})}),(0,W.jsxs)(`div`,{className:`flex flex-col gap-1.5`,children:[(0,W.jsxs)(`span`,{className:`text-sm font-medium`,children:[`Event `,(0,W.jsx)(`span`,{className:`font-normal text-muted-foreground`,children:`(any of)`})]}),(0,W.jsx)(`div`,{className:`flex flex-wrap gap-2`,children:nt.map(e=>{let t=k.events.includes(e.value);return(0,W.jsx)(kt,{active:t,title:e.hint,onClick:()=>{let n=t?k.events.filter(t=>t!==e.value):[...k.events,e.value];n.length&&L(`events`,n)},children:e.label},e.value)})})]})]}),k.conditions.length>0&&(0,W.jsx)(`div`,{className:`space-y-2`,children:k.conditions.map((e,t)=>{let n=rt.find(t=>t.key===e.field);return(0,W.jsxs)(`div`,{className:`grid grid-cols-[2.25rem_1fr_auto] items-center gap-2 sm:grid-cols-[2.25rem_minmax(0,240px)_1fr_auto]`,children:[(0,W.jsx)(`span`,{className:`text-xs font-medium uppercase tracking-wide text-muted-foreground`,title:`Same condition again = either may match (OR); different conditions must all match (AND)`,children:k.conditions.slice(0,t).some(t=>at(t.field)===at(e.field))?`or`:`and`}),(0,W.jsx)(`select`,{className:X,value:e.field,onChange:e=>L(`conditions`,k.conditions.map((n,r)=>r===t?{...n,field:e.target.value}:n)),children:rt.map(e=>(0,W.jsx)(`option`,{value:e.key,children:e.label},e.key))}),(0,W.jsxs)(`div`,{className:`order-4 col-span-3 flex gap-2 sm:order-3 sm:col-span-1`,children:[(0,W.jsx)(w,{className:S(Z,`font-mono`),placeholder:n?.hint,value:e.value,onChange:e=>L(`conditions`,k.conditions.map((n,r)=>r===t?{...n,value:e.target.value}:n))}),[`path`,`pathExact`,`eventPathExact`].includes(e.field)&&B(`condition`,t,`Browse the workspace trees`)]}),(0,W.jsx)(C,{size:`sm`,variant:`ghost`,className:`order-3 h-10 w-10 p-0 text-muted-foreground sm:order-4`,title:`Remove condition`,onClick:()=>L(`conditions`,k.conditions.filter((e,n)=>n!==t)),children:(0,W.jsx)(c,{className:`h-4 w-4`})}),e.field===`eventPathExact`&&(0,W.jsx)(`p`,{className:`order-5 col-span-full text-xs text-muted-foreground`,children:`Matches new filing events only; Apply to existing items is unavailable. Choose “is directly in the folder” or “is under the folder” to match current membership.`})]},t)})}),(0,W.jsxs)(`div`,{className:`flex flex-wrap items-center gap-3`,children:[(0,W.jsxs)(C,{size:`sm`,variant:`outline`,onClick:()=>L(`conditions`,[...k.conditions,{field:k.schema===`email`?`from`:`path`,value:``}]),children:[(0,W.jsx)(u,{className:`mr-1 h-4 w-4`}),` Add condition`]}),(0,W.jsxs)(`span`,{className:`text-xs text-muted-foreground`,children:[`Contains matches literal text. Regex is case-insensitive: enter the pattern without /…/ delimiters; | stays part of the expression. Email sender and recipient filters, folder filters and file types accept alternatives separated by `,(0,W.jsx)(`span`,{className:`font-mono`,children:`|`}),`, e.g. `,(0,W.jsx)(`span`,{className:`font-mono`,children:`accounting@example.com | invoices@example.com`}),`. Exact sender, thread, conversation and platform IDs are literal; add another condition of the same type for alternatives.`]})]})]}),(0,W.jsxs)(`section`,{className:`space-y-4`,children:[(0,W.jsx)(At,{step:2,title:`Then…`,hint:`Actions run in order. The item keeps its id, tags and folders unless an action says otherwise.`}),k.actions.map((t,n)=>{let r=e=>L(`actions`,k.actions.map((t,r)=>r===n?{...t,...e}:t)),i=F.find(e=>e.address===t.a),a=i?.capabilities?.paths===!0,o=We&&a,l=st(t.kind),u=n=>(0,W.jsxs)(`div`,{className:`space-y-3 rounded-lg border border-dashed p-3`,children:[(0,W.jsxs)(`p`,{className:`text-sm font-medium`,children:[`What to do with the `,n]}),(0,W.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,W.jsx)(Q,{label:`Save as a note at`,hint:`Context path by default, dir:/path for the directory tree.`,children:(0,W.jsx)(de,{inputClassName:Z,placeholder:`/notes/summaries (optional)`,value:t.notePath,onChange:e=>r({notePath:e}),fixedWorkspaceName:e,pickerTitle:`Save note under…`,onPickTarget:(e,t)=>r({notePath:t.treeType===`directory`?`dir:${e}`:e})})}),t.notePath.trim()&&(0,W.jsx)(Q,{label:`Note title`,children:(0,W.jsx)(w,{className:Z,placeholder:`Summary: {{doc.data.subject}}`,value:t.noteTitle,onChange:e=>r({noteTitle:e.target.value})})}),(0,W.jsx)(Q,{label:`Save as a file at`,hint:`Relative path under the workspace home folder or in the data blob store.`,children:(0,W.jsx)(w,{className:S(Z,`font-mono`),placeholder:`logs/agent.log (optional)`,value:t.filePath,onChange:e=>r({filePath:e.target.value})})}),t.filePath.trim()&&(0,W.jsxs)(W.Fragment,{children:[(0,W.jsx)(Q,{label:`File lives in`,children:(0,W.jsxs)(`select`,{className:X,value:t.fileBackend,onChange:e=>r({fileBackend:e.target.value}),children:[(0,W.jsx)(`option`,{value:`home`,children:`the workspace home folder`}),(0,W.jsx)(`option`,{value:`data`,children:`the data blob store`})]})}),(0,W.jsx)(Q,{label:`Also file the saved file under`,hint:`Index it as a document at this tree path.`,children:(0,W.jsx)(de,{inputClassName:Z,placeholder:`/path (optional)`,value:t.fileInsert,onChange:e=>r({fileInsert:e}),fixedWorkspaceName:e,tabs:[`context`],pickerTitle:`File under…`,onPickTarget:e=>r({fileInsert:e})})})]})]}),(0,W.jsx)($,{checked:t.notifyReply,onChange:e=>r({notifyReply:e}),label:`Send me a notification with the result`})]}),d=Y(k.conditions),f=t.kind===`store`&&t.a&&(!t.recursive||o)?ht(t,k.conditions,i):null,p=t.kind===`extractAttachments`&&t.a?Ge(t.a,t.storeFolder,t.attachmentPath):null;return(0,W.jsxs)(`div`,{className:`space-y-4 rounded-xl border bg-background p-4`,children:[(0,W.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,W.jsx)(jt,{icon:l.icon,tone:l.tone}),(0,W.jsx)(`select`,{className:S(X,`flex-1 font-medium`),value:t.kind,onChange:e=>r(K(e.target.value)),children:ot.map(e=>(0,W.jsx)(`option`,{value:e.key,children:e.label},e.key))}),(0,W.jsx)(C,{size:`sm`,variant:`ghost`,className:`h-10 w-10 shrink-0 p-0 text-muted-foreground`,title:`Remove action`,disabled:k.actions.length===1,onClick:()=>L(`actions`,k.actions.filter((e,t)=>t!==n)),children:(0,W.jsx)(c,{className:`h-4 w-4`})})]}),(t.kind===`link`||t.kind===`unlink`)&&(0,W.jsxs)(`div`,{className:`space-y-3`,children:[(0,W.jsx)(Q,{label:t.kind===`link`?`Folder(s)`:`Remove from folder(s)`,hint:`Context-tree path by default; dir:/path for the directory tree. Comma-separate several.`,children:(0,W.jsxs)(`div`,{className:`flex gap-2`,children:[(0,W.jsx)(w,{className:S(Z,`font-mono`),placeholder:t.kind===`link`?`/work/urgent or dir:/projects/x`:`/inbox or dir:/staging`,value:t.a,onChange:e=>r({a:e.target.value})}),B(`action`,n)]})}),t.kind===`link`&&(0,W.jsx)(Q,{label:`Tags`,hint:`Optional, comma-separated.`,children:(0,W.jsx)(w,{className:S(Z,`font-mono`),placeholder:`custom/design, ui`,value:t.b,onChange:e=>r({b:e.target.value})})}),(0,W.jsx)($,{checked:t.recursive,onChange:e=>r({recursive:e}),label:`Recreate sub-folder path in destination`,hint:V?`The part of the item's path below the "is under the folder" prefix is appended to the target: …/foo/a/b → target/a/b.`:`Needs an "is under the folder" condition to know where sub-folders start.`,disabled:!V})]}),t.kind===`moveMessage`&&(0,W.jsxs)(`div`,{className:`space-y-2`,children:[(0,W.jsx)(Q,{label:`Mail folder`,hint:`The folder on the email's own IMAP account, with / between levels (works for servers that use . too). {{YYYY}}, {{MM}}, {{DD}} = the email's date.`,children:(0,W.jsx)(w,{className:S(Z,`font-mono`),placeholder:`INBOX/Accounting/{{YYYY}}/Expenses`,value:t.a,onChange:e=>r({a:e.target.value})})}),(0,W.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Moves the message on the mail server, like dragging it in a mail client. Put this after Extract attachments so the files are copied first. The folder must already exist on the server; subscribe to it in the mailbox settings to see the moved mail in Canvas.`})]}),t.kind===`tag`&&(0,W.jsx)(Q,{label:`Tags`,hint:`Comma-separated.`,children:(0,W.jsx)(w,{className:S(Z,`font-mono`),placeholder:`urgent, follow-up`,value:t.a,onChange:e=>r({a:e.target.value})})}),t.kind===`store`&&(0,W.jsxs)(`div`,{className:`space-y-4`,children:[(0,W.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-2`,children:[(0,W.jsx)(Q,{label:`Storage backend`,hint:`Where the file's bytes should live. Only writable backends are listed.`,children:H(t.a,e=>r({a:e}),`pick a backend…`)}),(0,W.jsx)(Q,{label:`Destination root folder`,hint:`Choose the folder beneath which the path will be recreated. Leave empty to use the backend root.`,children:(0,W.jsxs)(`div`,{className:`flex gap-2`,children:[(0,W.jsx)(w,{className:S(Z,`font-mono`),placeholder:`Projects/Canvas/UI`,value:t.storeFolder,onChange:e=>r({storeFolder:e.target.value})}),B(`storeFolder`,n,`Browse storage backends`)]})}),(0,W.jsx)(Q,{label:`File name`,children:(0,W.jsx)(`select`,{className:X,value:t.storeName,onChange:e=>r({storeName:e.target.value}),children:ut.map(e=>(0,W.jsx)(`option`,{value:e.value,children:e.label},e.value))})}),(0,W.jsx)(Q,{label:`Move or copy`,hint:t.storeMode===`move`?`Remove only the selected source copy after the destination is safely stored.`:`Preserve every existing copy.`,children:(0,W.jsx)(Ot,{value:t.storeMode,onChange:e=>r({storeMode:e}),options:[{value:`copy`,label:`Copy`},{value:`move`,label:`Move`}]})}),t.storeMode===`move`&&(0,W.jsx)(Q,{className:`sm:col-span-2`,label:`Move bytes from (required)`,hint:`Context membership does not identify a source copy. If the file is absent here, nothing is moved. Multiple locations on this backend make the move ambiguous; use copy.`,children:H(t.storeFrom,e=>r({storeFrom:e}),`choose a source backend…`,`workspace:data`)}),t.storeName===`custom`&&(0,W.jsx)(Q,{className:`sm:col-span-2`,label:`Name template`,hint:`Tokens: {{YYYY}} {{MM}} {{DD}} {{HH}} {{mm}} {{ss}} (photo capture time when present), {{ext}} {{basename}} {{filename}} {{title}} {{id}}, plus {{doc.…}} fields. Slashes create sub-folders.`,children:(0,W.jsx)(w,{className:S(Z,`font-mono`),placeholder:`{{YYYY}}-{{MM}}-{{DD}} {{title}}{{ext}}`,value:t.b,onChange:e=>r({b:e.target.value})})})]}),(0,W.jsx)($,{checked:t.recursive,onChange:e=>r({recursive:e}),label:d===null?`Recreate sub-folder path in destination`:`Recreate directory path in destination`,hint:a?We?d===null?`The path below the source folder is appended beneath the destination root: …/UI/mobile → Root/mobile. Missing destination folders are created.`:`Only inserts or links directly into ctx:${d} trigger this rule. Its full path is appended beneath the destination root; descendant inserts do not match.`:`Choose a source folder. Context paths use the destination of the insertion or link event.`:`Choose a destination that reports support for folder paths. Content-addressed blob stores cannot recreate sub-folder paths.`,disabled:!o&&!t.recursive}),f&&(0,W.jsxs)(`div`,{className:`space-y-1.5 rounded-lg bg-muted/60 px-3 py-3 text-sm`,"aria-live":`polite`,children:[(0,W.jsx)(`p`,{className:`font-medium`,children:`Destination preview`}),(0,W.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Root folder: `,(0,W.jsxs)(`span`,{className:`break-all font-mono`,children:[f.root,`/`]})]}),t.recursive&&(0,W.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Path added beneath it: `,(0,W.jsxs)(`span`,{className:`break-all font-mono`,children:[f.recreated||`(root)`,`/`]})]}),(0,W.jsx)(`p`,{className:`break-all font-mono`,children:f.result})]}),(0,W.jsxs)(`details`,{className:`group rounded-lg border`,children:[(0,W.jsxs)(`summary`,{className:`flex cursor-pointer select-none items-center gap-2 px-3 py-2 text-sm font-medium`,children:[(0,W.jsx)(s,{className:`h-4 w-4 transition-transform group-open:rotate-180`}),` More options`]}),(0,W.jsxs)(`div`,{className:`grid gap-4 border-t p-3 sm:grid-cols-2`,children:[t.storeMode===`copy`&&(0,W.jsx)(Q,{label:`Copy bytes from`,hint:`Optional source restriction. Default: any readable copy outside the destination backend.`,children:H(t.storeFrom,e=>r({storeFrom:e}),`any readable source`,`workspace:data (optional)`)}),(0,W.jsx)(Q,{label:`If the name is already taken`,children:(0,W.jsxs)(`select`,{className:X,value:t.storeConflict,onChange:e=>r({storeConflict:e.target.value}),children:[(0,W.jsx)(`option`,{value:`rename`,children:`add -1, -2, … to the name`}),(0,W.jsx)(`option`,{value:`error`,children:`skip the file`}),(0,W.jsx)(`option`,{value:`overwrite`,children:`overwrite the existing file`})]})})]})]}),t.storeMode===`copy`&&(0,W.jsx)($,{checked:t.deleteSource,onChange:e=>r({deleteSource:e}),label:`Delete source link from Canvas`,hint:`For links without stored bytes, download the target and remove the link only after success. Files are copied normally.`}),(0,W.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`The item keeps its id and virtual tree memberships. A move removes the chosen physical source location from the backend tree.`})]}),t.kind===`extractAttachments`&&(0,W.jsxs)(`div`,{className:`space-y-4`,children:[(0,W.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-2`,children:[(0,W.jsx)(Q,{label:`Attachment types`,hint:`MIME types, comma-separated. application/pdf for PDFs, image/* for images, or * for all.`,children:(0,W.jsx)(w,{className:S(Z,`font-mono`),placeholder:`application/pdf`,value:t.attachmentMime,onChange:e=>r({attachmentMime:e.target.value})})}),(0,W.jsx)(Q,{label:`Attachment filename contains`,hint:`Optional: invoice, faktura, or another literal filename fragment. Every selected attachment must also match its type.`,children:(0,W.jsx)(w,{className:Z,placeholder:`Any matching filename`,value:t.attachmentName,onChange:e=>r({attachmentName:e.target.value})})}),(0,W.jsx)(Q,{label:`Storage backend`,hint:`Choose a writable backend that supports folder paths.`,children:H(t.a,e=>r({a:e}),`pick a backend…`)}),(0,W.jsx)(Q,{label:`Destination root folder`,hint:`Choose the folder beneath which date subfolders will be created. Leave empty to use the backend root.`,children:(0,W.jsxs)(`div`,{className:`flex gap-2`,children:[(0,W.jsx)(w,{className:S(Z,`font-mono`),placeholder:`Accounting`,value:t.storeFolder,onChange:e=>r({storeFolder:e.target.value})}),B(`storeFolder`,n,`Browse storage backends`)]})}),(0,W.jsx)(Q,{label:`Sub-folder path template`,hint:`Appended beneath the root folder. {{YYYY}} = year, {{MM}} = month, {{DD}} = day of the email. Leave empty to file directly in the root folder.`,children:(0,W.jsx)(w,{className:S(Z,`font-mono`),placeholder:`No subfolders`,value:t.attachmentPath,onChange:e=>r({attachmentPath:e.target.value})})}),(0,W.jsx)(Q,{label:`If the attachment name is already taken`,children:(0,W.jsxs)(`select`,{className:X,value:t.storeConflict,onChange:e=>r({storeConflict:e.target.value}),children:[(0,W.jsx)(`option`,{value:`rename`,children:`add -1, -2, … to the name`}),(0,W.jsx)(`option`,{value:`error`,children:`skip the file and report the conflict`})]})})]}),!a&&(0,W.jsx)(`p`,{className:`text-sm text-amber-700 dark:text-amber-400`,children:`This destination has not reported support for folder paths. Select a supported backend before saving.`}),p&&(0,W.jsxs)(`div`,{className:`space-y-1.5 rounded-lg bg-muted/60 px-3 py-3 text-sm`,"aria-live":`polite`,children:[(0,W.jsx)(`p`,{className:`font-medium`,children:`Destination preview`}),(0,W.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Example email dated `,p.date,`. Each email supplies its own date.`]}),(0,W.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Root folder: `,(0,W.jsxs)(`span`,{className:`break-all font-mono`,children:[p.root,`/`]})]}),(0,W.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`Path added beneath it: `,(0,W.jsx)(`span`,{className:`break-all font-mono`,children:p.added?`${p.added}/`:`(none)`})]}),(0,W.jsx)(`p`,{className:`break-all font-mono`,children:p.result})]}),(0,W.jsx)($,{checked:t.includeInline,onChange:e=>r({includeInline:e}),label:`Include inline attachments`,hint:`Off by default, so signature images and embedded resources are excluded.`}),(0,W.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Copies matching attachments and keeps the email and its original files. Missing folders are created on the backend. Dates use the email's sent date (received/content date, then creation date if absent), in the server's timezone. This does not read the invoice date from the PDF.`}),(0,W.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Use Apply on the saved rule to process existing mail within the selected batch size. Add a subject or attachment filename condition if you need to distinguish invoices from other PDFs.`})]}),t.kind===`download`&&(0,W.jsxs)(`div`,{className:`space-y-4`,children:[(0,W.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-2`,children:[(0,W.jsx)(Q,{label:`Download`,hint:lt.find(e=>e.value===t.dlKind)?.hint,children:(0,W.jsx)(`select`,{className:X,value:t.dlKind,onChange:e=>r({dlKind:e.target.value}),children:lt.map(e=>(0,W.jsx)(`option`,{value:e.value,children:e.label},e.value))})}),t.dlKind===`website`?(0,W.jsx)(Q,{label:`Mirror depth`,hint:`How many link hops to follow on the same site (1–5).`,children:(0,W.jsx)(w,{type:`number`,min:1,max:5,className:S(Z,`sm:max-w-32`),value:t.dlDepth,onChange:e=>r({dlDepth:e.target.value})})}):(0,W.jsx)(`div`,{className:`hidden sm:block`}),(0,W.jsx)(Q,{label:`Storage backend`,hint:`Where the downloaded file's bytes should live.`,children:H(t.a,e=>r({a:e}),`workspace:home (default)`)}),(0,W.jsx)(Q,{label:`Folder on that backend`,hint:`Relative to the backend root.`,children:(0,W.jsxs)(`div`,{className:`flex gap-2`,children:[(0,W.jsx)(w,{className:S(Z,`font-mono`),placeholder:`Downloads`,value:t.storeFolder,onChange:e=>r({storeFolder:e.target.value})}),B(`storeFolder`,n,`Browse storage backends`)]})}),(0,W.jsx)(Q,{label:`File the download under`,hint:`Leave empty to file it in the same folder(s) as the link. Comma-separate several.`,children:(0,W.jsxs)(`div`,{className:`flex gap-2`,children:[(0,W.jsx)(w,{className:S(Z,`font-mono`),placeholder:`same folders as the link`,value:t.b,onChange:e=>r({b:e.target.value})}),B(`action`,n)]})}),(0,W.jsx)(Q,{label:`Tags for the download`,hint:`Optional, comma-separated.`,children:(0,W.jsx)(w,{className:S(Z,`font-mono`),placeholder:`downloaded, custom/paper`,value:t.dlTags,onChange:e=>r({dlTags:e.target.value})})})]}),(0,W.jsx)($,{checked:t.recursive,onChange:e=>r({recursive:e}),label:`Recreate sub-folder path in destination`,hint:V?`A link filed under …/folder/a/b is downloaded into Folder/a/b.`:`Add an "is under the folder" condition to mirror sub-folders.`,disabled:!V}),(0,W.jsx)($,{checked:t.deleteSource,onChange:e=>r({deleteSource:e}),label:`Delete source link from Canvas`,hint:`Remove the source item only after the download is saved successfully. Kept links are related to their downloads.`}),(0,W.jsxs)(`p`,{className:`text-xs text-muted-foreground`,children:[`The download becomes a file item at the filing destination. Repeated events reuse the saved download. Videos need `,(0,W.jsx)(`span`,{className:`font-mono`,children:`yt-dlp`}),`, pages and websites `,(0,W.jsx)(`span`,{className:`font-mono`,children:`wget`}),` on the server.`]})]}),t.kind===`unstore`&&(0,W.jsxs)(`div`,{className:`space-y-4`,children:[(0,W.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-2`,children:[(0,W.jsx)(Q,{label:`Delete the file from`,children:H(t.a,e=>r({a:e}),`pick a backend…`,`workspace:data`)}),(0,W.jsx)(Q,{label:`…but only once it is also on`,hint:`Safety: the copy is dropped only after another backend holds the file.`,children:H(t.b,e=>r({b:e}),`anywhere else`,`workspace:home (optional)`)})]}),(0,W.jsx)($,{checked:t.keepLast,onChange:e=>r({keepLast:e}),label:`Never delete the last copy`,hint:`Off means the rule may delete the only remaining copy of a file. Leave it on unless you mean exactly that.`}),(0,W.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Deletes the stored bytes on that backend only — copies elsewhere and the item itself are kept.`})]}),t.kind===`sendFile`&&(0,W.jsxs)(`div`,{className:`space-y-4`,children:[(0,W.jsx)(Q,{label:`Files to send`,children:(0,W.jsxs)(`select`,{className:X,value:t.sendSource,onChange:e=>r({sendSource:e.target.value}),children:[(0,W.jsx)(`option`,{value:`document`,children:`The file that triggered this rule`}),(0,W.jsx)(`option`,{value:`attachments`,children:`Matching attachments from the email`}),(0,W.jsx)(`option`,{value:`download`,children:`Files from an earlier Download action`})]})}),t.sendSource===`attachments`&&(0,W.jsxs)(`div`,{className:`grid gap-4 sm:grid-cols-2`,children:[(0,W.jsx)(Q,{label:`Attachment types`,hint:`application/pdf for invoices; * for all files.`,children:(0,W.jsx)(w,{className:Z,value:t.attachmentMime,onChange:e=>r({attachmentMime:e.target.value})})}),(0,W.jsx)(Q,{label:`Attachment filename contains`,hint:`Optional literal filename fragment.`,children:(0,W.jsx)(w,{className:Z,placeholder:`invoice`,value:t.attachmentName,onChange:e=>r({attachmentName:e.target.value})})})]}),t.sendSource===`attachments`&&(0,W.jsx)($,{checked:t.includeInline,onChange:e=>r({includeInline:e}),label:`Include inline attachments`,hint:`Signature images are excluded by default.`}),(0,W.jsx)(Q,{label:`Sending account`,hint:`Enable sending for the account in Connected services.`,children:(0,W.jsxs)(`select`,{className:X,value:t.a?`${t.sendDriver}:${t.a}`:``,onChange:e=>{let t=he.find(t=>`${t.driver}:${t.address}`===e.target.value);t&&r({a:t.address,sendDriver:t.driver,b:``})},children:[(0,W.jsx)(`option`,{value:``,disabled:!0,children:`Choose email, WhatsApp or Slack…`}),t.a&&!he.some(e=>e.driver===t.sendDriver&&e.address===t.a)&&(0,W.jsxs)(`option`,{value:`${t.sendDriver}:${t.a}`,disabled:!0,children:[t.sendDriver,`: `,t.a,` (unavailable)`]}),he.map(e=>(0,W.jsxs)(`option`,{value:`${e.driver}:${e.address}`,disabled:!e.canSend,children:[e.driver===`imap`?`Email (SMTP)`:e.driver===`whatsapp`?`WhatsApp`:`Slack`,` · `,e.from||e.address,e.canSend?``:` — sending disabled`]},`${e.driver}:${e.address}`))]})}),_e&&(0,W.jsx)(`p`,{className:`text-xs text-destructive`,role:`status`,children:_e}),(0,W.jsx)(Q,{label:t.sendDriver===`imap`?`Destination email address`:`Destination conversation`,hint:t.sendDriver===`imap`?`The accounting ingestion address; separate multiple recipients with commas.`:t.sendDriver===`slack`?`A configured Slack channel ID or name. The account needs files:write permission.`:`A configured WhatsApp chat ID, e.g. 421…@s.whatsapp.net or …@g.us.`,children:(0,W.jsx)(w,{className:Z,value:t.b,placeholder:t.sendDriver===`imap`?`invoices@accounting-firm.example`:t.sendDriver===`slack`?`C0123456789`:`421…@s.whatsapp.net`,onChange:e=>r({b:e.target.value})})}),t.sendDriver===`imap`&&(0,W.jsx)(Q,{label:`Email subject`,hint:`{{file.name}} inserts the attachment filename.`,children:(0,W.jsx)(w,{className:Z,value:t.sendSubject,onChange:e=>r({sendSubject:e.target.value})})}),(0,W.jsx)(Q,{label:t.sendDriver===`imap`?`Email body (optional)`:`Message / caption (optional)`,hint:`Templates: {{file.name}}, {{doc.data.subject}}, {{doc.data.title}}.`,children:(0,W.jsx)(`textarea`,{className:`min-h-20 w-full rounded-md border bg-background p-3 text-sm`,value:t.sendMessage,onChange:e=>r({sendMessage:e.target.value})})}),(0,W.jsxs)(`div`,{className:`rounded-lg border bg-muted/30 p-3 text-sm`,"aria-label":`File delivery preview`,children:[t.sendSource===`attachments`?`Each matching email attachment`:t.sendSource===`download`?`Each downloaded file`:`The triggering file`,` → `,t.sendDriver===`imap`?`email attachment`:t.sendDriver===`slack`?`Slack file upload`:`WhatsApp document`,` → `,t.b||`choose a destination`]}),(0,W.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`Sends each file in a separate message and keeps the original. Maximum 18 MB per file. Replaying this rule does not resend the same file version to the same destination. Unconfirmed deliveries are recorded for review, not retried automatically.`}),t.sendSource===`document`&&(0,W.jsx)(`p`,{className:`text-xs text-muted-foreground`,children:`For files created by another automation, enable this rule’s option to also run on automation events.`})]}),t.kind===`notify`&&(0,W.jsx)(Q,{label:`Notification`,hint:`Notifies you through your bound channel, or in Canvas. Templates: {{doc.data.subject}}, {{doc.data.from}}, {{doc.data.title}}…`,children:(0,W.jsx)(w,{className:Z,placeholder:`New mail from {{doc.data.from}}: {{doc.data.subject}}`,value:t.a,onChange:e=>r({a:e.target.value})})}),t.kind===`delete`&&(0,W.jsx)(`p`,{className:`text-sm text-muted-foreground`,children:`Removes the item from the Canvas index. Files, blobs and mail on storage backends stay untouched.`}),t.kind===`destroy`&&(0,W.jsx)(`p`,{className:`rounded-lg border border-destructive/40 bg-destructive/5 p-3 text-sm text-destructive`,children:`⚠ Irreversible: deletes the stored bytes too (blobs, workspace files, mail on the server), then removes the item from the index.`}),t.kind===`agent`&&(0,W.jsxs)(`div`,{className:`space-y-3`,children:[(0,W.jsx)(Q,{label:`Agent`,hint:`The agent's slug.`,children:(0,W.jsx)(w,{className:S(Z,`font-mono sm:max-w-xs`),placeholder:`assistant`,value:t.a,onChange:e=>r({a:e.target.value})})}),(0,W.jsx)(Q,{label:`Prompt`,hint:`Templates use indexed fields: {{doc.id}}, {{doc.data.subject}}, {{doc.data.bodyPreview}} (emails), {{doc.data.url}}… Ask the agent to use canvas_doc_get_by_id for full email content. Objects are inserted as JSON.`,children:(0,W.jsx)(`textarea`,{className:`min-h-28 w-full rounded-md border bg-background p-3 text-sm outline-none focus:ring-2 focus:ring-ring`,placeholder:`Read email #{{doc.id}} in full with canvas_doc_get_by_id and summarize it in plain markdown.
|
|
4
|
+
|
|
5
|
+
Subject: {{doc.data.subject}}
|
|
6
|
+
Preview: {{doc.data.bodyPreview}}`,value:t.b,onChange:e=>r({b:e.target.value})})}),u(`reply`)]}),t.kind===`script`&&(0,W.jsxs)(`div`,{className:`space-y-3`,children:[(0,W.jsx)(Q,{label:`Script`,hint:`From the Scripts section of this workspace.`,children:fe.length?(0,W.jsxs)(`select`,{className:S(X,`font-mono sm:max-w-md`),value:t.a,onChange:e=>r({a:e.target.value}),children:[(0,W.jsx)(`option`,{value:``,children:`pick a script…`}),fe.map(e=>(0,W.jsx)(`option`,{value:`scripts/${e}`,children:e},e))]}):(0,W.jsx)(w,{className:S(Z,`font-mono sm:max-w-md`),placeholder:`scripts/my-script.sh`,value:t.a,onChange:e=>r({a:e.target.value})})}),u(`output`)]})]},n)}),(0,W.jsxs)(C,{size:`sm`,variant:`outline`,onClick:()=>L(`actions`,[...k.actions,K(`tag`)]),children:[(0,W.jsx)(u,{className:`mr-1 h-4 w-4`}),` Add another action`]})]}),(0,W.jsxs)(`section`,{className:`space-y-3`,children:[(0,W.jsx)(At,{step:3,title:`Options`}),(0,W.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,W.jsx)($,{checked:k.approval,onChange:e=>L(`approval`,e),label:`Ask me before running`,hint:`Actions are held in the Pending queue for review — approve (optionally amended) or decline — instead of running automatically.`}),(0,W.jsx)($,{checked:k.cascade,onChange:e=>L(`cascade`,e),label:`Also react to items created by automation`,hint:`Off by default so rules, hooks and agents cannot trigger each other in a loop. A server-side depth limit still stops runaway chains.`})]})]}),(0,W.jsxs)(`div`,{className:`flex flex-wrap gap-2 border-t pt-4`,children:[(0,W.jsxs)(C,{className:`h-10 px-5`,onClick:je,disabled:N||se,children:[N?(0,W.jsx)(_,{className:`mr-1.5 h-4 w-4 animate-spin`}):(0,W.jsx)(a,{className:`mr-1.5 h-4 w-4`}),` `,k.id?`Save changes`:`Create rule`]}),(0,W.jsx)(C,{className:`h-10`,variant:`outline`,onClick:()=>{A(null),g?.()},children:`Cancel`})]})]}),R&&(0,W.jsx)(ue,{onClose:()=>z(null),children:(0,W.jsx)(ie,{sizeClassName:`h-full w-[380px] max-w-[90vw] max-md:w-full`,fixedWorkspaceName:e,multiple:R.target!==`storeFolder`&&!(R.target===`condition`&&k?.actions.some(e=>e.kind===`store`)),tabs:R.target===`condition`?[`context`,`directory`,`backends`]:R.target===`storeFolder`?[`backends`]:[`context`,`directory`],title:R.target===`condition`?`Choose source folder…`:R.target===`storeFolder`?`Store files under…`:`File into…`,confirmLabel:R.target===`storeFolder`?`Use folder`:`Use path`,onConfirm:Ue,onClose:()=>z(null)})}),!p&&(se?(0,W.jsx)(`p`,{className:`rounded-xl border p-6 text-center text-sm text-muted-foreground`,children:`Loading…`}):x.length===0?!j&&!k&&(0,W.jsxs)(`div`,{className:`space-y-4`,children:[(0,W.jsxs)(`div`,{className:`rounded-xl border border-dashed p-6 text-center`,children:[(0,W.jsx)(`p`,{className:`text-base font-medium`,children:`No rules yet`}),(0,W.jsx)(`p`,{className:`mt-1 text-sm text-muted-foreground`,children:`Pick a starting point below, or right-click a folder in the tree and choose “Create rule…”.`})]}),U]}):(0,W.jsxs)(`div`,{className:`space-y-6`,children:[qe.length>0&&(0,W.jsxs)(`section`,{className:`space-y-3`,children:[(0,W.jsxs)(`div`,{className:`flex flex-wrap items-baseline gap-x-2 gap-y-1 text-sm text-muted-foreground`,children:[(0,W.jsxs)(`h3`,{className:`flex items-center gap-2 font-semibold uppercase tracking-wide`,children:[(0,W.jsx)(m,{className:`h-4 w-4 shrink-0`}),` Folder & storage rules`]}),(0,W.jsx)(`p`,{children:`Right-click a folder in the tree to add one`})]}),(0,W.jsx)(`div`,{className:`space-y-3`,children:qe.map(e=>(0,W.jsx)(Xe,{rule:e},e.id))})]}),Je.length>0&&(0,W.jsxs)(`section`,{className:`space-y-3`,children:[qe.length>0&&(0,W.jsxs)(`h3`,{className:`flex items-center gap-2 text-sm font-semibold uppercase tracking-wide text-muted-foreground`,children:[(0,W.jsx)(b,{className:`h-4 w-4`}),` Other rules`]}),(0,W.jsx)(`div`,{className:`space-y-3`,children:Je.map(e=>(0,W.jsx)(Xe,{rule:e},e.id))})]})]}))]})}export{z as A,ge as C,k as D,pe as E,he as F,ye as I,De as L,R as M,j as N,Te as O,Pe as P,ke as S,F as T,Ne as _,$e as a,Be as b,We as c,Ie as d,Me as f,Ve as g,M as h,Ze as i,be as j,Ae as k,I as l,xe as m,et as n,Xe as o,Ee as p,Qe as r,Ye as s,Mt as t,Ue as u,Oe as v,Fe as w,Ce as x,A as y};
|