easy_flow 0.30.0 → 0.31.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 716b3bb1b37acda25c8915e40725db11b6bd9734dca76165aa22edebcb355263
4
- data.tar.gz: 29f457f14f8f03d4cd9f7d60ff50cde7ca803501ec87fba000badc41cbf196a8
3
+ metadata.gz: 9c29c87cf730dc97ed5566ffe62dcd6c370fd10095d97e0155efd8f65b0589e7
4
+ data.tar.gz: a43f91c9a2124ca19137a7dfec1ab1dc632cb26e67109227a9bc3c85b6254bca
5
5
  SHA512:
6
- metadata.gz: ed172bae87ce450d5678893e61aead1391b19f30848d20cbc6a6a6311a7fd9039f03e1cf5275f66f766ea4445350c925dcbb312cb8cc7f1e09b57c3ce2550165
7
- data.tar.gz: 3261c170b1c631272d44c00d2f5557bc71c4949397939a7f9d7e8ec62472a8171b01f854644f0b55885623483750592fda3ca502c8a4c3d7c3fb6d27271a5b1e
6
+ metadata.gz: cfb248eca765ea58f0a5d77a070131a67929592601485ab5f5a4106f5e8dcadbc711941d9736d55b41c81ffbf6b7b10949e7ed1911cf5e2ac35c967bca199e00
7
+ data.tar.gz: c3863cb2a21b5866b87fc0b5f1d029f841ee46e6f8cb9492621bd1481f64a05b6767c2f5b6721e74f147d9d229fef37f3e97924dc963d77403f7d7db712b3fdf
@@ -1 +1 @@
1
- (()=>{var Lt=globalThis.ReactDOM;var{createPortal:Be,createRoot:Z,flushSync:Te,hydrateRoot:Ee,preconnect:Pe,prefetchDNS:De,preinit:$e,preinitModule:Ae,preload:_e,preloadModule:Le,requestFormReset:Ie,unstable_batchedUpdates:Me,useFormState:Oe,useFormStatus:He,version:Fe}=Lt;var Q=globalThis.React,e=Q,{Children:Ve,Component:We,Fragment:Ue,PureComponent:Ye,StrictMode:Xe,Suspense:Ge,cloneElement:qe,createContext:Je,createElement:Ke,createRef:Ze,forwardRef:Qe,isValidElement:Re,lazy:to,memo:eo,startTransition:oo,useCallback:ro,useContext:no,useDebugValue:so,useDeferredValue:ao,useEffect:P,useId:io,useImperativeHandle:lo,useLayoutEffect:R,useMemo:D,useReducer:co,useRef:W,useState:x,useSyncExternalStore:po,useTransition:uo}=Q;var tt=new Map,I=new Map,et=(t,o)=>tt.set(t,o),ot=()=>{I.forEach(t=>t.unmount()),I.clear()},rt=(t,o)=>t.querySelectorAll("[data-react-ui]").forEach(n=>{if(I.has(n))return;let r=tt.get(n.dataset.reactUi),a=o(n);I.set(n,a),a.render(e.createElement(r,JSON.parse(n.dataset.props)))});var nt=(t,o)=>{let n=()=>rt(t,o);t.addEventListener("turbo:load",n),t.addEventListener("turbo:frame-load",n),t.addEventListener("turbo:before-cache",ot),t.readyState==="loading"?t.addEventListener("DOMContentLoaded",n):n()};var S=(...t)=>t.filter(Boolean).join(" ");var It={primary:"ks-button-primary",secondary:"ks-button-secondary",danger:"ks-button-danger"},Mt={sm:"ks-button-sm",md:"ks-button-md",lg:"ks-button-lg"},Ot=({variant:t="primary",size:o="md",className:n,children:r,...a})=>{let l=a.href?"a":"button";return e.createElement(l,{...a,className:S("ks-button",It[t],Mt[o],n)},r)},b=Ot;var Ht="border border-amber-500 bg-white text-amber-700 dark:bg-zinc-900 dark:text-amber-400",Ft="border border-gray-300 bg-white text-gray-500 dark:border-zinc-600 dark:bg-zinc-900 dark:text-gray-400",jt="border border-accent-600 bg-accent-600 text-white",Vt=({name:t,connected:o,armed:n,onArm:r,connecting:a})=>e.createElement("button",{onClick:l=>{a||(l.stopPropagation(),r(l))},title:n?"Now choose a step to connect to":"Connect this branch",className:n?jt:o?Ft:Ht,style:{padding:"1px 8px",marginRight:4,borderRadius:999,fontSize:11,cursor:"pointer"}},t||"next"),st=Vt;var Wt={width:240,boxSizing:"border-box",borderRadius:8},Ut={padding:"8px 14px",textAlign:"center",fontWeight:600},Yt={fontWeight:600,lineHeight:1.3},Xt=(t,o,n)=>{let r=n?"ring-4 ring-accent-600/15":"shadow-sm";return t||n&&!o?`border-accent-600 ${r}`:o?`border-red-600 ${r}`:"border-gray-300 shadow-sm dark:border-zinc-700"},Gt=({node:t,selected:o,armed:n,connecting:r,onSelect:a,onOpen:l,onArm:i,onDragEnd:d,onDragStart:m})=>{let c=t.begins_here||t.ends_here,y=t.begins_here,u=t.ends_here?[]:t.ports,f=r&&!y;return e.createElement("div",{ref:t.ref,"data-step":t.id,draggable:!y,onDragStart:p=>{p.dataTransfer.effectAllowed="move",p.dataTransfer.setData("text/plain",t.id),m()},onDragEnd:d,onClick:t.opens&&!r?()=>l(t.opens):a,className:`bg-white border-2 dark:bg-zinc-900 ${Xt(f,t.violations.length>0,o)}`,style:{...Wt,padding:c?0:"12px 14px",cursor:y?"default":r?"crosshair":"grab"}},c&&e.createElement("div",{className:"text-gray-500 dark:text-gray-400",style:Ut},t.label),!c&&e.createElement("div",{style:Yt},t.label),!c&&e.createElement("div",{className:"text-gray-500 dark:text-gray-400",style:{fontSize:11,marginTop:2}},t.type),t.starts_a_flow&&e.createElement("div",{className:"text-accent-600 dark:text-accent-400",style:{fontSize:11,marginTop:2}},"Runs a flow"),t.opens&&e.createElement(b,{variant:"secondary",size:"sm",className:"mt-2",onClick:p=>{p.stopPropagation(),a()}},"Settings"),t.violations.map(p=>e.createElement("div",{key:p.problem+p.detail,className:"text-red-600 dark:text-red-400",style:{fontSize:11,padding:"0 14px 6px"}},p.problem.replace(/_/g," "),p.detail?`: ${p.detail}`:"")),u.length>0&&e.createElement("div",{style:{padding:t.begins_here?"0 14px 8px":"10px 0 0"}},u.map(p=>e.createElement(st,{key:p,name:p,connected:t.connected.includes(p),connecting:r,armed:n===p,onArm:w=>i(p,w)}))))},U=Gt;var Y=(t,o)=>t.includes(o)?t.filter(n=>n!==o):[...t,o],at=(t,o)=>({...o?.choices||{},...t?.choices||{}});var qt=({as:t="input",disabled:o,className:n,...r})=>e.createElement(t,{...r,disabled:o,className:S("ks-input",o&&"ks-input-disabled",n)}),z=qt;var Jt=t=>e.createElement(z,{...t,as:"select"}),it=Jt;var Kt=({className:t,...o})=>e.createElement("input",{type:"checkbox",...o,className:S("ks-checkbox",t)}),M=Kt;var lt=t=>(t||[]).map(o=>typeof o=="object"?o:{value:o,label:o}),Zt=({type:t,value:o,choices:n,onChange:r,onSettle:a,onPick:l,pictureUrl:i})=>{if(t==="picture")return e.createElement("div",{className:"mb-3"},o&&i&&e.createElement("img",{src:i,alt:"The step's picture",style:{maxWidth:"100%"}}),o&&e.createElement("button",{type:"button","data-remove-picture":!0,className:"ks-button ks-button-secondary ks-button-sm",onClick:()=>a("")},"Remove picture"),e.createElement("input",{type:"file",accept:"image/*",onChange:d=>d.target.files[0]&&l(d.target.files[0])}));if(t==="boolean")return e.createElement(M,{checked:!!o,onChange:d=>a(d.target.checked)});if(t==="select"||t==="previous_step"||t==="from_step"||t==="flow")return e.createElement(it,{className:"mb-3",value:o??"",onChange:d=>a(d.target.value)},e.createElement("option",{value:""}),lt(n).map(d=>e.createElement("option",{key:d.value,value:d.value},d.label)));if(t==="multi_select"){let d=Array.isArray(o)?o:[],m=c=>a(Y(d,c));return e.createElement("div",{style:{display:"flex",flexWrap:"wrap",gap:8}},(n||[]).map(c=>e.createElement("label",{key:c,style:{display:"inline-flex",alignItems:"center",gap:4}},e.createElement(M,{checked:d.includes(c),onChange:()=>m(c)}),e.createElement("span",null,c))))}if(t==="flows"){let d=Array.isArray(o)?o:[];return e.createElement("div",{style:{display:"flex",flexDirection:"column",gap:4},className:"mb-3"},lt(n).map(m=>e.createElement("label",{key:m.value,style:{display:"inline-flex",alignItems:"center",gap:4}},e.createElement(M,{checked:d.includes(m.value),onChange:()=>a(Y(d,m.value))}),e.createElement("span",null,m.label))))}return t==="integer"||t==="float"?e.createElement(z,{className:"mb-3",type:"number",step:t==="integer"?"1":"any",value:o??"",onChange:d=>r(d.target.value),onBlur:d=>a(d.target.value)}):e.createElement(z,{className:"mb-3",type:"text",value:o??"",onChange:d=>r(d.target.value),onBlur:d=>a(d.target.value)})},O=Zt;var dt=(t,o,n,r)=>t.map((a,l)=>l===o?{...a,[n]:r}:a);var Qt=(t,o,n,r)=>{let a=(t||{})[n],l=(o||{})[n];return l?(a||{})[r[l]]:a},Rt=({holds:t,labels:o,rows:n,choices:r,outputsOf:a,onChange:l,onSettle:i})=>{let d=Array.isArray(n)?n:[],m=(c,y,u,f)=>{let p=dt(d,c,y,u);f?i(p):l(p)};return e.createElement("div",{style:{marginBottom:12}},d.map((c,y)=>e.createElement("div",{key:y,className:"rounded-md border border-gray-200 dark:border-zinc-700",style:{padding:"8px 8px 2px",marginBottom:6}},Object.entries(t).map(([u,f])=>e.createElement("label",{key:u,style:{display:"block"}},e.createElement("span",{className:"text-gray-500 dark:text-gray-400",style:{display:"block",marginBottom:2,fontSize:11}},(o||{})[u]||u),e.createElement(O,{type:f,value:c[u],choices:Qt(r,a,u,c),onChange:p=>m(y,u,p,!1),onSettle:p=>m(y,u,p,!0)}))),e.createElement(b,{variant:"secondary",size:"sm",className:"mb-1.5",onClick:()=>i(d.filter((u,f)=>f!==y))},"Remove"))),e.createElement(b,{variant:"secondary",size:"sm",className:"w-full",onClick:()=>i([...d,{}])},"Add"))},ct=Rt;var te=({as:t="div",className:o,children:n,...r})=>e.createElement(t,{...r,className:S("ks-panel",o)},n),A=te;var H=(t,o)=>({className:n,children:r,...a})=>e.createElement(t,{...a,className:S(o,n)},r),L=H("label","ks-label"),rr=H("p","ks-hint"),nr=H("p","ks-error"),sr=H("span","ks-required");var ee={width:280,padding:20,overflowY:"auto"},oe=({node:t,fields:o,holds:n,labels:r,recordLabels:a,recordChoices:l,recordOutputsOf:i,choices:d,onSave:m,onDelete:c,onClose:y,onPickPicture:u})=>{let[f,p]=x(t.config),[w,k]=x(t.picture_url);P(()=>k(t.picture_url),[t.id,t.picture_url]),P(()=>p(t.config),[t.id,t.config]);let N=h=>{p(h),JSON.stringify(h)!==JSON.stringify(t.config)&&m(h)};return e.createElement(A,{as:"aside",style:ee,"data-inspector":!0},e.createElement("div",{style:{display:"flex",alignItems:"start",justifyContent:"space-between",gap:8}},e.createElement("h2",{style:{fontWeight:600,marginBottom:2}},t.label),e.createElement("button",{title:"Close",onClick:y,className:"text-gray-500 dark:text-gray-400",style:{border:"none",background:"none",cursor:"pointer",fontSize:18,lineHeight:1}},"\xD7")),e.createElement("p",{className:"text-gray-500 dark:text-gray-400",style:{fontSize:11,marginBottom:16}},t.id," \xB7 ",t.type),Object.entries(o).map(([h,B])=>e.createElement(L,{key:h},e.createElement("span",{style:{display:"block",marginBottom:3}},r[h]||h),B==="list"?e.createElement(ct,{holds:n[h]||{},labels:a[h]||{},rows:f[h],choices:{...(l||{})[h],...(t.record_choices||{})[h]},outputsOf:(i||{})[h],onChange:v=>p({...f,[h]:v}),onSettle:v=>N({...f,[h]:v})}):e.createElement(O,{type:B,value:f[h],choices:d[h],pictureUrl:w,onChange:v=>p({...f,[h]:v}),onSettle:v=>N({...f,[h]:v}),onPick:async v=>{let _=await u(v);_&&(k(_.url),N({...f,[h]:_.reference}))}}))),e.createElement(b,{variant:"danger",size:"sm",className:"w-full",onClick:c},"Delete step"))},pt=oe;var re={width:240,boxSizing:"border-box",padding:"10px 14px",borderRadius:8,textAlign:"center",fontSize:12,cursor:"pointer"},ne="border-2 border-dashed border-amber-500 bg-amber-50 text-amber-700 dark:bg-amber-950 dark:text-amber-300",se="border-2 border-dashed border-accent-600 bg-accent-50 text-accent-800 dark:bg-accent-950 dark:text-accent-200",ae=({node:t,dragging:o,onFill:n,onDrop:r})=>e.createElement("div",{ref:t.ref,"data-placeholder":t.id,title:`Choose the step \u201C${t.label}\u201D should lead to`,onClick:n,onDragOver:a=>{o&&(a.preventDefault(),a.dataTransfer.dropEffect="move")},onDrop:a=>{a.preventDefault(),r()},className:o?se:ne,style:re},e.createElement("div",{style:{fontWeight:600}},t.label),e.createElement("div",{style:{fontSize:11}},o?"drop a step here":"leads nowhere yet \u2014 click to choose")),ut=ae;var ie=({entries:t,at:o,onPick:n,onConnect:r,onDismiss:a})=>e.createElement(A,{className:"shadow-lg",style:{position:"absolute",zIndex:9,top:o.y,left:o.x,width:210,padding:8,borderRadius:8}},e.createElement("p",{className:"text-gray-500 dark:text-gray-400",style:{margin:"0 0 6px",fontSize:11}},"Add a step"),t.map(l=>e.createElement(b,{key:l.type,variant:"secondary",size:"sm",className:"w-full mb-1.5 flex-col",onClick:()=>n(l)},l.label,e.createElement("span",{className:"opacity-75",style:{display:"block",fontSize:11}},l.type))),r&&e.createElement(b,{variant:"secondary",size:"sm",className:"w-full mb-1.5",onClick:r},"Connect to a step already here"),e.createElement(b,{variant:"secondary",size:"sm",className:"w-full",onClick:a},"Cancel")),mt=ie;var le={width:24,height:24,padding:0,fontSize:15,lineHeight:"15px"},ft=({label:t,title:o,idle:n,enabled:r,onUse:a})=>e.createElement(b,{variant:"secondary",size:"sm",title:r?o:n,disabled:!r,onClick:a,style:{opacity:r?1:.4,cursor:r?"pointer":"default"}},t),de=({undoable:t,redoable:o,onAdd:n,onUndo:r,onRedo:a})=>e.createElement("div",{style:{position:"absolute",top:16,left:16,zIndex:5,display:"flex",gap:8}},e.createElement(b,{variant:"secondary",className:"rounded-full",style:le,title:"Add a step",onClick:n},"+"),e.createElement(ft,{label:"\u21B6 Undo",title:"Undo the last change",idle:"Nothing to undo",enabled:t,onUse:r}),e.createElement(ft,{label:"\u21B7 Redo",title:"Redo the change you undid",idle:"Nothing to redo",enabled:o,onUse:a})),gt=de;var yt=t=>{let o=t.problem.replace(/_/g," ");return t.node?`\u201C${t.node}\u201D ${o}`:o};var ht=({version:t,published:o})=>t?o?o===t?`Version ${t} \xB7 live`:`Version ${t} \xB7 visitors still on ${o}`:`Version ${t} \xB7 never published`:"No version yet";var ce={width:280,padding:20,overflowY:"auto"},X={fontWeight:600,marginBottom:6,marginTop:14},F={fontSize:12,marginBottom:4,lineHeight:1.4},bt={display:"block",marginBottom:3},xt=(t,o,n)=>r=>{r.target.value!==(t[o]??"")&&n({[o]:r.target.value})},pe=({flow:t,changes:o,problems:n,refusal:r,notice:a,onCreate:l,onPublish:i,onSaveDetails:d,onClose:m})=>e.createElement(A,{as:"aside",style:ce,"data-builder-panel":!0},e.createElement("div",{style:{display:"flex",alignItems:"start",justifyContent:"space-between",gap:8}},e.createElement("h2",{style:{fontWeight:600},"data-flow-name":!0},t.title||t.slug),e.createElement("button",{title:"Close",onClick:m,className:"text-gray-500 dark:text-gray-400",style:{border:"none",background:"none",cursor:"pointer",fontSize:18,lineHeight:1}},"\xD7")),e.createElement("a",{className:"text-accent-600 dark:text-accent-400",style:{fontSize:12,display:"block"},href:t.history_url,"data-history":!0},ht(t)),e.createElement("h2",{style:X},"Problems"),r&&e.createElement("p",{className:"text-red-800 dark:text-red-400",style:{...F,fontWeight:600},"data-refusal":!0},r),a&&!r&&e.createElement("p",{className:"text-emerald-800 dark:text-emerald-400",style:{...F,fontWeight:600},"data-notice":!0},a),n.length===0&&!r?e.createElement("p",{className:"text-gray-500 dark:text-gray-400",style:{fontSize:12}},"Nothing wrong with this flow."):n.map(c=>e.createElement("p",{key:`${c.node}-${c.problem}`,className:"text-amber-700 dark:text-amber-400",style:F,"data-problem":!0},"\u26A0 ",yt(c))),e.createElement("h2",{style:X},"Changes since the last version"),o.length===0?e.createElement("p",{className:"text-gray-500 dark:text-gray-400",style:{fontSize:12}},"Nothing has changed."):o.map((c,y)=>e.createElement("p",{key:y,style:F,"data-change":!0},c)),e.createElement("h2",{style:X},"Details"),e.createElement(L,null,e.createElement("span",{style:bt},"Title"),e.createElement(z,{className:"mb-3",defaultValue:t.title??"",onBlur:xt(t,"title",d),"data-flow-title":!0})),e.createElement(L,null,e.createElement("span",{style:bt},"Start label"),e.createElement(z,{className:"mb-3",defaultValue:t.start_label??"",onBlur:xt(t,"start_label",d),"data-flow-start-label":!0})),e.createElement("div",{style:{marginTop:16}},e.createElement(b,{variant:"secondary",size:"sm",className:"w-full mb-1.5",onClick:l,"data-create-version":!0},"Create version"),e.createElement(b,{size:"sm",className:"w-full mb-1.5",onClick:i,"data-publish":!0},"Publish"),e.createElement(b,{variant:"secondary",size:"sm",className:"w-full mb-1.5",href:t.definition_url,"data-definition":!0},"Definition"),e.createElement(b,{variant:"secondary",size:"sm",className:"w-full mb-1.5",href:t.details_url,"data-details":!0},"Edit details"))),vt=pe;var kt={width:24,height:24,padding:0,fontSize:15,lineHeight:"15px"},ue=({link:t,onInsert:o,onRemove:n,onDrop:r,dragging:a})=>{let[l,i]=x(!1),d=l||a;return e.createElement("div",{"data-connector":`${t.source}-${t.target}`,style:{position:"absolute",left:t.midX-34,top:t.midY-20,width:68,height:40,zIndex:4},onMouseEnter:()=>i(!0),onMouseLeave:()=>i(!1),onDragEnter:()=>i(!0),onDragLeave:()=>i(!1),onDragOver:m=>{m.preventDefault(),m.dataTransfer.dropEffect="move"},onDrop:m=>{m.preventDefault(),i(!1),r()}},e.createElement("div",{style:{display:"flex",gap:4,justifyContent:"center",alignItems:"center",height:"100%",opacity:d?1:0,transition:"opacity .12s"}},e.createElement(b,{variant:"secondary",title:a?"Move the step here":"Insert a step here",onClick:o,className:"rounded-full data-[over=true]:ring-2 data-[over=true]:ring-accent-600","data-over":!!(a&&l),style:kt},"+"),!a&&e.createElement(b,{variant:"danger",title:"Remove this connection",onClick:n,className:"rounded-full",style:kt},"\xD7")))},wt=ue;var me=({links:t,extent:o,dragging:n,onInsert:r,onRemove:a,onDrop:l})=>e.createElement(e.Fragment,null,e.createElement("svg",{width:o.width,height:o.height,style:{position:"absolute",top:0,left:0,pointerEvents:"none",zIndex:1}},e.createElement("defs",null,e.createElement("marker",{id:"easy_flow-arrow",viewBox:"0 0 10 10",refX:"8",refY:"5",markerWidth:"5",markerHeight:"5",orient:"auto"},e.createElement("path",{d:"M 0 0 L 10 5 L 0 10 z",className:"fill-gray-400 dark:fill-zinc-500"}))),t.map(i=>e.createElement("path",{key:i.id,"data-link":i.id,className:"stroke-gray-400 dark:stroke-zinc-500",fill:"none",strokeWidth:"1.5",markerEnd:"url(#easy_flow-arrow)",d:i.path}))),t.filter(i=>i.label).map(i=>e.createElement("div",{key:`${i.id}-label`,"data-link-label":i.id,className:"bg-surface-50 text-gray-500 dark:bg-surface-950 dark:text-gray-400",style:{position:"absolute",left:i.midX-10,top:i.midY-18,zIndex:3,fontSize:11,padding:"0 3px"}},i.label)),t.filter(i=>!i.placeholder).map(i=>e.createElement(wt,{key:i.id,link:i,dragging:!!n,onInsert:()=>r(i),onRemove:()=>a(i),onDrop:()=>l(i)}))),Ct=me;var St="Your change was not saved because the server could not be reached.",Nt=({base:t,token:o,fetch:n,onFlow:r,onError:a,onNotice:l})=>async(i,d,m)=>{let c=await n(t+i,{method:d,headers:{"Content-Type":"application/json","X-CSRF-Token":o},body:m&&JSON.stringify(m)}).catch(()=>null);if(!c)return l(null),a(St);let y=await c.json().catch(()=>({}));if(!c.ok)return l(null),a(y.error||"That change was refused");a(null),l(y.notice||null),r(await(await n(t+".json",{headers:{Accept:"application/json"}})).json())},zt=({base:t,token:o,fetch:n,onError:r})=>async a=>{let l=new FormData;l.append("picture",a);let i=await n(t+"/pictures",{method:"POST",headers:{"X-CSRF-Token":o},body:l}).catch(()=>null);if(!i)return r(St),null;let d=await i.json().catch(()=>({}));return i.ok?(r(null),d):(r(d.error||"That picture was refused"),null)};var fe=(t,o,n)=>{let[r,a]=x(n),[l,i]=x(null),[d,m]=x(null),c=D(()=>Nt({base:t,token:o,fetch:(...u)=>window.fetch(...u),onFlow:a,onError:i,onNotice:m}),[t,o]),y=D(()=>zt({base:t,token:o,fetch:(...u)=>window.fetch(...u),onError:i}),[t,o]);return{flow:r,error:l,notice:d,send:c,pickPicture:y}},Bt=fe;var j=(t,o,n,r)=>{let a=t.left-n.left+r.scrollLeft,l=t.top-n.top+r.scrollTop;return o==="left"?{x:a,y:l+t.height/2}:o==="right"?{x:a+t.width,y:l+t.height/2}:o==="top"?{x:a+t.width/2,y:l}:{x:a+t.width/2,y:l+t.height}},ge=(t,o)=>o==="top"?{x:t.x,y:t.y-3}:o==="left"?{x:t.x-3,y:t.y}:o==="right"?{x:t.x+3,y:t.y}:{x:t.x,y:t.y+3},ye=(t,o,n,r,a)=>{let l={straight:`M ${o.x} ${o.y} L ${n.x} ${n.y}`,turn:`M ${o.x} ${o.y} H ${n.x} V ${n.y}`,lane:`M ${o.x} ${o.y} V ${r} H ${n.x} V ${n.y}`,detour:`M ${o.x} ${o.y} H ${a} V ${n.y} H ${n.x}`}[t.route];return{...t,path:l,midX:t.route==="detour"?a:(o.x+n.x)/2,midY:t.route==="lane"?r:(o.y+n.y)/2}},he=(t,o,n,r)=>{let[a,l]=x([]),[i,d]=x({width:"100%",height:"100%"});return R(()=>{let m=()=>{let y=o.current?.getBoundingClientRect();y&&(d({width:o.current.scrollWidth,height:o.current.scrollHeight}),l(t.edges.flatMap(u=>{let f=n.current[u.source]?.getBoundingClientRect(),p=n.current[u.target]?.getBoundingClientRect();if(!f||!p)return[];let w=j(f,u.leaves,y,o.current),k=ge(j(p,u.enters,y,o.current),u.enters),N=(j(f,"bottom",y,o.current).y+j(p,"top",y,o.current).y)/2,h=u.leaves==="left"?Math.min(w.x,k.x)-28:Math.max(w.x,k.x)+28;return[ye(u,w,k,N,h)]})))};m(),window.addEventListener("resize",m);let c=new ResizeObserver(m);return o.current&&c.observe(o.current),()=>{window.removeEventListener("resize",m),c.disconnect()}},r),{links:a,extent:i}},Tt=he;var Et=(t,o)=>{let n=new Set(o),r=t,a=2;for(;n.has(r);)r=`${t}_${a++}`;return r};var ve={display:"flex",height:"100%",minHeight:0,fontSize:13},ke={flex:1,overflow:"auto",position:"relative"},we={position:"absolute",top:56,left:16,zIndex:5,width:264,padding:12,borderRadius:8},Ce={display:"grid",rowGap:64,columnGap:0,padding:40,justifyContent:"center",position:"relative"},Se={position:"sticky",zIndex:8,top:8,margin:"8px auto 0",width:"fit-content",padding:"6px 12px",borderRadius:6,fontSize:12},Ne=({port:t,onCancel:o})=>e.createElement("div",{className:"bg-accent-100 text-accent-800 dark:bg-accent-900 dark:text-accent-100",style:Se},"Choose the step \u201C",t||"next","\u201D should lead to \u2014 ",e.createElement("button",{onClick:o,className:"text-accent-800 underline dark:text-accent-100",style:{border:"none",background:"none",cursor:"pointer",fontSize:12,padding:0}},"cancel")),ze=({base:t,token:o,initial:n})=>{let{flow:r,error:a,notice:l,send:i,pickPicture:d}=Bt(t,o,n),[m,c]=x(null),[y,u]=x(null),[f,p]=x(null),[w,k]=x(null),[N,h]=x(!1),B=W({}),v=W(null);P(()=>{let s=()=>{c(null),h(!0)};return document.addEventListener("easy_flow:open-flow",s),()=>document.removeEventListener("easy_flow:open-flow",s)},[]),P(()=>{if(!N)return;let s=g=>{g.target.closest("[data-builder-panel], [data-open-panel]")||h(!1)};return document.addEventListener("click",s),()=>document.removeEventListener("click",s)},[N]),P(()=>{document.dispatchEvent(new CustomEvent("easy_flow:flow-named",{detail:r.flow?.title||r.flow?.slug}))},[r.flow?.title,r.flow?.slug]);let _=D(()=>Object.fromEntries(r.nodes.map(s=>[s.id,s])),[r.nodes]),{links:Dt,extent:$t}=Tt(r,v,B,[r,m,_]),G=D(()=>{let s={};return r.violations.forEach(g=>{var C;return(s[C=g.node]||(s[C]=[])).push(g)}),s},[r.violations]),V=r.nodes.filter(s=>!s.loose),q=r.nodes.filter(s=>s.loose),At=Math.max(0,...V.map(s=>s.row))+1,_t=Math.max(0,...V.map(s=>s.column))+1,J=s=>{if(!f)return;let[g,C]=f;p(null),g!==s&&i("/edges","POST",{from:g,to:s,on:C||null})},T=r.nodes.find(s=>s.id===m),E=r.palette.find(s=>s.type===T?.type);return e.createElement("div",{className:"text-gray-900 dark:text-gray-100",style:ve,onMouseUp:()=>k(null),onKeyDown:s=>{s.key==="Escape"&&(c(null),p(null),u(null))},tabIndex:-1},e.createElement("div",{ref:v,className:"bg-surface-50 dark:bg-surface-950",style:ke,onClick:s=>{s.target===v.current&&(c(null),p(null),h(!1))}},f&&e.createElement(Ne,{port:f[1],onCancel:()=>p(null)}),e.createElement(gt,{undoable:r.undoable,redoable:r.redoable,onAdd:()=>u({at:{x:16,y:52}}),onUndo:()=>{c(null),i("/undo","POST")},onRedo:()=>{c(null),i("/redo","POST")}}),e.createElement(Ct,{links:Dt,extent:$t,dragging:w,onInsert:s=>u({from:s.source,to:s.target,at:{x:s.midX+30,y:s.midY}}),onRemove:s=>{c(null),i("/edges","DELETE",{from:s.source,to:s.target})},onDrop:s=>{let g=w;k(null),i("/steps/"+g+"/move","PATCH",{from:s.source,to:s.target})}}),q.length>0&&e.createElement("div",{"data-loose":!0,className:"border border-dashed border-gray-300 bg-gray-50 dark:border-zinc-700 dark:bg-zinc-900",style:we},e.createElement("div",{className:"text-gray-500 dark:text-gray-400",style:{fontSize:11,marginBottom:6}},"Not in the flow yet \u2014 drag one onto a connection"),q.map(s=>e.createElement("div",{key:s.id,style:{marginBottom:8}},e.createElement(U,{node:{...s,ref:g=>{B.current[s.id]=g},violations:G[s.id]||[],connected:[]},selected:m===s.id,armed:f&&f[0]===s.id?f[1]:null,connecting:!!f,onSelect:()=>f?J(s.id):c(s.id),onOpen:g=>window.location.assign(g),onArm:(g,C)=>{C.stopPropagation(),p([s.id,g])},onDragStart:()=>k(s.id),onDragEnd:()=>k(null)})))),e.createElement("div",{style:{...Ce,gridTemplateColumns:`repeat(${_t+1}, ${280/2}px)`,gridTemplateRows:`repeat(${At}, auto)`}},V.map(s=>e.createElement("div",{key:s.id,style:{gridRow:s.row+1,gridColumn:`${s.column+1} / span 2`,zIndex:2}},s.placeholder&&e.createElement(ut,{node:{...s,ref:g=>{B.current[s.id]=g}},dragging:!!w,onFill:()=>u({from:s.from,on:s.on,at:{x:16,y:52}}),onDrop:()=>{let g=w;k(null),g&&i("/edges","POST",{from:s.from,to:g,on:s.on})}}),!s.placeholder&&e.createElement(U,{node:{...s,ref:g=>{B.current[s.id]=g},violations:G[s.id]||[],connected:r.edges.filter(g=>g.source===s.id).map(g=>g.label||null)},selected:s.id===m,armed:f&&f[0]===s.id?f[1]:null,connecting:!!f&&f[0]!==s.id,onSelect:()=>f?J(s.id):c(s.id),onOpen:g=>window.location.assign(g),onArm:(g,C)=>{let K=v.current.getBoundingClientRect();u({from:s.id,on:g,at:{x:C.clientX-K.left+v.current.scrollLeft+8,y:C.clientY-K.top+v.current.scrollTop+8}})},onDragEnd:()=>k(null),onDragStart:()=>k(s.id)})))),y&&e.createElement(mt,{entries:r.palette,at:y.at,onDismiss:()=>u(null),onConnect:y.on!==void 0?()=>{p([y.from,y.on]),u(null)}:null,onPick:s=>{let g=y;u(null),i("/steps","POST",{id:Et(s.type,r.nodes.map(C=>C.id)),type:s.type,from:g.from,to:g.to,on:g.on})}})),N&&!T&&e.createElement(vt,{flow:r.flow||{},changes:r.changes||[],problems:r.violations,refusal:a,notice:l,onClose:()=>h(!1),onCreate:()=>i("/versions","POST"),onPublish:()=>i("/publish","POST"),onSaveDetails:s=>i("/details","PATCH",{flow:s})}),T&&e.createElement(pt,{node:T,fields:E?.fields||{},holds:E?.records||{},labels:E?.labels||{},recordLabels:E?.record_labels||{},recordChoices:E?.record_choices||{},recordOutputsOf:E?.record_outputs_of||{},choices:at(T,E),onClose:()=>c(null),onSave:s=>i(`/steps/${T.id}`,"PATCH",{config:s}),onPickPicture:d,onDelete:()=>{c(null),i(`/steps/${T.id}`,"DELETE")}}))},Pt=ze;et("easy_flow/flow-editor",Pt);document.addEventListener("easy_flow:flow-named",t=>{let o=document.querySelector("[data-flow-heading]");o&&(o.textContent=t.detail)});nt(document,Z);})();
1
+ (()=>{var Lt=globalThis.ReactDOM;var{createPortal:Be,createRoot:Q,flushSync:Te,hydrateRoot:Ee,preconnect:Pe,prefetchDNS:De,preinit:$e,preinitModule:Ae,preload:_e,preloadModule:Le,requestFormReset:Ie,unstable_batchedUpdates:Me,useFormState:Oe,useFormStatus:He,version:Fe}=Lt;var R=globalThis.React,e=R,{Children:We,Component:Ve,Fragment:Ue,PureComponent:Ye,StrictMode:Xe,Suspense:Ge,cloneElement:qe,createContext:Je,createElement:Ke,createRef:Ze,forwardRef:Qe,isValidElement:Re,lazy:to,memo:eo,startTransition:oo,useCallback:ro,useContext:no,useDebugValue:so,useDeferredValue:ao,useEffect:D,useId:io,useImperativeHandle:lo,useLayoutEffect:tt,useMemo:$,useReducer:co,useRef:U,useState:b,useSyncExternalStore:po,useTransition:uo}=R;var et=new Map,M=new Map,ot=(t,o)=>et.set(t,o),rt=()=>{M.forEach(t=>t.unmount()),M.clear()},nt=(t,o)=>t.querySelectorAll("[data-react-ui]").forEach(n=>{if(M.has(n))return;let r=et.get(n.dataset.reactUi),a=o(n);M.set(n,a),a.render(e.createElement(r,JSON.parse(n.dataset.props)))});var st=(t,o)=>{let n=()=>nt(t,o);t.addEventListener("turbo:load",n),t.addEventListener("turbo:frame-load",n),t.addEventListener("turbo:before-cache",rt),t.readyState==="loading"?t.addEventListener("DOMContentLoaded",n):n()};var N=(...t)=>t.filter(Boolean).join(" ");var It={primary:"ks-button-primary",secondary:"ks-button-secondary",danger:"ks-button-danger"},Mt={sm:"ks-button-sm",md:"ks-button-md",lg:"ks-button-lg"},Ot=({variant:t="primary",size:o="md",className:n,children:r,...a})=>{let l=a.href?"a":"button";return e.createElement(l,{...a,className:N("ks-button",It[t],Mt[o],n)},r)},x=Ot;var Ht="border border-amber-500 bg-white text-amber-700 dark:bg-zinc-900 dark:text-amber-400",Ft="border border-gray-300 bg-white text-gray-500 dark:border-zinc-600 dark:bg-zinc-900 dark:text-gray-400",jt="border border-accent-600 bg-accent-600 text-white",Wt=({name:t,connected:o,armed:n,onArm:r,connecting:a})=>e.createElement("button",{onClick:l=>{a||(l.stopPropagation(),r(l))},title:n?"Now choose a step to connect to":"Connect this branch",className:n?jt:o?Ft:Ht,style:{padding:"1px 8px",marginRight:4,borderRadius:999,fontSize:11,cursor:"pointer"}},t||"next"),at=Wt;var Vt={width:240,boxSizing:"border-box",borderRadius:8},Ut={padding:"8px 14px",textAlign:"center",fontWeight:600},Yt={fontWeight:600,lineHeight:1.3},Xt=(t,o,n)=>{let r=n?"ring-4 ring-accent-600/15":"shadow-sm";return t||n&&!o?`border-accent-600 ${r}`:o?`border-red-600 ${r}`:"border-gray-300 shadow-sm dark:border-zinc-700"},Gt=({node:t,selected:o,armed:n,connecting:r,onSelect:a,onOpen:l,onArm:i,onDragEnd:d,onDragStart:m})=>{let c=t.begins_here||t.ends_here,g=t.begins_here,u=t.ends_here?[]:t.ports,y=r&&!g;return e.createElement("div",{ref:t.ref,"data-step":t.id,draggable:!g,onDragStart:p=>{p.dataTransfer.effectAllowed="move",p.dataTransfer.setData("text/plain",t.id),m()},onDragEnd:d,onClick:t.opens&&!r?()=>l(t.opens):a,className:`bg-white border-2 dark:bg-zinc-900 ${Xt(y,t.violations.length>0,o)}`,style:{...Vt,padding:c?0:"12px 14px",cursor:g?"default":r?"crosshair":"grab"}},c&&e.createElement("div",{className:"text-gray-500 dark:text-gray-400",style:Ut},t.label),!c&&e.createElement("div",{style:Yt},t.label),!c&&e.createElement("div",{className:"text-gray-500 dark:text-gray-400",style:{fontSize:11,marginTop:2}},t.type),t.starts_a_flow&&e.createElement("div",{className:"text-accent-600 dark:text-accent-400",style:{fontSize:11,marginTop:2}},"Runs a flow"),t.opens&&e.createElement(x,{variant:"secondary",size:"sm",className:"mt-2",onClick:p=>{p.stopPropagation(),a()}},"Settings"),t.violations.map(p=>e.createElement("div",{key:p.problem+p.detail,className:"text-red-600 dark:text-red-400",style:{fontSize:11,padding:"0 14px 6px"}},p.problem.replace(/_/g," "),p.detail?`: ${p.detail}`:"")),u.length>0&&e.createElement("div",{style:{padding:t.begins_here?"0 14px 8px":"10px 0 0"}},u.map(p=>e.createElement(at,{key:p,name:p,connected:t.connected.includes(p),connecting:r,armed:n===p,onArm:v=>i(p,v)}))))},Y=Gt;var X=(t,o)=>t.includes(o)?t.filter(n=>n!==o):[...t,o],it=(t,o)=>({...o?.choices||{},...t?.choices||{}});var qt=({as:t="input",disabled:o,className:n,...r})=>e.createElement(t,{...r,disabled:o,className:N("ks-input",o&&"ks-input-disabled",n)}),T=qt;var Jt=t=>e.createElement(T,{...t,as:"select"}),lt=Jt;var Kt=({className:t,...o})=>e.createElement("input",{type:"checkbox",...o,className:N("ks-checkbox",t)}),O=Kt;var dt=t=>(t||[]).map(o=>typeof o=="object"?o:{value:o,label:o}),Zt=({type:t,value:o,choices:n,onChange:r,onSettle:a,onPick:l,pictureUrl:i})=>{if(t==="picture")return e.createElement("div",{className:"mb-3"},o&&i&&e.createElement("img",{src:i,alt:"The step's picture",style:{maxWidth:"100%"}}),o&&e.createElement("button",{type:"button","data-remove-picture":!0,className:"ks-button ks-button-secondary ks-button-sm",onClick:()=>a("")},"Remove picture"),e.createElement("input",{type:"file",accept:"image/*",onChange:d=>d.target.files[0]&&l(d.target.files[0])}));if(t==="boolean")return e.createElement(O,{checked:!!o,onChange:d=>a(d.target.checked)});if(t==="select"||t==="previous_step"||t==="from_step"||t==="flow")return e.createElement(lt,{className:"mb-3",value:o??"",onChange:d=>a(d.target.value)},e.createElement("option",{value:""}),dt(n).map(d=>e.createElement("option",{key:d.value,value:d.value},d.label)));if(t==="multi_select"){let d=Array.isArray(o)?o:[],m=c=>a(X(d,c));return e.createElement("div",{style:{display:"flex",flexWrap:"wrap",gap:8}},(n||[]).map(c=>e.createElement("label",{key:c,style:{display:"inline-flex",alignItems:"center",gap:4}},e.createElement(O,{checked:d.includes(c),onChange:()=>m(c)}),e.createElement("span",null,c))))}if(t==="flows"){let d=Array.isArray(o)?o:[];return e.createElement("div",{style:{display:"flex",flexDirection:"column",gap:4},className:"mb-3"},dt(n).map(m=>e.createElement("label",{key:m.value,style:{display:"inline-flex",alignItems:"center",gap:4}},e.createElement(O,{checked:d.includes(m.value),onChange:()=>a(X(d,m.value))}),e.createElement("span",null,m.label))))}return t==="integer"||t==="float"?e.createElement(T,{className:"mb-3",type:"number",step:t==="integer"?"1":"any",value:o??"",onChange:d=>r(d.target.value),onBlur:d=>a(d.target.value)}):e.createElement(T,{className:"mb-3",type:"text",value:o??"",onChange:d=>r(d.target.value),onBlur:d=>a(d.target.value)})},H=Zt;var ct=(t,o,n,r)=>t.map((a,l)=>l===o?{...a,[n]:r}:a);var Qt=(t,o,n,r)=>{let a=(t||{})[n],l=(o||{})[n];return l?(a||{})[r[l]]:a},Rt=({holds:t,labels:o,rows:n,choices:r,outputsOf:a,onChange:l,onSettle:i})=>{let d=Array.isArray(n)?n:[],m=(c,g,u,y)=>{let p=ct(d,c,g,u);y?i(p):l(p)};return e.createElement("div",{style:{marginBottom:12}},d.map((c,g)=>e.createElement("div",{key:g,className:"rounded-md border border-gray-200 dark:border-zinc-700",style:{padding:"8px 8px 2px",marginBottom:6}},Object.entries(t).map(([u,y])=>e.createElement("label",{key:u,style:{display:"block"}},e.createElement("span",{className:"text-gray-500 dark:text-gray-400",style:{display:"block",marginBottom:2,fontSize:11}},(o||{})[u]||u),e.createElement(H,{type:y,value:c[u],choices:Qt(r,a,u,c),onChange:p=>m(g,u,p,!1),onSettle:p=>m(g,u,p,!0)}))),e.createElement(x,{variant:"secondary",size:"sm",className:"mb-1.5",onClick:()=>i(d.filter((u,y)=>y!==g))},"Remove"))),e.createElement(x,{variant:"secondary",size:"sm",className:"w-full",onClick:()=>i([...d,{}])},"Add"))},pt=Rt;var te=({as:t="div",className:o,children:n,...r})=>e.createElement(t,{...r,className:N("ks-panel",o)},n),_=te;var F=(t,o)=>({className:n,children:r,...a})=>e.createElement(t,{...a,className:N(o,n)},r),I=F("label","ks-label"),rr=F("p","ks-hint"),nr=F("p","ks-error"),sr=F("span","ks-required");var ee={width:280,padding:20,overflowY:"auto"},oe=({node:t,fields:o,holds:n,labels:r,recordLabels:a,recordChoices:l,recordOutputsOf:i,choices:d,onSave:m,onDelete:c,onClose:g,onPickPicture:u,refusal:y})=>{let[p,v]=b(t.config),[k,B]=b(t.picture_url);D(()=>B(t.picture_url),[t.id,t.picture_url]),D(()=>v(t.config),[t.id,t.config]);let S=h=>{v(h),JSON.stringify(h)!==JSON.stringify(t.config)&&m(h)};return e.createElement(_,{as:"aside",style:ee,"data-inspector":!0},e.createElement("div",{style:{display:"flex",alignItems:"start",justifyContent:"space-between",gap:8}},e.createElement("h2",{style:{fontWeight:600,marginBottom:2}},t.label),e.createElement("button",{title:"Close",onClick:g,className:"text-gray-500 dark:text-gray-400",style:{border:"none",background:"none",cursor:"pointer",fontSize:18,lineHeight:1}},"\xD7")),e.createElement("p",{className:"text-gray-500 dark:text-gray-400",style:{fontSize:11,marginBottom:16}},t.id," \xB7 ",t.type),y&&e.createElement("p",{className:"text-red-800 dark:text-red-400",style:{fontWeight:600,marginBottom:12},"data-refusal":!0},y),Object.entries(o).map(([h,z])=>e.createElement(I,{key:h},e.createElement("span",{style:{display:"block",marginBottom:3}},r[h]||h),z==="list"?e.createElement(pt,{holds:n[h]||{},labels:a[h]||{},rows:p[h],choices:{...(l||{})[h],...(t.record_choices||{})[h]},outputsOf:(i||{})[h],onChange:w=>v({...p,[h]:w}),onSettle:w=>S({...p,[h]:w})}):e.createElement(H,{type:z,value:p[h],choices:d[h],pictureUrl:k,onChange:w=>v({...p,[h]:w}),onSettle:w=>S({...p,[h]:w}),onPick:async w=>{let L=await u(w);L&&(B(L.url),S({...p,[h]:L.reference}))}}))),e.createElement(x,{variant:"danger",size:"sm",className:"w-full",onClick:c},"Delete step"))},ut=oe;var re={width:240,boxSizing:"border-box",padding:"10px 14px",borderRadius:8,textAlign:"center",fontSize:12,cursor:"pointer"},ne="border-2 border-dashed border-amber-500 bg-amber-50 text-amber-700 dark:bg-amber-950 dark:text-amber-300",se="border-2 border-dashed border-accent-600 bg-accent-50 text-accent-800 dark:bg-accent-950 dark:text-accent-200",ae=({node:t,dragging:o,onFill:n,onDrop:r})=>e.createElement("div",{ref:t.ref,"data-placeholder":t.id,title:`Choose the step \u201C${t.label}\u201D should lead to`,onClick:n,onDragOver:a=>{o&&(a.preventDefault(),a.dataTransfer.dropEffect="move")},onDrop:a=>{a.preventDefault(),r()},className:o?se:ne,style:re},e.createElement("div",{style:{fontWeight:600}},t.label),e.createElement("div",{style:{fontSize:11}},o?"drop a step here":"leads nowhere yet \u2014 click to choose")),mt=ae;var ie=({entries:t,at:o,onPick:n,onConnect:r,onDismiss:a})=>e.createElement(_,{className:"shadow-lg",style:{position:"absolute",zIndex:9,top:o.y,left:o.x,width:210,padding:8,borderRadius:8}},e.createElement("p",{className:"text-gray-500 dark:text-gray-400",style:{margin:"0 0 6px",fontSize:11}},"Add a step"),t.map(l=>e.createElement(x,{key:l.type,variant:"secondary",size:"sm",className:"w-full mb-1.5 flex-col",onClick:()=>n(l)},l.label,e.createElement("span",{className:"opacity-75",style:{display:"block",fontSize:11}},l.type))),r&&e.createElement(x,{variant:"secondary",size:"sm",className:"w-full mb-1.5",onClick:r},"Connect to a step already here"),e.createElement(x,{variant:"secondary",size:"sm",className:"w-full",onClick:a},"Cancel")),ft=ie;var le={width:24,height:24,padding:0,fontSize:15,lineHeight:"15px"},gt=({label:t,title:o,idle:n,enabled:r,onUse:a})=>e.createElement(x,{variant:"secondary",size:"sm",title:r?o:n,disabled:!r,onClick:a,style:{opacity:r?1:.4,cursor:r?"pointer":"default"}},t),de=({undoable:t,redoable:o,onAdd:n,onUndo:r,onRedo:a})=>e.createElement("div",{style:{position:"absolute",top:16,left:16,zIndex:5,display:"flex",gap:8}},e.createElement(x,{variant:"secondary",className:"rounded-full",style:le,title:"Add a step",onClick:n},"+"),e.createElement(gt,{label:"\u21B6 Undo",title:"Undo the last change",idle:"Nothing to undo",enabled:t,onUse:r}),e.createElement(gt,{label:"\u21B7 Redo",title:"Redo the change you undid",idle:"Nothing to redo",enabled:o,onUse:a})),yt=de;var ht=t=>{let o=t.problem.replace(/_/g," ");return t.node?`\u201C${t.node}\u201D ${o}`:o};var xt=({version:t,published:o})=>t?o?o===t?`Version ${t} \xB7 live`:`Version ${t} \xB7 visitors still on ${o}`:`Version ${t} \xB7 never published`:"No version yet";var ce={width:280,padding:20,overflowY:"auto"},G={fontWeight:600,marginBottom:6,marginTop:14},j={fontSize:12,marginBottom:4,lineHeight:1.4},bt={display:"block",marginBottom:3},vt=(t,o,n)=>r=>{r.target.value!==(t[o]??"")&&n({[o]:r.target.value})},pe=({flow:t,changes:o,problems:n,refusal:r,notice:a,onCreate:l,onPublish:i,onSaveDetails:d,onClose:m})=>e.createElement(_,{as:"aside",style:ce,"data-builder-panel":!0},e.createElement("div",{style:{display:"flex",alignItems:"start",justifyContent:"space-between",gap:8}},e.createElement("h2",{style:{fontWeight:600},"data-flow-name":!0},t.title||t.slug),e.createElement("button",{title:"Close",onClick:m,className:"text-gray-500 dark:text-gray-400",style:{border:"none",background:"none",cursor:"pointer",fontSize:18,lineHeight:1}},"\xD7")),e.createElement("a",{className:"text-accent-600 dark:text-accent-400",style:{fontSize:12,display:"block"},href:t.history_url,"data-history":!0},xt(t)),e.createElement("h2",{style:G},"Problems"),r&&e.createElement("p",{className:"text-red-800 dark:text-red-400",style:{...j,fontWeight:600},"data-refusal":!0},r),a&&!r&&e.createElement("p",{className:"text-emerald-800 dark:text-emerald-400",style:{...j,fontWeight:600},"data-notice":!0},a),n.length===0&&!r?e.createElement("p",{className:"text-gray-500 dark:text-gray-400",style:{fontSize:12}},"Nothing wrong with this flow."):n.map(c=>e.createElement("p",{key:`${c.node}-${c.problem}`,className:"text-amber-700 dark:text-amber-400",style:j,"data-problem":!0},"\u26A0 ",ht(c))),e.createElement("h2",{style:G},"Changes since the last version"),o.length===0?e.createElement("p",{className:"text-gray-500 dark:text-gray-400",style:{fontSize:12}},"Nothing has changed."):o.map((c,g)=>e.createElement("p",{key:g,style:j,"data-change":!0},c)),e.createElement("h2",{style:G},"Details"),e.createElement(I,null,e.createElement("span",{style:bt},"Title"),e.createElement(T,{className:"mb-3",defaultValue:t.title??"",onBlur:vt(t,"title",d),"data-flow-title":!0})),e.createElement(I,null,e.createElement("span",{style:bt},"Start label"),e.createElement(T,{className:"mb-3",defaultValue:t.start_label??"",onBlur:vt(t,"start_label",d),"data-flow-start-label":!0})),e.createElement("div",{style:{marginTop:16}},e.createElement(x,{variant:"secondary",size:"sm",className:"w-full mb-1.5",onClick:l,"data-create-version":!0},"Create version"),e.createElement(x,{size:"sm",className:"w-full mb-1.5",onClick:i,"data-publish":!0},"Publish"),e.createElement(x,{variant:"secondary",size:"sm",className:"w-full mb-1.5",href:t.definition_url,"data-definition":!0},"Definition"),e.createElement(x,{variant:"secondary",size:"sm",className:"w-full mb-1.5",href:t.details_url,"data-details":!0},"Edit details"))),kt=pe;var wt={width:24,height:24,padding:0,fontSize:15,lineHeight:"15px"},ue=({link:t,onInsert:o,onRemove:n,onDrop:r,dragging:a})=>{let[l,i]=b(!1),d=l||a;return e.createElement("div",{"data-connector":`${t.source}-${t.target}`,style:{position:"absolute",left:t.midX-34,top:t.midY-20,width:68,height:40,zIndex:4},onMouseEnter:()=>i(!0),onMouseLeave:()=>i(!1),onDragEnter:()=>i(!0),onDragLeave:()=>i(!1),onDragOver:m=>{m.preventDefault(),m.dataTransfer.dropEffect="move"},onDrop:m=>{m.preventDefault(),i(!1),r()}},e.createElement("div",{style:{display:"flex",gap:4,justifyContent:"center",alignItems:"center",height:"100%",opacity:d?1:0,transition:"opacity .12s"}},e.createElement(x,{variant:"secondary",title:a?"Move the step here":"Insert a step here",onClick:o,className:"rounded-full data-[over=true]:ring-2 data-[over=true]:ring-accent-600","data-over":!!(a&&l),style:wt},"+"),!a&&e.createElement(x,{variant:"danger",title:"Remove this connection",onClick:n,className:"rounded-full",style:wt},"\xD7")))},Ct=ue;var me=({links:t,extent:o,dragging:n,onInsert:r,onRemove:a,onDrop:l})=>e.createElement(e.Fragment,null,e.createElement("svg",{width:o.width,height:o.height,style:{position:"absolute",top:0,left:0,pointerEvents:"none",zIndex:1}},e.createElement("defs",null,e.createElement("marker",{id:"easy_flow-arrow",viewBox:"0 0 10 10",refX:"8",refY:"5",markerWidth:"5",markerHeight:"5",orient:"auto"},e.createElement("path",{d:"M 0 0 L 10 5 L 0 10 z",className:"fill-gray-400 dark:fill-zinc-500"}))),t.map(i=>e.createElement("path",{key:i.id,"data-link":i.id,className:"stroke-gray-400 dark:stroke-zinc-500",fill:"none",strokeWidth:"1.5",markerEnd:"url(#easy_flow-arrow)",d:i.path}))),t.filter(i=>i.label).map(i=>e.createElement("div",{key:`${i.id}-label`,"data-link-label":i.id,className:"bg-surface-50 text-gray-500 dark:bg-surface-950 dark:text-gray-400",style:{position:"absolute",left:i.midX-10,top:i.midY-18,zIndex:3,fontSize:11,padding:"0 3px"}},i.label)),t.filter(i=>!i.placeholder).map(i=>e.createElement(Ct,{key:i.id,link:i,dragging:!!n,onInsert:()=>r(i),onRemove:()=>a(i),onDrop:()=>l(i)}))),St=me;var Nt="Your change was not saved because the server could not be reached.",zt=({base:t,token:o,fetch:n,onFlow:r,onError:a,onNotice:l})=>async(i,d,m)=>{let c=await n(t+i,{method:d,headers:{"Content-Type":"application/json","X-CSRF-Token":o},body:m&&JSON.stringify(m)}).catch(()=>null);if(!c)return l(null),a(Nt);let g=await c.json().catch(()=>({}));if(!c.ok)return l(null),a(g.error||"That change was refused");a(null),l(g.notice||null),r(await(await n(t+".json",{headers:{Accept:"application/json"}})).json())},Bt=({base:t,token:o,fetch:n,onError:r})=>async a=>{let l=new FormData;l.append("picture",a);let i=await n(t+"/pictures",{method:"POST",headers:{"X-CSRF-Token":o},body:l}).catch(()=>null);if(!i)return r(Nt),null;let d=await i.json().catch(()=>({}));return i.ok?(r(null),d):(r(d.error||"That picture was refused"),null)};var fe=(t,o,n)=>{let[r,a]=b(n),[l,i]=b(null),[d,m]=b(null),c=$(()=>zt({base:t,token:o,fetch:(...u)=>window.fetch(...u),onFlow:a,onError:i,onNotice:m}),[t,o]),g=$(()=>Bt({base:t,token:o,fetch:(...u)=>window.fetch(...u),onError:i}),[t,o]);return{flow:r,error:l,notice:d,send:c,pickPicture:g}},Tt=fe;var W=(t,o,n,r)=>{let a=t.left-n.left+r.scrollLeft,l=t.top-n.top+r.scrollTop;return o==="left"?{x:a,y:l+t.height/2}:o==="right"?{x:a+t.width,y:l+t.height/2}:o==="top"?{x:a+t.width/2,y:l}:{x:a+t.width/2,y:l+t.height}},ge=(t,o)=>o==="top"?{x:t.x,y:t.y-3}:o==="left"?{x:t.x-3,y:t.y}:o==="right"?{x:t.x+3,y:t.y}:{x:t.x,y:t.y+3},ye=(t,o,n,r,a)=>{let l={straight:`M ${o.x} ${o.y} L ${n.x} ${n.y}`,turn:`M ${o.x} ${o.y} H ${n.x} V ${n.y}`,lane:`M ${o.x} ${o.y} V ${r} H ${n.x} V ${n.y}`,detour:`M ${o.x} ${o.y} H ${a} V ${n.y} H ${n.x}`}[t.route];return{...t,path:l,midX:t.route==="detour"?a:(o.x+n.x)/2,midY:t.route==="lane"?r:(o.y+n.y)/2}},he=(t,o,n,r)=>{let[a,l]=b([]),[i,d]=b({width:"100%",height:"100%"});return tt(()=>{let m=()=>{let g=o.current?.getBoundingClientRect();g&&(d({width:o.current.scrollWidth,height:o.current.scrollHeight}),l(t.edges.flatMap(u=>{let y=n.current[u.source]?.getBoundingClientRect(),p=n.current[u.target]?.getBoundingClientRect();if(!y||!p)return[];let v=W(y,u.leaves,g,o.current),k=ge(W(p,u.enters,g,o.current),u.enters),B=(W(y,"bottom",g,o.current).y+W(p,"top",g,o.current).y)/2,S=u.leaves==="left"?Math.min(v.x,k.x)-28:Math.max(v.x,k.x)+28;return[ye(u,v,k,B,S)]})))};m(),window.addEventListener("resize",m);let c=new ResizeObserver(m);return o.current&&c.observe(o.current),()=>{window.removeEventListener("resize",m),c.disconnect()}},r),{links:a,extent:i}},Et=he;var Pt=(t,o)=>{let n=new Set(o),r=t,a=2;for(;n.has(r);)r=`${t}_${a++}`;return r};var ve={display:"flex",height:"100%",minHeight:0,fontSize:13},ke={flex:1,overflow:"auto",position:"relative"},we={position:"absolute",top:56,left:16,zIndex:5,width:264,padding:12,borderRadius:8},Ce={display:"grid",rowGap:64,columnGap:0,padding:40,justifyContent:"center",position:"relative"},Se={position:"sticky",zIndex:8,top:8,margin:"8px auto 0",width:"fit-content",padding:"6px 12px",borderRadius:6,fontSize:12},Ne=({port:t,onCancel:o})=>e.createElement("div",{className:"bg-accent-100 text-accent-800 dark:bg-accent-900 dark:text-accent-100",style:Se},"Choose the step \u201C",t||"next","\u201D should lead to \u2014 ",e.createElement("button",{onClick:o,className:"text-accent-800 underline dark:text-accent-100",style:{border:"none",background:"none",cursor:"pointer",fontSize:12,padding:0}},"cancel")),ze=({base:t,token:o,initial:n})=>{let{flow:r,error:a,notice:l,send:i,pickPicture:d}=Tt(t,o,n),[m,c]=b(null),[g,u]=b(null),[y,p]=b(null),[v,k]=b(null),[B,S]=b(!1),h=U({}),z=U(null);D(()=>{let s=()=>{c(null),S(!0)};return document.addEventListener("easy_flow:open-flow",s),()=>document.removeEventListener("easy_flow:open-flow",s)},[]),D(()=>{if(!B)return;let s=f=>{f.target.closest("[data-builder-panel], [data-open-panel]")||S(!1)};return document.addEventListener("click",s),()=>document.removeEventListener("click",s)},[B]),D(()=>{document.dispatchEvent(new CustomEvent("easy_flow:flow-named",{detail:r.flow?.title||r.flow?.slug}))},[r.flow?.title,r.flow?.slug]);let w=$(()=>Object.fromEntries(r.nodes.map(s=>[s.id,s])),[r.nodes]),{links:L,extent:$t}=Et(r,z,h,[r,m,w]),q=$(()=>{let s={};return r.violations.forEach(f=>{var C;return(s[C=f.node]||(s[C]=[])).push(f)}),s},[r.violations]),V=r.nodes.filter(s=>!s.loose),J=r.nodes.filter(s=>s.loose),At=Math.max(0,...V.map(s=>s.row))+1,_t=Math.max(0,...V.map(s=>s.column))+1,K=s=>{if(!y)return;let[f,C]=y;p(null),f!==s&&i("/edges","POST",{from:f,to:s,on:C||null})},E=r.nodes.find(s=>s.id===m),P=r.palette.find(s=>s.type===E?.type);return e.createElement("div",{className:"text-gray-900 dark:text-gray-100",style:ve,onMouseUp:()=>k(null),onKeyDown:s=>{s.key==="Escape"&&(c(null),p(null),u(null))},tabIndex:-1},e.createElement("div",{ref:z,className:"bg-surface-50 dark:bg-surface-950",style:ke,onClick:s=>{s.target===z.current&&(c(null),p(null),S(!1))}},y&&e.createElement(Ne,{port:y[1],onCancel:()=>p(null)}),e.createElement(yt,{undoable:r.undoable,redoable:r.redoable,onAdd:()=>u({at:{x:16,y:52}}),onUndo:()=>{c(null),i("/undo","POST")},onRedo:()=>{c(null),i("/redo","POST")}}),e.createElement(St,{links:L,extent:$t,dragging:v,onInsert:s=>u({from:s.source,to:s.target,at:{x:s.midX+30,y:s.midY}}),onRemove:s=>{c(null),i("/edges","DELETE",{from:s.source,to:s.target})},onDrop:s=>{let f=v;k(null),i("/steps/"+f+"/move","PATCH",{from:s.source,to:s.target})}}),J.length>0&&e.createElement("div",{"data-loose":!0,className:"border border-dashed border-gray-300 bg-gray-50 dark:border-zinc-700 dark:bg-zinc-900",style:we},e.createElement("div",{className:"text-gray-500 dark:text-gray-400",style:{fontSize:11,marginBottom:6}},"Not in the flow yet \u2014 drag one onto a connection"),J.map(s=>e.createElement("div",{key:s.id,style:{marginBottom:8}},e.createElement(Y,{node:{...s,ref:f=>{h.current[s.id]=f},violations:q[s.id]||[],connected:[]},selected:m===s.id,armed:y&&y[0]===s.id?y[1]:null,connecting:!!y,onSelect:()=>y?K(s.id):c(s.id),onOpen:f=>window.location.assign(f),onArm:(f,C)=>{C.stopPropagation(),p([s.id,f])},onDragStart:()=>k(s.id),onDragEnd:()=>k(null)})))),e.createElement("div",{style:{...Ce,gridTemplateColumns:`repeat(${_t+1}, ${280/2}px)`,gridTemplateRows:`repeat(${At}, auto)`}},V.map(s=>e.createElement("div",{key:s.id,style:{gridRow:s.row+1,gridColumn:`${s.column+1} / span 2`,zIndex:2}},s.placeholder&&e.createElement(mt,{node:{...s,ref:f=>{h.current[s.id]=f}},dragging:!!v,onFill:()=>u({from:s.from,on:s.on,at:{x:16,y:52}}),onDrop:()=>{let f=v;k(null),f&&i("/edges","POST",{from:s.from,to:f,on:s.on})}}),!s.placeholder&&e.createElement(Y,{node:{...s,ref:f=>{h.current[s.id]=f},violations:q[s.id]||[],connected:r.edges.filter(f=>f.source===s.id).map(f=>f.label||null)},selected:s.id===m,armed:y&&y[0]===s.id?y[1]:null,connecting:!!y&&y[0]!==s.id,onSelect:()=>y?K(s.id):c(s.id),onOpen:f=>window.location.assign(f),onArm:(f,C)=>{let Z=z.current.getBoundingClientRect();u({from:s.id,on:f,at:{x:C.clientX-Z.left+z.current.scrollLeft+8,y:C.clientY-Z.top+z.current.scrollTop+8}})},onDragEnd:()=>k(null),onDragStart:()=>k(s.id)})))),g&&e.createElement(ft,{entries:r.palette,at:g.at,onDismiss:()=>u(null),onConnect:g.on!==void 0?()=>{p([g.from,g.on]),u(null)}:null,onPick:s=>{let f=g;u(null),i("/steps","POST",{id:Pt(s.type,r.nodes.map(C=>C.id)),type:s.type,from:f.from,to:f.to,on:f.on})}})),B&&!E&&e.createElement(kt,{flow:r.flow||{},changes:r.changes||[],problems:r.violations,refusal:a,notice:l,onClose:()=>S(!1),onCreate:()=>i("/versions","POST"),onPublish:()=>i("/publish","POST"),onSaveDetails:s=>i("/details","PATCH",{flow:s})}),E&&e.createElement(ut,{node:E,fields:P?.fields||{},holds:P?.records||{},labels:P?.labels||{},recordLabels:P?.record_labels||{},recordChoices:P?.record_choices||{},recordOutputsOf:P?.record_outputs_of||{},choices:it(E,P),onClose:()=>c(null),onSave:s=>i(`/steps/${E.id}`,"PATCH",{config:s}),onPickPicture:d,refusal:a,onDelete:()=>{c(null),i(`/steps/${E.id}`,"DELETE")}}))},Dt=ze;ot("easy_flow/flow-editor",Dt);document.addEventListener("easy_flow:flow-named",t=>{let o=document.querySelector("[data-flow-heading]");o&&(o.textContent=t.detail)});st(document,Q);})();
@@ -55,6 +55,8 @@ module EasyFlow
55
55
  render json: { reference: reference, url: EasyFlow.picture_url(reference) }
56
56
  rescue NoPictureStore
57
57
  render json: { error: "Pictures cannot be added yet. Ask the app's developer to set up a picture store." }, status: :unprocessable_entity
58
+ rescue PictureRefused => refusal
59
+ render json: { error: refusal.message }, status: :unprocessable_entity
58
60
  end
59
61
 
60
62
  def configure_step
@@ -192,6 +192,7 @@ const Canvas = ({ base, token, initial }) => {
192
192
  onClose={() => setSelected(null)}
193
193
  onSave={(config) => send(`/steps/${selectedNode.id}`, "PATCH", { config })}
194
194
  onPickPicture={pickPicture}
195
+ refusal={error}
195
196
  onDelete={() => { setSelected(null); send(`/steps/${selectedNode.id}`, "DELETE") }} />
196
197
  )}
197
198
  </div>
@@ -7,7 +7,7 @@ import { Label } from "keystone_ui-react/src/FieldText.jsx"
7
7
 
8
8
  const panel = { width: 280, padding: 20, overflowY: "auto" }
9
9
 
10
- const Inspector = ({ node, fields, holds, labels, recordLabels, recordChoices, recordOutputsOf, choices, onSave, onDelete, onClose, onPickPicture }) => {
10
+ const Inspector = ({ node, fields, holds, labels, recordLabels, recordChoices, recordOutputsOf, choices, onSave, onDelete, onClose, onPickPicture, refusal }) => {
11
11
  const [ draft, setDraft ] = useState(node.config)
12
12
  const [ pictureUrl, setPictureUrl ] = useState(node.picture_url)
13
13
  useEffect(() => setPictureUrl(node.picture_url), [ node.id, node.picture_url ])
@@ -26,6 +26,7 @@ const Inspector = ({ node, fields, holds, labels, recordLabels, recordChoices, r
26
26
  style={{ border: "none", background: "none", cursor: "pointer", fontSize: 18, lineHeight: 1 }}>×</button>
27
27
  </div>
28
28
  <p className="text-gray-500 dark:text-gray-400" style={{ fontSize: 11, marginBottom: 16 }}>{node.id} · {node.type}</p>
29
+ {refusal && <p className="text-red-800 dark:text-red-400" style={{ fontWeight: 600, marginBottom: 12 }} data-refusal>{refusal}</p>}
29
30
  {Object.entries(fields).map(([ name, type ]) => (
30
31
  <Label key={name}>
31
32
  <span style={{ display: "block", marginBottom: 3 }}>{labels[name] || name}</span>
@@ -1,3 +1,3 @@
1
1
  module EasyFlow
2
- VERSION = "0.30.0"
2
+ VERSION = "0.31.0"
3
3
  end
data/lib/easy_flow.rb CHANGED
@@ -24,6 +24,7 @@ module EasyFlow
24
24
  class Withdrawn < StandardError; end
25
25
  class NoFileStore < StandardError; end
26
26
  class NoPictureStore < StandardError; end
27
+ class PictureRefused < StandardError; end
27
28
 
28
29
  DRAWING = "easy_flow/steps/choosing".freeze
29
30
 
@@ -98,6 +98,7 @@ A Rails engine for flows an admin draws on a canvas and a visitor runs one step
98
98
 
99
99
  - The store answers `keep(file, flow:)`, called with the chosen picture and the flow whose step it is added to. It keeps the picture and returns a string reference to it, and the step keeps that reference as its `picture` setting.
100
100
  - The store answers `url_of(reference)`, called with a reference `keep` returned. It returns the address a page loads the picture from.
101
+ - The store refuses a file it will not keep, such as one that is not an image or is too large, by raising `EasyFlow::PictureRefused` with the message the admin should see. The canvas shows that message and leaves the step's picture as it was.
101
102
  - With no store set, an admin who chooses a picture on the canvas is told "Pictures cannot be added yet. Ask the app's developer to set up a picture store." and the step is left unchanged.
102
103
  11. Leave `EasyFlow.check` out unless the developer asks for it. The engine already turns on `:unrouted_value`, `:unfollowed_path` and `:dead_end` at boot. Any other name raises `EasyFlow::UnknownCheck` when the app boots.
103
104
  12. Check that the app loads Active Job (`require "rails/all"` or `require "active_job/railtie"` in `config/application.rb`) and has a queue adapter that runs jobs from the `default` queue. When a run started by a Flow step, or by a step type of the app's own that starts another flow, ends, the engine records its output in the run it was started from and queues a job on `default` that moves that run on. If no adapter runs that queue, the run that holds the step stays at it until its visitor next loads its page. If `config.active_job.queue_adapter` is not set for an environment, ask the developer which adapter to use there.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy_flow
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.30.0
4
+ version: 0.31.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - tylercschneider