@taskforcehq/taskforce 0.3.304 → 0.3.305
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/README.md +140 -247
- package/dist/TaskforceCore.js +165 -70
- package/dist/TaskforceCore.test.js +799 -90
- package/dist/compat/workspaceSyncCompat.js +6 -0
- package/dist/components/features/DocumentIndex.d.ts +1 -1
- package/dist/components/features/DocumentIndex.js +1 -1
- package/dist/components/features/DocumentViewer.d.ts +1 -1
- package/dist/components/features/DocumentViewer.js +32 -9
- package/dist/components/features/DocumentWorkspace.d.ts +5 -22
- package/dist/components/features/DocumentWorkspace.js +12 -155
- package/dist/components/features/DocumentWorkspace.test.js +193 -6
- package/dist/components/features/TaskSettings.js +29 -3
- package/dist/components/features/TaskSettings.test.js +42 -1
- package/dist/components/features/documentWorkspaceModel.d.ts +24 -0
- package/dist/components/features/documentWorkspaceModel.js +57 -0
- package/dist/components/features/useDocumentWorkspaceController.d.ts +34 -0
- package/dist/components/features/useDocumentWorkspaceController.js +113 -0
- package/dist/components/task/TaskForm.d.ts +8 -8
- package/dist/components/task/TaskForm.js +358 -221
- package/dist/components/task/TaskForm.test.js +456 -381
- package/dist/components/task/TaskKanban.js +2 -1
- package/dist/components/views/PlanComparisonPage.js +5 -8
- package/dist/components/views/PlanComparisonPage.test.js +51 -41
- package/dist/components/views/PlansPage.js +126 -84
- package/dist/components/views/PlansPage.test.js +308 -39
- package/dist/components/views/StandaloneLayout.js +28 -22
- package/dist/components/views/panels/FilterToolbar.test.js +6 -4
- package/dist/components/views/standalone/modals/AccountHubModal.d.ts +2 -14
- package/dist/components/views/standalone/modals/AccountHubModal.js +12 -14
- package/dist/components/views/standalone/modals/AccountHubModal.test.js +24 -1
- package/dist/config/envSchema.js +1 -1
- package/dist/core/AiProfileService.d.ts +6 -1
- package/dist/core/AiProfileService.js +161 -16
- package/dist/core/AiProfileService.test.js +3 -1
- package/dist/core/AiProfiles.test.js +200 -0
- package/dist/core/AuthTokenService.test.d.ts +1 -0
- package/dist/core/AuthTokenService.test.js +78 -0
- package/dist/core/EntitlementsPolicy.test.js +75 -13
- package/dist/core/PlanEntitlementService.d.ts +7 -1
- package/dist/core/PlanEntitlementService.js +117 -42
- package/dist/core/PlanVersionPolicy.test.js +19 -26
- package/dist/core/SignupMonetizationSettings.test.js +46 -21
- package/dist/core/SystemAdmin.test.js +212 -56
- package/dist/core/TaskTaxonomyValidation.test.js +53 -0
- package/dist/core/Taskforce.d.ts +3 -0
- package/dist/core/Taskforce.js +50 -10
- package/dist/core/WorkspacePlanMode.test.js +12 -12
- package/dist/core/shared.d.ts +2 -0
- package/dist/core/shared.js +11 -0
- package/dist/hooks/sync/auth.js +3 -1
- package/dist/hooks/sync/transfers.d.ts +2 -1
- package/dist/hooks/sync/transfers.js +8 -4
- package/dist/hooks/useSyncOrchestrator.d.ts +7 -4
- package/dist/hooks/useSyncOrchestrator.js +75 -7
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +80 -10
- package/dist/hooks/useTaskMutations.d.ts +2 -1
- package/dist/hooks/useTaskMutations.js +12 -1
- package/dist/hooks/useTaskMutations.test.js +30 -1
- package/dist/hooks/useTaskforce.d.ts +5 -2
- package/dist/hooks/useTaskforce.js +17 -5
- package/dist/hooks/useTaskforce.sync-behavior.test.js +78 -0
- package/dist/hooks/useWorkspaceSyncController.d.ts +3 -1
- package/dist/hooks/useWorkspaceSyncController.js +11 -1
- package/dist/hooks/useWorkspaceSyncController.test.js +1 -0
- package/dist/mcp/adminWorkspaceRegistrar.d.ts +2 -0
- package/dist/mcp/adminWorkspaceRegistrar.js +154 -0
- package/dist/mcp/collaborationRegistrar.d.ts +2 -0
- package/dist/mcp/collaborationRegistrar.js +71 -0
- package/dist/mcp/documentAssetRegistrar.d.ts +2 -0
- package/dist/mcp/documentAssetRegistrar.js +346 -0
- package/dist/mcp/runtime.js +2362 -3530
- package/dist/mcp/runtime.test.js +159 -0
- package/dist/mcp/taskPlanningRegistrar.d.ts +2 -0
- package/dist/mcp/taskPlanningRegistrar.js +418 -0
- package/dist/mcp/toolCatalog.d.ts +35 -0
- package/dist/mcp/toolCatalog.js +3 -0
- package/dist/server/routes/admin.d.ts +1 -5
- package/dist/server/routes/admin.js +138 -61
- package/dist/server/routes/annotatedAttachments.d.ts +1 -1
- package/dist/server/routes/annotatedAttachments.js +1 -1
- package/dist/server/routes/auth.d.ts +1 -4
- package/dist/server/routes/auth.js +23 -63
- package/dist/server/routes/authSupport.d.ts +30 -0
- package/dist/server/routes/authSupport.js +81 -0
- package/dist/server/routes/billing.d.ts +1 -1
- package/dist/server/routes/billing.js +104 -188
- package/dist/server/routes/billing.test.js +214 -86
- package/dist/server/routes/documentReviews.d.ts +1 -1
- package/dist/server/routes/documentReviews.js +1 -1
- package/dist/server/routes/documents.d.ts +4 -2
- package/dist/server/routes/documents.js +73 -7
- package/dist/server/routes/primitives.d.ts +11 -0
- package/dist/server/routes/primitives.js +73 -0
- package/dist/server/routes/resources.d.ts +1 -1
- package/dist/server/routes/resources.js +1 -1
- package/dist/server/routes/shared.d.ts +1 -1
- package/dist/server/routes/sync.d.ts +1 -1
- package/dist/server/routes/sync.js +1 -1
- package/dist/server/routes/tasks.d.ts +1 -1
- package/dist/server/routes/tasks.js +1 -1
- package/dist/server/routes/workspaces.d.ts +1 -1
- package/dist/server/routes/workspaces.js +1 -1
- package/dist/server/routes.d.ts +2 -9
- package/dist/server/routes.js +76 -162
- package/dist/server/routes.test.js +672 -30
- package/dist/sync/contentSyncState.js +16 -7
- package/dist/sync/syncApplyHandlers.test.js +2 -0
- package/dist/sync/syncService.d.ts +1 -0
- package/dist/sync/syncService.js +8 -0
- package/dist/sync/syncService.test.js +14 -0
- package/dist/sync/workspaceSyncModel.d.ts +3 -0
- package/dist/sync/workspaceSyncModel.js +12 -3
- package/dist/sync/workspaceSyncModel.test.js +34 -0
- package/dist/sync/workspaceSyncState.d.ts +2 -0
- package/dist/sync/workspaceSyncState.js +1 -0
- package/dist/ui/assets/{AgentsModule-BLWVbuKP.js → AgentsModule-N2MnQBZk.js} +1 -1
- package/dist/ui/assets/{AnnotatedAttachmentWorkspace-BlS-cqnl.js → AnnotatedAttachmentWorkspace-BG6P_GVW.js} +1 -1
- package/dist/ui/assets/DocumentWorkspace-B3nV_Gc5.css +1 -0
- package/dist/ui/assets/DocumentWorkspace-DRbDMwh8.js +252 -0
- package/dist/ui/assets/{InitiativesModule-BjR6iBf9.js → InitiativesModule-Dhm7M8e7.js} +1 -1
- package/dist/ui/assets/PlansPage-Cq0zXj3I.js +1 -0
- package/dist/ui/assets/TaskSettings-ln0aF7xc.js +9 -0
- package/dist/ui/assets/{WorkflowsModule-DnFqdUME.js → WorkflowsModule-BcS4afRn.js} +1 -1
- package/dist/ui/assets/{index-Ii0B0rTO.css → index-C2-OXZV7.css} +1 -1
- package/dist/ui/assets/index-DcSI5F86.js +6 -0
- package/dist/ui/assets/{vendor-icons-I7ZwG1z_.js → vendor-icons-BSUaRwF8.js} +1 -1
- package/dist/ui/index.html +3 -3
- package/dist/utils/commercialLifecyclePresentation.d.ts +19 -0
- package/dist/utils/commercialLifecyclePresentation.js +196 -0
- package/package.json +8 -1
- package/scripts/check-cloud-mcp.mjs +83 -0
- package/scripts/playwright-auth.sh +5 -1
- package/scripts/run-billing-performance-smoke.sh +24 -0
- package/dist/ui/assets/DocumentWorkspace-BH_6DF6x.js +0 -250
- package/dist/ui/assets/DocumentWorkspace-C_8T8oz-.css +0 -1
- package/dist/ui/assets/PlansPage-CSDQ4sLa.js +0 -1
- package/dist/ui/assets/TaskSettings-CEDy34Jo.js +0 -9
- package/dist/ui/assets/index-DXUdtH1B.js +0 -6
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import{j as e,r,s as Wt,R as Oe}from"./vendor-react-CKJs5o3c.js";import{h as Te,t as M,f as I,i as lt,j as ct,k as Gt,m as Ut,R as Kt,n as B,o as dt,q as Jt,s as Vt}from"./index-DcSI5F86.js";import{r as Qt,t as Yt,u as qt,l as Xt,au as Zt,av as We,m as en,Z as Ge,X as yt,aw as ut,e as gt,ax as xt,ay as tn,az as nn,a as sn,i as an,aA as rn,aB as on,aC as ln,aD as Se,aE as cn,s as dn,at as He,aF as un,D as mn,aG as hn,T as fn,R as pn,aH as vn,B as wn,U as yn,S as gn}from"./vendor-icons-BSUaRwF8.js";import{s as xn,M as Ce,r as je}from"./vendor-markdown-BUxTU7dS.js";import"./vendor-dnd-DRzYolkg.js";import"./vendor-router-BbWMxlnO.js";const _n="_index_18mna_1",kn="_header_18mna_8",bn="_title_18mna_17",Sn="_refreshBtn_18mna_26",Cn="_search_18mna_48",jn="_searchIcon_18mna_54",Nn="_searchInput_18mna_63",Tn="_list_18mna_80",En="_state_18mna_89",Rn="_stateError_18mna_97",An="_item_18mna_104",Dn="_itemActive_18mna_124",$n="_itemIcon_18mna_132",Bn="_itemBody_18mna_142",In="_itemTitle_18mna_150",Ln="_itemTask_18mna_162",Pn="_itemBadge_18mna_172",Mn="_itemMeta_18mna_185",zn="_itemMetaDetails_18mna_195",Fn="_itemMetaReference_18mna_202",E={index:_n,header:kn,title:bn,refreshBtn:Sn,search:Cn,searchIcon:jn,searchInput:Nn,list:Tn,state:En,stateError:Rn,item:An,itemActive:Dn,itemIcon:$n,itemBody:Bn,itemTitle:In,itemTask:Ln,itemBadge:Pn,itemMeta:Mn,itemMetaDetails:zn,itemMetaReference:Fn};function Ue(t){let c=t;try{c=decodeURIComponent(t)}catch{c=t}return c.trim().replace(/\\/g,"/").replace(/^\/+/,"").replace(/^\.\//,"").replace(/^\.taskforce\//,"")}function On(t,c){return!!(t===c||t.endsWith(`/${c}`)||c.endsWith(`/${t}`))}function mt(t){const c=Ue(String(t||""));if(!c)return null;const o=c.match(/(^|\/)(asset-[a-f0-9]{32})(?=[^/]*$)/i);return o?.[2]?o[2].toLowerCase():null}function Je(t){return t.attachmentState==="attached"||t.attachmentState==="unattached"?t.attachmentState:(typeof t.attachmentCount=="number"&&Number.isFinite(t.attachmentCount)?t.attachmentCount:0)>0||t.taskId?"attached":"unattached"}function Hn(t,c,o,i){const u=c.trim().toLowerCase();return t.filter(m=>{const y=`${Te(m)} ${m.originalFilename||""}`.toLowerCase(),g=u.length===0||y.includes(u),w=o.length===0||o.includes(m.docType),h=Je(m),_=i.length===0||i.includes(h);return g&&w&&_})}function Wn({docType:t}){switch(t){case"implementation-plan":return e.jsx(en,{size:13});case"review":return e.jsx(We,{size:13});case"walkthrough":return e.jsx(Zt,{size:13});default:return e.jsx(Xt,{size:13})}}function Gn(t){return t<1024?`${t}B`:t<1024*1024?`${(t/1024).toFixed(1)}KB`:`${(t/(1024*1024)).toFixed(1)}MB`}function Un(t){if(!t)return"";const c=new Date(t),i=new Date().getTime()-c.getTime(),u=Math.floor(i/(1e3*60*60*24));return u===0?"Today":u===1?"Yesterday":u<7?`${u}d ago`:u<30?`${Math.floor(u/7)}w ago`:c.toLocaleDateString()}function Kn(t,c){t.key!=="Enter"&&t.key!==" "||(t.preventDefault(),c())}function Jn({documents:t,selectedDocId:c,loading:o,error:i,searchQuery:u,taskById:m,onSearchChange:v,onSelect:y,onRefresh:g,hasActiveFilters:w}){return e.jsxs("div",{className:E.index,children:[e.jsxs("div",{className:E.header,children:[e.jsxs("span",{className:E.title,children:[e.jsx(Qt,{size:14}),"Documents"]}),e.jsx("button",{className:E.refreshBtn,onClick:g,title:"Refresh document list",disabled:o,children:e.jsx(Yt,{size:13,className:o?M.docSpinning:void 0})})]}),e.jsxs("div",{className:E.search,children:[e.jsx(qt,{size:12,className:E.searchIcon}),e.jsx("input",{type:"text",placeholder:"Search documents…",value:u,onChange:h=>v(h.target.value),className:E.searchInput})]}),e.jsxs("div",{className:`${E.list} tf-scrollbar`,children:[o&&e.jsx("div",{className:E.state,children:"Loading documents…"}),!o&&i&&e.jsx("div",{className:E.stateError,children:i}),!o&&!i&&t.length===0&&e.jsx("div",{className:E.state,children:w?"No documents match your filters.":"No documents found. Documents added as task attachments will appear here."}),!o&&t.map(h=>{const _=h.taskId?m.get(h.taskId):null,N=h.id===c,R=Te(h),A=Je(h),z=typeof h.attachmentCount=="number"&&Number.isFinite(h.attachmentCount)?h.attachmentCount:h.taskId?1:0,D=z>1?`${z} tasks linked`:z===1?_?.title||"1 task linked":null;return e.jsxs("div",{role:"button",tabIndex:0,className:`${E.item} ${N?E.itemActive:""}`,onClick:()=>y(h),onKeyDown:L=>Kn(L,()=>y(h)),children:[e.jsx("div",{className:E.itemIcon,children:e.jsx(Wn,{docType:h.docType})}),e.jsxs("div",{className:E.itemBody,children:[e.jsx("span",{className:E.itemTitle,title:R,children:R}),A==="unattached"&&e.jsx("span",{className:E.itemBadge,children:"Unattached"}),D&&e.jsx("span",{className:E.itemTask,title:D,children:D}),e.jsxs("span",{className:E.itemMeta,children:[e.jsxs("span",{className:E.itemMetaDetails,children:[Gn(h.sizeBytes),h.updatedAt&&e.jsxs(e.Fragment,{children:[" · ",Un(h.updatedAt)]})]}),h.referenceLabel&&e.jsx("span",{className:E.itemMetaReference,children:h.referenceLabel})]})]})]},h.id)})]})]})}function Ne(t){return function(c){return xn(c,t)}}const Vn="_viewer_9t0y6_1",Qn="_viewerMonochrome_9t0y6_10",Yn="_metaDocumentName_9t0y6_10",qn="_viewerEditMode_9t0y6_14",Xn="_meta_9t0y6_10",Zn="_metaLeft_9t0y6_30",es="_metaRenameRow_9t0y6_49",ts="_typeBadge_9t0y6_56",ns="_typeBadgeImplementationPlan_9t0y6_71",ss="_typeBadgeReview_9t0y6_77",as="_typeBadgeWalkthrough_9t0y6_83",rs="_metaTaskName_9t0y6_89",is="_statusBadge_9t0y6_98",os="_metaDate_9t0y6_113",ls="_metaSize_9t0y6_114",cs="_actions_9t0y6_122",ds="_actionBtn_9t0y6_129",us="_dangerBtn_9t0y6_156",ms="_generateBtn_9t0y6_167",hs="_editBtn_9t0y6_178",fs="_saveBtn_9t0y6_189",ps="_layoutToggle_9t0y6_205",vs="_layoutBtn_9t0y6_213",ws="_layoutBtnActive_9t0y6_229",ys="_saveStatus_9t0y6_234",gs="_saveStatusSaved_9t0y6_241",xs="_saveStatusError_9t0y6_245",_s="_unsaved_9t0y6_250",ks="_viewerContent_9t0y6_256",bs="_viewerBody_9t0y6_265",Ss="_viewerBodyFullWidth_9t0y6_273",Cs="_viewerMain_9t0y6_277",js="_reviewRail_9t0y6_285",Ns="_printHint_9t0y6_291",Ts="_reviewSection_9t0y6_298",Es="_reviewHeader_9t0y6_307",Rs="_reviewTitle_9t0y6_315",As="_reviewSubtitle_9t0y6_324",Ds="_reviewControls_9t0y6_331",$s="_reviewSelect_9t0y6_338",Bs="_reviewSessionMeta_9t0y6_342",Is="_reviewStatusResolved_9t0y6_350",Ls="_reviewSessionLabel_9t0y6_356",Ps="_reviewTitleEditRow_9t0y6_361",Ms="_reviewSessionTimestamp_9t0y6_368",zs="_reviewAnchorLabel_9t0y6_372",Fs="_reviewComposer_9t0y6_378",Os="_reviewAnchorChip_9t0y6_385",Hs="_reviewAnchorSnippet_9t0y6_398",Ws="_reviewAnchorClear_9t0y6_403",Gs="_reviewCommentActions_9t0y6_416",Us="_reviewCommentAction_9t0y6_416",Ks="_reviewCommentEditor_9t0y6_437",Js="_viewerState_9t0y6_443",Vs="_viewerStateError_9t0y6_450",Qs="_editorArea_9t0y6_457",Ys="_editorPane_9t0y6_464",qs="_editorLayoutSplit_9t0y6_472",Xs="_previewPane_9t0y6_473",Zs="_editorLayoutEditor_9t0y6_477",ea="_editorLayoutPreview_9t0y6_478",ta="_editorPaneLabel_9t0y6_482",na="_editorTextarea_9t0y6_494",sa="_markdownSurface_9t0y6_536",a={viewer:Vn,viewerMonochrome:Qn,metaDocumentName:Yn,viewerEditMode:qn,meta:Xn,metaLeft:Zn,metaRenameRow:es,typeBadge:ts,typeBadgeImplementationPlan:ns,typeBadgeReview:ss,typeBadgeWalkthrough:as,metaTaskName:rs,statusBadge:is,metaDate:os,metaSize:ls,actions:cs,actionBtn:ds,dangerBtn:us,generateBtn:ms,editBtn:hs,saveBtn:fs,layoutToggle:ps,layoutBtn:vs,layoutBtnActive:ws,saveStatus:ys,saveStatusSaved:gs,saveStatusError:xs,unsaved:_s,viewerContent:ks,viewerBody:bs,viewerBodyFullWidth:Ss,viewerMain:Cs,reviewRail:js,printHint:Ns,reviewSection:Ts,reviewHeader:Es,reviewTitle:Rs,reviewSubtitle:As,reviewControls:Ds,reviewSelect:$s,reviewSessionMeta:Bs,reviewStatusResolved:Is,reviewSessionLabel:Ls,reviewTitleEditRow:Ps,reviewSessionTimestamp:Ms,reviewAnchorLabel:zs,reviewComposer:Fs,reviewAnchorChip:Os,reviewAnchorSnippet:Hs,reviewAnchorClear:Ws,reviewCommentActions:Gs,reviewCommentAction:Us,reviewCommentEditor:Ks,viewerState:Js,viewerStateError:Vs,editorArea:Qs,editorPane:Ys,editorLayoutSplit:qs,previewPane:Xs,editorLayoutEditor:Zs,editorLayoutPreview:ea,editorPaneLabel:ta,editorTextarea:na,markdownSurface:sa},aa="_overlay_1unik_1",ra="_modal_1unik_12",ia="_header_1unik_16",oa="_title_1unik_20",la="_docName_1unik_24",ca="_body_1unik_34",da="_state_1unik_41",ua="_stateError_1unik_52",ma="_stateDone_1unik_63",ha="_toolbar_1unik_84",fa="_toolbarCount_1unik_95",pa="_toolbarActions_1unik_100",va="_tree_1unik_105",wa="_taskRow_1unik_113",ya="_taskRowDimmed_1unik_126",ga="_taskCheck_1unik_130",xa="_taskExpandBtn_1unik_139",_a="_taskExpandSpacer_1unik_155",ka="_taskTitle_1unik_160",ba="_taskBadge_1unik_169",Sa="_footer_1unik_179",j={overlay:aa,modal:ra,header:ia,title:oa,docName:la,body:ca,state:da,stateError:ua,stateDone:ma,toolbar:ha,toolbarCount:fa,toolbarActions:pa,tree:va,taskRow:wa,taskRowDimmed:ya,taskCheck:ga,taskExpandBtn:xa,taskExpandSpacer:_a,taskTitle:ka,taskBadge:ba,footer:Sa},Ca={1:"Low",2:"Medium",3:"High"};function ve(t,c){return t.map(o=>({...o,selected:c,children:ve(o.children,c)}))}function _t(t,c,o){return t.map(i=>i.idempotencyKey===c?{...i,selected:o,children:ve(i.children,o)}:{...i,children:_t(i.children,c,o)})}function Ke(t){let c=0;for(const o of t)o.selected&&c++,c+=Ke(o.children);return c}function kt({node:t,depth:c,onToggle:o}){const[i,u]=r.useState(!0),m=t.children.length>0,v=c*20;return e.jsxs("div",{children:[e.jsxs("div",{className:`${j.taskRow} ${t.selected?"":j.taskRowDimmed}`,style:{paddingLeft:`${12+v}px`},children:[e.jsx("button",{className:j.taskCheck,onClick:()=>o(t.idempotencyKey,!t.selected),title:t.selected?"Deselect":"Select",children:t.selected?e.jsx(tn,{size:14,style:{color:"var(--brand-primary-strong)"}}):e.jsx(nn,{size:14,style:{color:"var(--text-muted)"}})}),m?e.jsx("button",{className:j.taskExpandBtn,onClick:()=>u(y=>!y),children:i?e.jsx(sn,{size:12}):e.jsx(an,{size:12})}):e.jsx("span",{className:j.taskExpandSpacer}),e.jsx("span",{className:j.taskTitle,title:t.description||void 0,children:t.title}),e.jsx("span",{className:j.taskBadge,style:{color:lt(t.type),borderColor:lt(t.type)},children:t.type}),e.jsx("span",{className:j.taskBadge,style:{color:ct(t.priority),borderColor:ct(t.priority)},children:Ca[t.priority]})]}),m&&i&&e.jsx("div",{children:t.children.map(y=>e.jsx(kt,{node:y,depth:c+1,onToggle:o},y.idempotencyKey))})]})}function ja({content:t,docTitle:c,apiBaseUrl:o="",onClose:i,onGenerated:u}){const[m,v]=r.useState("preview"),[y,g]=r.useState(null),[w,h]=r.useState([]),[_,N]=r.useState(!0),[R,A]=r.useState(0),[z,D]=r.useState(null);r.useEffect(()=>{let x=!1;return N(!0),g(null),I("/api/taskforce/documents/generate-tasks/preview",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:t})},o).then(S=>S.json()).then(S=>{if(!x){if(S.error)throw new Error(S.error);h(S.tasks||[]),v("preview")}}).catch(S=>{x||(g(S?.message||"Failed to parse plan"),v("error"))}).finally(()=>{x||N(!1)}),()=>{x=!0}},[t,o]);const L=r.useCallback((x,S)=>{h(W=>_t(W,x,S))},[]),K=()=>h(x=>ve(x,!0)),Q=()=>h(x=>ve(x,!1)),J=Ke(w),Y=async()=>{v("generating"),D(null);try{const x=await I("/api/taskforce/documents/generate-tasks/commit",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({tasks:w})},o),S=await x.json().catch(()=>({}));if(!x.ok)throw new Error(S.error||`Generation failed (${x.status})`);A(S.created??0),v("done"),u(S.created??0)}catch(x){D(x?.message||"Generation failed"),v("error")}};return e.jsx("div",{className:j.overlay,onClick:x=>{x.target===x.currentTarget&&i()},children:e.jsxs("div",{className:`tf-surface-modal tf-modal-shell ${j.modal}`,children:[e.jsxs("div",{className:`tf-modal-header ${j.header}`,children:[e.jsxs("div",{className:`tf-modal-title ${j.title}`,children:[e.jsx(Ge,{size:16,style:{color:"var(--brand-primary-strong)"}}),"Generate Tasks from Plan"]}),e.jsx("span",{className:j.docName,children:c}),e.jsx("button",{className:"tf-control-icon",onClick:i,title:"Close",children:e.jsx(yt,{size:16})})]}),e.jsxs("div",{className:j.body,children:[_&&e.jsxs("div",{className:j.state,children:[e.jsx(ut,{size:20,className:M.docSpinning}),"Parsing plan…"]}),!_&&m==="error"&&e.jsxs("div",{className:j.stateError,children:[e.jsx(gt,{size:16}),y||z||"An error occurred"]}),!_&&m==="done"&&e.jsxs("div",{className:j.stateDone,children:[e.jsx(xt,{size:24,style:{color:"var(--status-success)"}}),e.jsxs("strong",{children:[R," task",R!==1?"s":""," created"]}),e.jsx("p",{children:"Tasks are now in your board. Switch to the Kanban or Hierarchy view to see them."})]}),!_&&(m==="preview"||m==="confirm"||m==="generating")&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:j.toolbar,children:[e.jsxs("span",{className:j.toolbarCount,children:[J," of ",Ke(ve(w,!0))," tasks selected"]}),e.jsxs("div",{className:j.toolbarActions,children:[e.jsx("button",{className:"tf-control-icon",onClick:K,children:"Select all"}),e.jsx("button",{className:"tf-control-icon",onClick:Q,children:"Deselect all"})]})]}),w.length===0?e.jsx("div",{className:j.state,children:"No tasks could be parsed from this document. Make sure the document uses ## H2 headings for phases and bullet points for tasks."}):e.jsx("div",{className:`${j.tree} tf-scrollbar`,children:w.map(x=>e.jsx(kt,{node:x,depth:0,onToggle:L},x.idempotencyKey))})]})]}),!_&&m!=="done"&&m!=="error"&&e.jsxs("div",{className:j.footer,children:[e.jsx("button",{className:"tf-button-secondary",onClick:i,children:"Cancel"}),e.jsx("button",{className:"tf-button-primary",onClick:Y,disabled:J===0||m==="generating",children:m==="generating"?e.jsxs(e.Fragment,{children:[e.jsx(ut,{size:13,className:M.docSpinning})," Generating…"]}):e.jsxs(e.Fragment,{children:[e.jsx(Ge,{size:13})," Generate ",J," task",J!==1?"s":""]})})]}),!_&&m==="done"&&e.jsx("div",{className:j.footer,children:e.jsx("button",{className:"tf-button-primary",onClick:i,children:"Done"})})]})})}const Na={"implementation-plan":"Implementation Plan",review:"Review",walkthrough:"Walkthrough",planning:"Planning",other:"Document"},Ta={"implementation-plan":a.typeBadgeImplementationPlan,review:a.typeBadgeReview,walkthrough:a.typeBadgeWalkthrough,planning:void 0,other:void 0},Ea={editor:a.editorLayoutEditor,split:a.editorLayoutSplit,preview:a.editorLayoutPreview},Ra=1500,Aa=`
|
|
2
|
+
@page {
|
|
3
|
+
margin: 0.94in 1.02in 1in;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
html,
|
|
7
|
+
body {
|
|
8
|
+
margin: 0;
|
|
9
|
+
padding: 0;
|
|
10
|
+
background: #fff;
|
|
11
|
+
color: #111;
|
|
12
|
+
-webkit-print-color-adjust: exact;
|
|
13
|
+
print-color-adjust: exact;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
body {
|
|
17
|
+
font: 12.15pt/1.66 Georgia, "Times New Roman", Times, serif;
|
|
18
|
+
letter-spacing: 0;
|
|
19
|
+
text-rendering: optimizeLegibility;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.tf-print-document {
|
|
23
|
+
max-width: 5.95in;
|
|
24
|
+
margin: 0 auto;
|
|
25
|
+
overflow: visible;
|
|
26
|
+
color: #171717;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.tf-print-document > :first-child {
|
|
30
|
+
margin-top: 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.tf-print-document > :last-child {
|
|
34
|
+
margin-bottom: 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.tf-print-document h1,
|
|
38
|
+
.tf-print-document h2,
|
|
39
|
+
.tf-print-document h3,
|
|
40
|
+
.tf-print-document h4 {
|
|
41
|
+
font-family: "Helvetica Neue", "Arial Nova", Arial, sans-serif;
|
|
42
|
+
color: #101010;
|
|
43
|
+
font-weight: 700;
|
|
44
|
+
line-height: 1.08;
|
|
45
|
+
letter-spacing: -0.03em;
|
|
46
|
+
break-after: avoid-page;
|
|
47
|
+
page-break-after: avoid;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.tf-print-document h1 {
|
|
51
|
+
font-size: 32pt;
|
|
52
|
+
font-weight: 800;
|
|
53
|
+
line-height: 0.98;
|
|
54
|
+
letter-spacing: -0.055em;
|
|
55
|
+
margin: 0 0 1.18em;
|
|
56
|
+
padding: 0 0 0.38em;
|
|
57
|
+
border-bottom: 2px solid #d8d8d8;
|
|
58
|
+
max-width: 84%;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.tf-print-document h1 + p,
|
|
62
|
+
.tf-print-document h1 + ul,
|
|
63
|
+
.tf-print-document h1 + ol {
|
|
64
|
+
margin-top: 0.4em;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.tf-print-document h2,
|
|
68
|
+
.tf-print-document h3,
|
|
69
|
+
.tf-print-document h4 {
|
|
70
|
+
margin-bottom: 0.28em;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.tf-print-document h2 {
|
|
74
|
+
font-size: 16.5pt;
|
|
75
|
+
font-weight: 750;
|
|
76
|
+
margin-top: 2.2em;
|
|
77
|
+
padding-bottom: 0.22em;
|
|
78
|
+
border-bottom: 1px solid #dfdfdf;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.tf-print-document h3 {
|
|
82
|
+
font-size: 13.3pt;
|
|
83
|
+
font-weight: 700;
|
|
84
|
+
margin-top: 1.48em;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.tf-print-document h4 {
|
|
88
|
+
font-size: 11.2pt;
|
|
89
|
+
font-weight: 700;
|
|
90
|
+
margin-top: 1.14em;
|
|
91
|
+
text-transform: uppercase;
|
|
92
|
+
letter-spacing: 0.08em;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.tf-print-document p,
|
|
96
|
+
.tf-print-document ul,
|
|
97
|
+
.tf-print-document ol,
|
|
98
|
+
.tf-print-document blockquote,
|
|
99
|
+
.tf-print-document table,
|
|
100
|
+
.tf-print-document pre,
|
|
101
|
+
.tf-print-document hr {
|
|
102
|
+
margin: 0.78em 0;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.tf-print-document ul,
|
|
106
|
+
.tf-print-document ol {
|
|
107
|
+
padding-left: 1.1em;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.tf-print-document li {
|
|
111
|
+
margin: 0.24em 0;
|
|
112
|
+
padding-left: 0.1em;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.tf-print-document li > ul,
|
|
116
|
+
.tf-print-document li > ol {
|
|
117
|
+
margin-top: 0.34em;
|
|
118
|
+
margin-bottom: 0.2em;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.tf-print-document a {
|
|
122
|
+
color: #121212;
|
|
123
|
+
text-decoration: underline;
|
|
124
|
+
text-underline-offset: 2px;
|
|
125
|
+
text-decoration-thickness: 0.65px;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.tf-print-document code {
|
|
129
|
+
font-family: "SFMono-Regular", "SF Mono", Consolas, "Liberation Mono", monospace;
|
|
130
|
+
font-size: 0.78em;
|
|
131
|
+
background: transparent;
|
|
132
|
+
color: #4a4a4a;
|
|
133
|
+
border: 0;
|
|
134
|
+
padding: 0;
|
|
135
|
+
border-radius: 0;
|
|
136
|
+
overflow-wrap: anywhere;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.tf-print-section-label {
|
|
140
|
+
font-family: "Helvetica Neue", "Arial Nova", Arial, sans-serif;
|
|
141
|
+
font-size: 10.7pt;
|
|
142
|
+
font-weight: 700;
|
|
143
|
+
line-height: 1.18;
|
|
144
|
+
letter-spacing: 0.12em;
|
|
145
|
+
text-transform: uppercase;
|
|
146
|
+
color: #191919;
|
|
147
|
+
margin-top: 2.2em;
|
|
148
|
+
margin-bottom: 0.58em;
|
|
149
|
+
padding-bottom: 0;
|
|
150
|
+
border-bottom: 0;
|
|
151
|
+
break-after: avoid-page;
|
|
152
|
+
page-break-after: avoid;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.tf-print-section-label strong {
|
|
156
|
+
font-weight: inherit;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.tf-print-document pre {
|
|
160
|
+
background: #fafafa;
|
|
161
|
+
border: 1px solid #e1e1e1;
|
|
162
|
+
border-radius: 6px;
|
|
163
|
+
padding: 10pt 11pt;
|
|
164
|
+
overflow: visible;
|
|
165
|
+
white-space: pre-wrap;
|
|
166
|
+
word-break: break-word;
|
|
167
|
+
break-inside: avoid-page;
|
|
168
|
+
page-break-inside: avoid;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.tf-print-document pre code {
|
|
172
|
+
background: transparent;
|
|
173
|
+
padding: 0;
|
|
174
|
+
border-radius: 0;
|
|
175
|
+
white-space: inherit;
|
|
176
|
+
word-break: inherit;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.tf-print-document blockquote {
|
|
180
|
+
border-left: 2px solid #9f9f9f;
|
|
181
|
+
color: #434343;
|
|
182
|
+
margin-left: 0;
|
|
183
|
+
padding-left: 9pt;
|
|
184
|
+
font-style: italic;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.tf-print-document table {
|
|
188
|
+
width: 100%;
|
|
189
|
+
border-collapse: collapse;
|
|
190
|
+
table-layout: fixed;
|
|
191
|
+
break-inside: auto;
|
|
192
|
+
page-break-inside: auto;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.tf-print-document thead {
|
|
196
|
+
display: table-header-group;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.tf-print-document tr {
|
|
200
|
+
break-inside: avoid-page;
|
|
201
|
+
page-break-inside: avoid;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.tf-print-document th,
|
|
205
|
+
.tf-print-document td {
|
|
206
|
+
border: 1px solid #dbdbdb;
|
|
207
|
+
padding: 6.5pt 7.5pt;
|
|
208
|
+
text-align: left;
|
|
209
|
+
vertical-align: top;
|
|
210
|
+
word-break: break-word;
|
|
211
|
+
background: #fff;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.tf-print-document th {
|
|
215
|
+
background: #f7f7f7;
|
|
216
|
+
color: #1e1e1e;
|
|
217
|
+
font-size: 9.4pt;
|
|
218
|
+
font-weight: 680;
|
|
219
|
+
letter-spacing: 0.018em;
|
|
220
|
+
text-transform: uppercase;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.tf-print-document hr {
|
|
224
|
+
border: 0;
|
|
225
|
+
border-top: 1px solid #e1e1e1;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.tf-print-document img {
|
|
229
|
+
max-width: 100%;
|
|
230
|
+
height: auto;
|
|
231
|
+
break-inside: avoid-page;
|
|
232
|
+
page-break-inside: avoid;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.tf-print-document input[type="checkbox"] {
|
|
236
|
+
accent-color: #111;
|
|
237
|
+
margin-right: 0.45em;
|
|
238
|
+
}
|
|
239
|
+
`;function Da(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:`${(t/(1024*1024)).toFixed(1)} MB`}function ht(t){return t?new Date(t).toLocaleString():"—"}function $a(){const t=i=>!i||!Array.isArray(i.children)?!1:i.children.some(u=>u?u.type==="element"&&u.tagName==="input"&&u.properties?.type==="checkbox"?!0:t(u):!1),c=i=>!i||!Array.isArray(i.children)?!1:i.children.some(u=>typeof u?.checked=="boolean"?!0:t(u)),o=i=>{const u=Oe.Children.toArray(i).filter(g=>typeof g!="string"?!0:g.trim().length>0);if(u.length!==1)return null;const m=u[0];if(!Oe.isValidElement(m)||m.type!=="strong")return null;const v=m.props,y=Oe.Children.toArray(v.children).join("").trim();return y||null};return{input({type:i,checked:u,...m}){return i!=="checkbox"?e.jsx("input",{type:i,checked:u,...m}):e.jsx("input",{...m,type:"checkbox",checked:!!u,disabled:!0,readOnly:!0})},ul({children:i,node:u,...m}){const v=c(u);return e.jsx("ul",{...m,style:v?{paddingLeft:"1.2em"}:void 0,children:i})},ol({children:i,node:u,...m}){const v=c(u);return e.jsx("ol",{...m,style:v?{paddingLeft:"1.2em"}:void 0,children:i})},li({children:i,node:u,...m}){const v=typeof u?.checked=="boolean"||t(u);return e.jsx("li",{...m,style:v?{listStyleType:"none",listStyle:"none",marginLeft:0}:void 0,children:i})},p({children:i,...u}){const m=o(i);return m?e.jsx("p",{...u,className:"tf-print-section-label",children:m}):e.jsx("p",{...u,children:i})}}}function Ba(t){const c=Wt.renderToStaticMarkup(e.jsx("div",{className:"tf-print-document",children:e.jsx(Ce,{remarkPlugins:[je],rehypePlugins:[Ne],components:$a(),children:t})}));return`<!doctype html>
|
|
240
|
+
<html lang="en">
|
|
241
|
+
<head>
|
|
242
|
+
<meta charset="utf-8" />
|
|
243
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
244
|
+
<title>Taskforce print document</title>
|
|
245
|
+
<style>${Aa}</style>
|
|
246
|
+
</head>
|
|
247
|
+
<body>${c}</body>
|
|
248
|
+
</html>`}async function Ia(t,c){try{await c.fonts?.ready}catch{}await new Promise(o=>{const i=t.requestAnimationFrame?.bind(t)??(u=>window.setTimeout(()=>u(0),0));i(()=>i(()=>o()))})}function La(t){return window.setTimeout(t,Ra)}function ft(t){try{return new Date(t).toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return t}}function pt(t){return t?t.kind==="document"?"Entire document":t.kind==="quote"?t.quote?`Quote: "${t.quote}"`:"Quoted text":t.kind==="line-range"?t.startLine===t.endLine?`Line ${t.startLine}`:`Lines ${t.startLine}-${t.endLine}`:null:null}function Pa(t){return t.authorActor?.label?t.authorActor.label:t.authorActorId==="user"||t.authorActorId==="human"?"You":t.authorActorId?t.authorActorId:"Reviewer"}function vt(t){return t.replace(/\s+/g," ").trim()}function Ma(t,c){if(!c)return 0;let o=0,i=0;for(;i>=0&&(i=t.indexOf(c,i),!(i<0));)o+=1,i+=c.length;return o}function za(t,c,o){const i=document.createTreeWalker(t,NodeFilter.SHOW_TEXT);let u=i.nextNode(),m=0;for(;u;){const v=u.textContent||"";if(u===c)return m+Math.max(0,Math.min(o,v.length));m+=v.length,u=i.nextNode()}return null}function Fa(t,c,o){const i=o.replace(/\s+/g," ").trim();if(!i)return null;const u=t.textContent||"",m=vt(u),v=[];let y=m.indexOf(i);for(;y>=0;)v.push(y),y=m.indexOf(i,y+i.length);let g=null;const w=za(t,c.startContainer,c.startOffset);if(w!==null){const A=vt(u.slice(0,w));g=Ma(A,i)}const h=g!==null&&g>=0&&g<v.length?g:v.length===1?0:null,_=h!==null?v[h]:v[0]??-1;if(_<0)return{kind:"quote",quote:i,occurrenceIndex:g};const N=m.slice(Math.max(0,_-40),_).trim()||null,R=m.slice(_+i.length,_+i.length+40).trim()||null;return{kind:"quote",quote:i,occurrenceIndex:h,prefix:N,suffix:R}}function Oa(t,c,o){if(c<0)return t;const i=t.split(`
|
|
249
|
+
`);let u=-1;const m=/^(\s*(?:[-*+]|\d+\.)\s+)\[( |x|X)\](.*)$/,v=o?"x":" ";return i.map(g=>{const w=g.match(m);return!w||(u+=1,u!==c)?g:`${w[1]}[${v}]${w[3]}`}).join(`
|
|
250
|
+
`)}function Ha({doc:t,taskTitle:c,apiBaseUrl:o="",onSaved:i,onDeleted:u,enableTaskGeneration:m=!1}){const v=Te(t),[y,g]=r.useState(v),w=y,h=Gt({...t,displayName:y}),_=Ut(t),[N,R]=r.useState(null),[A,z]=r.useState(!1),[D,L]=r.useState(null),[K,Q]=r.useState(!1),[J,Y]=r.useState(!1),[x,S]=r.useState([]),[W,ne]=r.useState(!1),[se,$]=r.useState(null),[Ee,F]=r.useState(null),[V,q]=r.useState(""),[C,P]=r.useState(!1),[k,G]=r.useState(null),[Z,ee]=r.useState(!1),[oe,Re]=r.useState(""),[le,fe]=r.useState(null),[we,ce]=r.useState(""),[ae,bt]=r.useState(!0),[T,ye]=r.useState(!1),[O,de]=r.useState(""),[H,Ae]=r.useState("split"),[X,U]=r.useState({type:"idle"}),[St,De]=r.useState(!1),[Ve,Ct]=r.useState(!1),[ge,Qe]=r.useState(!1),[xe,re]=r.useState(!1),[$e,ue]=r.useState(w),me=t.editable!==!1,pe=Je(t),jt=!!t.assetId,Be=T&&O!==(N??""),Ie=r.useRef(null),Le=r.useRef(null),Ye=r.useRef(null),he=r.useRef(null),_e=r.useRef(null),qe=r.useRef(null),Xe=r.useRef(null),p=x.find(n=>n.id===Ee)||x[0]||null,Ze=r.useCallback(async()=>{z(!0),L(null),R(null);try{const n=await I(t.apiUrl,{credentials:"same-origin"},o);if(!n.ok)throw new Error(`Failed to load document (${n.status})`);const s=await n.text();R(s),de(s)}catch(n){L(n?.message||"Failed to load document")}finally{z(!1)}},[o,t.apiUrl]),ke=r.useCallback(async n=>{if(!t.assetId){S([]),F(null),$(null);return}const s=n?.silent===!0;s||(ne(!0),$(null));try{const l=await I(`/api/taskforce/document-reviews/sessions?assetId=${encodeURIComponent(t.assetId)}`,{credentials:"include"},o),d=await l.json().catch(()=>({}));if(!l.ok)throw new Error(d.error||`Failed to load reviews (${l.status})`);const f=Array.isArray(d.sessions)?d.sessions:[];S(f),F(b=>b&&f.some(te=>te.id===b)?b:f[0]?.id??null)}catch(l){s||($(l?.message||"Failed to load reviews"),S([]),F(null))}finally{s||ne(!1)}},[o,t.assetId]),Pe=r.useCallback(async()=>{if(!t.assetId||C)return null;P(!0),$(null);try{const n=await I("/api/taskforce/document-reviews/sessions",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({assetId:t.assetId,title:`Review ${x.length+1}`})},o),s=await n.json().catch(()=>({}));if(!n.ok)throw new Error(s.error||`Failed to create review (${n.status})`);const l=s.session||null;if(!l)throw new Error("Review session payload missing.");return S(d=>[l,...d.filter(f=>f.id!==l.id)]),F(l.id),l}catch(n){return $(n?.message||"Failed to create review"),null}finally{P(!1)}},[o,t.assetId,C,x.length]);r.useEffect(()=>{Ze(),ke(),ye(!1),U({type:"idle"}),re(!1);const n=Te(t);g(n),ue(n),Q(!1),Y(!1),q(""),G(null),ee(!1),Re(""),fe(null),ce("")},[t,Ze,ke]),r.useEffect(()=>{if(!p)return;const n=qe.current;typeof n?.scrollIntoView=="function"&&n.scrollIntoView({block:"end"})},[p?.comments.length,p?.id]),r.useEffect(()=>{Re(p?.title?.trim()||""),ee(!1)},[p?.id,p?.title]),r.useEffect(()=>{xe&&window.setTimeout(()=>{Le.current?.focus(),Le.current?.select()},0)},[xe]),r.useEffect(()=>{if(!t.assetId||T)return;const n=()=>{document.visibilityState==="visible"&&ke({silent:!0})},s=window.setInterval(n,15e3);return window.addEventListener("focus",n),document.addEventListener("visibilitychange",n),()=>{window.clearInterval(s),window.removeEventListener("focus",n),document.removeEventListener("visibilitychange",n)}},[t.assetId,T,ke]),r.useEffect(()=>{if(!T)return;const n=s=>{(s.metaKey||s.ctrlKey)&&s.key==="s"&&(s.preventDefault(),et())};return window.addEventListener("keydown",n),()=>window.removeEventListener("keydown",n)},[T,O]);const ie=r.useCallback(()=>{_e.current!==null&&(window.clearTimeout(_e.current),_e.current=null),he.current&&(he.current.remove(),he.current=null)},[]);r.useEffect(()=>()=>{ie()},[ie]);const be=r.useCallback(n=>{if(!T||H!=="split")return;const s=Ie.current,l=Ye.current;if(!s||!l)return;const d=n==="editor"?s:l,f=n==="editor"?l:s,b=Math.max(d.scrollHeight-d.clientHeight,0),te=Math.max(f.scrollHeight-f.clientHeight,0),Fe=b<=0?0:d.scrollTop/b,ot=te*Fe;Math.abs(f.scrollTop-ot)<=1||(f.scrollTop=ot)},[T,H]);r.useEffect(()=>{!T||H!=="split"||be("editor")},[O,T,H,be]);const Nt=()=>{me&&(de(N??""),U({type:"idle"}),ye(!0),setTimeout(()=>Ie.current?.focus(),50))},Tt=()=>{Be&&!window.confirm("Discard unsaved changes?")||(ye(!1),de(N??""),U({type:"idle"}))},et=r.useCallback(async()=>{if(me&&X.type!=="saving"){U({type:"saving"});try{const n=await I("/api/taskforce/documents/save",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({fsPath:t.fsPath,content:O})},o),s=await n.json().catch(()=>({}));if(!n.ok)throw new Error(s.error||`Save failed (${n.status})`);const l=s.updatedAt||new Date().toISOString();R(O),U({type:"saved",savedAt:l}),i?.(l),ye(!1)}catch(n){U({type:"error",message:n?.message||"Save failed"})}}},[o,t.fsPath,O,X.type,i,me]),Et=r.useCallback(()=>{const n=T?O:N??"";if(!n.trim())return;ie();const s=document.createElement("iframe");s.setAttribute("aria-hidden","true"),s.tabIndex=-1,s.style.position="fixed",s.style.right="0",s.style.bottom="0",s.style.width="0",s.style.height="0",s.style.border="0",s.style.opacity="0",s.style.pointerEvents="none",document.body.appendChild(s),he.current=s;const l=s.contentWindow,d=s.contentDocument;if(!l||!d){ie();return}d.open(),d.write(Ba(n)),d.close();let f=!1;const b=async()=>{f||he.current!==s||(f=!0,await Ia(l,d),he.current===s&&(l.focus(),l.print(),_e.current=La(ie)))};l.addEventListener("afterprint",ie,{once:!0}),b()},[ie,N,O,T]),Rt=async()=>{const n=t.apiUrl,s=new URL(dt(n,o),window.location.origin).toString();try{await navigator.clipboard.writeText(s)}catch{const l=document.createElement("textarea");l.value=s,document.body.appendChild(l),l.select(),document.execCommand("copy"),document.body.removeChild(l)}Q(!0),setTimeout(()=>Q(!1),2e3)},At=r.useCallback(async()=>{if(_){try{await navigator.clipboard.writeText(_)}catch{const n=document.createElement("textarea");n.value=_,document.body.appendChild(n),n.select(),document.execCommand("copy"),document.body.removeChild(n)}Y(!0),setTimeout(()=>Y(!1),2e3)}},[_]),Dt=()=>{const n=t.apiUrl.includes("?")?"&":"?",s=dt(`${t.apiUrl}${n}download=1&filename=${encodeURIComponent(h)}`,o),l=document.createElement("a");l.href=s,l.click()},Me=r.useCallback(async()=>{if(!t.assetId)return;const n=$e.trim();if(!n){ue(w),re(!1);return}if(n===w){re(!1);return}const s=await I(`/api/taskforce/documents/${encodeURIComponent(t.assetId)}`,{method:"PATCH",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({displayName:n})},o),l=await s.json().catch(()=>({}));if(!s.ok){window.alert(l.error||`Rename failed (${s.status})`);return}g(n),ue(n),re(!1),i?.(l.updatedAt||new Date().toISOString())},[o,t.assetId,i,w,$e]),$t=r.useCallback(n=>{if(n.key==="Enter"){n.preventDefault(),Me();return}n.key==="Escape"&&(n.preventDefault(),ue(w),re(!1))},[Me,w]),Bt=r.useCallback(async()=>{if(!t.assetId||ge)return;const n=pe==="attached",s=Math.max(0,Number(t.attachmentCount||0)),l=n?`Delete "${w}" everywhere?
|
|
251
|
+
|
|
252
|
+
This will remove it from ${s} linked task${s===1?"":"s"} and soft-delete the document across sync.`:`Permanently delete "${w}" from storage?`;if(window.confirm(l)){Qe(!0);try{const d=await I(`/api/taskforce/documents/${encodeURIComponent(t.assetId)}`,{method:"DELETE",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify(n?{forceDetach:!0}:{})},o),f=await d.json().catch(()=>({}));if(!d.ok)throw new Error(f.error||`Delete failed (${d.status})`);u?.()}catch(d){window.alert(d?.message||"Delete failed")}finally{Qe(!1)}}},[o,pe,ge,t.assetId,t.attachmentCount,u,w]),It=r.useCallback(async()=>{if(!(!p||C)){P(!0),$(null);try{const n=p.status==="resolved"?"open":"resolved",s=await I(`/api/taskforce/document-reviews/sessions/${encodeURIComponent(p.id)}`,{method:"PATCH",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({status:n})},o),l=await s.json().catch(()=>({}));if(!s.ok)throw new Error(l.error||`Failed to update review (${s.status})`);const d=l.session||null;if(!d)throw new Error("Review session payload missing.");S(f=>f.map(b=>b.id===d.id?d:b))}catch(n){$(n?.message||"Failed to update review")}finally{P(!1)}}},[p,o,C]),Lt=r.useCallback(async()=>{if(!p||C)return;const n=oe.trim();P(!0),$(null);try{const s=await I(`/api/taskforce/document-reviews/sessions/${encodeURIComponent(p.id)}`,{method:"PATCH",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:n||null})},o),l=await s.json().catch(()=>({}));if(!s.ok)throw new Error(l.error||`Failed to update review (${s.status})`);const d=l.session||null;if(!d)throw new Error("Review session payload missing.");S(f=>f.map(b=>b.id===d.id?d:b)),ee(!1)}catch(s){$(s?.message||"Failed to update review")}finally{P(!1)}},[p,o,C,oe]),tt=T?O:N??"",Pt=r.useCallback(()=>{if(T||!ae)return;const n=typeof window.getSelection=="function"?window.getSelection():null,s=n?.toString().replace(/\s+/g," ").trim()||"";if(!n||!s)return;const l=n.rangeCount>0?n.getRangeAt(0):null,d=Xe.current;if(!l||!d)return;const f=l.commonAncestorContainer,b=f.nodeType===Node.TEXT_NODE?f.parentNode:f;if(!(b instanceof Node)||!d.contains(b))return;const te=Fa(d,l,s);te&&G(te)},[T,ae]),Mt=r.useCallback(()=>{bt(n=>{const s=!n;return s||G(null),s})},[]),nt=r.useCallback(async()=>{const n=V.trim();if(!n||C)return;let s=p;if(s||(s=await Pe()),!!s){P(!0),$(null);try{const l=await I(`/api/taskforce/document-reviews/sessions/${encodeURIComponent(s.id)}/comments`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({body:n,anchor:k||{kind:"document"}})},o),d=await l.json().catch(()=>({}));if(!l.ok)throw new Error(d.error||`Failed to add comment (${l.status})`);const f=d.session||null;if(!f)throw new Error("Review session payload missing.");S(b=>{const te=b.filter(Fe=>Fe.id!==f.id);return[f,...te]}),F(f.id),q(""),G(null)}catch(l){$(l?.message||"Failed to add comment")}finally{P(!1)}}},[p,o,Pe,k,C,V]),zt=r.useCallback((n,s)=>{fe(n),ce(s)},[]),Ft=r.useCallback(async()=>{if(!p||!le||C)return;const n=we.trim();if(n){P(!0),$(null);try{const s=await I(`/api/taskforce/document-reviews/sessions/${encodeURIComponent(p.id)}/comments/${encodeURIComponent(le)}`,{method:"PATCH",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({body:n})},o),l=await s.json().catch(()=>({}));if(!s.ok)throw new Error(l.error||`Failed to update comment (${s.status})`);const d=l.session||null;if(!d)throw new Error("Review session payload missing.");S(f=>f.map(b=>b.id===d.id?d:b)),fe(null),ce("")}catch(s){$(s?.message||"Failed to update comment")}finally{P(!1)}}},[p,o,we,le,C]),Ot=r.useCallback(async n=>{if(!(!p||C)&&window.confirm("Delete this review comment?")){P(!0),$(null);try{const s=await I(`/api/taskforce/document-reviews/sessions/${encodeURIComponent(p.id)}/comments/${encodeURIComponent(n)}`,{method:"DELETE",credentials:"include"},o),l=await s.json().catch(()=>({}));if(!s.ok)throw new Error(l.error||`Failed to delete comment (${s.status})`);const d=l.session||null;if(!d)throw new Error("Review session payload missing.");S(f=>f.map(b=>b.id===d.id?d:b)),le===n&&(fe(null),ce(""))}catch(s){$(s?.message||"Failed to delete comment")}finally{P(!1)}}},[p,o,le,C]),st=r.useCallback(async n=>{if(!me)return!1;U({type:"saving"});try{const s=await I("/api/taskforce/documents/save",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({fsPath:t.fsPath,content:n})},o),l=await s.json().catch(()=>({}));if(!s.ok)throw new Error(l.error||`Save failed (${s.status})`);const d=l.updatedAt||new Date().toISOString();return R(n),de(n),U({type:"saved",savedAt:d}),i?.(d),!0}catch(s){return U({type:"error",message:s?.message||"Save failed"}),!1}},[o,t.fsPath,i,me]),Ht=r.useCallback((n,s)=>{const l=T?O:N??"",d=Oa(l,n,s);if(d!==l){if(T){de(d),U(f=>f.type==="saving"?f:{type:"idle"});return}st(d)}},[N,O,T,st]);let at=-1;const ze=n=>!n||!Array.isArray(n.children)?!1:n.children.some(s=>s?s.type==="element"&&s.tagName==="input"&&s.properties?.type==="checkbox"?!0:ze(s):!1),rt=n=>!n||!Array.isArray(n.children)?!1:n.children.some(s=>typeof s?.checked=="boolean"?!0:ze(s)),it={input({type:n,checked:s,...l}){if(n!=="checkbox")return e.jsx("input",{type:n,checked:s,...l});at+=1;const d=at;return e.jsx("input",{...l,type:"checkbox",checked:!!s,disabled:!1,onClick:f=>f.stopPropagation(),onChange:f=>Ht(d,f.currentTarget.checked)})},ul({children:n,node:s,...l}){const d=rt(s);return e.jsx("ul",{...l,style:d?{paddingLeft:"1.25em"}:void 0,"data-task-list":d?"true":void 0,children:n})},ol({children:n,node:s,...l}){const d=rt(s);return e.jsx("ol",{...l,style:d?{paddingLeft:"1.25em"}:void 0,"data-task-list":d?"true":void 0,children:n})},li({children:n,node:s,...l}){const d=typeof s?.checked=="boolean"||ze(s);return e.jsx("li",{...l,style:d?{listStyleType:"none",listStyle:"none",marginLeft:0}:void 0,"data-task-item":d?"true":void 0,children:n})}};return e.jsxs("div",{className:`${a.viewer} ${T?a.viewerEditMode:""} ${Ve?a.viewerMonochrome:""}`,children:[e.jsxs("div",{className:a.meta,children:[e.jsxs("div",{className:a.metaLeft,children:[e.jsxs("span",{className:`${a.typeBadge} ${Ta[t.docType]??""}`,children:[e.jsx(rn,{size:10}),Na[t.docType]]}),xe?e.jsx("div",{className:a.metaRenameRow,children:e.jsx("input",{ref:Le,type:"text",className:M.input,value:$e,onChange:n=>ue(n.target.value),onBlur:()=>{Me()},onKeyDown:$t})}):e.jsx("span",{className:a.metaDocumentName,title:w,onDoubleClick:()=>{t.assetId&&(ue(w),re(!0))},children:w}),c&&e.jsx("span",{className:a.metaTaskName,title:`From task: ${c}`,children:c}),pe==="unattached"&&e.jsx("span",{className:a.statusBadge,children:"Unattached"}),t.updatedAt&&e.jsxs("span",{className:a.metaDate,title:ht(t.updatedAt),children:[e.jsx(on,{size:11}),ht(t.updatedAt)]}),e.jsxs("span",{className:a.metaSize,children:[e.jsx(ln,{size:11}),Da(t.sizeBytes)]}),_&&e.jsx(Kt,{label:_,copied:J,onClick:()=>{At()},title:"Copy document reference"}),X.type==="saved"&&e.jsxs("span",{className:`${a.saveStatus} ${a.saveStatusSaved}`,children:[e.jsx(xt,{size:11}),"Saved"]}),X.type==="error"&&e.jsxs("span",{className:`${a.saveStatus} ${a.saveStatusError}`,title:X.message,children:[e.jsx(gt,{size:11}),X.message||"Save failed"]}),Be&&X.type!=="saving"&&e.jsx("span",{className:a.unsaved,children:"Unsaved changes"})]}),e.jsx("div",{className:a.actions,children:T?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:a.layoutToggle,children:[e.jsx("button",{className:`${a.layoutBtn} ${H==="editor"?a.layoutBtnActive:""}`,onClick:()=>Ae("editor"),title:"Editor only",children:e.jsx(Se,{size:12})}),e.jsx("button",{className:`${a.layoutBtn} ${H==="split"?a.layoutBtnActive:""}`,onClick:()=>Ae("split"),title:"Split view",children:e.jsx(cn,{size:12})}),e.jsx("button",{className:`${a.layoutBtn} ${H==="preview"?a.layoutBtnActive:""}`,onClick:()=>Ae("preview"),title:"Preview only",children:e.jsx(We,{size:12})})]}),e.jsxs("button",{className:a.actionBtn,onClick:Tt,title:"Discard changes",children:[e.jsx(yt,{size:13}),"Cancel"]}),e.jsxs("button",{className:`${a.actionBtn} ${a.saveBtn}`,onClick:et,disabled:X.type==="saving"||!Be,title:"Save (Ctrl+S)",children:[e.jsx(dn,{size:13}),X.type==="saving"?"Saving…":"Save"]})]}):e.jsxs(e.Fragment,{children:[t.assetId&&e.jsxs("button",{className:a.actionBtn,onClick:()=>re(n=>!n),title:"Rename document",children:[e.jsx(Se,{size:13}),xe?"Close Rename":"Rename"]}),me&&e.jsxs("button",{className:`${a.actionBtn} ${a.editBtn}`,onClick:Nt,title:"Edit document",children:[e.jsx(Se,{size:13}),"Edit"]}),e.jsxs("button",{className:a.actionBtn,onClick:Mt,title:ae?"Hide review and comments":"Show review and comments",children:[e.jsx(He,{size:13}),ae?"Hide Review":"Show Review"]}),e.jsxs("button",{className:a.actionBtn,onClick:Rt,title:"Copy link",children:[e.jsx(un,{size:13}),K?"Copied!":"Copy link"]}),e.jsxs("button",{className:a.actionBtn,onClick:Dt,title:"Download .md",children:[e.jsx(mn,{size:13}),"Download"]}),e.jsxs("button",{className:a.actionBtn,onClick:Et,title:"Print",children:[e.jsx(hn,{size:13}),"Print"]}),e.jsxs("button",{className:a.actionBtn,onClick:()=>Ct(n=>!n),title:"Toggle black and white style",children:[e.jsx(We,{size:13}),Ve?"Color":"B/W"]}),m&&t.docType==="implementation-plan"&&!T&&e.jsxs("button",{className:`${a.actionBtn} ${a.generateBtn}`,onClick:()=>De(!0),title:"Generate tasks from this plan",children:[e.jsx(Ge,{size:13}),"Generate Tasks"]}),jt&&e.jsxs("button",{className:`${a.actionBtn} ${a.dangerBtn}`,onClick:()=>{Bt()},disabled:ge,title:pe==="attached"?"Remove this document from linked tasks and delete it":"Permanently delete this unattached document",children:[e.jsx(fn,{size:13}),ge?"Deleting…":pe==="attached"?"Delete & Unlink":"Delete Permanently"]})]})})]}),A&&e.jsx("div",{className:a.viewerState,children:"Loading…"}),!A&&D&&e.jsx("div",{className:a.viewerStateError,children:D}),!A&&!D&&(T?e.jsxs("div",{className:`${a.editorArea} ${Ea[H]}`,children:[(H==="editor"||H==="split")&&e.jsxs("div",{className:a.editorPane,children:[e.jsx("div",{className:a.editorPaneLabel,children:"Markdown"}),e.jsx("textarea",{ref:Ie,className:`${a.editorTextarea} tf-scrollbar`,value:O,onScroll:()=>be("editor"),onChange:n=>{de(n.target.value),U(s=>s.type==="saving"?s:{type:"idle"})},spellCheck:!0,placeholder:"Write markdown here…"})]}),(H==="preview"||H==="split")&&e.jsxs("div",{className:a.previewPane,children:[e.jsx("div",{className:a.editorPaneLabel,children:"Preview"}),e.jsx("div",{ref:Ye,className:`${M.docMarkdown} ${a.markdownSurface}`,"data-testid":"doc-preview-scroll",onScroll:()=>be("preview"),children:e.jsx(Ce,{remarkPlugins:[je],rehypePlugins:[Ne],components:it,children:tt})})]})]}):e.jsxs("div",{className:`${a.viewerBody} ${ae?"":a.viewerBodyFullWidth}`,children:[e.jsx("div",{className:`${a.viewerContent} ${a.viewerMain} tf-scrollbar`,children:e.jsx("div",{ref:Xe,className:`${M.docMarkdown} ${a.markdownSurface}`,onMouseUp:ae?Pt:void 0,children:e.jsx(Ce,{remarkPlugins:[je],rehypePlugins:[Ne],components:it,children:tt})})}),ae&&e.jsx("aside",{className:a.reviewRail,children:e.jsxs("section",{className:a.reviewSection,"aria-label":"Review and comments",children:[e.jsxs("div",{className:a.reviewHeader,children:[e.jsxs("div",{children:[e.jsxs("div",{className:a.reviewTitle,children:[e.jsx(He,{size:14}),"Review & Comments"]}),e.jsx("p",{className:a.reviewSubtitle,children:"Comments stay attached to this document review session."})]}),e.jsxs("div",{className:a.reviewControls,children:[x.length>1&&e.jsx("select",{className:`${M.select} ${a.reviewSelect}`,value:p?.id||"",onChange:n=>F(n.target.value||null),"aria-label":"Select review session",children:x.map(n=>e.jsx("option",{value:n.id,children:n.title?.trim()||"Untitled review"},n.id))}),e.jsxs("button",{type:"button",className:a.actionBtn,onClick:()=>{Pe()},disabled:C||!t.assetId,children:[e.jsx(He,{size:13}),"Start Review"]}),p&&e.jsxs("button",{type:"button",className:a.actionBtn,onClick:()=>{It()},disabled:C,children:[p.status==="resolved"?e.jsx(pn,{size:13}):e.jsx(vn,{size:13}),p.status==="resolved"?"Reopen":"Resolve"]})]})]}),p&&e.jsxs("div",{className:a.reviewSessionMeta,children:[e.jsx("span",{className:`${a.statusBadge} ${p.status==="resolved"?a.reviewStatusResolved:""}`,children:p.status==="resolved"?"Resolved":"Open"}),Z?e.jsxs("div",{className:a.reviewTitleEditRow,children:[e.jsx("input",{type:"text",className:M.input,value:oe,onChange:n=>Re(n.target.value),placeholder:"Untitled review"}),e.jsx("button",{type:"button",className:M.secondaryHeaderBtn,onClick:()=>{Lt()},disabled:C,children:"Save Title"})]}):e.jsx("span",{className:a.reviewSessionLabel,children:p.title?.trim()||"Untitled review"}),e.jsxs("span",{className:a.reviewSessionTimestamp,children:["Updated ",ft(p.updatedAt)]}),!Z&&e.jsxs("button",{type:"button",className:a.actionBtn,onClick:()=>ee(!0),disabled:C,children:[e.jsx(Se,{size:13}),"Rename Review"]})]}),se&&e.jsx("div",{className:a.viewerStateError,children:se}),e.jsxs("div",{className:B.commentPanel,children:[e.jsxs("div",{className:B.commentThread,children:[W&&e.jsx("div",{className:B.emptyComments,children:"Loading review comments…"}),!W&&!p&&e.jsx("div",{className:B.emptyComments,children:"Start a review to collect comments for this document."}),!W&&p&&p.comments.length===0&&e.jsx("div",{className:B.emptyComments,children:"No comments yet. Add the first review note for this document."}),!W&&p&&p.comments.map(n=>{const s=n.authorActor?.kind==="ai",l=pt(n.anchor),d=s?wn:yn,f=le===n.id;return e.jsxs("div",{className:`${B.comment} ${s?B.commentAi:B.commentUser}`,children:[e.jsxs("div",{className:B.commentHeader,children:[e.jsxs("span",{className:B.commentAuthor,style:n.authorActor?.color?{color:n.authorActor.color}:void 0,children:[e.jsx(d,{size:12,strokeWidth:1.5}),Pa(n)]}),e.jsx("span",{className:B.commentTime,children:ft(n.updatedAt)}),e.jsxs("span",{className:a.reviewCommentActions,children:[!f&&e.jsx("button",{type:"button",className:a.reviewCommentAction,onClick:()=>zt(n.id,n.body),disabled:C,children:"Edit"}),f&&e.jsx("button",{type:"button",className:a.reviewCommentAction,onClick:()=>{fe(null),ce("")},disabled:C,children:"Cancel"}),e.jsx("button",{type:"button",className:a.reviewCommentAction,onClick:()=>{Ot(n.id)},disabled:C,children:"Delete"})]})]}),l&&e.jsx("span",{className:a.reviewAnchorLabel,children:l}),e.jsx("div",{className:B.commentText,children:f?e.jsxs("div",{className:a.reviewCommentEditor,children:[e.jsx("textarea",{className:B.commentInput,value:we,onChange:b=>ce(b.target.value),disabled:C}),e.jsx("button",{type:"button",className:M.secondaryHeaderBtn,onClick:()=>{Ft()},disabled:C||!we.trim(),children:"Save Comment"})]}):e.jsx(Ce,{remarkPlugins:[je],rehypePlugins:[Ne],children:n.body})})]},n.id)}),e.jsx("div",{ref:qe})]}),e.jsxs("div",{className:B.commentInputArea,children:[e.jsxs("div",{className:a.reviewComposer,children:[k&&e.jsxs("div",{className:a.reviewAnchorChip,children:[e.jsx("span",{children:pt(k)||"Selected text"}),"quote"in k&&k.quote&&e.jsxs("span",{className:a.reviewAnchorSnippet,children:['"',k.quote,'"']}),e.jsx("button",{type:"button",className:a.reviewAnchorClear,onClick:()=>G(null),children:"Clear"})]}),e.jsx("textarea",{className:B.commentInput,placeholder:p?.status==="resolved"?"Reopen this review to add more comments…":k?"Add a comment for the selected text…":"Add a comment for this document review…",value:V,onChange:n=>q(n.target.value),disabled:C||p?.status==="resolved",onKeyDown:n=>{n.key==="Enter"&&!n.shiftKey&&(n.preventDefault(),nt())}})]}),e.jsx("button",{type:"button",className:B.sendCommentBtn,onClick:()=>{nt()},disabled:C||!V.trim()||p?.status==="resolved","aria-label":"Send review comment",title:"Send review comment",children:e.jsx(gn,{size:15})})]})]})]})})]})),m&&St&&N!==null&&e.jsx(ja,{content:N,docTitle:t.title,apiBaseUrl:o,onClose:()=>De(!1),onGenerated:n=>De(!1)}),!T&&e.jsx("div",{className:a.printHint,children:"For the cleanest output, disable browser Headers and footers in the print dialog."})]})}function wt(t){return typeof t=="string"?t.trim().replace(/\/+$/,""):""}function Wa(t){return t.runtimeMode==="local"?"":wt(t.apiBaseUrl)||wt(t.cloudAuthBaseUrl)||""}function Ga({runtimeMode:t="local",apiBaseUrl:c="",cloudAuthBaseUrl:o="",typeFilters:i,attachmentFilters:u,onTypeFiltersChange:m,onAttachmentFiltersChange:v,requestedDocPath:y=null,requestedDocAssetId:g=null,onRequestedDocHandled:w}){const[h,_]=r.useState([]),[N,R]=r.useState(!0),[A,z]=r.useState(null),[D,L]=r.useState(null),[K,Q]=r.useState(""),[J,Y]=r.useState(()=>Jt.map(k=>k.value)),[x,S]=r.useState(()=>Vt.map(k=>k.value)),W=Wa({runtimeMode:t,apiBaseUrl:c,cloudAuthBaseUrl:o}),ne=i??J,se=u??x,$=m??Y,Ee=v??S,F=r.useCallback(async()=>{R(!0),z(null);try{const k=await I("/api/taskforce/documents",{credentials:"include"},W);if(!k.ok)throw new Error(`Failed to load documents (${k.status})`);const G=await k.json(),Z=Array.isArray(G.documents)?G.documents:[];Z.length,_(Z)}catch(k){z(k?.message||"Failed to load documents"),k?.message}finally{R(!1)}},[W,t]);r.useEffect(()=>{F()},[F]);const V=r.useMemo(()=>Hn(h,K,ne,se),[se,h,K,ne]),q=r.useMemo(()=>D?h.find(k=>k.id===D)??null:null,[h,D]);r.useEffect(()=>{if(!y&&!g||h.length===0)return;const k=y?Ue(y):"",G=String(g||"").trim().toLowerCase()||mt(y),Z=h.find(ee=>{const oe=mt(ee.fsPath)||String(ee.assetId||"").trim().toLowerCase()||null;return G&&oe&&oe===G?!0:k?On(Ue(ee.fsPath),k):!1});Z&&(L(Z.id),w?.())},[h,w,g,y]),r.useEffect(()=>{if(!((y||g)&&!q)){if(V.length===0){D!==null&&L(null);return}q&&V.some(k=>k.id===q.id)||L(V[0].id)}},[V,g,y,q,D]);const C=r.useCallback(async()=>{L(null),await F()},[F]),P=K.trim().length>0||ne.length>0||se.length>0;return{documentApiBaseUrl:W,documents:h,filteredDocs:V,loading:N,error:A,selectedDoc:q,searchQuery:K,typeFilters:ne,attachmentFilters:se,hasActiveFilters:P,setSearchQuery:Q,handleTypeFiltersChange:$,handleAttachmentFiltersChange:Ee,fetchDocuments:F,selectDoc:k=>L(k?.id??null),handleDeleteSelected:C}}function Ua({tasks:t,apiBaseUrl:c="",documents:o,loading:i,error:u,selectedDoc:m,searchQuery:v,hasActiveFilters:y,onSearchChange:g,onSelectDoc:w,onRefresh:h,onDeleteSelected:_,enableTaskGeneration:N=!1}){const R=new Map(t.map(A=>[A.id,A]));return e.jsxs("div",{className:M.docWorkspace,children:[e.jsx("div",{className:M.docIndexPanel,children:e.jsx(Jn,{documents:o,selectedDocId:m?.id??null,loading:i,error:u,searchQuery:v,onSearchChange:g,onSelect:A=>w(A),onRefresh:h,taskById:R,hasActiveFilters:y})}),e.jsx("div",{className:M.docViewerPanel,children:m?e.jsx(Ha,{doc:m,taskTitle:m.taskId?R.get(m.taskId)?.title??null:null,apiBaseUrl:c,onSaved:A=>h(),onDeleted:()=>{_()},enableTaskGeneration:N}):!i&&e.jsx("div",{className:M.docViewerEmpty,children:e.jsx("p",{className:"tf-empty-copy",children:o.length===0?"No documents match your current filters.":"Select a document to view it."})})})]})}function Xa({tasks:t,runtimeMode:c="local",apiBaseUrl:o="",cloudAuthBaseUrl:i="",typeFilters:u,attachmentFilters:m,onTypeFiltersChange:v,onAttachmentFiltersChange:y,requestedDocPath:g=null,requestedDocAssetId:w=null,onRequestedDocHandled:h,enableTaskGeneration:_=!1}){const{documentApiBaseUrl:N,filteredDocs:R,loading:A,error:z,selectedDoc:D,searchQuery:L,hasActiveFilters:K,setSearchQuery:Q,fetchDocuments:J,selectDoc:Y,handleDeleteSelected:x}=Ga({runtimeMode:c,apiBaseUrl:o,cloudAuthBaseUrl:i,typeFilters:u,attachmentFilters:m,onTypeFiltersChange:v,onAttachmentFiltersChange:y,requestedDocPath:g,requestedDocAssetId:w,onRequestedDocHandled:h});return e.jsx(Ua,{tasks:t,apiBaseUrl:N,documents:R,loading:A,error:z,selectedDoc:D,searchQuery:L,hasActiveFilters:K,onSearchChange:Q,onSelectDoc:Y,onRefresh:J,onDeleteSelected:x,enableTaskGeneration:_})}export{Vt as DOCUMENT_ATTACHMENT_FILTER_OPTIONS,Jt as DOCUMENT_TYPE_FILTER_OPTIONS,Ua as DocumentWorkspace,Xa as DocumentWorkspaceShell};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as i,j as s}from"./vendor-react-CKJs5o3c.js";import{t as e}from"./index-
|
|
1
|
+
import{r as i,j as s}from"./vendor-react-CKJs5o3c.js";import{t as e}from"./index-DcSI5F86.js";import{h as g,Z as v,b as j,k as f}from"./vendor-icons-BSUaRwF8.js";import"./vendor-markdown-BUxTU7dS.js";import"./vendor-dnd-DRzYolkg.js";import"./vendor-router-BbWMxlnO.js";function T({initiativeTemplates:n,onRefreshInitiativeTemplates:u,onCreateInitiativeFromTemplate:l}){const[a,o]=i.useState(""),[c,x]=i.useState(""),[d,m]=i.useState(!1),[r,p]=i.useState(null);return i.useEffect(()=>{if(!a&&n.length>0){const t=n[0];o(t.id)}},[n,a]),s.jsx("div",{className:`${e.standalonePage} ${e.standaloneContent}`,style:{overflow:"auto"},children:s.jsx("div",{className:e.settingsContent,style:{maxWidth:900,margin:"0 auto",width:"100%"},children:s.jsxs("div",{className:e.settingGroup,children:[s.jsxs("div",{className:e.settingTitleRow,children:[s.jsx("h2",{className:e.settingTitle,children:"Initiatives"}),s.jsx("button",{className:e.copyBtn,onClick:()=>{u?.()},children:"Refresh"})]}),s.jsx("p",{className:`${e.settingsHint} ${e.marginBottom12}`,children:"Create initiative-ready planning structures from reusable templates."}),s.jsxs("div",{className:e.exportItem,children:[s.jsx("label",{className:e.label,children:"Template"}),s.jsx("select",{className:e.input,value:a,onChange:t=>{const h=t.target.value;o(h)},children:n.map(t=>s.jsx("option",{value:t.id,children:t.name},t.id))})]}),s.jsxs("div",{className:`${e.exportItem} ${e.marginTop12}`,children:[s.jsx("label",{className:e.label,children:"Initiative Title"}),s.jsx("input",{className:e.input,placeholder:"e.g. Taskforce Private Beta Launch",value:c,onChange:t=>x(t.target.value)})]}),s.jsxs("button",{className:`${e.secondaryHeaderBtn} ${e.marginTop12}`,disabled:d||!a||!c.trim()||!l,onClick:async()=>{if(!l)return;m(!0);const t=await l({templateId:a,title:c.trim()});m(!1),p({type:t.success?"success":"error",message:t.success?"Initiative created from template.":t.error||"Failed to create initiative."})},children:[d?s.jsx(g,{size:14,className:e.spinner}):s.jsx(v,{size:14}),"Create Initiative"]}),r&&s.jsxs("div",{className:`${r.type==="success"?e.successMessage:e.errorMessage} ${e.marginTop12}`,children:[r.type==="success"?s.jsx(j,{size:14}):s.jsx(f,{size:14}),r.message]})]})})})}export{T as InitiativesModule};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as s,j as e}from"./vendor-react-CKJs5o3c.js";import{y as le,t as ke,z as xe,B as me,C as ne,E as ae,F as je,G as Ne}from"./index-DcSI5F86.js";import{aK as Ie,h as Pe,U as Re}from"./vendor-icons-BSUaRwF8.js";import{u as Te,a as Be}from"./vendor-router-BbWMxlnO.js";import"./vendor-markdown-BUxTU7dS.js";import"./vendor-dnd-DRzYolkg.js";const Ee="_plansWrapper_1i5vs_1",$e="_contentFrame_1i5vs_28",Ae="_shellOwnsScroll_1i5vs_36",Me="_withChrome_1i5vs_42",Ue="_siteVariant_1i5vs_46",Fe="_title_1i5vs_54",Le="_subtitle_1i5vs_63",Oe="_header_1i5vs_67",Ve="_planCard_1i5vs_79",Ke="_grid_1i5vs_92",Ye="_planName_1i5vs_98",De="_featureText_1i5vs_102",He="_currentBadge_1i5vs_106",ze="_navAction_1i5vs_110",Ge="_backBtn_1i5vs_111",qe="_priceRows_1i5vs_122",We="_headerBar_1i5vs_139",Qe="_headerActions_1i5vs_148",Je="_debugMeta_1i5vs_175",Xe="_clickablePlanCard_1i5vs_204",Ze="_activePlanCard_1i5vs_219",et="_callToAction_1i5vs_272",tt="_primaryCta_1i5vs_284",rt="_secondaryCta_1i5vs_295",nt="_currentCta_1i5vs_307",at="_featuresList_1i5vs_321",st="_priceRow_1i5vs_122",it="_priceRowAmount_1i5vs_346",ot="_priceRowInterval_1i5vs_352",ct="_ctaRow_1i5vs_357",lt="_featureItem_1i5vs_363",ut="_featureIcon_1i5vs_369",dt="_emptyState_1i5vs_383",mt="_marketingEmptyState_1i5vs_392",pt="_emptyBadge_1i5vs_420",ft="_emptyHighlights_1i5vs_435",gt="_loader_1i5vs_457",ht="_spinner_1i5vs_467",yt="_statusBanner_1i5vs_520",_t="_successBanner_1i5vs_528",vt="_infoBanner_1i5vs_534",Ct="_errorBanner_1i5vs_540",r={plansWrapper:Ee,contentFrame:$e,shellOwnsScroll:Ae,withChrome:Me,siteVariant:Ue,title:Fe,subtitle:Le,header:Oe,planCard:Ve,grid:Ke,planName:Ye,featureText:De,currentBadge:He,navAction:ze,backBtn:Ge,priceRows:qe,headerBar:We,headerActions:Qe,debugMeta:Je,clickablePlanCard:Xe,activePlanCard:Ze,callToAction:et,primaryCta:tt,secondaryCta:rt,currentCta:nt,featuresList:at,priceRow:st,priceRowAmount:it,priceRowInterval:ot,ctaRow:ct,featureItem:lt,featureIcon:ut,emptyState:dt,marketingEmptyState:mt,emptyBadge:pt,emptyHighlights:ft,loader:gt,spinner:ht,statusBanner:yt,successBanner:_t,infoBanner:vt,errorBanner:Ct};function St(){const n=globalThis.__DEBUG_MODE__;return typeof n=="boolean"?n:!1}function bt(n){const o=String(n?.environment||"").trim(),y=String(n?.runtimeMode||"").trim();return!o&&!y?null:o&&y?`${o} (${y})`:o||y||null}function wt(n,o){if(n==null||!o)return"Contact Sales";try{return new Intl.NumberFormat("en-US",{style:"currency",currency:o.toUpperCase(),minimumFractionDigits:0}).format(n/100)}catch{return`${o.toUpperCase()} ${n/100}`}}function kt(){return"$0.00"}function ye(n){return n?n.pricingType==="free"?!0:n.unitAmount!=null&&n.currency!=null:!1}function _e(n){return n?n.pricingType==="free"?kt():wt(n.unitAmount,n.currency):"Unavailable"}function ve(n){const o=[n.pricing.month,n.pricing.year].filter(Boolean);if(o.some(g=>g.pricingType==="free"))return 0;const y=o.map(g=>g.pricingType==="stripe"&&typeof g.unitAmount=="number"?g.unitAmount:null).filter(g=>g!=null);return y.length>0?Math.min(...y):Number.POSITIVE_INFINITY}function xt({heading:n,subtitle:o,variant:y="app",chrome:g,footer:L,isAuthenticated:O,authSessionResolved:ue=!0,currentPlanId:X,currentPlanVersionId:D,currentEntitlementState:Z,canManageCurrentPlan:N=!0,pricingEndpoint:se,statusBanner:V,onBack:I,backLabel:ee,backDisabled:b=!1,topActions:v,shellOwnsScroll:w=!1,showPageBackButton:te=!0,fallbackPricingSource:H=null,onSelectPlan:T}){const[ie,c]=s.useState([]),[z,G]=s.useState(null),[A,E]=s.useState(!0),[C,k]=s.useState(null),[de,q]=s.useState(0);s.useEffect(()=>{let i=!0;return(async()=>{const u=String(se||"/api/taskforce/public/pricing").trim()||"/api/taskforce/public/pricing";i&&(E(!0),k(null));try{const S=await fetch(u,{method:"GET",credentials:"include"}),_=await S.json().catch(()=>({}));if(S.ok){i&&(c(Array.isArray(_?.plans)?_.plans:[]),G(_?.pricingSource&&typeof _.pricingSource=="object"?_.pricingSource:null));return}throw new Error(String(_?.error||`Failed to load pricing (${S.status})`))}catch(S){if(i){const _=S instanceof Error?S.message:"Failed to load pricing";k(_||"Failed to load pricing"),G(null)}}finally{i&&E(!1)}})(),()=>{i=!1}},[se,de]);const re=s.useMemo(()=>[...ie].sort((i,x)=>{const u=ve(i),S=ve(x);if(u!==S)return u-S;const _=i.defaultVersion?.versionNumber||0,l=x.defaultVersion?.versionNumber||0;return _!==l?_-l:String(i.displayName||i.planId).localeCompare(String(x.displayName||x.planId))}),[ie]),M=s.useMemo(()=>bt(z||H),[H,z]),P=`${r.plansWrapper} ${w?r.shellOwnsScroll:"tf-scrollbar"} ${y==="site"?r.siteVariant:""} ${g?r.withChrome:""}`.trim(),W=i=>w?e.jsxs(e.Fragment,{children:[g,i,L]}):e.jsxs("div",{className:ke.standaloneWrapper,"data-theme":"dark",children:[g,i,L]});return W(A||!ue?e.jsx(e.Fragment,{children:e.jsx("div",{className:P,children:e.jsx("div",{className:r.contentFrame,children:e.jsxs("div",{className:r.loader,children:[e.jsx(Pe,{size:48,className:r.spinner}),e.jsx("p",{children:"Loading plans..."})]})})})}):C?e.jsx(e.Fragment,{children:e.jsx("div",{className:P,children:e.jsx("div",{className:r.contentFrame,children:e.jsxs("div",{className:r.emptyState,children:[e.jsx("h2",{children:"Connecting to plan pricing..."}),e.jsx("p",{children:C}),e.jsx("button",{className:r.backBtn,onClick:()=>q(i=>i+1),children:"Retry"})]})})})}):e.jsx(e.Fragment,{children:e.jsx("div",{className:P,children:e.jsxs("div",{className:r.contentFrame,children:[e.jsxs("div",{className:r.header,children:[!g&&(te||v)&&e.jsxs("div",{className:r.headerBar,children:[e.jsx("div",{children:te?e.jsx("button",{className:r.backBtn,onClick:I,disabled:b,children:ee}):null}),e.jsx("div",{className:r.headerActions,children:v})]}),e.jsx("h1",{className:r.title,children:n}),o&&e.jsx("p",{className:r.subtitle,children:o}),St()&&M?e.jsxs("p",{className:r.debugMeta,children:["Pricing source: ",M]}):null,V&&e.jsx("div",{className:`${r.statusBanner} ${V.type==="success"?r.successBanner:V.type==="info"?r.infoBanner:r.errorBanner}`,children:V.message})]}),re.length===0?e.jsxs("div",{className:`${r.emptyState} ${r.marketingEmptyState}`,children:[e.jsx("span",{className:r.emptyBadge,children:"Coming Soon"}),e.jsx("h2",{children:"Paid plans are getting their final polish."}),e.jsx("p",{children:"Taskforce pricing is on the way with flexible options for solo operators, teams, and larger rollouts. Check back soon for launch tiers, feature bundles, and early access details."}),e.jsxs("div",{className:r.emptyHighlights,"aria-label":"Upcoming pricing highlights",children:[e.jsx("span",{children:"Launch-ready tiers"}),e.jsx("span",{children:"Team billing controls"}),e.jsx("span",{children:"Feature-based packaging"})]})]}):e.jsx("div",{className:r.grid,children:re.map(i=>{const x=i.pricing.month,u=i.pricing.year,S=ye(x),_=ye(u),l=String(i.defaultVersion?.planVersionId||"").trim(),$=le(Z)&&(!!(l&&D&&D===l)||!D&&!!(X&&X===i.planId)),R=S?"month":_?"year":null,U=R==="year"?u:x,p=!!l&&($?N:!!R),Q=()=>{if(l){if($){if(!N)return;T({planId:i.planId,planVersionId:l,interval:R||"month",pricingType:U?.pricingType||"stripe",isCurrentPlan:!0});return}R&&T({planId:i.planId,planVersionId:l,interval:R,pricingType:U?.pricingType||"stripe",isCurrentPlan:!1})}};return e.jsxs("div",{className:`${r.planCard} ${$?r.activePlanCard:""} ${p?r.clickablePlanCard:""}`,"data-testid":`plan-card-${i.planId}`,role:p?"button":void 0,tabIndex:p?0:void 0,onClick:p?Q:void 0,onKeyDown:p?h=>{(h.key==="Enter"||h.key===" ")&&(h.preventDefault(),Q())}:void 0,children:[$&&e.jsx("span",{className:r.currentBadge,children:"Current Plan"}),e.jsx("h3",{className:r.planName,children:i.displayName}),e.jsx("div",{className:r.featuresList,children:Array.isArray(i.features)&&i.features.length>0?i.features.map((h,K)=>e.jsxs("div",{className:r.featureItem,children:[e.jsx(Ie,{className:r.featureIcon}),e.jsx("span",{className:r.featureText,children:String(h.featureKey||"").replace(/[_\-.]+/g," ").replace(/\b\w/g,oe=>oe.toUpperCase())})]},`${h.featureKey}-${K}`)):e.jsx("span",{className:r.featureText,children:"No additional features included"})}),e.jsxs("div",{className:r.priceRows,children:[e.jsxs("div",{className:r.priceRow,children:[e.jsx("span",{className:r.priceRowAmount,children:_e(x)}),e.jsx("span",{className:r.priceRowInterval,children:"/ month"})]}),e.jsxs("div",{className:r.priceRow,children:[e.jsx("span",{className:r.priceRowAmount,children:_e(u)}),e.jsx("span",{className:r.priceRowInterval,children:"/ year"})]})]}),$?e.jsx("button",{className:`${r.callToAction} ${r.currentCta}`,"data-testid":`plan-manage-${i.planId}`,onClick:h=>{h.stopPropagation(),N&&T({planId:i.planId,planVersionId:l,interval:R||"month",pricingType:U?.pricingType||"stripe",isCurrentPlan:!0})},disabled:!l||!N,children:O&&N?"Manage Plan":"Current Plan"}):e.jsxs("div",{className:r.ctaRow,children:[e.jsx("button",{className:`${r.callToAction} ${r.secondaryCta}`,"data-testid":`plan-select-${i.planId}-month`,onClick:h=>{h.stopPropagation(),T({planId:i.planId,planVersionId:l,interval:"month",pricingType:x?.pricingType||"stripe",isCurrentPlan:!1})},disabled:!l||!S,children:x?.pricingType==="free"?O?"Select Free":"Get Started Free":O?"Choose Monthly":"Get Started Monthly"}),e.jsx("button",{className:`${r.callToAction} ${r.primaryCta}`,"data-testid":`plan-select-${i.planId}-year`,onClick:h=>{h.stopPropagation(),T({planId:i.planId,planVersionId:l,interval:"year",pricingType:u?.pricingType||"stripe",isCurrentPlan:!1})},disabled:!l||!_,children:u?.pricingType==="free"?O?"Select Free":"Get Started Free":O?"Choose Yearly":"Get Started Yearly"})]})]},i.planId)})})]})})}))}const jt=1600,Nt=[0,500,1e3,2e3];function It(n,o){return n===401?!0:String(o||"").trim().toUpperCase()==="CHECKOUT_SESSION_INCOMPLETE"}function Pt(n){return n==="year"?"year":"month"}function Ce(n){const o=String(n||"").trim();return o?o.replace(/\/+$/,""):""}function pe(n={}){const o=new URLSearchParams;o.set("screen","plans");for(const[y,g]of Object.entries(n)){const L=String(g||"").trim();L&&o.set(y,L)}return`/?${o.toString()}`}function Mt({isAuthenticated:n,authUserId:o,runtimeMode:y,authSessionResolved:g,currentTheme:L="dark",projectName:O,currentWorkspaceId:ue,apiBaseUrl:X,connectedEnvironmentSource:D,resolveCloudAuthUrl:Z,embedded:N=!1,shellOwnsScroll:se=!1,onAccountProfileSummaryChange:V,onContinueToTaskforce:I,continueBusy:ee=!1}){const b=Te(),v=Be(),[w,te]=s.useState(null),[H,T]=s.useState(!1),[ie,c]=s.useState(null),z=s.useRef(!1),G=s.useRef(null),A=s.useRef(null),E=s.useMemo(()=>new URLSearchParams(v.search),[v.search]),C=String(E.get("checkout")||"").trim().toLowerCase(),k=String(E.get("gate")||"").trim().toLowerCase(),de=String(E.get("planId")||"").trim(),q=String(E.get("planVersionId")||"").trim(),re=Pt(E.get("interval")),M=String(E.get("session_id")||"").trim(),P=s.useMemo(()=>Ce(X),[X]),W=s.useMemo(()=>Ce(D),[D]),i=s.useMemo(()=>({environment:xe(W||P),runtimeMode:y==="cloud"?"cloud":"local"}),[P,W,y]),x=s.useCallback(t=>{const a=String(t||"").trim();return P?`${P}${a.startsWith("/")?a:`/${a}`}`:a},[P]),u=s.useCallback(t=>Z?Z(t):x(t),[x,Z]),S=s.useCallback(()=>{const t=new URLSearchParams(v.search);t.delete("screen"),t.delete("gate"),t.delete("checkout"),t.delete("planId"),t.delete("planVersionId"),t.delete("interval");const a=t.toString();b(`/${a?`?${a}`:""}${v.hash||""}`)},[v.hash,v.search,b]),_=s.useMemo(()=>[P?`${P}/api/taskforce/public/pricing`:"","/api/taskforce/public/pricing"].map(a=>String(a||"").trim()).filter((a,d,f)=>a&&f.indexOf(a)===d),[P]),l=s.useMemo(()=>me(w,k),[w,k]),B=s.useMemo(()=>l.allowReturnToApp,[l.allowReturnToApp]),$=s.useMemo(()=>l.message,[l.message]),R=s.useCallback(()=>{const t=new URLSearchParams(v.search);t.delete("checkout"),t.delete("session_id"),t.delete("gate"),t.delete("planId"),t.delete("planVersionId"),t.delete("interval");const a=t.toString();b(`${v.pathname}${a?`?${a}`:""}${v.hash||""}`,{replace:!0})},[v.hash,v.pathname,v.search,b]),U=s.useCallback(()=>{A.current!=null&&window.clearTimeout(A.current),A.current=window.setTimeout(()=>{R(),A.current=null},jt)},[R]),p=s.useCallback(async t=>{const a=u(ne);if(!n)return te(null),ae(a,{identityKey:o}),null;try{const d=await je(a,{identityKey:o,force:t?.force===!0});return te(d),V?.(d),d}catch{return null}},[o,u,n,V]),Q=s.useCallback((t,a)=>{const d=me(t,k).message;return d||String(a||"Unable to confirm checkout completion.").trim()||"Unable to confirm checkout completion."},[k]),h=s.useCallback((t,a)=>!me(t,a).allowReturnToApp,[]),K=s.useCallback(async(t,a,d)=>{if(!t){c({type:"error",message:"Selected plan is missing a default plan version."});return}T(!0),c(null);try{const f=await fetch(u("/api/taskforce/billing/checkout-session"),{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({planVersionId:t,interval:a})}),m=await f.json().catch(()=>({}));if(!f.ok){c({type:"error",message:String(m?.error||"Unable to start checkout for selected plan.")});return}const j=String(m?.checkoutState||"").trim().toLowerCase();if(j==="free"){c({type:"success",message:"Plan selected. Your access is ready."}),ae(u(ne),{identityKey:o});const Y=await p({force:!0}),J=String(Y?.entitlementState||"").trim().toLowerCase();d?.autoContinueOnActivation===!0&&le(J)&&await I?.();return}if(j==="updated"){c({type:"success",message:String(m?.message||"Your subscription was updated successfully.")}),ae(u(ne),{identityKey:o});const Y=await p({force:!0}),J=String(Y?.entitlementState||"").trim().toLowerCase();d?.autoContinueOnActivation===!0&&le(J)&&await I?.();return}if(j==="already_current_plan"){c({type:"success",message:String(m?.message||"You are already on this plan.")}),ae(u(ne),{identityKey:o}),await p();return}const F=String(m?.returnBaseUrl||"").trim();if(y==="local"&&F)try{const Y=window.location.origin,J=new URL(F,Y).origin;if(J!==Y){c({type:"error",message:`Checkout return is misconfigured for this runtime. Expected ${Y} but got ${J}.`});return}}catch{c({type:"error",message:"Checkout return URL is invalid for this runtime."});return}const he=String(m?.url||"").trim();if(!he){c({type:"error",message:"Checkout did not return a redirect URL."});return}window.location.assign(he)}catch{c({type:"error",message:"Unable to start checkout for selected plan."})}finally{T(!1)}},[o,u,p,I,y]),oe=s.useCallback(async(t,a)=>{if(!t)return{confirmed:!1,errorMessage:"Checkout session is missing.",retryable:!1};try{const d=await fetch(u("/api/taskforce/billing/checkout-session/confirm"),{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionId:t})}),f=await d.json().catch(()=>({}));if(!d.ok){const F=String(f?.code||"").trim();return{confirmed:!1,errorMessage:String(f?.error||"Unable to confirm checkout completion."),retryable:It(d.status,F)}}ae(u(ne),{identityKey:o});const m=await p({force:!0}),j=String(m?.entitlementState||"").trim().toLowerCase();return a?.autoContinueOnActivation===!0&&le(j)&&await I?.(),{confirmed:!0}}catch{return{confirmed:!1,errorMessage:"Unable to confirm checkout completion.",retryable:!0}}},[o,u,p,I]),ce=s.useCallback(async()=>{if(!n){b(`/login?mode=login&next=${encodeURIComponent(pe())}`);return}T(!0),c(null);try{const t=await fetch(u("/api/taskforce/billing/portal-session"),{method:"POST",credentials:"include"}),a=await t.json().catch(()=>({}));if(!t.ok){c({type:"error",message:String(a?.error||"Failed to open billing portal.")});return}const d=String(a?.url||"").trim();if(!d){c({type:"error",message:"Portal session did not return a redirect URL."});return}window.location.assign(d)}catch{c({type:"error",message:"Failed to open billing portal."})}finally{T(!1)}},[u,n,b]);s.useEffect(()=>{p()},[p]),s.useEffect(()=>{B&&k==="missing_entitlement"&&R()},[R,k,B]),s.useEffect(()=>()=>{A.current!=null&&window.clearTimeout(A.current)},[]),s.useEffect(()=>{C!=="success"&&(G.current=null)},[C]),s.useEffect(()=>{let t=!1;const a=new Set,d=async f=>{f<=0||await new Promise(m=>{const j=window.setTimeout(()=>{a.delete(j),m()},f);a.add(j)})};if(C==="success"){if(z.current=!0,c({type:"success",message:"Checkout completed successfully. Finalizing your plan..."}),!g)return()=>{t=!0,a.forEach(m=>window.clearTimeout(m)),a.clear()};if(!n)return c({type:"error",message:"Sign in to finish activating your plan."}),()=>{t=!0,a.forEach(m=>window.clearTimeout(m)),a.clear()};const f=M||"__missing_session__";return G.current===f?()=>{t=!0,a.forEach(m=>window.clearTimeout(m)),a.clear()}:(G.current=f,(async()=>{const m=await p({force:!0});if(t)return;let j=M?{confirmed:!1,errorMessage:"Unable to confirm checkout completion.",retryable:!0}:{confirmed:!1,errorMessage:"Checkout session is missing.",retryable:!1};for(const F of Nt){if(await d(F),t||(j=M?await oe(M,{autoContinueOnActivation:h(m,k)}):{confirmed:!1,errorMessage:"Checkout session is missing.",retryable:!1},t))return;if(j.confirmed){c({type:"success",message:"Checkout completed successfully."}),U();return}if(!j.retryable)break}if(!t&&!j.confirmed){const F=await p({force:!0});if(t)return;c({type:"error",message:Q(F,j.errorMessage)}),U();return}})(),()=>{t=!0,a.forEach(m=>window.clearTimeout(m)),a.clear()})}if(C==="cancel"){(async()=>{const f=await p({force:!0});c({type:"error",message:Q(f,"Checkout was canceled. No charge was made.")}),U()})();return}if((C==="start"||C==="free")&&n&&q&&!z.current){z.current=!0,(async()=>{const f=await p({force:!0});await K(q,re,{autoContinueOnActivation:h(f,k)})})();return}},[g,C,oe,k,n,p,re,q,M,Q,U,h,K]),s.useEffect(()=>{if(!(C==="success"||C==="cancel"||C==="start"||C==="free")){if($){c({type:l.statusTone,message:$});return}c(t=>!t||t.type!=="error"?t:t.message===l.message?null:t)}},[C,$,l.message,l.statusTone]);const Se=s.useCallback(async t=>{if(!n){const d=t.pricingType==="free"?"free":"start",f=pe({checkout:d,planId:t.planId,planVersionId:t.planVersionId,interval:t.interval});b(`/login?mode=register&planId=${encodeURIComponent(t.planId)}&planVersionId=${encodeURIComponent(t.planVersionId)}&interval=${encodeURIComponent(t.interval)}&next=${encodeURIComponent(f)}`);return}if(t.isCurrentPlan){if(!w?.stripeCustomerId){c({type:"success",message:"Your current plan does not use Stripe billing."});return}await ce();return}const a=h(w,k);if(t.pricingType==="free"){await K(t.planVersionId,t.interval,{autoContinueOnActivation:a});return}await K(t.planVersionId,t.interval,{autoContinueOnActivation:a})},[w,k,n,b,ce,h,K]),fe=s.useCallback(()=>{if(B&&I){I();return}if(N){S();return}if(window.history.length>1){b(-1);return}b("/")},[S,N,B,b,I]),be=B&&I?e.jsx("button",{className:r.navAction,onClick:()=>{I()},disabled:ee||H,children:"Take Me to Taskforce"}):null,ge=N?e.jsxs(e.Fragment,{children:[be,n&&w?.stripeCustomerId&&e.jsx("button",{className:r.navAction,onClick:()=>{ce()},disabled:H,children:"Manage billing"})]}):e.jsxs(e.Fragment,{children:[e.jsx("button",{className:r.navAction,onClick:fe,disabled:ee||n&&!B,children:B?"Take Me to Taskforce":"Back"}),n&&w?.stripeCustomerId&&e.jsx("button",{className:r.navAction,onClick:()=>{ce()},disabled:H,children:"Manage billing"}),!n&&e.jsxs("button",{className:r.navAction,onClick:()=>b(`/login?mode=login&next=${encodeURIComponent(pe())}`),children:[e.jsx(Re,{size:16,style:{marginRight:"8px",verticalAlign:"text-bottom"}}),"Sign In"]})]}),we=N?null:e.jsx(Ne,{projectName:O,currentWorkspaceId:ue,runtimeMode:y==="cloud"?"cloud":"local",theme:L,actions:ge});return e.jsx(xt,{chrome:we,heading:"Subscription Plans",subtitle:"Manage your subscription and explore available features. Your current plan is highlighted below.",isAuthenticated:n,authSessionResolved:g,currentPlanId:String(w?.planId||de||"").trim()||null,currentPlanVersionId:String(w?.planVersionId||q||"").trim()||null,currentEntitlementState:String(w?.entitlementState||"").trim()||null,canManageCurrentPlan:!!w?.stripeCustomerId,pricingEndpoint:_[0],statusBanner:ie,onBack:fe,backLabel:B?"Take Me to Taskforce":N?"Back to Board":"Back to App",backDisabled:ee||n&&!B,topActions:N?ge:null,shellOwnsScroll:se,showPageBackButton:!N,fallbackPricingSource:i,onSelectPlan:Se})}export{Mt as PlansPage};
|