ocean-brain 0.3.0 → 0.3.1
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/package.json +1 -1
- package/server/client/dist/assets/Calendar-DynpmB3D.js +25 -0
- package/server/client/dist/assets/{Callout-B2kPcDrq.js → Callout-tNHgPhLM.js} +1 -1
- package/server/client/dist/assets/Graph-DMXLUfCv.js +1 -0
- package/server/client/dist/assets/Image-ZxF459sC.js +1 -0
- package/server/client/dist/assets/{Image.es-Dld9r9MJ.js → Image.es-Dnn4SMzG.js} +1 -1
- package/server/client/dist/assets/{ModalActionRow-CES9L_Gy.js → ModalActionRow-B3vNjcDc.js} +1 -1
- package/server/client/dist/assets/Note-PDMuj62M.js +1 -0
- package/server/client/dist/assets/{Note-SK4hDhEM.css → Note-PEevDKBh.css} +1 -1
- package/server/client/dist/assets/Reminders-ComtTLuN.js +1 -0
- package/server/client/dist/assets/{Search-Cp17DGR6.js → Search-BJeZTbVu.js} +1 -1
- package/server/client/dist/assets/SurfaceCard-DAcVMY4f.js +1 -0
- package/server/client/dist/assets/{Tag-CwmuMPmo.js → Tag-BuNCDGD5.js} +1 -1
- package/server/client/dist/assets/TagNotes-ajFOP5pZ.js +1 -0
- package/server/client/dist/assets/{Trash.es-B3KWD8_C.js → Trash.es-DLiHgjNo.js} +1 -1
- package/server/client/dist/assets/{image.api-DJgOBt8S.js → image.api-CjJgNbC0.js} +1 -1
- package/server/client/dist/assets/{index-DYUg2N-6.js → index-CDrZmLC2.js} +1 -1
- package/server/client/dist/assets/index-DAZMX8bQ.css +1 -0
- package/server/client/dist/assets/index-DqFkOWbi.js +205 -0
- package/server/client/dist/assets/manage-image-CVyZTDT_.js +1 -0
- package/server/client/dist/assets/{manage-image-detail-BVaDZHRu.js → manage-image-detail-Bp17tylS.js} +1 -1
- package/server/client/dist/assets/mcp-BpD7VH-d.js +1 -0
- package/server/client/dist/assets/placeholder-DSf4QF4v.js +34 -0
- package/server/client/dist/assets/trash-Ceb17h_s.js +1 -0
- package/server/client/dist/assets/useReminderMutate-CzyOQ_VB.js +82 -0
- package/server/client/dist/index.html +2 -2
- package/server/dist/modules/blocknote.js +149 -3
- package/server/dist/modules/blocknote.js.map +1 -1
- package/server/dist/modules/note-authoring.js +16 -3
- package/server/dist/modules/note-authoring.js.map +1 -1
- package/server/client/dist/assets/Calendar-DRv2aEl8.js +0 -28
- package/server/client/dist/assets/Graph-DotbTrZR.js +0 -1
- package/server/client/dist/assets/Image-B5R7gF2P.js +0 -1
- package/server/client/dist/assets/Note-cIbXJc1v.js +0 -1
- package/server/client/dist/assets/Reminders-4LunlZRb.js +0 -1
- package/server/client/dist/assets/SurfaceCard-yzVU4Qkx.js +0 -1
- package/server/client/dist/assets/TagNotes-gGroWMtT.js +0 -1
- package/server/client/dist/assets/color-wpu7wT_s.js +0 -1
- package/server/client/dist/assets/index-40Y2UsVr.js +0 -205
- package/server/client/dist/assets/index-BnxpTwtL.css +0 -1
- package/server/client/dist/assets/manage-image-ByY1mRZx.js +0 -1
- package/server/client/dist/assets/mcp-Jj3061aI.js +0 -1
- package/server/client/dist/assets/placeholder-4P_GK7fV.js +0 -34
- package/server/client/dist/assets/trash-CPBwY07S.js +0 -1
- package/server/client/dist/assets/useReminderMutate-1YVndM2T.js +0 -82
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as e}from"./note-vendor-BofYbzmZ.js";import{k as x,q as m,ag as p,G as y,w as j,I,P as E,Q as A,E as N,L as M,ah as v,B as G,f as S,S as l,e as w,a9 as T}from"./index-DqFkOWbi.js";import"./graph-vendor-CUxe67Lr.js";import{I as _}from"./Image-ZxF459sC.js";import{S as b}from"./SurfaceCard-DAcVMY4f.js";import{f as P,d as R}from"./image.api-CjJgNbC0.js";import{c as k,n as q}from"./Trash.es-DLiHgjNo.js";import"./note-core-BCgMq5QA.js";const C=r=>{const{data:n}=x({queryKey:m.images.list(r.searchParams),async queryFn(){const t=await P({offset:r.searchParams.offset,limit:r.searchParams.limit});if(t.type==="error")throw t;return t.allImages}});return r.render(n)},L=240,Q=20,D=4,d=w(T),J=()=>{const r=p(),n=y(),t=d.useNavigate(),{page:o}=d.useSearch(),{containerRef:u,limit:i}=j({minItemWidth:L,gap:Q,rows:D}),h=I({mutationFn:R,onSuccess:a=>{if(a.type==="error")throw a;n.invalidateQueries({queryKey:m.images.listAll(),exact:!1})}}),f=async a=>{await r("Are you really sure?")&&h.mutate(a)};return e.jsx(E,{title:"Images",variant:"subtle",description:"Manage images uploaded to your notes",children:e.jsx("div",{ref:u,children:e.jsx(A,{fallback:e.jsxs("div",{className:"grid-auto-cards grid gap-4",children:[e.jsx(l,{height:"200px"}),e.jsx(l,{height:"200px"}),e.jsx(l,{height:"200px"})]}),errorTitle:"Failed to load images",errorDescription:"Retry loading uploaded image metadata.",resetKeys:[o,i],children:e.jsx(C,{searchParams:{offset:(o-1)*i,limit:i},render:({images:a,totalCount:c})=>a.length===0?e.jsx(N,{title:"There are no images",description:"Try drag and drop an image on the note editor."}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"grid-auto-cards grid gap-4",children:a.map(s=>e.jsxs(b,{flush:!0,children:[e.jsx(M,{to:v,params:{id:s.id},className:"block overflow-hidden",children:e.jsx(_,{className:"h-48 w-full object-cover transition-transform duration-200 hover:scale-[1.02]",src:s.url,alt:s.id})}),e.jsxs("div",{className:"flex items-center justify-between border-t border-border-subtle px-3 py-2.5",children:[e.jsxs("span",{className:"flex items-center gap-1.5 text-sm font-medium text-fg-tertiary",children:[e.jsx(k,{className:"h-3.5 w-3.5"}),s.referenceCount]}),e.jsx(G,{variant:"ghost",size:"icon-sm",disabled:s.referenceCount>0,onClick:()=>f(s.id),children:e.jsx(q,{className:"h-4 w-4"})})]})]},s.id))}),c&&i<c&&e.jsx(S,{page:o,last:Math.ceil(c/i),onChange:s=>{t({search:g=>({...g,page:s})})}})]})})})})})};export{J as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./note-vendor-BofYbzmZ.js";import{p as
|
|
1
|
+
import{j as e}from"./note-vendor-BofYbzmZ.js";import{p as b,ai as y,L as f,N as C,x as E,aj as A,ag as v,A as w,G as I,u as h,q as d,ak as M,P as T,a9 as u,b as S,al as Z,B as p,am as _,e as D,ah as F}from"./index-DqFkOWbi.js";import{I as R}from"./Image-ZxF459sC.js";import{S as x}from"./SurfaceCard-DAcVMY4f.js";import{a}from"./graph-vendor-CUxe67Lr.js";import{a as q,d as G}from"./image.api-CjJgNbC0.js";import{c as z,n as k}from"./Trash.es-DLiHgjNo.js";import{I as B}from"./Image.es-Dnn4SMzG.js";import"./note-core-BCgMq5QA.js";const O=new Map([["bold",a.createElement(a.Fragment,null,a.createElement("path",{d:"M178,36c-20.09,0-37.92,7.93-50,21.56C115.92,43.93,98.09,36,78,36a66.08,66.08,0,0,0-66,66c0,72.34,105.81,130.14,110.31,132.57a12,12,0,0,0,11.38,0C138.19,232.14,244,174.34,244,102A66.08,66.08,0,0,0,178,36Zm-5.49,142.36A328.69,328.69,0,0,1,128,210.16a328.69,328.69,0,0,1-44.51-31.8C61.82,159.77,36,131.42,36,102A42,42,0,0,1,78,60c17.8,0,32.7,9.4,38.89,24.54a12,12,0,0,0,22.22,0C145.3,69.4,160.2,60,178,60a42,42,0,0,1,42,42C220,131.42,194.18,159.77,172.51,178.36Z"}))],["duotone",a.createElement(a.Fragment,null,a.createElement("path",{d:"M232,102c0,66-104,122-104,122S24,168,24,102A54,54,0,0,1,78,48c22.59,0,41.94,12.31,50,32,8.06-19.69,27.41-32,50-32A54,54,0,0,1,232,102Z",opacity:"0.2"}),a.createElement("path",{d:"M178,40c-20.65,0-38.73,8.88-50,23.89C116.73,48.88,98.65,40,78,40a62.07,62.07,0,0,0-62,62c0,70,103.79,126.66,108.21,129a8,8,0,0,0,7.58,0C136.21,228.66,240,172,240,102A62.07,62.07,0,0,0,178,40ZM128,214.8C109.74,204.16,32,155.69,32,102A46.06,46.06,0,0,1,78,56c19.45,0,35.78,10.36,42.6,27a8,8,0,0,0,14.8,0c6.82-16.67,23.15-27,42.6-27a46.06,46.06,0,0,1,46,46C224,155.61,146.24,204.15,128,214.8Z"}))],["fill",a.createElement(a.Fragment,null,a.createElement("path",{d:"M240,102c0,70-103.79,126.66-108.21,129a8,8,0,0,1-7.58,0C119.79,228.66,16,172,16,102A62.07,62.07,0,0,1,78,40c20.65,0,38.73,8.88,50,23.89C139.27,48.88,157.35,40,178,40A62.07,62.07,0,0,1,240,102Z"}))],["light",a.createElement(a.Fragment,null,a.createElement("path",{d:"M178,42c-21,0-39.26,9.47-50,25.34C117.26,51.47,99,42,78,42a60.07,60.07,0,0,0-60,60c0,29.2,18.2,59.59,54.1,90.31a334.68,334.68,0,0,0,53.06,37,6,6,0,0,0,5.68,0,334.68,334.68,0,0,0,53.06-37C219.8,161.59,238,131.2,238,102A60.07,60.07,0,0,0,178,42ZM128,217.11C111.59,207.64,30,157.72,30,102A48.05,48.05,0,0,1,78,54c20.28,0,37.31,10.83,44.45,28.27a6,6,0,0,0,11.1,0C140.69,64.83,157.72,54,178,54a48.05,48.05,0,0,1,48,48C226,157.72,144.41,207.64,128,217.11Z"}))],["regular",a.createElement(a.Fragment,null,a.createElement("path",{d:"M178,40c-20.65,0-38.73,8.88-50,23.89C116.73,48.88,98.65,40,78,40a62.07,62.07,0,0,0-62,62c0,70,103.79,126.66,108.21,129a8,8,0,0,0,7.58,0C136.21,228.66,240,172,240,102A62.07,62.07,0,0,0,178,40ZM128,214.8C109.74,204.16,32,155.69,32,102A46.06,46.06,0,0,1,78,56c19.45,0,35.78,10.36,42.6,27a8,8,0,0,0,14.8,0c6.82-16.67,23.15-27,42.6-27a46.06,46.06,0,0,1,46,46C224,155.61,146.24,204.15,128,214.8Z"}))],["thin",a.createElement(a.Fragment,null,a.createElement("path",{d:"M178,44c-21.44,0-39.92,10.19-50,27.07C117.92,54.19,99.44,44,78,44a58.07,58.07,0,0,0-58,58c0,28.59,18,58.47,53.4,88.79a333.81,333.81,0,0,0,52.7,36.73,4,4,0,0,0,3.8,0,333.81,333.81,0,0,0,52.7-36.73C218,160.47,236,130.59,236,102A58.07,58.07,0,0,0,178,44ZM128,219.42c-14-8-100-59.35-100-117.42A50.06,50.06,0,0,1,78,52c21.11,0,38.85,11.31,46.3,29.51a4,4,0,0,0,7.4,0C139.15,63.31,156.89,52,178,52a50.06,50.06,0,0,1,50,50C228,160,142,211.46,128,219.42Z"}))]]),j=a.forwardRef((i,c)=>a.createElement(b,{ref:c,...i,weights:O}));j.displayName="HeartIcon";const L=j;function U({id:i,title:c,tags:s,createdAt:o,updatedAt:m}){const n=new Date(Number(o)),r=y(Number(m));return e.jsx("div",{className:"border-b-2 border-dashed border-border-subtle last:border-b-0",children:e.jsxs("div",{className:"py-4 flex flex-col gap-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"text-fg-tertiary text-xs font-medium",children:r}),e.jsxs("span",{className:"text-fg-placeholder text-xs",children:["(",n.toDateString(),")"]})]}),e.jsx(f,{className:"font-bold text-fg-default hover:text-accent-primary transition-colors",to:C,params:{id:i},children:c||"Untitled"}),s&&s.length>0&&e.jsx("div",{className:"flex flex-wrap gap-1.5",children:s.map(l=>e.jsx(f,{to:E,params:{id:l.id},search:{page:1},children:e.jsx(A,{name:l.name})},l.id))})]})})}const g=D(F),Y=()=>{const i=v(),c=w(),{id:s}=g.useParams(),o=g.useNavigate(),m=I(),{data:n}=h({queryKey:d.images.detail(s??""),async queryFn(){const t=await q(s);if(t.type==="error")throw t;return t.image},enabled:!!s}),{data:r}=h({queryKey:d.images.notes(s??""),async queryFn(){const t=await M(n.url);if(t.type==="error")throw t;return t.imageNotes},enabled:!!n}),l=!r||(r?.length||0)>0,N=async()=>{if(!l&&await i("Are you really sure?")){const t=await G(s);if(t.type==="error"){c(t.errors[0].message);return}if(!t.deleteImage){c("Failed to delete image");return}o({to:u,search:{page:1}})}};return e.jsxs(T,{title:"Image Detail",variant:"none",children:[e.jsxs(f,{to:u,search:{page:1},className:"mb-4 inline-flex items-center gap-1 text-sm font-medium text-fg-secondary transition-colors hover:text-fg-default",children:[e.jsx(S,{size:16}),"Back to Images"]}),e.jsxs("div",{className:"flex flex-col gap-6 lg:flex-row",children:[n&&e.jsx("div",{className:"w-full lg:w-[400px] lg:flex-shrink-0",children:e.jsxs(x,{flush:!0,children:[e.jsx("div",{className:"flex items-center justify-center bg-muted/20 p-4",children:e.jsx(R,{className:"max-h-80 w-auto max-w-full rounded-[14px] object-contain",src:n.url})}),e.jsxs("div",{className:"flex flex-col gap-3 border-t border-border-subtle p-4",children:[e.jsx("div",{className:"flex items-center justify-between",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(z,{size:14,className:"text-fg-tertiary"}),e.jsxs("span",{className:"text-sm font-medium text-fg-secondary",children:[r?.length||0," ",(r?.length||0)===1?"reference":"references"]})]})}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(Z,{content:l?"Cannot delete while referenced by notes":"Delete this image",side:"bottom",children:e.jsxs(p,{variant:"soft-danger",size:"sm",className:"flex-1",disabled:l,onClick:N,children:[e.jsx(k,{size:16}),e.jsx("span",{children:"Delete"})]})}),e.jsxs(p,{variant:"primary",size:"sm",className:"flex-1",onClick:async()=>{await _("heroBanner",n.url),await m.invalidateQueries({queryKey:d.ui.heroBanner(),exact:!0})},children:[e.jsx(L,{size:16,className:"text-fg-secondary"}),e.jsx("span",{children:"Set hero banner"})]})]})]})]})}),e.jsx("div",{className:"flex-1 min-w-0",children:r&&r.length>0?e.jsxs(x,{children:[e.jsx("p",{className:"mb-3 border-b border-border-subtle pb-2 text-sm font-semibold text-fg-default",children:"Referenced Notes"}),e.jsx("ul",{className:"flex flex-col",children:r.map(t=>e.jsx("li",{children:e.jsx(U,{...t})},t.id))})]}):e.jsxs(x,{className:"flex flex-col items-center justify-center p-6 text-center",children:[e.jsx(B,{size:28,className:"mb-2 text-fg-disabled"}),e.jsx("p",{className:"text-sm font-semibold text-fg-secondary",children:"No notes reference this image"}),e.jsx("p",{className:"mt-1 text-sm text-fg-secondary",children:"This image can be safely deleted"})]})})]})]})};export{Y as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as e}from"./note-vendor-BofYbzmZ.js";import{ac as r,A as j,G as N,u as M,I as i,P as C,ad as S,B as h,X as f,Z as w,Y as P}from"./index-DqFkOWbi.js";import{a as g}from"./graph-vendor-CUxe67Lr.js";import{S as c}from"./SurfaceCard-DAcVMY4f.js";import"./note-core-BCgMq5QA.js";const T=async()=>{const{data:s}=await r.get("/api/mcp-admin/status");return s},A=async s=>{const{data:a}=await r.post("/api/mcp-admin/enabled",{enabled:s});return a},F=async()=>{const{data:s}=await r.post("/api/mcp-admin/token/rotate");return s},q=async()=>{const{data:s}=await r.post("/api/mcp-admin/token/revoke");return s},n=["mcp-admin","status"],I=s=>JSON.stringify({mcpServers:{"ocean-brain":{command:"npx",args:["-y","ocean-brain","mcp","--server",s,"--token-file","/path/to/token.txt"]}}},null,2),L=s=>JSON.stringify({mcpServers:{"ocean-brain":{command:"npx",args:["-y","ocean-brain","mcp","--server",s,"--token","your-token-here"]}}},null,2),B=()=>{const s=j(),a=N(),[o,y]=g.useState(()=>window.location.origin),[l,d]=g.useState(""),{data:u,isLoading:v}=M({queryKey:n,queryFn:T}),m=i({mutationFn:A,onSuccess:t=>{a.setQueryData(n,t),s(t.enabled?"MCP access enabled.":"MCP access disabled.")}}),x=i({mutationFn:F,onSuccess:async({token:t})=>{d(t),s("A new MCP token has been issued."),await a.invalidateQueries({queryKey:n})}}),p=i({mutationFn:q,onSuccess:t=>{d(""),a.setQueryData(n,t),s("The active MCP token has been revoked.")}}),b=u?.enabled??!1,k=!v&&!m.isPending;return e.jsx(C,{title:"MCP",variant:"subtle",description:"Manage MCP access and issue a single service token",children:e.jsxs("div",{className:"grid grid-cols-1 gap-4",children:[e.jsx(c,{className:"space-y-4",children:e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-subheading font-semibold text-fg-default",children:"MCP Access"}),e.jsx("p",{className:"text-label font-medium text-fg-tertiary",children:"Allow or block MCP requests at the server level."})]}),e.jsx("div",{className:"inline-flex items-center",children:e.jsx(S,{"aria-label":"Allow MCP access",checked:b,disabled:!k,onCheckedChange:()=>{m.mutate(!b)}})})]})}),e.jsxs(c,{className:"space-y-4",children:[e.jsxs("div",{className:"border-b border-border-subtle pb-4",children:[e.jsx("h2",{className:"text-subheading font-semibold text-fg-default",children:"Token Management"}),e.jsx("p",{className:"text-label font-medium text-fg-tertiary",children:"Ocean Brain supports one active MCP token at a time. Rotating immediately invalidates the previous one."})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx(h,{onClick:()=>x.mutate(void 0),isLoading:x.isPending,children:"Rotate token"}),e.jsx(h,{variant:"soft-danger",onClick:()=>p.mutate(),isLoading:p.isPending,disabled:!u?.hasActiveToken,children:"Revoke token"})]}),l&&e.jsxs("div",{className:"space-y-2",children:[e.jsx(f,{htmlFor:"issued-mcp-token",children:"Issued Token"}),e.jsx(w,{id:"issued-mcp-token",rows:3,readOnly:!0,value:l})]})]}),e.jsxs(c,{className:"space-y-4",children:[e.jsxs("div",{className:"border-b border-border-subtle pb-4",children:[e.jsx("h2",{className:"text-subheading font-semibold text-fg-default",children:"Connection Guide"}),e.jsx("p",{className:"text-label font-medium text-fg-tertiary",children:"How to connect your MCP client to this server."})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(f,{htmlFor:"mcp-server-url",children:"Server URL"}),e.jsx(P,{id:"mcp-server-url",value:o,onChange:t=>y(t.target.value)})]}),e.jsxs("div",{className:"space-y-3",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs("p",{className:"text-body font-semibold text-fg-default",children:["Token file"," ",e.jsx("span",{className:"text-label font-medium text-fg-tertiary",children:"(recommended — keeps token out of config)"})]}),e.jsx("pre",{className:"overflow-x-auto rounded-[14px] border border-border-subtle bg-surface px-4 py-3 text-xs text-fg-secondary",children:I(o)})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs("p",{className:"text-body font-semibold text-fg-default",children:["Inline token"," ",e.jsx("span",{className:"text-label font-medium text-fg-tertiary",children:"(quick local testing)"})]}),e.jsx("pre",{className:"overflow-x-auto rounded-[14px] border border-border-subtle bg-surface px-4 py-3 text-xs text-fg-secondary",children:L(o)})]})]})]})]})})};export{B as default};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import{j as e}from"./note-vendor-BofYbzmZ.js";import{p as D,g as y,A as I,G as O,q as x,an as $,u as H,I as P,P as q,B as f,_ as Z,ao as F,ap as v,o as k,M as p,X as g,Y as j,F as Q,f as T,e as K,aa as B}from"./index-DqFkOWbi.js";import{a as t}from"./graph-vendor-CUxe67Lr.js";import{C as U}from"./Callout-tNHgPhLM.js";import{n as X,M as G}from"./ModalActionRow-B3vNjcDc.js";import{S as C}from"./SurfaceCard-DAcVMY4f.js";import"./note-core-BCgMq5QA.js";const Y=new Map([["bold",t.createElement(t.Fragment,null,t.createElement("path",{d:"M216.49,168.49a12,12,0,0,1-17,0L128,97,56.49,168.49a12,12,0,0,1-17-17l80-80a12,12,0,0,1,17,0l80,80A12,12,0,0,1,216.49,168.49Z"}))],["duotone",t.createElement(t.Fragment,null,t.createElement("path",{d:"M208,160H48l80-80Z",opacity:"0.2"}),t.createElement("path",{d:"M213.66,154.34l-80-80a8,8,0,0,0-11.32,0l-80,80A8,8,0,0,0,48,168H208a8,8,0,0,0,5.66-13.66ZM67.31,152,128,91.31,188.69,152Z"}))],["fill",t.createElement(t.Fragment,null,t.createElement("path",{d:"M215.39,163.06A8,8,0,0,1,208,168H48a8,8,0,0,1-5.66-13.66l80-80a8,8,0,0,1,11.32,0l80,80A8,8,0,0,1,215.39,163.06Z"}))],["light",t.createElement(t.Fragment,null,t.createElement("path",{d:"M212.24,164.24a6,6,0,0,1-8.48,0L128,88.49,52.24,164.24a6,6,0,0,1-8.48-8.48l80-80a6,6,0,0,1,8.48,0l80,80A6,6,0,0,1,212.24,164.24Z"}))],["regular",t.createElement(t.Fragment,null,t.createElement("path",{d:"M213.66,165.66a8,8,0,0,1-11.32,0L128,91.31,53.66,165.66a8,8,0,0,1-11.32-11.32l80-80a8,8,0,0,1,11.32,0l80,80A8,8,0,0,1,213.66,165.66Z"}))],["thin",t.createElement(t.Fragment,null,t.createElement("path",{d:"M210.83,162.83a4,4,0,0,1-5.66,0L128,85.66,50.83,162.83a4,4,0,0,1-5.66-5.66l80-80a4,4,0,0,1,5.66,0l80,80A4,4,0,0,1,210.83,162.83Z"}))]]),A=t.forwardRef((l,r)=>t.createElement(D,{ref:r,...l,weights:Y}));A.displayName="CaretUpIcon";const z=A,S=["id","name","template","replacement","createdAt","updatedAt"],J=new Set(S),V=`query FetchPlaceholders(
|
|
2
|
+
$searchFilter: SearchFilterInput,
|
|
3
|
+
$pagination: PaginationInput
|
|
4
|
+
) {
|
|
5
|
+
allPlaceholders(
|
|
6
|
+
searchFilter: $searchFilter,
|
|
7
|
+
pagination: $pagination
|
|
8
|
+
) {
|
|
9
|
+
totalCount
|
|
10
|
+
placeholders {
|
|
11
|
+
__PLACEHOLDER_FIELDS__ }
|
|
12
|
+
}
|
|
13
|
+
}`,W=l=>{const r=l&&l.length>0?l.filter(n=>J.has(n)):S;return Array.from(new Set(r)).map(n=>" "+n).join(`
|
|
14
|
+
`)+`
|
|
15
|
+
`},ee=async({limit:l=25,offset:r=0,query:d="",fields:n}={})=>{const h=W(n),c=V.replace("__PLACEHOLDER_FIELDS__",h);return y(c,{searchFilter:{query:d},pagination:{limit:l,offset:r}})},te=l=>y(`mutation CreatePlaceholder(
|
|
16
|
+
$name: String!,
|
|
17
|
+
$template: String!,
|
|
18
|
+
$replacement: String!
|
|
19
|
+
) {
|
|
20
|
+
createPlaceholder(
|
|
21
|
+
name: $name,
|
|
22
|
+
template: $template,
|
|
23
|
+
replacement: $replacement
|
|
24
|
+
) {
|
|
25
|
+
id
|
|
26
|
+
name
|
|
27
|
+
template
|
|
28
|
+
replacement
|
|
29
|
+
createdAt
|
|
30
|
+
updatedAt
|
|
31
|
+
}
|
|
32
|
+
}`,l),ae=l=>y(`mutation DeletePlaceholder($id: ID!) {
|
|
33
|
+
deletePlaceholder(id: $id)
|
|
34
|
+
}`,{id:l}),L=K(B),de=()=>{const l=I(),r=O(),d=L.useNavigate(),{page:n}=L.useSearch(),[h,c]=t.useState(!1),[u,b]=t.useState(!1),[s,m]=t.useState({name:"",template:"",replacement:""}),i=25,_=x.placeholders.list({limit:i,offset:(n-1)*i}),[w]=t.useState($),{data:o,isLoading:N}=H({queryKey:_,queryFn:async()=>{const a=await ee({offset:(n-1)*i,limit:i});if(a.type==="error")throw a;return a.allPlaceholders}}),E=P({mutationFn:te,onSuccess:async()=>{l("Placeholder added successfully"),c(!1),m({name:"",template:"",replacement:""}),await r.invalidateQueries({queryKey:x.placeholders.listAll(),exact:!1})}}),M=P({mutationFn:ae,onSuccess:async()=>{l("Placeholder deleted successfully"),await r.invalidateQueries({queryKey:x.placeholders.listAll(),exact:!1})}});return e.jsxs(q,{title:"Placeholders",variant:"subtle",description:"Manage template variables for note cloning",children:[e.jsx(U,{className:"mb-4",children:e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("span",{children:"Placeholders will be replaced with new note data during cloning."}),e.jsx(f,{variant:"subtle",size:"icon-sm",onClick:()=>c(!0),children:e.jsx(X,{width:20,height:20})})]})}),e.jsxs("div",{className:"mt-3 flex flex-col gap-3",children:[e.jsxs("button",{type:"button",onClick:()=>b(!u),className:"focus-ring-soft surface-base flex items-center justify-between gap-2 rounded-[18px] px-4 py-3 text-left text-sm font-semibold text-fg-default transition-colors hover:bg-hover-subtle",children:[e.jsx("div",{children:"System Placeholders"}),e.jsx("div",{className:"flex h-6 w-6 items-center justify-center text-fg-tertiary",children:u?e.jsx(z,{}):e.jsx(Z,{})})]}),u&&e.jsx("div",{className:"grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3",children:w.map(a=>e.jsxs(C,{children:[e.jsx("div",{className:"text-sm font-semibold text-fg-default",children:a.name}),e.jsxs("div",{className:"text-xs font-medium text-fg-tertiary",children:[F,a.template,v," = '",a.replacement,"'"]})]},a.name))}),!N&&o?.placeholders&&o.placeholders.length>0&&e.jsx("div",{className:"grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3",children:o.placeholders.map(a=>e.jsxs(C,{className:"relative",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("div",{className:"text-sm font-semibold text-fg-default",children:a.name}),e.jsx("button",{type:"button",className:"focus-ring-soft inline-flex h-8 w-8 items-center justify-center rounded-[10px] text-fg-tertiary transition-colors hover:bg-hover-subtle hover:text-fg-default",onClick:()=>M.mutate(a.id.toString()),children:e.jsx(k,{})})]}),e.jsxs("div",{className:"text-xs font-medium text-fg-tertiary",children:[F,a.template,v," = '",a.replacement,"'"]})]},a.id))})]}),e.jsxs(p,{isOpen:h,onClose:()=>c(!1),children:[e.jsx(p.Header,{title:"Add Placeholder",onClose:()=>c(!1)}),e.jsx(p.Body,{children:e.jsxs("div",{className:"flex flex-col gap-3",children:[e.jsx(g,{htmlFor:"name",children:"Name:"}),e.jsx(j,{id:"name",type:"text",value:s.name,onChange:a=>m({...s,name:a.target.value}),placeholder:"Description of this placeholder"}),e.jsx(g,{htmlFor:"template",children:"Placeholder:"}),e.jsx(j,{id:"template",type:"text",value:s.template,onChange:a=>m({...s,template:a.target.value}),placeholder:"note_app"}),e.jsx(g,{htmlFor:"replacement",children:"Replacement:"}),e.jsx(j,{id:"replacement",type:"text",value:s.replacement,onChange:a=>m({...s,replacement:a.target.value}),placeholder:"Ocean Brain"})]})}),e.jsx(p.Footer,{children:e.jsxs(G,{children:[e.jsx(f,{variant:"ghost",onClick:()=>c(!1),children:"Cancel"}),e.jsx(f,{variant:"primary",isLoading:E.isPending,onClick:()=>{if(!s.name||!s.template||!s.replacement){l("All fields are required");return}E.mutate({name:s.name,template:s.template,replacement:s.replacement})},children:"Add"})]})})]}),e.jsx(Q,{fallback:null,children:o?.totalCount&&i<o.totalCount&&e.jsx(T,{page:n,last:Math.ceil(o.totalCount/i),onChange:a=>{d({search:R=>({...R,page:a})})}})})]})};export{de as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{j as e}from"./note-vendor-BofYbzmZ.js";import{P as x,Q as p,S as d,e as f,a3 as y,G as g,A as j,k as b,ae as v,q as i,I as N,af as T,N as S,F as q,a4 as E,B as R,f as Q,E as w,d as C}from"./index-DqFkOWbi.js";import"./graph-vendor-CUxe67Lr.js";import{S as K}from"./SurfaceCard-DAcVMY4f.js";import"./note-core-BCgMq5QA.js";const a=25,c=f(y),m=t=>C(t).format("YYYY-MM-DD HH:mm"),k=()=>{const{page:t}=c.useSearch(),u=c.useNavigate(),r=g(),h=j(),{data:l}=b({queryKey:i.notes.trash({limit:a,offset:(t-1)*a}),queryFn:async()=>{const s=await v({limit:a,offset:(t-1)*a});if(s.type==="error")throw s;return s.trashedNotes}}),o=N({mutationFn:T,onSuccess:async s=>{if(s.type==="error")throw s;await Promise.all([r.invalidateQueries({queryKey:i.notes.all(),exact:!1}),r.invalidateQueries({queryKey:i.tags.all(),exact:!1}),r.invalidateQueries({queryKey:i.reminders.all(),exact:!1}),r.invalidateQueries({queryKey:i.images.all(),exact:!1}),r.invalidateQueries({queryKey:["calendar"],exact:!1})]),h("The note has been restored."),u({to:S,params:{id:s.restoreTrashedNote.id}})},onError:()=>{h("Failed to restore the note.")}});return e.jsx(q,{fallback:e.jsx(w,{title:"Trash is empty",description:"Deleted notes stay here until you restore them or retention cleanup removes them."}),children:l.notes.length>0&&e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"grid gap-4",children:l.notes.map(s=>e.jsx(K,{children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("h2",{className:"text-subheading font-semibold text-fg-default",children:s.title}),s.pinned&&e.jsxs("span",{className:"text-label inline-flex items-center gap-1 rounded-full border border-border-subtle bg-hover-subtle px-2 py-0.5 font-medium text-fg-secondary",children:[e.jsx(E,{className:"h-3.5 w-3.5"}),"Pinned"]})]}),e.jsxs("div",{className:"text-meta text-fg-secondary",children:["Deleted ",m(s.deletedAt)]}),e.jsxs("div",{className:"text-label text-fg-tertiary",children:["Last edited ",m(s.updatedAt)]}),s.tagNames.length>0&&e.jsx("div",{className:"flex flex-wrap gap-2",children:s.tagNames.map(n=>e.jsx("span",{className:"text-label rounded-full border border-border-subtle bg-hover-subtle px-2 py-0.5 font-medium text-fg-secondary",children:n},`${s.id}-${n}`))})]}),e.jsx(R,{variant:"subtle",isLoading:o.isPending&&o.variables===s.id,onClick:()=>o.mutate(s.id),children:"Restore"})]})},s.id))}),l.totalCount>a&&e.jsx(Q,{page:t,last:Math.ceil(l.totalCount/a),onChange:s=>{u({search:n=>({...n,page:s})})}})]})})},Y=()=>{const{page:t}=c.useSearch();return e.jsx(x,{title:"Trash",variant:"subtle",description:"Restore notes removed from your active workspace before retention cleanup clears them",children:e.jsx(p,{fallback:e.jsxs("div",{className:"grid gap-4",children:[e.jsx(d,{height:"128px"}),e.jsx(d,{height:"128px"}),e.jsx(d,{height:"128px"})]}),errorTitle:"Failed to load trash",errorDescription:"Retry loading deleted notes.",resetKeys:[t],children:e.jsx(k,{})})})};export{Y as default};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import{a as n}from"./graph-vendor-CUxe67Lr.js";import{p as f,g as c,k as R,q as a,A as V,G as $}from"./index-DqFkOWbi.js";import{j as y}from"./note-vendor-BofYbzmZ.js";const h=new Map([["bold",n.createElement(n.Fragment,null,n.createElement("path",{d:"M216.49,79.52l-56-56A12,12,0,0,0,152,20H56A20,20,0,0,0,36,40V216a20,20,0,0,0,20,20H200a20,20,0,0,0,20-20V88A12,12,0,0,0,216.49,79.52ZM160,57l23,23H160ZM60,212V44h76V92a12,12,0,0,0,12,12h48V212Z"}))],["duotone",n.createElement(n.Fragment,null,n.createElement("path",{d:"M208,88H152V32Z",opacity:"0.2"}),n.createElement("path",{d:"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Z"}))],["fill",n.createElement(n.Fragment,null,n.createElement("path",{d:"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM152,88V44l44,44Z"}))],["light",n.createElement(n.Fragment,null,n.createElement("path",{d:"M212.24,83.76l-56-56A6,6,0,0,0,152,26H56A14,14,0,0,0,42,40V216a14,14,0,0,0,14,14H200a14,14,0,0,0,14-14V88A6,6,0,0,0,212.24,83.76ZM158,46.48,193.52,82H158ZM200,218H56a2,2,0,0,1-2-2V40a2,2,0,0,1,2-2h90V88a6,6,0,0,0,6,6h50V216A2,2,0,0,1,200,218Z"}))],["regular",n.createElement(n.Fragment,null,n.createElement("path",{d:"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Z"}))],["thin",n.createElement(n.Fragment,null,n.createElement("path",{d:"M210.83,85.17l-56-56A4,4,0,0,0,152,28H56A12,12,0,0,0,44,40V216a12,12,0,0,0,12,12H200a12,12,0,0,0,12-12V88A4,4,0,0,0,210.83,85.17ZM156,41.65,198.34,84H156ZM200,220H56a4,4,0,0,1-4-4V40a4,4,0,0,1,4-4h92V88a4,4,0,0,0,4,4h52V216A4,4,0,0,1,200,220Z"}))]]),g=n.forwardRef((e,t)=>n.createElement(f,{ref:t,...e,weights:h}));g.displayName="FileIcon";const w=g,A=(e={})=>({limit:e.limit??10,offset:e.offset??0}),H=async(e,t)=>c(`
|
|
2
|
+
query FetchNoteReminders($noteId: ID!, $pagination: PaginationInput) {
|
|
3
|
+
noteReminders(noteId: $noteId, pagination: $pagination) {
|
|
4
|
+
totalCount
|
|
5
|
+
reminders {
|
|
6
|
+
id
|
|
7
|
+
noteId
|
|
8
|
+
reminderDate
|
|
9
|
+
priority
|
|
10
|
+
content
|
|
11
|
+
completed
|
|
12
|
+
createdAt
|
|
13
|
+
updatedAt
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
`,{noteId:e,pagination:A(t)}),D=async e=>c(`
|
|
18
|
+
query FetchUpcomingReminders($pagination: PaginationInput) {
|
|
19
|
+
upcomingReminders(pagination: $pagination) {
|
|
20
|
+
totalCount
|
|
21
|
+
reminders {
|
|
22
|
+
id
|
|
23
|
+
noteId
|
|
24
|
+
reminderDate
|
|
25
|
+
priority
|
|
26
|
+
content
|
|
27
|
+
completed
|
|
28
|
+
createdAt
|
|
29
|
+
updatedAt
|
|
30
|
+
note {
|
|
31
|
+
id
|
|
32
|
+
title
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
`,{pagination:A(e)}),M=async e=>{const{noteId:t,reminderDate:o,priority:s="medium",content:i}=e;return c(`
|
|
38
|
+
mutation CreateReminder($noteId: ID!, $reminderDate: String!, $priority: ReminderPriority, $content: String) {
|
|
39
|
+
createReminder(
|
|
40
|
+
noteId: $noteId,
|
|
41
|
+
reminderDate: $reminderDate,
|
|
42
|
+
priority: $priority,
|
|
43
|
+
content: $content
|
|
44
|
+
) {
|
|
45
|
+
id
|
|
46
|
+
noteId
|
|
47
|
+
reminderDate
|
|
48
|
+
completed
|
|
49
|
+
priority
|
|
50
|
+
createdAt
|
|
51
|
+
updatedAt
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
`,{noteId:t,reminderDate:o.toISOString(),priority:s,content:i})},Z=async({id:e,reminderDate:t,completed:o,priority:s,content:i})=>{const r={id:e};return t&&(r.reminderDate=t.toISOString()),o!==void 0&&(r.completed=o),s&&(r.priority=s),i!==void 0&&(r.content=i),c(`
|
|
55
|
+
mutation UpdateReminder(
|
|
56
|
+
$id: ID!,
|
|
57
|
+
$reminderDate: String,
|
|
58
|
+
$completed: Boolean,
|
|
59
|
+
$priority: ReminderPriority,
|
|
60
|
+
$content: String
|
|
61
|
+
) {
|
|
62
|
+
updateReminder(
|
|
63
|
+
id: $id,
|
|
64
|
+
reminderDate: $reminderDate,
|
|
65
|
+
completed: $completed,
|
|
66
|
+
priority: $priority,
|
|
67
|
+
content: $content
|
|
68
|
+
) {
|
|
69
|
+
id
|
|
70
|
+
noteId
|
|
71
|
+
reminderDate
|
|
72
|
+
completed
|
|
73
|
+
priority
|
|
74
|
+
createdAt
|
|
75
|
+
updatedAt
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
`,r)},I=async e=>c(`
|
|
79
|
+
mutation DeleteReminder($id: ID!) {
|
|
80
|
+
deleteReminder(id: $id)
|
|
81
|
+
}
|
|
82
|
+
`,{id:e});function v({noteId:e,searchParams:t,render:o}){const{data:s}=R({queryKey:e?a.reminders.note(e,t):a.reminders.upcoming(t),queryFn:async()=>{if(e){const r=await H(e,t);if(r.type==="error")throw r;return r.noteReminders}const i=await D(t);if(i.type==="error")throw i;return i.upcomingReminders}});return y.jsx(y.Fragment,{children:o(s)})}function Q(){const e=V(),t=$(),o=n.useCallback(async(r,m,l="medium",d,u)=>{const p=await M({noteId:r,reminderDate:m,priority:l,content:u});if(p.type==="error"){e(p.errors[0].message);return}await Promise.all([t.invalidateQueries({queryKey:a.reminders.noteAllPages(r),exact:!1}),t.invalidateQueries({queryKey:a.reminders.upcomingAllPages(),exact:!1}),t.invalidateQueries({queryKey:a.reminders.inDateRangeAll(),exact:!1})]),d&&d()},[t,e]),s=n.useCallback(async(r,m,l,d)=>{const u=await Z({id:r,...l});if(u.type==="error"){e(u.errors[0].message);return}await Promise.all([t.invalidateQueries({queryKey:a.reminders.noteAllPages(m),exact:!1}),t.invalidateQueries({queryKey:a.reminders.upcomingAllPages(),exact:!1}),t.invalidateQueries({queryKey:a.reminders.inDateRangeAll(),exact:!1})]),d&&d()},[t,e]),i=n.useCallback(async(r,m,l)=>{const d=await I(r);if(d.type==="error"){e(d.errors[0].message);return}await Promise.all([t.invalidateQueries({queryKey:a.reminders.noteAllPages(m),exact:!1}),t.invalidateQueries({queryKey:a.reminders.upcomingAllPages(),exact:!1}),t.invalidateQueries({queryKey:a.reminders.inDateRangeAll(),exact:!1})]),l&&l()},[t,e]);return{onCreate:o,onUpdate:s,onDelete:i}}export{v as R,w as s,Q as u};
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
<link rel="icon" type="image/png" href="/icon.png" />
|
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
8
8
|
<title>Ocean Brain</title>
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-DqFkOWbi.js"></script>
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/graph-vendor-CUxe67Lr.js">
|
|
11
11
|
<link rel="modulepreload" crossorigin href="/assets/note-core-BCgMq5QA.js">
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/assets/note-vendor-BofYbzmZ.js">
|
|
13
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
13
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DAZMX8bQ.css">
|
|
14
14
|
</head>
|
|
15
15
|
|
|
16
16
|
<body>
|
|
@@ -1,4 +1,33 @@
|
|
|
1
1
|
import { ServerBlockNoteEditor } from "@blocknote/server-util";
|
|
2
|
+
import models from "../models.js";
|
|
3
|
+
import { ensureTagByName } from "./tag-organization.js";
|
|
4
|
+
const UNSUPPORTED_MARKDOWN_BLOCK_TYPES = /* @__PURE__ */ new Set([
|
|
5
|
+
"tableOfContents"
|
|
6
|
+
]);
|
|
7
|
+
const defaultMarkdownImportDeps = {
|
|
8
|
+
ensureTag: async (name) => ensureTagByName(name),
|
|
9
|
+
findNotesByTitle: async (title) => {
|
|
10
|
+
const notes = await models.note.findMany({
|
|
11
|
+
select: {
|
|
12
|
+
id: true,
|
|
13
|
+
title: true
|
|
14
|
+
},
|
|
15
|
+
where: { title },
|
|
16
|
+
orderBy: { createdAt: "asc" },
|
|
17
|
+
take: 2
|
|
18
|
+
});
|
|
19
|
+
return notes.map((note) => ({
|
|
20
|
+
id: String(note.id),
|
|
21
|
+
title: note.title
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
function stripUnsupportedMarkdownBlocks(blocks) {
|
|
26
|
+
return blocks.filter((block) => !UNSUPPORTED_MARKDOWN_BLOCK_TYPES.has(block.type)).map((block) => ({
|
|
27
|
+
...block,
|
|
28
|
+
children: block.children?.length ? stripUnsupportedMarkdownBlocks(block.children) : []
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
2
31
|
function preprocessCustomInlineContent(blocks) {
|
|
3
32
|
return blocks.map((block) => ({
|
|
4
33
|
...block,
|
|
@@ -23,6 +52,116 @@ function preprocessCustomInlineContent(blocks) {
|
|
|
23
52
|
children: block.children?.length ? preprocessCustomInlineContent(block.children) : []
|
|
24
53
|
}));
|
|
25
54
|
}
|
|
55
|
+
function createTextInline(text, styles = {}) {
|
|
56
|
+
return {
|
|
57
|
+
type: "text",
|
|
58
|
+
text,
|
|
59
|
+
styles
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function appendInline(target, inline) {
|
|
63
|
+
const previous = target.at(-1);
|
|
64
|
+
if (previous?.type === "text" && inline.type === "text" && previous.text !== void 0 && inline.text !== void 0 && JSON.stringify(previous.styles ?? {}) === JSON.stringify(inline.styles ?? {})) {
|
|
65
|
+
previous.text += inline.text;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
target.push(inline);
|
|
69
|
+
}
|
|
70
|
+
async function restoreCustomInlineContent(blocks, deps) {
|
|
71
|
+
const tagCache = /* @__PURE__ */ new Map();
|
|
72
|
+
const noteCache = /* @__PURE__ */ new Map();
|
|
73
|
+
const getTag = (token) => {
|
|
74
|
+
let existing = tagCache.get(token);
|
|
75
|
+
if (!existing) {
|
|
76
|
+
existing = deps.ensureTag(token.slice(1)).then((result) => ({
|
|
77
|
+
id: "tag" in result ? result.tag.id : result.id,
|
|
78
|
+
tag: "tag" in result ? result.tag.name : result.name
|
|
79
|
+
}));
|
|
80
|
+
tagCache.set(token, existing);
|
|
81
|
+
}
|
|
82
|
+
return existing;
|
|
83
|
+
};
|
|
84
|
+
const getNotesByTitle = (title) => {
|
|
85
|
+
let existing = noteCache.get(title);
|
|
86
|
+
if (!existing) {
|
|
87
|
+
existing = deps.findNotesByTitle(title);
|
|
88
|
+
noteCache.set(title, existing);
|
|
89
|
+
}
|
|
90
|
+
return existing;
|
|
91
|
+
};
|
|
92
|
+
const restoreTextInline = async (inline) => {
|
|
93
|
+
if (inline.type !== "text" || typeof inline.text !== "string" || !inline.text || inline.styles?.code === true) {
|
|
94
|
+
return [inline];
|
|
95
|
+
}
|
|
96
|
+
const restored = [];
|
|
97
|
+
const styles = inline.styles ?? {};
|
|
98
|
+
let cursor = 0;
|
|
99
|
+
while (cursor < inline.text.length) {
|
|
100
|
+
if (inline.text.startsWith("[[", cursor)) {
|
|
101
|
+
const closeIndex = inline.text.indexOf("]]", cursor + 2);
|
|
102
|
+
if (closeIndex !== -1) {
|
|
103
|
+
const title = inline.text.slice(cursor + 2, closeIndex);
|
|
104
|
+
const matchingNotes = await getNotesByTitle(title);
|
|
105
|
+
if (matchingNotes.length === 1) {
|
|
106
|
+
appendInline(restored, {
|
|
107
|
+
type: "reference",
|
|
108
|
+
props: {
|
|
109
|
+
id: matchingNotes[0].id,
|
|
110
|
+
title: matchingNotes[0].title
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
cursor = closeIndex + 2;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (inline.text[cursor] === "#" && (cursor === 0 || /\s/.test(inline.text[cursor - 1]))) {
|
|
119
|
+
const remainder = inline.text.slice(cursor);
|
|
120
|
+
const tagMatch = remainder.match(/^#[^\s[\]]+/);
|
|
121
|
+
if (tagMatch) {
|
|
122
|
+
const tag = await getTag(tagMatch[0]);
|
|
123
|
+
appendInline(restored, {
|
|
124
|
+
type: "tag",
|
|
125
|
+
props: tag
|
|
126
|
+
});
|
|
127
|
+
cursor += tagMatch[0].length;
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
let nextCursor = cursor + 1;
|
|
132
|
+
while (nextCursor < inline.text.length && !inline.text.startsWith("[[", nextCursor) && !(inline.text[nextCursor] === "#" && /\s/.test(inline.text[nextCursor - 1] ?? ""))) {
|
|
133
|
+
nextCursor += 1;
|
|
134
|
+
}
|
|
135
|
+
appendInline(restored, createTextInline(inline.text.slice(cursor, nextCursor), styles));
|
|
136
|
+
cursor = nextCursor;
|
|
137
|
+
}
|
|
138
|
+
return restored;
|
|
139
|
+
};
|
|
140
|
+
return Promise.all(
|
|
141
|
+
blocks.map(async (block) => ({
|
|
142
|
+
...block,
|
|
143
|
+
content: block.content ? (await Promise.all(block.content.map((inline) => restoreTextInline(inline)))).flat() : void 0,
|
|
144
|
+
children: block.children?.length ? await restoreCustomInlineContent(block.children, deps) : []
|
|
145
|
+
}))
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
function collectTagIds(blocks) {
|
|
149
|
+
const tagIds = /* @__PURE__ */ new Set();
|
|
150
|
+
const visit = (items) => {
|
|
151
|
+
for (const block of items) {
|
|
152
|
+
for (const inline of block.content ?? []) {
|
|
153
|
+
if (inline.type === "tag" && typeof inline.props?.id === "string") {
|
|
154
|
+
tagIds.add(inline.props.id);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (block.children?.length) {
|
|
158
|
+
visit(block.children);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
visit(blocks);
|
|
163
|
+
return [...tagIds];
|
|
164
|
+
}
|
|
26
165
|
let editorInstance = null;
|
|
27
166
|
function getEditor() {
|
|
28
167
|
if (!editorInstance) {
|
|
@@ -33,20 +172,27 @@ function getEditor() {
|
|
|
33
172
|
async function blocksToMarkdown(contentJson) {
|
|
34
173
|
try {
|
|
35
174
|
const blocks = JSON.parse(contentJson);
|
|
36
|
-
const
|
|
175
|
+
const supportedBlocks = stripUnsupportedMarkdownBlocks(blocks);
|
|
176
|
+
const processed = preprocessCustomInlineContent(supportedBlocks);
|
|
37
177
|
const editor = getEditor();
|
|
38
178
|
return await editor.blocksToMarkdownLossy(processed);
|
|
39
179
|
} catch {
|
|
40
180
|
return "";
|
|
41
181
|
}
|
|
42
182
|
}
|
|
43
|
-
async function markdownToBlocksJson(markdown) {
|
|
183
|
+
async function markdownToBlocksJson(markdown, deps = defaultMarkdownImportDeps) {
|
|
44
184
|
const editor = getEditor();
|
|
45
185
|
const blocks = await editor.tryParseMarkdownToBlocks(markdown);
|
|
46
|
-
|
|
186
|
+
const restoredBlocks = await restoreCustomInlineContent(blocks, deps);
|
|
187
|
+
return JSON.stringify(restoredBlocks);
|
|
188
|
+
}
|
|
189
|
+
function extractTagIdsFromContentJson(contentJson) {
|
|
190
|
+
const blocks = JSON.parse(contentJson);
|
|
191
|
+
return collectTagIds(blocks);
|
|
47
192
|
}
|
|
48
193
|
export {
|
|
49
194
|
blocksToMarkdown,
|
|
195
|
+
extractTagIdsFromContentJson,
|
|
50
196
|
markdownToBlocksJson
|
|
51
197
|
};
|
|
52
198
|
//# sourceMappingURL=blocknote.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/modules/blocknote.ts"],"sourcesContent":["import { ServerBlockNoteEditor } from '@blocknote/server-util';\n\ninterface BlockNote {\n id?: string;\n type: string;\n props?: Record<string, unknown>;\n content?: BlockNote[];\n children?: BlockNote[];\n text?: string;\n styles?: Record<string, unknown>;\n}\n\nfunction preprocessCustomInlineContent(blocks: BlockNote[]): BlockNote[] {\n return blocks.map((block) => ({\n ...block,\n content: block.content?.map((inline) => {\n if (inline.type === 'reference') {\n return {\n type: 'text',\n text: `[[${inline.props?.title || inline.props?.id || ''}]]`,\n styles: {}\n };\n }\n if (inline.type === 'tag') {\n const tag = (inline.props?.tag as string)?.replace(/^@/, '') || '';\n return {\n type: 'text',\n text: `#${tag}`,\n styles: {}\n };\n }\n return inline;\n }),\n children: block.children?.length\n ? preprocessCustomInlineContent(block.children)\n : []\n }));\n}\n\nlet editorInstance: ServerBlockNoteEditor | null = null;\n\nfunction getEditor(): ServerBlockNoteEditor {\n if (!editorInstance) {\n editorInstance = ServerBlockNoteEditor.create();\n }\n return editorInstance;\n}\n\nexport async function blocksToMarkdown(contentJson: string): Promise<string> {\n try {\n const blocks = JSON.parse(contentJson);\n const processed = preprocessCustomInlineContent(blocks);\n const editor = getEditor();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return await editor.blocksToMarkdownLossy(processed as any);\n } catch {\n return '';\n }\n}\n\nexport async function markdownToBlocksJson(markdown: string): Promise<string> {\n const editor = getEditor();\n const blocks = await editor.tryParseMarkdownToBlocks(markdown);\n return JSON.stringify(blocks);\n}\n"],"mappings":"AAAA,SAAS,6BAA6B;AAYtC,SAAS,8BAA8B,QAAkC;AACrE,SAAO,OAAO,IAAI,CAAC,WAAW;AAAA,IAC1B,GAAG;AAAA,IACH,SAAS,MAAM,SAAS,IAAI,CAAC,WAAW;AACpC,UAAI,OAAO,SAAS,aAAa;AAC7B,eAAO;AAAA,UACH,MAAM;AAAA,UACN,MAAM,KAAK,OAAO,OAAO,SAAS,OAAO,OAAO,MAAM,EAAE;AAAA,UACxD,QAAQ,CAAC;AAAA,QACb;AAAA,MACJ;AACA,UAAI,OAAO,SAAS,OAAO;AACvB,cAAM,MAAO,OAAO,OAAO,KAAgB,QAAQ,MAAM,EAAE,KAAK;AAChE,eAAO;AAAA,UACH,MAAM;AAAA,UACN,MAAM,IAAI,GAAG;AAAA,UACb,QAAQ,CAAC;AAAA,QACb;AAAA,MACJ;AACA,aAAO;AAAA,IACX,CAAC;AAAA,IACD,UAAU,MAAM,UAAU,SACpB,8BAA8B,MAAM,QAAQ,IAC5C,CAAC;AAAA,EACX,EAAE;AACN;AAEA,IAAI,iBAA+C;AAEnD,SAAS,YAAmC;AACxC,MAAI,CAAC,gBAAgB;AACjB,qBAAiB,sBAAsB,OAAO;AAAA,EAClD;AACA,SAAO;AACX;AAEA,eAAsB,iBAAiB,aAAsC;AACzE,MAAI;AACA,UAAM,SAAS,KAAK,MAAM,WAAW;AACrC,UAAM,YAAY,8BAA8B,MAAM;AACtD,UAAM,SAAS,UAAU;AAEzB,WAAO,MAAM,OAAO,sBAAsB,SAAgB;AAAA,EAC9D,QAAQ;AACJ,WAAO;AAAA,EACX;AACJ;AAEA,eAAsB,qBAAqB,UAAmC;AAC1E,QAAM,SAAS,UAAU;AACzB,QAAM,SAAS,MAAM,OAAO,yBAAyB,QAAQ;AAC7D,SAAO,KAAK,UAAU,MAAM;AAChC;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/modules/blocknote.ts"],"sourcesContent":["import { ServerBlockNoteEditor } from '@blocknote/server-util';\n\nimport models from '~/models.js';\nimport { ensureTagByName } from './tag-organization.js';\n\ninterface BlockNote {\n id?: string;\n type: string;\n props?: Record<string, unknown>;\n content?: BlockNoteInline[];\n children?: BlockNote[];\n text?: string;\n styles?: Record<string, unknown>;\n}\n\ninterface BlockNoteInline {\n type: string;\n props?: Record<string, unknown>;\n text?: string;\n styles?: Record<string, unknown>;\n}\n\ninterface MarkdownImportDeps {\n ensureTag: (name: string) => Promise<\n | {\n id: string;\n name: string;\n }\n | {\n tag: {\n id: string;\n name: string;\n };\n }\n >;\n findNotesByTitle: (title: string) => Promise<Array<{\n id: string;\n title: string;\n }>>;\n}\n\nconst UNSUPPORTED_MARKDOWN_BLOCK_TYPES = new Set([\n 'tableOfContents'\n]);\n\nconst defaultMarkdownImportDeps: MarkdownImportDeps = {\n ensureTag: async (name) => ensureTagByName(name),\n findNotesByTitle: async (title) => {\n const notes = await models.note.findMany({\n select: {\n id: true,\n title: true\n },\n where: { title },\n orderBy: { createdAt: 'asc' },\n take: 2\n });\n\n return notes.map((note) => ({\n id: String(note.id),\n title: note.title\n }));\n }\n};\n\nfunction stripUnsupportedMarkdownBlocks(blocks: BlockNote[]): BlockNote[] {\n return blocks\n .filter((block) => !UNSUPPORTED_MARKDOWN_BLOCK_TYPES.has(block.type))\n .map((block) => ({\n ...block,\n children: block.children?.length\n ? stripUnsupportedMarkdownBlocks(block.children)\n : []\n }));\n}\n\nfunction preprocessCustomInlineContent(blocks: BlockNote[]): BlockNote[] {\n return blocks.map((block) => ({\n ...block,\n content: block.content?.map((inline) => {\n if (inline.type === 'reference') {\n return {\n type: 'text',\n text: `[[${inline.props?.title || inline.props?.id || ''}]]`,\n styles: {}\n };\n }\n if (inline.type === 'tag') {\n const tag = (inline.props?.tag as string)?.replace(/^@/, '') || '';\n return {\n type: 'text',\n text: `#${tag}`,\n styles: {}\n };\n }\n return inline;\n }),\n children: block.children?.length\n ? preprocessCustomInlineContent(block.children)\n : []\n }));\n}\n\nfunction createTextInline(text: string, styles: Record<string, unknown> = {}): BlockNoteInline {\n return {\n type: 'text',\n text,\n styles\n };\n}\n\nfunction appendInline(target: BlockNoteInline[], inline: BlockNoteInline) {\n const previous = target.at(-1);\n\n if (\n previous?.type === 'text' &&\n inline.type === 'text' &&\n previous.text !== undefined &&\n inline.text !== undefined &&\n JSON.stringify(previous.styles ?? {}) === JSON.stringify(inline.styles ?? {})\n ) {\n previous.text += inline.text;\n return;\n }\n\n target.push(inline);\n}\n\nasync function restoreCustomInlineContent(\n blocks: BlockNote[],\n deps: MarkdownImportDeps\n): Promise<BlockNote[]> {\n const tagCache = new Map<string, Promise<{ id: string; tag: string }>>();\n const noteCache = new Map<string, Promise<Array<{ id: string; title: string }>>>();\n\n const getTag = (token: string) => {\n let existing = tagCache.get(token);\n\n if (!existing) {\n existing = deps.ensureTag(token.slice(1)).then((result) => ({\n id: 'tag' in result ? result.tag.id : result.id,\n tag: 'tag' in result ? result.tag.name : result.name\n }));\n tagCache.set(token, existing);\n }\n\n return existing;\n };\n\n const getNotesByTitle = (title: string) => {\n let existing = noteCache.get(title);\n\n if (!existing) {\n existing = deps.findNotesByTitle(title);\n noteCache.set(title, existing);\n }\n\n return existing;\n };\n\n const restoreTextInline = async (inline: BlockNoteInline): Promise<BlockNoteInline[]> => {\n if (\n inline.type !== 'text' ||\n typeof inline.text !== 'string' ||\n !inline.text ||\n inline.styles?.code === true\n ) {\n return [inline];\n }\n\n const restored: BlockNoteInline[] = [];\n const styles = inline.styles ?? {};\n let cursor = 0;\n\n while (cursor < inline.text.length) {\n if (\n inline.text.startsWith('[[', cursor)\n ) {\n const closeIndex = inline.text.indexOf(']]', cursor + 2);\n\n if (closeIndex !== -1) {\n const title = inline.text.slice(cursor + 2, closeIndex);\n const matchingNotes = await getNotesByTitle(title);\n\n if (matchingNotes.length === 1) {\n appendInline(restored, {\n type: 'reference',\n props: {\n id: matchingNotes[0].id,\n title: matchingNotes[0].title\n }\n });\n cursor = closeIndex + 2;\n continue;\n }\n }\n }\n\n if (\n inline.text[cursor] === '#' &&\n (cursor === 0 || /\\s/.test(inline.text[cursor - 1]))\n ) {\n const remainder = inline.text.slice(cursor);\n const tagMatch = remainder.match(/^#[^\\s[\\]]+/);\n\n if (tagMatch) {\n const tag = await getTag(tagMatch[0]);\n appendInline(restored, {\n type: 'tag',\n props: tag\n });\n cursor += tagMatch[0].length;\n continue;\n }\n }\n\n let nextCursor = cursor + 1;\n\n while (\n nextCursor < inline.text.length &&\n !inline.text.startsWith('[[', nextCursor) &&\n !(\n inline.text[nextCursor] === '#' &&\n /\\s/.test(inline.text[nextCursor - 1] ?? '')\n )\n ) {\n nextCursor += 1;\n }\n\n appendInline(restored, createTextInline(inline.text.slice(cursor, nextCursor), styles));\n cursor = nextCursor;\n }\n\n return restored;\n };\n\n return Promise.all(\n blocks.map(async (block) => ({\n ...block,\n content: block.content\n ? (await Promise.all(block.content.map((inline) => restoreTextInline(inline)))).flat()\n : undefined,\n children: block.children?.length\n ? await restoreCustomInlineContent(block.children, deps)\n : []\n }))\n );\n}\n\nfunction collectTagIds(blocks: BlockNote[]): string[] {\n const tagIds = new Set<string>();\n\n const visit = (items: BlockNote[]) => {\n for (const block of items) {\n for (const inline of block.content ?? []) {\n if (inline.type === 'tag' && typeof inline.props?.id === 'string') {\n tagIds.add(inline.props.id);\n }\n }\n\n if (block.children?.length) {\n visit(block.children);\n }\n }\n };\n\n visit(blocks);\n return [...tagIds];\n}\n\nlet editorInstance: ServerBlockNoteEditor | null = null;\n\nfunction getEditor(): ServerBlockNoteEditor {\n if (!editorInstance) {\n editorInstance = ServerBlockNoteEditor.create();\n }\n return editorInstance;\n}\n\nexport async function blocksToMarkdown(contentJson: string): Promise<string> {\n try {\n const blocks = JSON.parse(contentJson);\n const supportedBlocks = stripUnsupportedMarkdownBlocks(blocks);\n const processed = preprocessCustomInlineContent(supportedBlocks);\n const editor = getEditor();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return await editor.blocksToMarkdownLossy(processed as any);\n } catch {\n return '';\n }\n}\n\nexport async function markdownToBlocksJson(\n markdown: string,\n deps: MarkdownImportDeps = defaultMarkdownImportDeps\n): Promise<string> {\n const editor = getEditor();\n const blocks = await editor.tryParseMarkdownToBlocks(markdown);\n const restoredBlocks = await restoreCustomInlineContent(blocks as BlockNote[], deps);\n return JSON.stringify(restoredBlocks);\n}\n\nexport function extractTagIdsFromContentJson(contentJson: string): string[] {\n const blocks = JSON.parse(contentJson) as BlockNote[];\n return collectTagIds(blocks);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import models from "../models.js";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
extractTagIdsFromContentJson,
|
|
4
|
+
markdownToBlocksJson
|
|
5
|
+
} from "./blocknote.js";
|
|
3
6
|
import { captureNoteBaseline } from "./note-snapshot.js";
|
|
4
7
|
class InvalidNoteAuthoringInputError extends Error {
|
|
5
8
|
constructor(message) {
|
|
@@ -51,9 +54,11 @@ const createNoteAuthoringService = (deps) => {
|
|
|
51
54
|
const replacedTitle = await replacePlaceholders(title);
|
|
52
55
|
const replacedMarkdown = await replacePlaceholders(input.markdown ?? "");
|
|
53
56
|
const content = await deps.parseMarkdownToContentJson(replacedMarkdown);
|
|
57
|
+
const tagIds = deps.extractTagIds(content);
|
|
54
58
|
const note = await deps.createNote({
|
|
55
59
|
title: replacedTitle,
|
|
56
60
|
content,
|
|
61
|
+
tagIds,
|
|
57
62
|
...input.layout ? { layout: input.layout } : {}
|
|
58
63
|
});
|
|
59
64
|
return serializeNote(note);
|
|
@@ -77,6 +82,7 @@ const createNoteAuthoringService = (deps) => {
|
|
|
77
82
|
if (input.markdown !== void 0) {
|
|
78
83
|
const replacedMarkdown = await replacePlaceholders(input.markdown);
|
|
79
84
|
nextData.content = await deps.parseMarkdownToContentJson(replacedMarkdown);
|
|
85
|
+
nextData.tagIds = deps.extractTagIds(nextData.content);
|
|
80
86
|
}
|
|
81
87
|
if (input.layout !== void 0) {
|
|
82
88
|
nextData.layout = input.layout;
|
|
@@ -97,7 +103,8 @@ const defaultNoteAuthoringService = createNoteAuthoringService({
|
|
|
97
103
|
data: {
|
|
98
104
|
title: input.title,
|
|
99
105
|
content: input.content,
|
|
100
|
-
...input.layout ? { layout: input.layout } : {}
|
|
106
|
+
...input.layout ? { layout: input.layout } : {},
|
|
107
|
+
...input.tagIds ? { tags: { connect: input.tagIds.map((id) => ({ id: Number(id) })) } } : {}
|
|
101
108
|
}
|
|
102
109
|
});
|
|
103
110
|
},
|
|
@@ -117,11 +124,17 @@ const defaultNoteAuthoringService = createNoteAuthoringService({
|
|
|
117
124
|
});
|
|
118
125
|
},
|
|
119
126
|
parseMarkdownToContentJson: markdownToBlocksJson,
|
|
127
|
+
extractTagIds: extractTagIdsFromContentJson,
|
|
120
128
|
captureBaseline: captureNoteBaseline,
|
|
121
129
|
updateNote: async (id, input) => {
|
|
122
130
|
return models.note.update({
|
|
123
131
|
where: { id },
|
|
124
|
-
data:
|
|
132
|
+
data: {
|
|
133
|
+
title: input.title,
|
|
134
|
+
content: input.content,
|
|
135
|
+
layout: input.layout,
|
|
136
|
+
...input.tagIds ? { tags: { set: input.tagIds.map((tagId) => ({ id: Number(tagId) })) } } : {}
|
|
137
|
+
}
|
|
125
138
|
});
|
|
126
139
|
}
|
|
127
140
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/modules/note-authoring.ts"],"sourcesContent":["import models, { type NoteLayout } from '~/models.js';\nimport { markdownToBlocksJson } from './blocknote.js';\nimport { captureNoteBaseline } from './note-snapshot.js';\n\ninterface PlaceholderRecord {\n template: string;\n replacement: string;\n}\n\ninterface NoteRecord {\n id: number;\n title: string;\n content: string;\n layout: NoteLayout;\n createdAt: Date;\n updatedAt: Date;\n}\n\ninterface NoteAuthoringDeps {\n createNote: (input: {\n title: string;\n content: string;\n layout?: NoteLayout;\n }) => Promise<NoteRecord>;\n findNoteById: (id: number) => Promise<NoteRecord | null>;\n findPlaceholders: (templates: string[]) => Promise<PlaceholderRecord[]>;\n parseMarkdownToContentJson: (markdown: string) => Promise<string>;\n captureBaseline: (input: {\n noteId: number;\n editSessionId?: string;\n meta?: string;\n }) => Promise<unknown>;\n updateNote: (id: number, input: {\n title?: string;\n content?: string;\n layout?: NoteLayout;\n }) => Promise<NoteRecord>;\n}\n\nexport interface CreateNoteAuthoringInput {\n title: string;\n markdown?: string;\n layout?: NoteLayout;\n}\n\nexport interface UpdateNoteAuthoringInput {\n id: number;\n title?: string;\n markdown?: string;\n layout?: NoteLayout;\n editSessionId?: string;\n snapshotMeta?: string;\n}\n\nexport interface AuthoredNoteSummary {\n id: string;\n title: string;\n layout: NoteLayout;\n createdAt: string;\n updatedAt: string;\n}\n\nexport class InvalidNoteAuthoringInputError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'InvalidNoteAuthoringInputError';\n }\n}\n\nconst PLACEHOLDER_PREFIX = '{%';\nconst PLACEHOLDER_SUFFIX = '%}';\n\nconst serializeNote = (note: NoteRecord): AuthoredNoteSummary => ({\n id: String(note.id),\n title: note.title,\n layout: note.layout,\n createdAt: note.createdAt.toISOString(),\n updatedAt: note.updatedAt.toISOString()\n});\n\nconst extractPlaceholderTemplates = (value: string) => {\n return Array.from(\n new Set(\n Array.from(\n value.matchAll(new RegExp(`${PLACEHOLDER_PREFIX}([^}]+)${PLACEHOLDER_SUFFIX}`, 'g')),\n (match) => match[1]\n )\n )\n );\n};\n\nexport const createNoteAuthoringService = (deps: NoteAuthoringDeps) => {\n const replacePlaceholders = async (value: string) => {\n const templates = extractPlaceholderTemplates(value);\n\n if (templates.length === 0) {\n return value;\n }\n\n const placeholders = await deps.findPlaceholders(templates);\n let replacedValue = value;\n\n for (const placeholder of placeholders) {\n replacedValue = replacedValue.replace(\n new RegExp(`${PLACEHOLDER_PREFIX}${placeholder.template}${PLACEHOLDER_SUFFIX}`, 'g'),\n placeholder.replacement\n );\n }\n\n return replacedValue;\n };\n\n return {\n createNote: async (input: CreateNoteAuthoringInput): Promise<AuthoredNoteSummary> => {\n const title = input.title.trim();\n\n if (!title) {\n throw new InvalidNoteAuthoringInputError('A note title is required.');\n }\n\n const replacedTitle = await replacePlaceholders(title);\n const replacedMarkdown = await replacePlaceholders(input.markdown ?? '');\n const content = await deps.parseMarkdownToContentJson(replacedMarkdown);\n const note = await deps.createNote({\n title: replacedTitle,\n content,\n ...(input.layout ? { layout: input.layout } : {})\n });\n\n return serializeNote(note);\n },\n\n updateNote: async (input: UpdateNoteAuthoringInput): Promise<AuthoredNoteSummary | null> => {\n if (\n input.title === undefined &&\n input.markdown === undefined &&\n input.layout === undefined\n ) {\n throw new InvalidNoteAuthoringInputError('At least one note field must be provided for update.');\n }\n\n const existingNote = await deps.findNoteById(input.id);\n\n if (!existingNote) {\n return null;\n }\n\n const nextData: {\n title?: string;\n content?: string;\n layout?: NoteLayout;\n } = {};\n\n if (input.title !== undefined) {\n const title = input.title.trim();\n\n if (!title) {\n throw new InvalidNoteAuthoringInputError('A note title is required.');\n }\n\n nextData.title = await replacePlaceholders(title);\n }\n\n if (input.markdown !== undefined) {\n const replacedMarkdown = await replacePlaceholders(input.markdown);\n nextData.content = await deps.parseMarkdownToContentJson(replacedMarkdown);\n }\n\n if (input.layout !== undefined) {\n nextData.layout = input.layout;\n }\n\n await deps.captureBaseline({\n noteId: input.id,\n ...(input.editSessionId ? { editSessionId: input.editSessionId } : {}),\n ...(input.snapshotMeta ? { meta: input.snapshotMeta } : {})\n });\n\n const updatedNote = await deps.updateNote(input.id, nextData);\n return serializeNote(updatedNote);\n }\n };\n};\n\nconst defaultNoteAuthoringService = createNoteAuthoringService({\n createNote: async (input) => {\n return models.note.create({\n data: {\n title: input.title,\n content: input.content,\n ...(input.layout ? { layout: input.layout } : {})\n }\n });\n },\n findNoteById: async (id) => {\n return models.note.findUnique({ where: { id } });\n },\n findPlaceholders: async (templates) => {\n if (templates.length === 0) {\n return [];\n }\n\n return models.placeholder.findMany({\n select: {\n template: true,\n replacement: true\n },\n where: { template: { in: templates } }\n });\n },\n parseMarkdownToContentJson: markdownToBlocksJson,\n captureBaseline: captureNoteBaseline,\n updateNote: async (id, input) => {\n return models.note.update({\n where: { id },\n data: input\n });\n }\n});\n\nexport const createNoteFromMarkdown = async (input: CreateNoteAuthoringInput) => {\n return defaultNoteAuthoringService.createNote(input);\n};\n\nexport const updateNoteFromMarkdown = async (input: UpdateNoteAuthoringInput) => {\n return defaultNoteAuthoringService.updateNote(input);\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/modules/note-authoring.ts"],"sourcesContent":["import models, { type NoteLayout } from '~/models.js';\nimport {\n extractTagIdsFromContentJson,\n markdownToBlocksJson\n} from './blocknote.js';\nimport { captureNoteBaseline } from './note-snapshot.js';\n\ninterface PlaceholderRecord {\n template: string;\n replacement: string;\n}\n\ninterface NoteRecord {\n id: number;\n title: string;\n content: string;\n layout: NoteLayout;\n createdAt: Date;\n updatedAt: Date;\n}\n\ninterface NoteAuthoringDeps {\n createNote: (input: {\n title: string;\n content: string;\n layout?: NoteLayout;\n tagIds?: string[];\n }) => Promise<NoteRecord>;\n findNoteById: (id: number) => Promise<NoteRecord | null>;\n findPlaceholders: (templates: string[]) => Promise<PlaceholderRecord[]>;\n parseMarkdownToContentJson: (markdown: string) => Promise<string>;\n extractTagIds: (contentJson: string) => string[];\n captureBaseline: (input: {\n noteId: number;\n editSessionId?: string;\n meta?: string;\n }) => Promise<unknown>;\n updateNote: (id: number, input: {\n title?: string;\n content?: string;\n layout?: NoteLayout;\n tagIds?: string[];\n }) => Promise<NoteRecord>;\n}\n\nexport interface CreateNoteAuthoringInput {\n title: string;\n markdown?: string;\n layout?: NoteLayout;\n}\n\nexport interface UpdateNoteAuthoringInput {\n id: number;\n title?: string;\n markdown?: string;\n layout?: NoteLayout;\n editSessionId?: string;\n snapshotMeta?: string;\n}\n\nexport interface AuthoredNoteSummary {\n id: string;\n title: string;\n layout: NoteLayout;\n createdAt: string;\n updatedAt: string;\n}\n\nexport class InvalidNoteAuthoringInputError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'InvalidNoteAuthoringInputError';\n }\n}\n\nconst PLACEHOLDER_PREFIX = '{%';\nconst PLACEHOLDER_SUFFIX = '%}';\n\nconst serializeNote = (note: NoteRecord): AuthoredNoteSummary => ({\n id: String(note.id),\n title: note.title,\n layout: note.layout,\n createdAt: note.createdAt.toISOString(),\n updatedAt: note.updatedAt.toISOString()\n});\n\nconst extractPlaceholderTemplates = (value: string) => {\n return Array.from(\n new Set(\n Array.from(\n value.matchAll(new RegExp(`${PLACEHOLDER_PREFIX}([^}]+)${PLACEHOLDER_SUFFIX}`, 'g')),\n (match) => match[1]\n )\n )\n );\n};\n\nexport const createNoteAuthoringService = (deps: NoteAuthoringDeps) => {\n const replacePlaceholders = async (value: string) => {\n const templates = extractPlaceholderTemplates(value);\n\n if (templates.length === 0) {\n return value;\n }\n\n const placeholders = await deps.findPlaceholders(templates);\n let replacedValue = value;\n\n for (const placeholder of placeholders) {\n replacedValue = replacedValue.replace(\n new RegExp(`${PLACEHOLDER_PREFIX}${placeholder.template}${PLACEHOLDER_SUFFIX}`, 'g'),\n placeholder.replacement\n );\n }\n\n return replacedValue;\n };\n\n return {\n createNote: async (input: CreateNoteAuthoringInput): Promise<AuthoredNoteSummary> => {\n const title = input.title.trim();\n\n if (!title) {\n throw new InvalidNoteAuthoringInputError('A note title is required.');\n }\n\n const replacedTitle = await replacePlaceholders(title);\n const replacedMarkdown = await replacePlaceholders(input.markdown ?? '');\n const content = await deps.parseMarkdownToContentJson(replacedMarkdown);\n const tagIds = deps.extractTagIds(content);\n const note = await deps.createNote({\n title: replacedTitle,\n content,\n tagIds,\n ...(input.layout ? { layout: input.layout } : {})\n });\n\n return serializeNote(note);\n },\n\n updateNote: async (input: UpdateNoteAuthoringInput): Promise<AuthoredNoteSummary | null> => {\n if (\n input.title === undefined &&\n input.markdown === undefined &&\n input.layout === undefined\n ) {\n throw new InvalidNoteAuthoringInputError('At least one note field must be provided for update.');\n }\n\n const existingNote = await deps.findNoteById(input.id);\n\n if (!existingNote) {\n return null;\n }\n\n const nextData: {\n title?: string;\n content?: string;\n layout?: NoteLayout;\n tagIds?: string[];\n } = {};\n\n if (input.title !== undefined) {\n const title = input.title.trim();\n\n if (!title) {\n throw new InvalidNoteAuthoringInputError('A note title is required.');\n }\n\n nextData.title = await replacePlaceholders(title);\n }\n\n if (input.markdown !== undefined) {\n const replacedMarkdown = await replacePlaceholders(input.markdown);\n nextData.content = await deps.parseMarkdownToContentJson(replacedMarkdown);\n nextData.tagIds = deps.extractTagIds(nextData.content);\n }\n\n if (input.layout !== undefined) {\n nextData.layout = input.layout;\n }\n\n await deps.captureBaseline({\n noteId: input.id,\n ...(input.editSessionId ? { editSessionId: input.editSessionId } : {}),\n ...(input.snapshotMeta ? { meta: input.snapshotMeta } : {})\n });\n\n const updatedNote = await deps.updateNote(input.id, nextData);\n return serializeNote(updatedNote);\n }\n };\n};\n\nconst defaultNoteAuthoringService = createNoteAuthoringService({\n createNote: async (input) => {\n return models.note.create({\n data: {\n title: input.title,\n content: input.content,\n ...(input.layout ? { layout: input.layout } : {}),\n ...(input.tagIds\n ? { tags: { connect: input.tagIds.map((id) => ({ id: Number(id) })) } }\n : {})\n }\n });\n },\n findNoteById: async (id) => {\n return models.note.findUnique({ where: { id } });\n },\n findPlaceholders: async (templates) => {\n if (templates.length === 0) {\n return [];\n }\n\n return models.placeholder.findMany({\n select: {\n template: true,\n replacement: true\n },\n where: { template: { in: templates } }\n });\n },\n parseMarkdownToContentJson: markdownToBlocksJson,\n extractTagIds: extractTagIdsFromContentJson,\n captureBaseline: captureNoteBaseline,\n updateNote: async (id, input) => {\n return models.note.update({\n where: { id },\n data: {\n title: input.title,\n content: input.content,\n layout: input.layout,\n ...(input.tagIds\n ? { tags: { set: input.tagIds.map((tagId) => ({ id: Number(tagId) })) } }\n : {})\n }\n });\n }\n});\n\nexport const createNoteFromMarkdown = async (input: CreateNoteAuthoringInput) => {\n return defaultNoteAuthoringService.createNote(input);\n};\n\nexport const updateNoteFromMarkdown = async (input: UpdateNoteAuthoringInput) => {\n return defaultNoteAuthoringService.updateNote(input);\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import{j as e}from"./note-vendor-BofYbzmZ.js";import{L as K,N as V,d as p,s as W,M as $,B as E,a as J,b as G,u as _,q as L,g as q,P as X,S as Z,T as ee,c as Y,e as te,C as se}from"./index-40Y2UsVr.js";import{a as y}from"./graph-vendor-CUxe67Lr.js";import{p as I}from"./color-wpu7wT_s.js";import{C as ae}from"./Callout-B2kPcDrq.js";import"./note-core-BCgMq5QA.js";const ne=({day:s,cellClassName:t,dayNumberClassName:a,isCurrentMonth:o,items:i,overflowCount:d,onOpenOverflow:u})=>e.jsxs("div",{className:`min-h-[140px] rounded-[14px] border p-2 ${t}`.trim(),children:[e.jsx("div",{className:"mb-2 flex justify-end",children:e.jsx("span",{className:`flex h-7 w-7 items-center justify-center rounded-[10px] text-sm ${a}`.trim(),children:s})}),o&&i.length>0?e.jsxs("div",{className:"flex flex-col gap-1",children:[i,d>0?e.jsxs("button",{type:"button",onClick:u,className:"rounded-[10px] py-1 text-center text-[10px] font-semibold text-fg-tertiary transition-colors hover:bg-hover-subtle hover:text-fg-muted",children:["+",d," more"]}):null]}):null]}),F=({params:s,toneClassName:t="",header:a,title:o,meta:i,titleClassName:d=""})=>e.jsx(K,{to:V,params:s,className:"group block min-h-[44px]",children:e.jsxs("div",{className:`surface-base flex h-full flex-col justify-center px-2 py-1.5 transition-colors group-hover:bg-hover-subtle ${t}`.trim(),children:[a?e.jsx("div",{className:"mb-0.5 flex items-center gap-1 text-fg-muted",children:a}):null,e.jsx("div",{className:`line-clamp-1 text-xs font-semibold text-fg-default ${d}`.trim(),children:o}),i?e.jsx("div",{className:"text-[10px] font-medium text-fg-secondary",children:i}):null]})}),re=({note:s,type:t})=>e.jsx(F,{params:{id:s.id},title:s.title,meta:p(Number(t==="create"?s.createdAt:s.updatedAt)).format("HH:mm")}),oe=({reminder:s})=>e.jsx(F,{params:{id:String(s.note?.id??s.noteId)},header:e.jsx(W,{size:12}),title:s.content||s.note?.title||"No title",titleClassName:s.completed?"line-through":"",meta:p(Number(s.reminderDate)).format("HH:mm")}),T=3,P=(s,t)=>s.map(a=>a.type==="note"?e.jsx(re,{note:a.item,type:t},`note-${a.item.id}`):e.jsx(oe,{reminder:a.item},`reminder-${a.item.id}`)),ie=({day:s,isCurrentMonth:t,isSunday:a,isToday:o,isPast:i,notes:d,reminders:u,type:c})=>{const[f,D]=y.useState(!1),g=y.useMemo(()=>{const C=d.map(N=>({type:"note",item:N})),v=u.map(N=>({type:"reminder",item:N}));return i?[...C,...v]:[...v,...C]},[i,d,u]),M=g.length>T,w=y.useMemo(()=>P(g.slice(0,T),c),[g,c]),n=y.useMemo(()=>P(g,c),[g,c]),l=y.useCallback(()=>D(!0),[]),m=y.useCallback(()=>D(!1),[]),j=()=>t?o?"border-border-secondary/70 bg-[color:color-mix(in_srgb,var(--surface)_88%,var(--accent-soft-primary)_12%)]":"bg-surface border-border-subtle":"bg-muted/18 border-border-subtle/70",S=()=>o?"bg-cta text-fg-on-filled font-semibold":t?a?"text-fg-weekend font-bold":"text-fg-secondary font-bold":"text-fg-disabled opacity-55";return e.jsxs(e.Fragment,{children:[e.jsx(ne,{day:s,cellClassName:j(),dayNumberClassName:S(),isCurrentMonth:t,items:w,overflowCount:M?g.length-T:0,onOpenOverflow:l}),M&&e.jsxs($,{isOpen:f,onClose:m,children:[e.jsx($.Header,{title:`Day ${s}`,onClose:m}),e.jsxs($.Body,{children:[e.jsxs($.Description,{className:"sr-only",children:["View all notes and reminders scheduled for day ",s,"."]}),e.jsx("div",{className:"flex max-h-[60vh] flex-col gap-2 overflow-y-auto",children:n})]})]})]})},le=y.memo(ie),de=["January","February","March","April","May","June","July","August","September","October","November","December"],ce=({month:s,year:t,onPrevMonth:a,onNextMonth:o,onToday:i})=>e.jsxs("div",{className:"flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4 mb-6",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("h1",{className:"text-2xl sm:text-3xl font-bold",children:de[s-1]}),e.jsx("span",{className:"text-xl sm:text-2xl text-fg-placeholder",children:t})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(E,{variant:"ghost",size:"sm",onClick:i,children:"Today"}),e.jsx(E,{variant:"ghost",size:"icon-sm",onClick:a,children:e.jsx(J,{width:18,height:18})}),e.jsx(E,{variant:"ghost",size:"icon-sm",onClick:o,children:e.jsx(G,{width:18,height:18})})]})]}),me=[{label:"High",className:I.high},{label:"Medium",className:I.medium},{label:"Low",className:I.low},{label:"Overdue",className:"bg-accent-soft-danger/70 dark:bg-emphasis/70"}],xe=()=>e.jsx("div",{className:"flex flex-wrap items-center gap-3 text-xs",children:me.map(({label:s,className:t})=>e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("div",{className:`h-3 w-3 rounded-full border border-border-subtle ${t}`}),e.jsx("span",{className:"text-fg-tertiary font-medium",children:s})]},s))}),ue=`
|
|
2
|
-
query NotesInDateRange($dateRange: DateRangeInput) {
|
|
3
|
-
notesInDateRange(dateRange: $dateRange) {
|
|
4
|
-
id
|
|
5
|
-
title
|
|
6
|
-
createdAt
|
|
7
|
-
updatedAt
|
|
8
|
-
}
|
|
9
|
-
}
|
|
10
|
-
`,he=`
|
|
11
|
-
query RemindersInDateRange($dateRange: DateRangeInput) {
|
|
12
|
-
remindersInDateRange(dateRange: $dateRange) {
|
|
13
|
-
id
|
|
14
|
-
noteId
|
|
15
|
-
reminderDate
|
|
16
|
-
completed
|
|
17
|
-
priority
|
|
18
|
-
content
|
|
19
|
-
note {
|
|
20
|
-
id
|
|
21
|
-
title
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
`,pe=async s=>{const t=await q(ue,{dateRange:s});if(t.type==="error")throw t;return t.notesInDateRange},ge=async s=>{const t=await q(he,{dateRange:s});if(t.type==="error")throw t;return t.remindersInDateRange},ye=({year:s,month:t})=>{const a=`${s}-${String(t).padStart(2,"0")}-01`,o=t===12?1:t+1,d=`${t===12?s+1:s}-${String(o).padStart(2,"0")}-01`,u={start:a,end:d},c=_({queryKey:L.calendar.notesInDateRange(s,t),queryFn:()=>pe(u)}),f=_({queryKey:L.reminders.inDateRange(s,t),queryFn:()=>ge(u)});return{notes:c.data??[],reminders:f.data??[],isLoading:c.isLoading||f.isLoading,isError:c.isError||f.isError}},fe=["SUN","MON","TUE","WED","THU","FRI","SAT"],be=[],Ne=[],H=te(se);function $e(){const s=H.useNavigate(),{year:t,month:a,type:o}=H.useSearch(),{notes:i,reminders:d,isLoading:u,isError:c}=ye({year:t,month:a}),f=y.useMemo(()=>{const n=p(),l=`${n.year()}-${n.month()+1}-${n.date()}`,m=new Map;for(const r of i){const h=o==="create"?p(Number(r.createdAt)):p(Number(r.updatedAt)),x=`${h.year()}-${h.month()+1}-${h.date()}`,b=m.get(x)||[];b.push(r),m.set(x,b)}const j=new Map;for(const r of d){const h=p(Number(r.reminderDate)),x=`${h.year()}-${h.month()+1}-${h.date()}`,b=j.get(x)||[];b.push(r),j.set(x,b)}const S=new Date(t,a-1,1),C=new Date(t,a,0),v=S.getDay(),N=C.getDate(),R=[],k=a===1?12:a-1,O=a===1?t-1:t,U=new Date(O,k,0).getDate();for(let r=v-1;r>=0;r--)R.push({day:U-r,isCurrentMonth:!1,year:O,month:k});for(let r=1;r<=N;r++)R.push({day:r,isCurrentMonth:!0,year:t,month:a});const A=(v+N)%7,Q=A===0?0:7-A,z=a===12?1:a+1,B=a===12?t+1:t;for(let r=1;r<=Q;r++)R.push({day:r,isCurrentMonth:!1,year:B,month:z});return R.map((r,h)=>{const x=`${r.year}-${r.month}-${r.day}`,b=p(`${r.year}-${String(r.month).padStart(2,"0")}-${String(r.day).padStart(2,"0")}`);return{key:x,day:r.day,isCurrentMonth:r.isCurrentMonth,isSunday:h%7===0,isToday:x===l,isPast:b.isBefore(n,"day"),notes:m.get(x)||be,reminders:j.get(x)||Ne}})},[t,a,i,d,o]),D=()=>{const n=a===1?12:a-1,l=a===1?t-1:t;s({search:m=>({...m,month:n,year:l})})},g=()=>{const n=a===12?1:a+1,l=a===12?t+1:t;s({search:m=>({...m,month:n,year:l})})},M=()=>{s({search:n=>({...n,month:p().month()+1,year:p().year()})})},w=n=>{n&&s({search:l=>({...l,type:n})})};return e.jsx(X,{title:"Calendar",variant:"none",children:e.jsxs("div",{className:"w-full px-4 sm:px-6 py-6 sm:py-10 max-w-screen-2xl mx-auto",children:[c?e.jsx(ae,{children:"Failed to load calendar data. Please try again later."}):e.jsxs("div",{className:"surface-base overflow-x-auto p-3 sm:p-4",children:[e.jsx(ce,{month:a,year:t,onPrevMonth:D,onNextMonth:g,onToday:M}),e.jsxs("div",{className:"min-w-[900px]",children:[e.jsx("div",{className:"grid grid-cols-7 gap-1 mb-2",children:fe.map((n,l)=>e.jsx("div",{className:`
|
|
26
|
-
py-2 text-center text-xs font-bold tracking-wider
|
|
27
|
-
${l===0?"text-fg-weekend":"text-fg-secondary"}
|
|
28
|
-
`,children:n},n))}),u?e.jsx("div",{className:"grid grid-cols-7 gap-1",children:Array.from({length:35}).map((n,l)=>e.jsx(Z,{height:140},l))}):e.jsx("div",{className:"grid grid-cols-7 gap-1",children:f.map(n=>e.jsx(le,{day:n.day,isCurrentMonth:n.isCurrentMonth,isSunday:n.isSunday,isToday:n.isToday,isPast:n.isPast,notes:n.notes,reminders:n.reminders,type:o},n.key))})]})]}),e.jsxs("div",{className:"flex flex-col sm:flex-row items-start sm:items-center justify-between gap-4 mt-6",children:[e.jsx(xe,{}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("span",{className:"text-sm text-fg-tertiary font-bold",children:"Display by:"}),e.jsxs(ee,{type:"single",variant:"pills",size:"sm",value:o,onValueChange:w,children:[e.jsx(Y,{value:"create",children:"Create date"}),e.jsx(Y,{value:"update",children:"Update date"})]})]})]})]})})}export{$e as default};
|