@mxpicture/print-backlog 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/public/assets/index-C4BbRvDB.js +1 -0
- package/dist/public/assets/{index-BnhoKdrs.css → index-D7yzmKDn.css} +1 -1
- package/dist/public/index.html +2 -2
- package/dist/server/api/events.d.ts +21 -0
- package/dist/server/api/events.d.ts.map +1 -0
- package/dist/server/api/events.js +201 -0
- package/dist/server/api/events.js.map +1 -0
- package/dist/server/api/items.d.ts +14 -1
- package/dist/server/api/items.d.ts.map +1 -1
- package/dist/server/api/items.js +49 -1
- package/dist/server/api/items.js.map +1 -1
- package/dist/server/app.d.ts +7 -1
- package/dist/server/app.d.ts.map +1 -1
- package/dist/server/app.js +8 -4
- package/dist/server/app.js.map +1 -1
- package/dist/server/bambuddy.d.ts +23 -6
- package/dist/server/bambuddy.d.ts.map +1 -1
- package/dist/server/bambuddy.js +95 -23
- package/dist/server/bambuddy.js.map +1 -1
- package/dist/server/cli.js +8 -1
- package/dist/server/cli.js.map +1 -1
- package/dist/server/matching.d.ts +22 -0
- package/dist/server/matching.d.ts.map +1 -0
- package/dist/server/matching.js +72 -0
- package/dist/server/matching.js.map +1 -0
- package/dist/shared/types.d.ts +42 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/public/assets/index-j0LpYaft.js +0 -1
- package/dist/server/api/hooks.d.ts +0 -9
- package/dist/server/api/hooks.d.ts.map +0 -1
- package/dist/server/api/hooks.js +0 -29
- package/dist/server/api/hooks.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var e,t,n,r,i,a,o,s,c,l,u,d,f,p,m={},h=[],g=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,_=Array.isArray;function v(e,t){for(var n in t)e[n]=t[n];return e}function y(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function b(t,n,r){var i,a,o,s={};for(o in n)o==`key`?i=n[o]:o==`ref`?a=n[o]:s[o]=n[o];if(arguments.length>2&&(s.children=arguments.length>3?e.call(arguments,2):r),typeof t==`function`&&t.defaultProps!=null)for(o in t.defaultProps)s[o]===void 0&&(s[o]=t.defaultProps[o]);return x(t,s,i,a,null)}function x(e,r,i,a,o){var s={type:e,props:r,key:i,ref:a,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:o??++n,__i:-1,__u:0};return o==null&&t.vnode!=null&&t.vnode(s),s}function S(e){return e.children}function C(e,t){this.props=e,this.context=t}function w(e,t){if(t==null)return e.__?w(e.__,e.__i+1):null;for(var n;t<e.__k.length;t++)if((n=e.__k[t])!=null&&n.__e!=null)return n.__e;return typeof e.type==`function`?w(e):null}function T(e){if(e.__P&&e.__d){var n=e.__v,r=n.__e,i=[],a=[],o=v({},n);o.__v=n.__v+1,t.vnode&&t.vnode(o),oe(e.__P,o,n,e.__n,e.__P.namespaceURI,32&n.__u?[r]:null,i,r??w(n),!!(32&n.__u),a),o.__v=n.__v,o.__.__k[o.__i]=o,ce(i,o,a),n.__e=n.__=null,o.__e!=r&&E(o)}}function E(e){if((e=e.__)!=null&&e.__c!=null)return e.__e=e.__c.base=null,e.__k.some(function(t){if(t!=null&&t.__e!=null)return e.__e=e.__c.base=t.__e}),E(e)}function D(e){(!e.__d&&(e.__d=!0)&&r.push(e)&&!O.__r++||i!=t.debounceRendering)&&((i=t.debounceRendering)||a)(O)}function O(){try{for(var e,t=1;r.length;)r.length>t&&r.sort(o),e=r.shift(),t=r.length,T(e)}finally{r.length=O.__r=0}}function ee(e,t,n,r,i,a,o,s,c,l,u){var d,f,p,g,_,v,y=r&&r.__k||h,b=t.length;for(c=k(n,t,y,c,b),d=0;d<b;d++)(p=n.__k[d])!=null&&(f=p.__i!=-1&&y[p.__i]||m,p.__i=d,v=oe(e,p,f,i,a,o,s,c,l,u),g=p.__e,p.ref&&f.ref!=p.ref&&(f.ref&&de(f.ref,null,p),u.push(p.ref,p.__c||g,p)),_==null&&g!=null&&(_=g),4&p.__u?(c=te(p,c,e),f.__e&&(f.__e=null)):typeof p.type==`function`&&v!==void 0?c=v:g&&(c=g.nextSibling),p.__u&=-7);return n.__e=_,c}function k(e,t,n,r,i){var a,o,s,c,l,u=n.length,d=u,f=0;for(e.__k=Array(i),a=0;a<i;a++)(o=t[a])!=null&&typeof o!=`boolean`&&typeof o!=`function`?(typeof o==`string`||typeof o==`number`||typeof o==`bigint`||o.constructor==String?o=e.__k[a]=x(null,o,null,null,null):_(o)?o=e.__k[a]=x(S,{children:o},null,null,null):o.constructor===void 0&&o.__b>0?o=e.__k[a]=x(o.type,o.props,o.key,o.ref?o.ref:null,o.__v):e.__k[a]=o,c=a+f,o.__=e,o.__b=e.__b+1,s=null,(l=o.__i=ne(o,n,c,d))!=-1&&(d--,(s=n[l])&&(s.__u|=2)),s==null||s.__v==null?(l==-1&&(i>u?f--:i<u&&f++),typeof o.type!=`function`&&(o.__u|=4)):l!=c&&(l==c-1?f--:l==c+1?f++:(l>c?f--:f++,o.__u|=4))):e.__k[a]=null;if(d)for(a=0;a<u;a++)(s=n[a])!=null&&!(2&s.__u)&&(s.__e==r&&(r=w(s)),fe(s,s));return r}function te(e,t,n){var r,i;if(typeof e.type==`function`){for(r=e.__k,i=0;r&&i<r.length;i++)r[i]&&(r[i].__=e,t=te(r[i],t,n));return t}e.__e!=t&&(t&&e.type&&!t.parentNode&&(t=w(e)),t=n.insertBefore(e.__e,t||null));do t&&=t.nextSibling;while(t!=null&&t.nodeType==8);return t}function ne(e,t,n,r){var i,a,o,s=e.key,c=e.type,l=t[n],u=l!=null&&!(2&l.__u);if(l===null&&s==null||u&&s==l.key&&c==l.type)return n;if(r>+!!u){for(i=n-1,a=n+1;i>=0||a<t.length;)if((l=t[o=i>=0?i--:a++])!=null&&!(2&l.__u)&&s==l.key&&c==l.type)return o}return-1}function re(e,t,n){t[0]==`-`?e.setProperty(t,n??``):e[t]=n==null?``:typeof n!=`number`||g.test(t)?n:n+`px`}function ie(e,t,n,r,i){var a,o;n:if(t==`style`){if(typeof n==`string`)e.style.cssText=n;else{if(typeof r==`string`&&(e.style.cssText=r=``),r)for(t in r)n&&t in n||re(e.style,t,``);if(n)for(t in n)r&&n[t]==r[t]||re(e.style,t,n[t])}}else if(t[0]==`o`&&t[1]==`n`)a=t!=(t=t.replace(u,`$1`)),o=t.toLowerCase(),t=o in e||t==`onFocusOut`||t==`onFocusIn`?o.slice(2):t.slice(2),e.l||={},e.l[t+a]=n,n?r?n[l]=r[l]:(n[l]=d,e.addEventListener(t,a?p:f,a)):e.removeEventListener(t,a?p:f,a);else{if(i==`http://www.w3.org/2000/svg`)t=t.replace(/xlink(H|:h)/,`h`).replace(/sName$/,`s`);else if(t!=`width`&&t!=`height`&&t!=`href`&&t!=`list`&&t!=`form`&&t!=`tabIndex`&&t!=`download`&&t!=`rowSpan`&&t!=`colSpan`&&t!=`role`&&t!=`popover`&&t in e)try{e[t]=n??``;break n}catch{}typeof n==`function`||(n==null||!1===n&&t[4]!=`-`?e.removeAttribute(t):e.setAttribute(t,t==`popover`&&n==1?``:n))}}function ae(e){return function(n){if(this.l){var r=this.l[n.type+e];if(n[c]==null)n[c]=d++;else if(n[c]<r[l])return;return r(t.event?t.event(n):n)}}}function oe(e,n,r,i,a,o,s,c,l,u){var d,f,p,m,g,b,x,T,E,D,O,k,te,ne,re,ie,ae=n.type;if(n.constructor!==void 0)return null;128&r.__u&&(l=!!(32&r.__u),o=[c=n.__e=r.__e]),(d=t.__b)&&d(n);n:if(typeof ae==`function`){f=s.length;try{if(E=n.props,D=ae.prototype&&ae.prototype.render,O=(d=ae.contextType)&&i[d.__c],k=d?O?O.props.value:d.__:i,r.__c?T=(p=n.__c=r.__c).__=p.__E:(D?n.__c=p=new ae(E,k):(n.__c=p=new C(E,k),p.constructor=ae,p.render=pe),O&&O.sub(p),p.state||(p.state={}),p.__n=i,m=p.__d=!0,p.__h=[],p._sb=[]),D&&p.__s==null&&(p.__s=p.state),D&&ae.getDerivedStateFromProps!=null&&(p.__s==p.state&&(p.__s=v({},p.__s)),v(p.__s,ae.getDerivedStateFromProps(E,p.__s))),g=p.props,b=p.state,p.__v=n,m)D&&ae.getDerivedStateFromProps==null&&p.componentWillMount!=null&&p.componentWillMount(),D&&p.componentDidMount!=null&&p.__h.push(p.componentDidMount);else{if(D&&ae.getDerivedStateFromProps==null&&E!==g&&p.componentWillReceiveProps!=null&&p.componentWillReceiveProps(E,k),n.__v==r.__v||!p.__e&&p.shouldComponentUpdate!=null&&!1===p.shouldComponentUpdate(E,p.__s,k)){n.__v!=r.__v&&(p.props=E,p.state=p.__s,p.__d=!1),n.__e=r.__e,n.__k=r.__k,n.__k.some(function(e){e&&(e.__=n)}),h.push.apply(p.__h,p._sb),p._sb=[],p.__h.length&&s.push(p),c=w(r);break n}p.componentWillUpdate!=null&&p.componentWillUpdate(E,p.__s,k),D&&p.componentDidUpdate!=null&&p.__h.push(function(){p.componentDidUpdate(g,b,x)})}if(p.context=k,p.props=E,p.__P=e,p.__e=!1,te=t.__r,ne=0,D)p.state=p.__s,p.__d=!1,te&&te(n),d=p.render(p.props,p.state,p.context),h.push.apply(p.__h,p._sb),p._sb=[];else do p.__d=!1,te&&te(n),d=p.render(p.props,p.state,p.context),p.state=p.__s;while(p.__d&&++ne<25);p.state=p.__s,p.getChildContext!=null&&(i=v(v({},i),p.getChildContext())),D&&!m&&p.getSnapshotBeforeUpdate!=null&&(x=p.getSnapshotBeforeUpdate(g,b)),re=d!=null&&d.type===S&&d.key==null?le(d.props.children):d,c=ee(e,_(re)?re:[re],n,r,i,a,o,s,c,l,u),p.base=n.__e,n.__u&=-161,p.__h.length&&s.push(p),T&&(p.__E=p.__=null)}catch(e){if(s.length=f,n.__v=null,l||o!=null){if(e.then){for(n.__u|=l?160:128;c&&c.nodeType==8&&c.nextSibling;)c=c.nextSibling;o!=null&&(o[o.indexOf(c)]=null),n.__e=c}else if(o!=null)for(ie=o.length;ie--;)y(o[ie])}else n.__e=r.__e;n.__k??=r.__k||[],e.then||se(n),t.__e(e,n,r)}}else o==null&&n.__v==r.__v?(n.__k=r.__k,n.__e=r.__e):c=n.__e=ue(r.__e,n,r,i,a,o,s,l,u);return(d=t.diffed)&&d(n),128&n.__u?void 0:c}function se(e){e&&(e.__c&&(e.__c.__e=!0),e.__k&&e.__k.some(se))}function ce(e,n,r){for(var i=0;i<r.length;i++)de(r[i],r[++i],r[++i]);t.__c&&t.__c(n,e),e.some(function(n){try{e=n.__h,n.__h=[],e.some(function(e){e.call(n)})}catch(e){t.__e(e,n.__v)}})}function le(e){return typeof e!=`object`||!e||e.__b>0?e:_(e)?e.map(le):e.constructor===void 0?v({},e):null}function ue(n,r,i,a,o,s,c,l,u){var d,f,p,h,g,v,b,x=i.props||m,S=r.props,C=r.type;if(C==`svg`?o=`http://www.w3.org/2000/svg`:C==`math`?o=`http://www.w3.org/1998/Math/MathML`:o||=`http://www.w3.org/1999/xhtml`,s!=null){for(d=0;d<s.length;d++)if((g=s[d])&&`setAttribute`in g==!!C&&(C?g.localName==C:g.nodeType==3)){n=g,s[d]=null;break}}if(n==null){if(C==null)return document.createTextNode(S);n=document.createElementNS(o,C,S.is&&S),l&&=(t.__m&&t.__m(r,s),!1),s=null}if(C==null)x===S||l&&n.data==S||(n.data=S);else{if(s=C==`textarea`&&S.defaultValue!=null?null:s&&e.call(n.childNodes),!l&&s!=null)for(x={},d=0;d<n.attributes.length;d++)x[(g=n.attributes[d]).name]=g.value;for(d in x)g=x[d],d==`dangerouslySetInnerHTML`?p=g:d==`children`||d in S||d==`value`&&`defaultValue`in S||d==`checked`&&`defaultChecked`in S||ie(n,d,null,g,o);for(d in S)g=S[d],d==`children`?h=g:d==`dangerouslySetInnerHTML`?f=g:d==`value`?v=g:d==`checked`?b=g:l&&typeof g!=`function`||x[d]===g||ie(n,d,g,x[d],o);if(f)l||p&&(f.__html==p.__html||f.__html==n.innerHTML)||(n.innerHTML=f.__html),r.__k=[];else if(p&&(n.innerHTML=``),ee(r.type==`template`?n.content:n,_(h)?h:[h],r,i,a,C==`foreignObject`?`http://www.w3.org/1999/xhtml`:o,s,c,s?s[0]:i.__k&&w(i,0),l,u),s!=null)for(d=s.length;d--;)y(s[d]);l&&C!=`textarea`||(d=`value`,C==`progress`&&v==null?n.removeAttribute(`value`):v!=null&&(v!==n[d]||C==`progress`&&!v||C==`option`&&v!=x[d])&&ie(n,d,v,x[d],o),d=`checked`,b!=null&&b!=n[d]&&ie(n,d,b,x[d],o))}return n}function de(e,n,r){try{if(typeof e==`function`){var i=typeof e.__u==`function`;i&&e.__u(),i&&n==null||(e.__u=e(n))}else e.current=n}catch(e){t.__e(e,r)}}function fe(e,n,r){var i,a;if(t.unmount&&t.unmount(e),(i=e.ref)&&(i.current&&i.current!=e.__e||de(i,null,n)),(i=e.__c)!=null){if(i.componentWillUnmount)try{i.componentWillUnmount()}catch(e){t.__e(e,n)}i.base=i.__P=i.__n=null}if(i=e.__k)for(a=0;a<i.length;a++)i[a]&&fe(i[a],n,r||typeof e.type!=`function`);r||y(e.__e),e.__c=e.__=e.__e=void 0}function pe(e,t,n){return this.constructor(e,n)}function me(n,r,i){var a,o,s,c;r==document&&(r=document.documentElement),t.__&&t.__(n,r),o=(a=typeof i==`function`)?null:i&&i.__k||r.__k,s=[],c=[],oe(r,n=(!a&&i||r).__k=b(S,null,[n]),o||m,m,r.namespaceURI,!a&&i?[i]:o?null:r.firstChild?e.call(r.childNodes):null,s,!a&&i?i:o?o.__e:r.firstChild,a,c),ce(s,n,c),n.props.children=null}e=h.slice,t={__e:function(e,t,n,r){for(var i,a,o;t=t.__;)if((i=t.__c)&&!i.__)try{if((a=i.constructor)&&a.getDerivedStateFromError!=null&&(i.setState(a.getDerivedStateFromError(e)),o=i.__d),i.componentDidCatch!=null&&(i.componentDidCatch(e,r||{}),o=i.__d),o)return i.__E=i}catch(t){e=t}throw e}},n=0,C.prototype.setState=function(e,t){var n=this.__s!=null&&this.__s!=this.state?this.__s:this.__s=v({},this.state);typeof e==`function`&&(e=e(v({},n),this.props)),e&&v(n,e),e!=null&&this.__v&&(t&&this._sb.push(t),D(this))},C.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),D(this))},C.prototype.render=S,r=[],a=typeof Promise==`function`?Promise.prototype.then.bind(Promise.resolve()):setTimeout,o=function(e,t){return e.__v.__b-t.__v.__b},O.__r=0,s=Math.random().toString(8),c=`__d`+s,l=`__a`+s,u=/(PointerCapture)$|Capture$/i,d=0,f=ae(!1),p=ae(!0);var he,A,ge,_e,ve=0,ye=[],j=t,be=j.__b,xe=j.__r,Se=j.diffed,Ce=j.__c,we=j.unmount,Te=j.__;function Ee(e,t){j.__h&&j.__h(A,e,ve||t),ve=0;var n=A.__H||(A.__H={__:[],__h:[]});return e>=n.__.length&&n.__.push({}),n.__[e]}function M(e){return ve=1,De(Re,e)}function De(e,t,n){var r=Ee(he++,2);if(r.t=e,!r.__c&&(r.__=[n?n(t):Re(void 0,t),function(e){var t=r.__N?r.__N[0]:r.__[0],n=r.t(t,e);t!==n&&(r.__N=[n,r.__[1]],r.__c.setState({}))}],r.__c=A,!A.__f)){var i=function(e,t,n){if(!r.__c.__H)return!0;var i=!1,o=r.__c.props!==e;if(r.__c.__H.__.some(function(e){if(e.__N){i=!0;var t=e.__[0];e.__=e.__N,e.__N=void 0,t!==e.__[0]&&(o=!0)}}),a){var s=a.call(this,e,t,n);return i?s||o:s}return!i||o};A.__f=!0;var a=A.shouldComponentUpdate,o=A.componentWillUpdate;A.componentWillUpdate=function(e,t,n){if(this.__e){var r=a;a=void 0,i(e,t,n),a=r}o&&o.call(this,e,t,n)},A.shouldComponentUpdate=i}return r.__N||r.__}function Oe(e,t){var n=Ee(he++,3);!j.__s&&Le(n.__H,t)&&(n.__=e,n.u=t,A.__H.__h.push(n))}function ke(e){return ve=5,Ae(function(){return{current:e}},[])}function Ae(e,t){var n=Ee(he++,7);return Le(n.__H,t)&&(n.__=e(),n.__H=t,n.__h=e),n.__}function je(e,t){return ve=8,Ae(function(){return e},t)}function Me(){for(var e;e=ye.shift();){var t=e.__H;if(e.__P&&t)try{t.__h.some(Fe),t.__h.some(Ie),t.__h=[]}catch(n){t.__h=[],j.__e(n,e.__v)}}}j.__b=function(e){A=null,be&&be(e)},j.__=function(e,t){e&&t.__k&&t.__k.__m&&(e.__m=t.__k.__m),Te&&Te(e,t)},j.__r=function(e){xe&&xe(e),he=0;var t=(A=e.__c).__H;t&&(ge===A?(t.__h=[],A.__h=[],t.__.some(function(e){e.__N&&(e.__=e.__N),e.u=e.__N=void 0})):(t.__h.some(Fe),t.__h.some(Ie),t.__h=[],he=0)),ge=A},j.diffed=function(e){Se&&Se(e);var t=e.__c;t&&t.__H&&(t.__H.__h.length&&(ye.push(t)!==1&&_e===j.requestAnimationFrame||((_e=j.requestAnimationFrame)||Pe)(Me)),t.__H.__.some(function(e){e.u&&=(e.__H=e.u,void 0)})),ge=A=null},j.__c=function(e,t){t.some(function(e){try{e.__h.some(Fe),e.__h=e.__h.filter(function(e){return!e.__||Ie(e)})}catch(n){t.some(function(e){e.__h&&=[]}),t=[],j.__e(n,e.__v)}}),Ce&&Ce(e,t)},j.unmount=function(e){we&&we(e);var t,n=e.__c;n&&n.__H&&(n.__H.__.some(function(e){try{Fe(e)}catch(e){t=e}}),n.__H=void 0,t&&j.__e(t,n.__v))};var Ne=typeof requestAnimationFrame==`function`;function Pe(e){var t,n=function(){clearTimeout(r),Ne&&cancelAnimationFrame(t),setTimeout(e)},r=setTimeout(n,35);Ne&&(t=requestAnimationFrame(n))}function Fe(e){var t=A,n=e.__c;typeof n==`function`&&(e.__c=void 0,n()),A=t}function Ie(e){var t=A;e.__c=e.__(),A=t}function Le(e,t){return!e||e.length!==t.length||t.some(function(t,n){return t!==e[n]})}function Re(e,t){return typeof t==`function`?t(e):t}var ze=[`queued`,`skipped`,`done`,`error`],Be=class extends Error{status;constructor(e,t){super(t),this.status=e}},Ve=()=>{throw location.reload(),new Be(401,`session expired, reloading`)},He=async(e,t={})=>{let n=await fetch(e,{...t,redirect:`manual`,headers:{Accept:`application/json`,...t.headers}});n.type===`opaqueredirect`&&Ve();let r=await n.json().catch(()=>null);if(!n.ok)throw new Be(n.status,r?.error??`HTTP ${n.status}`);return r},Ue=(e,t,n)=>He(t,{method:e,headers:{"Content-Type":`application/json`},body:JSON.stringify(n)}),We=(e,t,n)=>new Promise((r,i)=>{let a=new XMLHttpRequest;a.open(`POST`,e),a.setRequestHeader(`Accept`,`application/json`),a.responseType=`text`,a.upload.onprogress=e=>{e.lengthComputable&&n?.(e.loaded/e.total)},a.onerror=()=>i(new Be(0,`network error during upload`)),a.onload=()=>{if(!(a.getResponseHeader(`Content-Type`)??``).includes(`application/json`)){try{Ve()}catch(e){i(e)}return}let e=null;try{e=JSON.parse(a.responseText)}catch{}a.status>=200&&a.status<300?r(e):i(new Be(a.status,e?.error??`HTTP ${a.status}`))},a.send(t)}),Ge=e=>{let t=new URLSearchParams;return e.queue&&t.set(`queue`,String(e.queue)),e.status&&t.set(`status`,e.status),e.q&&t.set(`q`,e.q),e.trash&&t.set(`trash`,`1`),t.toString()},N={me:()=>He(`/api/v1/me`),queues:()=>He(`/api/v1/queues`),createQueue:e=>Ue(`POST`,`/api/v1/queues`,e),patchQueue:(e,t)=>Ue(`PATCH`,`/api/v1/queues/${e}`,t),deleteQueue:e=>Ue(`DELETE`,`/api/v1/queues/${e}`,{}),exportUrl:(e,t)=>`/api/v1/queues/${e}/export.zip${t?`?status=${t}`:``}`,items:e=>He(`/api/v1/items?${Ge(e)}`),item:e=>He(`/api/v1/items/${e}`),history:e=>He(`/api/v1/items/${e}/history`),patchItem:(e,t)=>Ue(`PATCH`,`/api/v1/items/${e}`,t),deleteItem:e=>Ue(`DELETE`,`/api/v1/items/${e}`,{}),restoreItem:e=>Ue(`POST`,`/api/v1/items/${e}/restore`,{}),uploadItems:async(e,t,n)=>{let r=t.reduce((e,t)=>e+t.size,0)||1,i=0,a={items:[],skipped:[]};for(let o=0;o<t.length;o+=50){let s=t.slice(o,o+50),c=s.reduce((e,t)=>e+t.size,0),l=new FormData;for(let e of s)l.append(`file`,e,e.name);let u=await We(`/api/v1/queues/${e}/items`,l,e=>n?.((i+e*c)/r));i+=c,a.items.push(...u.items),a.skipped.push(...u.skipped)}return a},uploadVersion:(e,t,n,r)=>{let i=new FormData;return i.append(`file`,t,t.name),n&&i.append(`comment`,n),We(`/api/v1/items/${e}/versions`,i,r)},patchVersion:(e,t,n)=>Ue(`PATCH`,`/api/v1/items/${e}/versions/${t}`,n),downloadUrl:(e,t)=>`/api/v1/items/${e}/versions/${t}/download`,sendToBambuddy:e=>Ue(`POST`,`/api/v1/items/${e}/send-to-bambuddy`,{}),openEvents:()=>He(`/api/v1/print-events?open=1`),assignEvent:(e,t)=>Ue(`POST`,`/api/v1/print-events/${e}/assign`,t),thumbnailUrl:(e,t)=>`/api/v1/items/${e}/versions/${t}/thumbnail`},P=e=>e instanceof Error?e.message:String(e),Ke=[`B`,`KB`,`MB`,`GB`],qe=e=>{let t=e,n=0;for(;t>=1024&&n<Ke.length-1;)t/=1024,n++;return`${n===0?t:t.toFixed(+(t<10))} ${Ke[n]}`},Je=new Intl.RelativeTimeFormat(void 0,{numeric:`auto`}),Ye=e=>{let t=new Date(e),n=(t.getTime()-Date.now())/1e3,r=Math.abs(n);return r<60?Je.format(Math.round(n),`second`):r<3600?Je.format(Math.round(n/60),`minute`):r<86400?Je.format(Math.round(n/3600),`hour`):r<2592e3?Je.format(Math.round(n/86400),`day`):t.toLocaleDateString()},Xe=e=>new Date(e).toLocaleString(),Ze=0;Array.isArray;function F(e,n,r,i,a,o){n||={};var s,c,l=n;if(`ref`in l)for(c in l={},n)c==`ref`?s=n[c]:l[c]=n[c];var u={type:e,props:l,key:r,ref:s,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:--Ze,__i:-1,__u:0,__source:a,__self:o};if(typeof e==`function`&&(s=e.defaultProps))for(c in s)l[c]===void 0&&(l[c]=s[c]);return t.vnode&&t.vnode(u),u}var Qe=1,$e=[],et=new Set,tt=()=>et.forEach(e=>e($e)),I=(e,t=`info`)=>{let n={id:Qe++,kind:t,text:e};$e=[...$e,n].slice(-4),tt(),setTimeout(()=>{$e=$e.filter(e=>e.id!==n.id),tt()},t===`error`?8e3:3500)},nt=()=>{let[e,t]=M($e);return Oe(()=>(et.add(t),()=>void et.delete(t)),[]),F(`div`,{class:`toasts`,role:`status`,"aria-live":`polite`,children:e.map(e=>F(`div`,{class:`toast toast-${e.kind}`,children:e.text},e.id))})},rt=e=>{switch(e.kind){case`status`:{let t=e.detail??{},n=typeof t.reason==`string`?` (${t.reason})`:``;if(e.from===null)return`created as ${e.to}`;if(e.source===`webhook`){let r=typeof t.printer==`string`?` on ${t.printer}`:``,i=typeof t.duration==`string`?`, ${t.duration}`:``,a=t.assigned?`assigned print`:`print`;return`${e.from} → ${e.to}: ${a}${r}${i}${n}`}return`${e.from} → ${e.to}${n}`}case`version`:return`version ${e.n} uploaded (${e.filename})`;case`print`:return`print event ${e.event}${e.printer?` on ${e.printer}`:``}${e.filename?`: ${e.filename}`:``}`;case`sent`:return`sent to Bambuddy (library file ${e.fileId})`}},it=e=>{let[t,n]=M(e.value);Oe(()=>n(e.value),[e.value]);let r={value:t,placeholder:e.placeholder,onInput:e=>n(e.currentTarget.value),onBlur:()=>{t.trim()!==e.value.trim()&&e.onSave(t).catch(t=>{I(P(t),`error`),n(e.value)})}};return F(`label`,{class:`field`,children:[F(`span`,{children:e.label}),e.multiline?F(`textarea`,{rows:4,...r}):F(`input`,{type:e.type??`text`,...r,onKeyDown:e=>e.key===`Enter`&&e.currentTarget.blur()})]})},at=({itemId:e,queues:t,revision:n,onClose:r,onChanged:i,onUploadVersion:a,bambuddy:o})=>{let[s,c]=M(null),[l,u]=M([]),[d,f]=M(``),[p,m]=M(!1),h=ke(null),g=()=>Promise.all([N.item(e),N.history(e)]).then(([e,t])=>{c(e),u(t)}).catch(e=>I(P(e),`error`));if(Oe(()=>{c(null),g()},[e,n]),!s)return F(`aside`,{class:`panel`,children:`Loading…`});let _=s.deletedAt!==null,v=async e=>{c(await N.patchItem(s.id,e)),u(await N.history(s.id)),i()},y=e=>v({status:e,...d.trim()?{reason:d.trim()}:{}}).then(()=>f(``)).catch(e=>I(P(e),`error`));return F(`aside`,{class:`panel`,"aria-label":`Item details`,children:[F(`header`,{class:`panel-head`,children:[F(`h2`,{children:s.title}),F(`button`,{class:`icon`,onClick:r,"aria-label":`Close`,children:`✕`})]}),s.current?.hasThumbnail&&F(`img`,{class:`preview`,src:N.thumbnailUrl(s.id,s.current.n),alt:`Preview of ${s.title}`}),_?F(`p`,{class:`muted`,children:[`In the trash since `,Xe(s.deletedAt),`.`]}):F(S,{children:[F(it,{label:`Title`,value:s.title,onSave:e=>v({title:e})}),F(`div`,{class:`field`,children:[F(`span`,{children:`Status`}),F(`div`,{class:`status-row`,children:ze.map(e=>F(`button`,{class:`chip status-${e}${s.status===e?` active`:``}`,"aria-pressed":s.status===e,onClick:()=>s.status!==e&&void y(e),children:e},e))}),F(`input`,{class:`reason`,placeholder:`Reason for the next change (optional)`,value:d,onInput:e=>f(e.currentTarget.value)})]}),F(it,{label:`Source URL`,type:`url`,placeholder:`https://www.printables.com/model/…`,value:s.sourceUrl??``,onSave:e=>v({sourceUrl:e.trim()||null})}),s.sourceUrl&&F(`a`,{class:`source`,href:s.sourceUrl,target:`_blank`,rel:`noopener noreferrer`,children:`Open source ↗`}),F(it,{label:`Notes`,multiline:!0,value:s.notes??``,onSave:e=>v({notes:e||null})}),F(`label`,{class:`field`,children:[F(`span`,{children:`Queue`}),F(`select`,{value:s.queueId,onChange:e=>{let n=Number(e.currentTarget.value);N.items({queue:n}).then(e=>v({move:{queueId:n,afterId:e.at(-1)?.id??null}})).then(()=>I(`Moved to ${t.find(e=>e.id===n)?.name??`queue`}`,`ok`)).catch(e=>I(P(e),`error`))},children:t.map(e=>F(`option`,{value:e.id,children:e.name},e.id))})]})]}),o&&!_&&s.current&&F(`section`,{class:`send`,children:[F(`button`,{disabled:!s.sendable||p,title:s.sendable?`Upload the current version into Bambuddy's library`:`Bambuddy cannot slice STEP files`,onClick:()=>{m(!0),N.sendToBambuddy(s.id).then(e=>(c(e.item),I(e.duplicate?`Bambuddy already had this file (library file ${e.item.bambuddyFileId})`:`Sent v${e.item.current?.n} to Bambuddy`,`ok`),N.history(s.id).then(u))).catch(e=>I(P(e),`error`)).finally(()=>m(!1))},children:p?`Sending…`:`➜ Send to Bambuddy`}),s.bambuddySentAt&&F(`span`,{class:`muted`,children:[`sent`,` `,F(`time`,{title:Xe(s.bambuddySentAt),children:Ye(s.bambuddySentAt)})]})]}),F(`section`,{children:[F(`header`,{class:`section-head`,children:[F(`h3`,{children:`Versions`}),!_&&F(S,{children:[F(`button`,{class:`small`,onClick:()=>h.current?.click(),children:`Upload new version`}),F(`input`,{ref:h,type:`file`,hidden:!0,accept:`.stl,.3mf,.step,.stp,.obj`,onChange:e=>{let t=e.currentTarget.files?.[0];t&&a(s,t),e.currentTarget.value=``}})]})]}),s.alsoIn.length>0&&F(`p`,{class:`muted`,children:[`Same file also in: `,s.alsoIn.map(e=>e.title).join(`, `)]}),F(`ul`,{class:`versions`,children:s.versions.map(e=>F(`li`,{class:e.current?`current`:``,children:[F(`div`,{class:`version-head`,children:[F(`b`,{children:[`v`,e.n]}),` `,e.filename,e.current&&F(`span`,{class:`badge`,children:`current`})]}),F(`div`,{class:`muted`,children:[qe(e.size),` · `,e.uploadedBy,` ·`,` `,F(`time`,{title:Xe(e.uploadedAt),children:Ye(e.uploadedAt)})]}),!_&&F(it,{label:`Comment`,value:e.comment??``,onSave:async t=>{c(await N.patchVersion(s.id,e.n,{comment:t.trim()||null}))}}),F(`div`,{class:`row-actions`,children:[F(`a`,{href:N.downloadUrl(s.id,e.n),children:`Download`}),!e.current&&!_&&F(`button`,{class:`small`,onClick:()=>N.patchVersion(s.id,e.n,{current:!0}).then(e=>{c(e),i()}).catch(e=>I(P(e),`error`)),children:`Make current`})]})]},e.n))})]}),F(`section`,{children:[F(`h3`,{children:`History`}),F(`ol`,{class:`history`,children:[...l].reverse().map((e,t)=>F(`li`,{children:[F(`time`,{title:Xe(e.at),children:Ye(e.at)}),` `,rt(e),`by`in e&&F(`span`,{class:`muted`,children:[` · `,e.by]})]},t))})]}),F(`footer`,{class:`panel-foot`,children:_?F(`button`,{onClick:()=>N.restoreItem(s.id).then(()=>{I(`Restored`,`ok`),i(),g()}).catch(e=>I(P(e),`error`)),children:`Restore`}):F(`button`,{class:`danger`,onClick:()=>N.deleteItem(s.id).then(()=>{I(`"${s.title}" moved to the trash`,`ok`),i(),r()}).catch(e=>I(P(e),`error`)),children:`Move to trash`})})]})};function ot(e,t,n){return(t=pt(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function st(){return st=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)({}).hasOwnProperty.call(n,r)&&(e[r]=n[r])}return e},st.apply(null,arguments)}function ct(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,r)}return n}function lt(e){for(var t=1;t<arguments.length;t++){var n=arguments[t]==null?{}:arguments[t];t%2?ct(Object(n),!0).forEach(function(t){ot(e,t,n[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):ct(Object(n)).forEach(function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))})}return e}function ut(e,t){if(e==null)return{};var n,r,i=dt(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r<a.length;r++)n=a[r],t.indexOf(n)===-1&&{}.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function dt(e,t){if(e==null)return{};var n={};for(var r in e)if({}.hasOwnProperty.call(e,r)){if(t.indexOf(r)!==-1)continue;n[r]=e[r]}return n}function ft(e,t){if(typeof e!=`object`||!e)return e;var n=e[Symbol.toPrimitive];if(n!==void 0){var r=n.call(e,t||`default`);if(typeof r!=`object`)return r;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(t===`string`?String:Number)(e)}function pt(e){var t=ft(e,`string`);return typeof t==`symbol`?t:t+``}function mt(e){"@babel/helpers - typeof";return mt=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},mt(e)}var ht=`1.15.7`;function gt(e){if(typeof window<`u`&&window.navigator)return!!navigator.userAgent.match(e)}var _t=gt(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i),vt=gt(/Edge/i),yt=gt(/firefox/i),bt=gt(/safari/i)&&!gt(/chrome/i)&&!gt(/android/i),xt=gt(/iP(ad|od|hone)/i),St=gt(/chrome/i)&>(/android/i),Ct={capture:!1,passive:!1};function L(e,t,n){e.addEventListener(t,n,!_t&&Ct)}function R(e,t,n){e.removeEventListener(t,n,!_t&&Ct)}function wt(e,t){if(t){if(t[0]===`>`&&(t=t.substring(1)),e)try{if(e.matches)return e.matches(t);if(e.msMatchesSelector)return e.msMatchesSelector(t);if(e.webkitMatchesSelector)return e.webkitMatchesSelector(t)}catch{return!1}return!1}}function Tt(e){return e.host&&e!==document&&e.host.nodeType&&e.host!==e?e.host:e.parentNode}function Et(e,t,n,r){if(e){n||=document;do{if(t!=null&&(t[0]===`>`?e.parentNode===n&&wt(e,t):wt(e,t))||r&&e===n)return e;if(e===n)break}while(e=Tt(e))}return null}var Dt=/\s+/g;function z(e,t,n){e&&t&&(e.classList?e.classList[n?`add`:`remove`](t):e.className=((` `+e.className+` `).replace(Dt,` `).replace(` `+t+` `,` `)+(n?` `+t:``)).replace(Dt,` `))}function B(e,t,n){var r=e&&e.style;if(r){if(n===void 0)return document.defaultView&&document.defaultView.getComputedStyle?n=document.defaultView.getComputedStyle(e,``):e.currentStyle&&(n=e.currentStyle),t===void 0?n:n[t];!(t in r)&&t.indexOf(`webkit`)===-1&&(t=`-webkit-`+t),r[t]=n+(typeof n==`string`?``:`px`)}}function Ot(e,t){var n=``;if(typeof e==`string`)n=e;else do{var r=B(e,`transform`);r&&r!==`none`&&(n=r+` `+n)}while(!t&&(e=e.parentNode));var i=window.DOMMatrix||window.WebKitCSSMatrix||window.CSSMatrix||window.MSCSSMatrix;return i&&new i(n)}function kt(e,t,n){if(e){var r=e.getElementsByTagName(t),i=0,a=r.length;if(n)for(;i<a;i++)n(r[i],i);return r}return[]}function At(){return document.scrollingElement||document.documentElement}function V(e,t,n,r,i){if(e.getBoundingClientRect||e===window){var a,o,s,c,l,u,d;if(e!==window&&e.parentNode&&e!==At()?(a=e.getBoundingClientRect(),o=a.top,s=a.left,c=a.bottom,l=a.right,u=a.height,d=a.width):(o=0,s=0,c=window.innerHeight,l=window.innerWidth,u=window.innerHeight,d=window.innerWidth),(t||n)&&e!==window&&(i||=e.parentNode,!_t))do if(i&&i.getBoundingClientRect&&(B(i,`transform`)!==`none`||n&&B(i,`position`)!==`static`)){var f=i.getBoundingClientRect();o-=f.top+parseInt(B(i,`border-top-width`)),s-=f.left+parseInt(B(i,`border-left-width`)),c=o+a.height,l=s+a.width;break}while(i=i.parentNode);if(r&&e!==window){var p=Ot(i||e),m=p&&p.a,h=p&&p.d;p&&(o/=h,s/=m,d/=m,u/=h,c=o+u,l=s+d)}return{top:o,left:s,bottom:c,right:l,width:d,height:u}}}function jt(e,t,n){for(var r=Lt(e,!0),i=V(e)[t];r;){var a=V(r)[n],o=void 0;if(o=n===`top`||n===`left`?i>=a:i<=a,!o)return r;if(r===At())break;r=Lt(r,!1)}return!1}function Mt(e,t,n,r){for(var i=0,a=0,o=e.children;a<o.length;){if(o[a].style.display!==`none`&&o[a]!==Q.ghost&&(r||o[a]!==Q.dragged)&&Et(o[a],n.draggable,e,!1)){if(i===t)return o[a];i++}a++}return null}function Nt(e,t){for(var n=e.lastElementChild;n&&(n===Q.ghost||B(n,`display`)===`none`||t&&!wt(n,t));)n=n.previousElementSibling;return n||null}function Pt(e,t){var n=0;if(!e||!e.parentNode)return-1;for(;e=e.previousElementSibling;)e.nodeName.toUpperCase()!==`TEMPLATE`&&e!==Q.clone&&(!t||wt(e,t))&&n++;return n}function Ft(e){var t=0,n=0,r=At();if(e)do{var i=Ot(e),a=i.a,o=i.d;t+=e.scrollLeft*a,n+=e.scrollTop*o}while(e!==r&&(e=e.parentNode));return[t,n]}function It(e,t){for(var n in e)if(e.hasOwnProperty(n)){for(var r in t)if(t.hasOwnProperty(r)&&t[r]===e[n][r])return Number(n)}return-1}function Lt(e,t){if(!e||!e.getBoundingClientRect)return At();var n=e,r=!1;do if(n.clientWidth<n.scrollWidth||n.clientHeight<n.scrollHeight){var i=B(n);if(n.clientWidth<n.scrollWidth&&(i.overflowX==`auto`||i.overflowX==`scroll`)||n.clientHeight<n.scrollHeight&&(i.overflowY==`auto`||i.overflowY==`scroll`)){if(!n.getBoundingClientRect||n===document.body)return At();if(r||t)return n;r=!0}}while(n=n.parentNode);return At()}function Rt(e,t){if(e&&t)for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n]);return e}function zt(e,t){return Math.round(e.top)===Math.round(t.top)&&Math.round(e.left)===Math.round(t.left)&&Math.round(e.height)===Math.round(t.height)&&Math.round(e.width)===Math.round(t.width)}var Bt;function Vt(e,t){return function(){if(!Bt){var n=arguments,r=this;n.length===1?e.call(r,n[0]):e.apply(r,n),Bt=setTimeout(function(){Bt=void 0},t)}}}function Ht(){clearTimeout(Bt),Bt=void 0}function Ut(e,t,n){e.scrollLeft+=t,e.scrollTop+=n}function Wt(e){var t=window.Polymer,n=window.jQuery||window.Zepto;return t&&t.dom?t.dom(e).cloneNode(!0):n?n(e).clone(!0)[0]:e.cloneNode(!0)}function Gt(e,t,n){var r={};return Array.from(e.children).forEach(function(i){if(Et(i,t.draggable,e,!1)&&!i.animated&&i!==n){var a=V(i);r.left=Math.min(r.left??1/0,a.left),r.top=Math.min(r.top??1/0,a.top),r.right=Math.max(r.right??-1/0,a.right),r.bottom=Math.max(r.bottom??-1/0,a.bottom)}}),r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}var H=`Sortable`+new Date().getTime();function Kt(){var e=[],t;return{captureAnimationState:function(){e=[],this.options.animation&&[].slice.call(this.el.children).forEach(function(t){if(B(t,`display`)!==`none`&&t!==Q.ghost){e.push({target:t,rect:V(t)});var n=lt({},e[e.length-1].rect);if(t.thisAnimationDuration){var r=Ot(t,!0);r&&(n.top-=r.f,n.left-=r.e)}t.fromRect=n}})},addAnimationState:function(t){e.push(t)},removeAnimationState:function(t){e.splice(It(e,{target:t}),1)},animateAll:function(n){var r=this;if(!this.options.animation)clearTimeout(t),typeof n==`function`&&n();else{var i=!1,a=0;e.forEach(function(e){var t=0,n=e.target,o=n.fromRect,s=V(n),c=n.prevFromRect,l=n.prevToRect,u=e.rect,d=Ot(n,!0);d&&(s.top-=d.f,s.left-=d.e),n.toRect=s,n.thisAnimationDuration&&zt(c,s)&&!zt(o,s)&&(u.top-s.top)/(u.left-s.left)===(o.top-s.top)/(o.left-s.left)&&(t=Jt(u,c,l,r.options)),zt(s,o)||(n.prevFromRect=o,n.prevToRect=s,t||=r.options.animation,r.animate(n,u,s,t)),t&&(i=!0,a=Math.max(a,t),clearTimeout(n.animationResetTimer),n.animationResetTimer=setTimeout(function(){n.animationTime=0,n.prevFromRect=null,n.fromRect=null,n.prevToRect=null,n.thisAnimationDuration=null},t),n.thisAnimationDuration=t)}),clearTimeout(t),i?t=setTimeout(function(){typeof n==`function`&&n()},a):typeof n==`function`&&n(),e=[]}},animate:function(e,t,n,r){if(r){B(e,`transition`,``),B(e,`transform`,``);var i=Ot(this.el),a=i&&i.a,o=i&&i.d,s=(t.left-n.left)/(a||1),c=(t.top-n.top)/(o||1);e.animatingX=!!s,e.animatingY=!!c,B(e,`transform`,`translate3d(`+s+`px,`+c+`px,0)`),this.forRepaintDummy=qt(e),B(e,`transition`,`transform `+r+`ms`+(this.options.easing?` `+this.options.easing:``)),B(e,`transform`,`translate3d(0,0,0)`),typeof e.animated==`number`&&clearTimeout(e.animated),e.animated=setTimeout(function(){B(e,`transition`,``),B(e,`transform`,``),e.animated=!1,e.animatingX=!1,e.animatingY=!1},r)}}}}function qt(e){return e.offsetWidth}function Jt(e,t,n,r){return Math.sqrt((t.top-e.top)**2+(t.left-e.left)**2)/Math.sqrt((t.top-n.top)**2+(t.left-n.left)**2)*r.animation}var Yt=[],Xt={initializeByDefault:!0},Zt={mount:function(e){for(var t in Xt)Xt.hasOwnProperty(t)&&!(t in e)&&(e[t]=Xt[t]);Yt.forEach(function(t){if(t.pluginName===e.pluginName)throw`Sortable: Cannot mount plugin ${e.pluginName} more than once`}),Yt.push(e)},pluginEvent:function(e,t,n){var r=this;this.eventCanceled=!1,n.cancel=function(){r.eventCanceled=!0};var i=e+`Global`;Yt.forEach(function(r){t[r.pluginName]&&(t[r.pluginName][i]&&t[r.pluginName][i](lt({sortable:t},n)),t.options[r.pluginName]&&t[r.pluginName][e]&&t[r.pluginName][e](lt({sortable:t},n)))})},initializePlugins:function(e,t,n,r){for(var i in Yt.forEach(function(r){var i=r.pluginName;if(e.options[i]||r.initializeByDefault){var a=new r(e,t,e.options);a.sortable=e,a.options=e.options,e[i]=a,st(n,a.defaults)}}),e.options)if(e.options.hasOwnProperty(i)){var a=this.modifyOption(e,i,e.options[i]);a!==void 0&&(e.options[i]=a)}},getEventProperties:function(e,t){var n={};return Yt.forEach(function(r){typeof r.eventProperties==`function`&&st(n,r.eventProperties.call(t[r.pluginName],e))}),n},modifyOption:function(e,t,n){var r;return Yt.forEach(function(i){e[i.pluginName]&&i.optionListeners&&typeof i.optionListeners[t]==`function`&&(r=i.optionListeners[t].call(e[i.pluginName],n))}),r}};function Qt(e){var t=e.sortable,n=e.rootEl,r=e.name,i=e.targetEl,a=e.cloneEl,o=e.toEl,s=e.fromEl,c=e.oldIndex,l=e.newIndex,u=e.oldDraggableIndex,d=e.newDraggableIndex,f=e.originalEvent,p=e.putSortable,m=e.extraEventProperties;if(t||=n&&n[H],t){var h,g=t.options,_=`on`+r.charAt(0).toUpperCase()+r.substr(1);window.CustomEvent&&!_t&&!vt?h=new CustomEvent(r,{bubbles:!0,cancelable:!0}):(h=document.createEvent(`Event`),h.initEvent(r,!0,!0)),h.to=o||n,h.from=s||n,h.item=i||n,h.clone=a,h.oldIndex=c,h.newIndex=l,h.oldDraggableIndex=u,h.newDraggableIndex=d,h.originalEvent=f,h.pullMode=p?p.lastPutMode:void 0;var v=lt(lt({},m),Zt.getEventProperties(r,t));for(var y in v)h[y]=v[y];n&&n.dispatchEvent(h),g[_]&&g[_].call(t,h)}}var $t=[`evt`],U=function(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},r=n.evt,i=ut(n,$t);Zt.pluginEvent.bind(Q)(e,t,lt({dragEl:G,parentEl:K,ghostEl:q,rootEl:J,nextEl:en,lastDownEl:tn,cloneEl:Y,cloneHidden:nn,dragStarted:vn,putSortable:X,activeSortable:Q.active,originalEvent:r,oldIndex:rn,oldDraggableIndex:on,newIndex:an,newDraggableIndex:sn,hideGhostForTarget:In,unhideGhostForTarget:Ln,cloneNowHidden:function(){nn=!0},cloneNowShown:function(){nn=!1},dispatchSortableEvent:function(e){W({sortable:t,name:e,originalEvent:r})}},i))};function W(e){Qt(lt({putSortable:X,cloneEl:Y,targetEl:G,rootEl:J,oldIndex:rn,oldDraggableIndex:on,newIndex:an,newDraggableIndex:sn},e))}var G,K,q,J,en,tn,Y,nn,rn,an,on,sn,cn,X,ln=!1,un=!1,dn=[],fn,pn,mn,hn,gn,_n,vn,yn,bn,xn=!1,Sn=!1,Cn,Z,wn=[],Tn=!1,En=[],Dn=typeof document<`u`,On=xt,kn=vt||_t?`cssFloat`:`float`,An=Dn&&!St&&!xt&&`draggable`in document.createElement(`div`),jn=function(){if(Dn){if(_t)return!1;var e=document.createElement(`x`);return e.style.cssText=`pointer-events:auto`,e.style.pointerEvents===`auto`}}(),Mn=function(e,t){var n=B(e),r=parseInt(n.width)-parseInt(n.paddingLeft)-parseInt(n.paddingRight)-parseInt(n.borderLeftWidth)-parseInt(n.borderRightWidth),i=Mt(e,0,t),a=Mt(e,1,t),o=i&&B(i),s=a&&B(a),c=o&&parseInt(o.marginLeft)+parseInt(o.marginRight)+V(i).width,l=s&&parseInt(s.marginLeft)+parseInt(s.marginRight)+V(a).width;if(n.display===`flex`)return n.flexDirection===`column`||n.flexDirection===`column-reverse`?`vertical`:`horizontal`;if(n.display===`grid`)return n.gridTemplateColumns.split(` `).length<=1?`vertical`:`horizontal`;if(i&&o.float&&o.float!==`none`){var u=o.float===`left`?`left`:`right`;return a&&(s.clear===`both`||s.clear===u)?`vertical`:`horizontal`}return i&&(o.display===`block`||o.display===`flex`||o.display===`table`||o.display===`grid`||c>=r&&n[kn]===`none`||a&&n[kn]===`none`&&c+l>r)?`vertical`:`horizontal`},Nn=function(e,t,n){var r=n?e.left:e.top,i=n?e.right:e.bottom,a=n?e.width:e.height,o=n?t.left:t.top,s=n?t.right:t.bottom,c=n?t.width:t.height;return r===o||i===s||r+a/2===o+c/2},Pn=function(e,t){var n;return dn.some(function(r){var i=r[H].options.emptyInsertThreshold;if(i&&!Nt(r)){var a=V(r),o=e>=a.left-i&&e<=a.right+i,s=t>=a.top-i&&t<=a.bottom+i;if(o&&s)return n=r}}),n},Fn=function(e){function t(e,n){return function(r,i,a,o){var s=r.options.group.name&&i.options.group.name&&r.options.group.name===i.options.group.name;if(e==null&&(n||s))return!0;if(e==null||e===!1)return!1;if(n&&e===`clone`)return e;if(typeof e==`function`)return t(e(r,i,a,o),n)(r,i,a,o);var c=(n?r:i).options.group.name;return e===!0||typeof e==`string`&&e===c||e.join&&e.indexOf(c)>-1}}var n={},r=e.group;r&&mt(r)==`object`||(r={name:r}),n.name=r.name,n.checkPull=t(r.pull,!0),n.checkPut=t(r.put),n.revertClone=r.revertClone,e.group=n},In=function(){!jn&&q&&B(q,`display`,`none`)},Ln=function(){!jn&&q&&B(q,`display`,``)};Dn&&!St&&document.addEventListener(`click`,function(e){if(un)return e.preventDefault(),e.stopPropagation&&e.stopPropagation(),e.stopImmediatePropagation&&e.stopImmediatePropagation(),un=!1,!1},!0);var Rn=function(e){if(G){e=e.touches?e.touches[0]:e;var t=Pn(e.clientX,e.clientY);if(t){var n={};for(var r in e)e.hasOwnProperty(r)&&(n[r]=e[r]);n.target=n.rootEl=t,n.preventDefault=void 0,n.stopPropagation=void 0,t[H]._onDragOver(n)}}},zn=function(e){G&&G.parentNode[H]._isOutsideThisEl(e.target)};function Q(e,t){if(!(e&&e.nodeType&&e.nodeType===1))throw`Sortable: \`el\` must be an HTMLElement, not ${{}.toString.call(e)}`;this.el=e,this.options=t=st({},t),e[H]=this;var n={group:null,sort:!0,disabled:!1,store:null,handle:null,draggable:/^[uo]l$/i.test(e.nodeName)?`>li`:`>*`,swapThreshold:1,invertSwap:!1,invertedSwapThreshold:null,removeCloneOnHide:!0,direction:function(){return Mn(e,this.options)},ghostClass:`sortable-ghost`,chosenClass:`sortable-chosen`,dragClass:`sortable-drag`,ignore:`a, img`,filter:null,preventOnFilter:!0,animation:0,easing:null,setData:function(e,t){e.setData(`Text`,t.textContent)},dropBubble:!1,dragoverBubble:!1,dataIdAttr:`data-id`,delay:0,delayOnTouchOnly:!1,touchStartThreshold:(Number.parseInt?Number:window).parseInt(window.devicePixelRatio,10)||1,forceFallback:!1,fallbackClass:`sortable-fallback`,fallbackOnBody:!1,fallbackTolerance:0,fallbackOffset:{x:0,y:0},supportPointer:Q.supportPointer!==!1&&`PointerEvent`in window&&(!bt||xt),emptyInsertThreshold:5};for(var r in Zt.initializePlugins(this,e,n),n)!(r in t)&&(t[r]=n[r]);for(var i in Fn(t),this)i.charAt(0)===`_`&&typeof this[i]==`function`&&(this[i]=this[i].bind(this));this.nativeDraggable=!t.forceFallback&&An,this.nativeDraggable&&(this.options.touchStartThreshold=1),t.supportPointer?L(e,`pointerdown`,this._onTapStart):(L(e,`mousedown`,this._onTapStart),L(e,`touchstart`,this._onTapStart)),this.nativeDraggable&&(L(e,`dragover`,this),L(e,`dragenter`,this)),dn.push(this.el),t.store&&t.store.get&&this.sort(t.store.get(this)||[]),st(this,Kt())}Q.prototype={constructor:Q,_isOutsideThisEl:function(e){!this.el.contains(e)&&e!==this.el&&(yn=null)},_getDirection:function(e,t){return typeof this.options.direction==`function`?this.options.direction.call(this,e,t,G):this.options.direction},_onTapStart:function(e){if(e.cancelable){var t=this,n=this.el,r=this.options,i=r.preventOnFilter,a=e.type,o=e.touches&&e.touches[0]||e.pointerType&&e.pointerType===`touch`&&e,s=(o||e).target,c=e.target.shadowRoot&&(e.path&&e.path[0]||e.composedPath&&e.composedPath()[0])||s,l=r.filter;if(Yn(n),!G&&!(/mousedown|pointerdown/.test(a)&&e.button!==0||r.disabled)&&!c.isContentEditable&&!(!this.nativeDraggable&&bt&&s&&s.tagName.toUpperCase()===`SELECT`)&&(s=Et(s,r.draggable,n,!1),!(s&&s.animated)&&tn!==s)){if(rn=Pt(s),on=Pt(s,r.draggable),typeof l==`function`){if(l.call(this,e,s,this)){W({sortable:t,rootEl:c,name:`filter`,targetEl:s,toEl:n,fromEl:n}),U(`filter`,t,{evt:e}),i&&e.preventDefault();return}}else if(l&&(l=l.split(`,`).some(function(r){if(r=Et(c,r.trim(),n,!1),r)return W({sortable:t,rootEl:r,name:`filter`,targetEl:s,fromEl:n,toEl:n}),U(`filter`,t,{evt:e}),!0}),l)){i&&e.preventDefault();return}(!r.handle||Et(c,r.handle,n,!1))&&this._prepareDragStart(e,o,s)}}},_prepareDragStart:function(e,t,n){var r=this,i=r.el,a=r.options,o=i.ownerDocument,s;if(n&&!G&&n.parentNode===i){var c=V(n);if(J=i,G=n,K=G.parentNode,en=G.nextSibling,tn=n,cn=a.group,Q.dragged=G,fn={target:G,clientX:(t||e).clientX,clientY:(t||e).clientY},gn=fn.clientX-c.left,_n=fn.clientY-c.top,this._lastX=(t||e).clientX,this._lastY=(t||e).clientY,G.style[`will-change`]=`all`,s=function(){U(`delayEnded`,r,{evt:e}),Q.eventCanceled?r._onDrop():(r._disableDelayedDragEvents(),!yt&&r.nativeDraggable&&(G.draggable=!0),r._triggerDragStart(e,t),W({sortable:r,name:`choose`,originalEvent:e}),z(G,a.chosenClass,!0))},a.ignore.split(`,`).forEach(function(e){kt(G,e.trim(),Hn)}),L(o,`dragover`,Rn),L(o,`mousemove`,Rn),L(o,`touchmove`,Rn),a.supportPointer?(L(o,`pointerup`,r._onDrop),!this.nativeDraggable&&L(o,`pointercancel`,r._onDrop)):(L(o,`mouseup`,r._onDrop),L(o,`touchend`,r._onDrop),L(o,`touchcancel`,r._onDrop)),yt&&this.nativeDraggable&&(this.options.touchStartThreshold=4,G.draggable=!0),U(`delayStart`,this,{evt:e}),a.delay&&(!a.delayOnTouchOnly||t)&&(!this.nativeDraggable||!(vt||_t))){if(Q.eventCanceled){this._onDrop();return}a.supportPointer?(L(o,`pointerup`,r._disableDelayedDrag),L(o,`pointercancel`,r._disableDelayedDrag)):(L(o,`mouseup`,r._disableDelayedDrag),L(o,`touchend`,r._disableDelayedDrag),L(o,`touchcancel`,r._disableDelayedDrag)),L(o,`mousemove`,r._delayedDragTouchMoveHandler),L(o,`touchmove`,r._delayedDragTouchMoveHandler),a.supportPointer&&L(o,`pointermove`,r._delayedDragTouchMoveHandler),r._dragStartTimer=setTimeout(s,a.delay)}else s()}},_delayedDragTouchMoveHandler:function(e){var t=e.touches?e.touches[0]:e;Math.max(Math.abs(t.clientX-this._lastX),Math.abs(t.clientY-this._lastY))>=Math.floor(this.options.touchStartThreshold/(this.nativeDraggable&&window.devicePixelRatio||1))&&this._disableDelayedDrag()},_disableDelayedDrag:function(){G&&Hn(G),clearTimeout(this._dragStartTimer),this._disableDelayedDragEvents()},_disableDelayedDragEvents:function(){var e=this.el.ownerDocument;R(e,`mouseup`,this._disableDelayedDrag),R(e,`touchend`,this._disableDelayedDrag),R(e,`touchcancel`,this._disableDelayedDrag),R(e,`pointerup`,this._disableDelayedDrag),R(e,`pointercancel`,this._disableDelayedDrag),R(e,`mousemove`,this._delayedDragTouchMoveHandler),R(e,`touchmove`,this._delayedDragTouchMoveHandler),R(e,`pointermove`,this._delayedDragTouchMoveHandler)},_triggerDragStart:function(e,t){t||=e.pointerType==`touch`&&e,!this.nativeDraggable||t?this.options.supportPointer?L(document,`pointermove`,this._onTouchMove):t?L(document,`touchmove`,this._onTouchMove):L(document,`mousemove`,this._onTouchMove):(L(G,`dragend`,this),L(J,`dragstart`,this._onDragStart));try{document.selection?Xn(function(){document.selection.empty()}):window.getSelection().removeAllRanges()}catch{}},_dragStarted:function(e,t){if(ln=!1,J&&G){U(`dragStarted`,this,{evt:t}),this.nativeDraggable&&L(document,`dragover`,zn);var n=this.options;!e&&z(G,n.dragClass,!1),z(G,n.ghostClass,!0),Q.active=this,e&&this._appendGhost(),W({sortable:this,name:`start`,originalEvent:t})}else this._nulling()},_emulateDragOver:function(){if(pn){this._lastX=pn.clientX,this._lastY=pn.clientY,In();for(var e=document.elementFromPoint(pn.clientX,pn.clientY),t=e;e&&e.shadowRoot&&(e=e.shadowRoot.elementFromPoint(pn.clientX,pn.clientY),e!==t);)t=e;if(G.parentNode[H]._isOutsideThisEl(e),t)do{if(t[H]){var n=void 0;if(n=t[H]._onDragOver({clientX:pn.clientX,clientY:pn.clientY,target:e,rootEl:t}),n&&!this.options.dragoverBubble)break}e=t}while(t=Tt(t));Ln()}},_onTouchMove:function(e){if(fn){var t=this.options,n=t.fallbackTolerance,r=t.fallbackOffset,i=e.touches?e.touches[0]:e,a=q&&Ot(q,!0),o=q&&a&&a.a,s=q&&a&&a.d,c=On&&Z&&Ft(Z),l=(i.clientX-fn.clientX+r.x)/(o||1)+(c?c[0]-wn[0]:0)/(o||1),u=(i.clientY-fn.clientY+r.y)/(s||1)+(c?c[1]-wn[1]:0)/(s||1);if(!Q.active&&!ln){if(n&&Math.max(Math.abs(i.clientX-this._lastX),Math.abs(i.clientY-this._lastY))<n)return;this._onDragStart(e,!0)}if(q){a?(a.e+=l-(mn||0),a.f+=u-(hn||0)):a={a:1,b:0,c:0,d:1,e:l,f:u};var d=`matrix(${a.a},${a.b},${a.c},${a.d},${a.e},${a.f})`;B(q,`webkitTransform`,d),B(q,`mozTransform`,d),B(q,`msTransform`,d),B(q,`transform`,d),mn=l,hn=u,pn=i}e.cancelable&&e.preventDefault()}},_appendGhost:function(){if(!q){var e=this.options.fallbackOnBody?document.body:J,t=V(G,!0,On,!0,e),n=this.options;if(On){for(Z=e;B(Z,`position`)===`static`&&B(Z,`transform`)===`none`&&Z!==document;)Z=Z.parentNode;Z!==document.body&&Z!==document.documentElement?(Z===document&&(Z=At()),t.top+=Z.scrollTop,t.left+=Z.scrollLeft):Z=At(),wn=Ft(Z)}q=G.cloneNode(!0),z(q,n.ghostClass,!1),z(q,n.fallbackClass,!0),z(q,n.dragClass,!0),B(q,`transition`,``),B(q,`transform`,``),B(q,`box-sizing`,`border-box`),B(q,`margin`,0),B(q,`top`,t.top),B(q,`left`,t.left),B(q,`width`,t.width),B(q,`height`,t.height),B(q,`opacity`,`0.8`),B(q,`position`,On?`absolute`:`fixed`),B(q,`zIndex`,`100000`),B(q,`pointerEvents`,`none`),Q.ghost=q,e.appendChild(q),B(q,`transform-origin`,gn/parseInt(q.style.width)*100+`% `+_n/parseInt(q.style.height)*100+`%`)}},_onDragStart:function(e,t){var n=this,r=e.dataTransfer,i=n.options;U(`dragStart`,this,{evt:e}),Q.eventCanceled?this._onDrop():(U(`setupClone`,this),Q.eventCanceled||(Y=Wt(G),Y.removeAttribute(`id`),Y.draggable=!1,Y.style[`will-change`]=``,this._hideClone(),z(Y,this.options.chosenClass,!1),Q.clone=Y),n.cloneId=Xn(function(){U(`clone`,n),Q.eventCanceled||(n.options.removeCloneOnHide||J.insertBefore(Y,G),n._hideClone(),W({sortable:n,name:`clone`}))}),!t&&z(G,i.dragClass,!0),t?(un=!0,n._loopId=setInterval(n._emulateDragOver,50)):(R(document,`mouseup`,n._onDrop),R(document,`touchend`,n._onDrop),R(document,`touchcancel`,n._onDrop),r&&(r.effectAllowed=`move`,i.setData&&i.setData.call(n,r,G)),L(document,`drop`,n),B(G,`transform`,`translateZ(0)`)),ln=!0,n._dragStartId=Xn(n._dragStarted.bind(n,t,e)),L(document,`selectstart`,n),vn=!0,window.getSelection().removeAllRanges(),bt&&B(document.body,`user-select`,`none`))},_onDragOver:function(e){var t=this.el,n=e.target,r,i,a,o=this.options,s=o.group,c=Q.active,l=cn===s,u=o.sort,d=X||c,f,p=this,m=!1;if(Tn)return;function h(o,s){U(o,p,lt({evt:e,isOwner:l,axis:f?`vertical`:`horizontal`,revert:a,dragRect:r,targetRect:i,canSort:u,fromSortable:d,target:n,completed:_,onMove:function(n,i){return Vn(J,t,G,r,n,V(n),e,i)},changed:v},s))}function g(){h(`dragOverAnimationCapture`),p.captureAnimationState(),p!==d&&d.captureAnimationState()}function _(r){return h(`dragOverCompleted`,{insertion:r}),r&&(l?c._hideClone():c._showClone(p),p!==d&&(z(G,X?X.options.ghostClass:c.options.ghostClass,!1),z(G,o.ghostClass,!0)),X!==p&&p!==Q.active?X=p:p===Q.active&&X&&(X=null),d===p&&(p._ignoreWhileAnimating=n),p.animateAll(function(){h(`dragOverAnimationComplete`),p._ignoreWhileAnimating=null}),p!==d&&(d.animateAll(),d._ignoreWhileAnimating=null)),(n===G&&!G.animated||n===t&&!n.animated)&&(yn=null),!o.dragoverBubble&&!e.rootEl&&n!==document&&(G.parentNode[H]._isOutsideThisEl(e.target),!r&&Rn(e)),!o.dragoverBubble&&e.stopPropagation&&e.stopPropagation(),m=!0}function v(){an=Pt(G),sn=Pt(G,o.draggable),W({sortable:p,name:`change`,toEl:t,newIndex:an,newDraggableIndex:sn,originalEvent:e})}if(e.preventDefault!==void 0&&e.cancelable&&e.preventDefault(),n=Et(n,o.draggable,t,!0),h(`dragOver`),Q.eventCanceled)return m;if(G.contains(e.target)||n.animated&&n.animatingX&&n.animatingY||p._ignoreWhileAnimating===n)return _(!1);if(un=!1,c&&!o.disabled&&(l?u||(a=K!==J):X===this||(this.lastPutMode=cn.checkPull(this,c,G,e))&&s.checkPut(this,c,G,e))){if(f=this._getDirection(e,n)===`vertical`,r=V(G),h(`dragOverValid`),Q.eventCanceled)return m;if(a)return K=J,g(),this._hideClone(),h(`revert`),Q.eventCanceled||(en?J.insertBefore(G,en):J.appendChild(G)),_(!0);var y=Nt(t,o.draggable);if(!y||Gn(e,f,this)&&!y.animated){if(y===G)return _(!1);if(y&&t===e.target&&(n=y),n&&(i=V(n)),Vn(J,t,G,r,n,i,e,!!n)!==!1)return g(),y&&y.nextSibling?t.insertBefore(G,y.nextSibling):t.appendChild(G),K=t,v(),_(!0)}else if(y&&Wn(e,f,this)){var b=Mt(t,0,o,!0);if(b===G)return _(!1);if(n=b,i=V(n),Vn(J,t,G,r,n,i,e,!1)!==!1)return g(),t.insertBefore(G,b),K=t,v(),_(!0)}else if(n.parentNode===t){i=V(n);var x=0,S,C=G.parentNode!==t,w=!Nn(G.animated&&G.toRect||r,n.animated&&n.toRect||i,f),T=f?`top`:`left`,E=jt(n,`top`,`top`)||jt(G,`top`,`top`),D=E?E.scrollTop:void 0;yn!==n&&(S=i[T],xn=!1,Sn=!w&&o.invertSwap||C),x=Kn(e,n,i,f,w?1:o.swapThreshold,o.invertedSwapThreshold==null?o.swapThreshold:o.invertedSwapThreshold,Sn,yn===n);var O;if(x!==0){var ee=Pt(G);do ee-=x,O=K.children[ee];while(O&&(B(O,`display`)===`none`||O===q))}if(x===0||O===n)return _(!1);yn=n,bn=x;var k=n.nextElementSibling,te=!1;te=x===1;var ne=Vn(J,t,G,r,n,i,e,te);if(ne!==!1)return(ne===1||ne===-1)&&(te=ne===1),Tn=!0,setTimeout(Un,30),g(),te&&!k?t.appendChild(G):n.parentNode.insertBefore(G,te?k:n),E&&Ut(E,0,D-E.scrollTop),K=G.parentNode,S!==void 0&&!Sn&&(Cn=Math.abs(S-V(n)[T])),v(),_(!0)}if(t.contains(G))return _(!1)}return!1},_ignoreWhileAnimating:null,_offMoveEvents:function(){R(document,`mousemove`,this._onTouchMove),R(document,`touchmove`,this._onTouchMove),R(document,`pointermove`,this._onTouchMove),R(document,`dragover`,Rn),R(document,`mousemove`,Rn),R(document,`touchmove`,Rn)},_offUpEvents:function(){var e=this.el.ownerDocument;R(e,`mouseup`,this._onDrop),R(e,`touchend`,this._onDrop),R(e,`pointerup`,this._onDrop),R(e,`pointercancel`,this._onDrop),R(e,`touchcancel`,this._onDrop),R(document,`selectstart`,this)},_onDrop:function(e){var t=this.el,n=this.options;an=Pt(G),sn=Pt(G,n.draggable),U(`drop`,this,{evt:e}),K=G&&G.parentNode,an=Pt(G),sn=Pt(G,n.draggable),Q.eventCanceled||(ln=!1,Sn=!1,xn=!1,clearInterval(this._loopId),clearTimeout(this._dragStartTimer),Zn(this.cloneId),Zn(this._dragStartId),this.nativeDraggable&&(R(document,`drop`,this),R(t,`dragstart`,this._onDragStart)),this._offMoveEvents(),this._offUpEvents(),bt&&B(document.body,`user-select`,``),B(G,`transform`,``),e&&(vn&&(e.cancelable&&e.preventDefault(),!n.dropBubble&&e.stopPropagation()),q&&q.parentNode&&q.parentNode.removeChild(q),(J===K||X&&X.lastPutMode!==`clone`)&&Y&&Y.parentNode&&Y.parentNode.removeChild(Y),G&&(this.nativeDraggable&&R(G,`dragend`,this),Hn(G),G.style[`will-change`]=``,vn&&!ln&&z(G,X?X.options.ghostClass:this.options.ghostClass,!1),z(G,this.options.chosenClass,!1),W({sortable:this,name:`unchoose`,toEl:K,newIndex:null,newDraggableIndex:null,originalEvent:e}),J===K?an!==rn&&an>=0&&(W({sortable:this,name:`update`,toEl:K,originalEvent:e}),W({sortable:this,name:`sort`,toEl:K,originalEvent:e})):(an>=0&&(W({rootEl:K,name:`add`,toEl:K,fromEl:J,originalEvent:e}),W({sortable:this,name:`remove`,toEl:K,originalEvent:e}),W({rootEl:K,name:`sort`,toEl:K,fromEl:J,originalEvent:e}),W({sortable:this,name:`sort`,toEl:K,originalEvent:e})),X&&X.save()),Q.active&&((an==null||an===-1)&&(an=rn,sn=on),W({sortable:this,name:`end`,toEl:K,originalEvent:e}),this.save())))),this._nulling()},_nulling:function(){U(`nulling`,this),J=G=K=q=en=Y=tn=nn=fn=pn=vn=an=sn=rn=on=yn=bn=X=cn=Q.dragged=Q.ghost=Q.clone=Q.active=null;var e=this.el;En.forEach(function(t){e.contains(t)&&(t.checked=!0)}),En.length=mn=hn=0},handleEvent:function(e){switch(e.type){case`drop`:case`dragend`:this._onDrop(e);break;case`dragenter`:case`dragover`:G&&(this._onDragOver(e),Bn(e));break;case`selectstart`:e.preventDefault()}},toArray:function(){for(var e=[],t,n=this.el.children,r=0,i=n.length,a=this.options;r<i;r++)t=n[r],Et(t,a.draggable,this.el,!1)&&e.push(t.getAttribute(a.dataIdAttr)||Jn(t));return e},sort:function(e,t){var n={},r=this.el;this.toArray().forEach(function(e,t){var i=r.children[t];Et(i,this.options.draggable,r,!1)&&(n[e]=i)},this),t&&this.captureAnimationState(),e.forEach(function(e){n[e]&&(r.removeChild(n[e]),r.appendChild(n[e]))}),t&&this.animateAll()},save:function(){var e=this.options.store;e&&e.set&&e.set(this)},closest:function(e,t){return Et(e,t||this.options.draggable,this.el,!1)},option:function(e,t){var n=this.options;if(t===void 0)return n[e];var r=Zt.modifyOption(this,e,t);n[e]=r===void 0?t:r,e===`group`&&Fn(n)},destroy:function(){U(`destroy`,this);var e=this.el;e[H]=null,R(e,`mousedown`,this._onTapStart),R(e,`touchstart`,this._onTapStart),R(e,`pointerdown`,this._onTapStart),this.nativeDraggable&&(R(e,`dragover`,this),R(e,`dragenter`,this)),Array.prototype.forEach.call(e.querySelectorAll(`[draggable]`),function(e){e.removeAttribute(`draggable`)}),this._onDrop(),this._disableDelayedDragEvents(),dn.splice(dn.indexOf(this.el),1),this.el=e=null},_hideClone:function(){if(!nn){if(U(`hideClone`,this),Q.eventCanceled)return;B(Y,`display`,`none`),this.options.removeCloneOnHide&&Y.parentNode&&Y.parentNode.removeChild(Y),nn=!0}},_showClone:function(e){if(e.lastPutMode!==`clone`)this._hideClone();else if(nn){if(U(`showClone`,this),Q.eventCanceled)return;G.parentNode==J&&!this.options.group.revertClone?J.insertBefore(Y,G):en?J.insertBefore(Y,en):J.appendChild(Y),this.options.group.revertClone&&this.animate(G,Y),B(Y,`display`,``),nn=!1}}};function Bn(e){e.dataTransfer&&(e.dataTransfer.dropEffect=`move`),e.cancelable&&e.preventDefault()}function Vn(e,t,n,r,i,a,o,s){var c,l=e[H],u=l.options.onMove,d;return window.CustomEvent&&!_t&&!vt?c=new CustomEvent(`move`,{bubbles:!0,cancelable:!0}):(c=document.createEvent(`Event`),c.initEvent(`move`,!0,!0)),c.to=t,c.from=e,c.dragged=n,c.draggedRect=r,c.related=i||t,c.relatedRect=a||V(t),c.willInsertAfter=s,c.originalEvent=o,e.dispatchEvent(c),u&&(d=u.call(l,c,o)),d}function Hn(e){e.draggable=!1}function Un(){Tn=!1}function Wn(e,t,n){var r=V(Mt(n.el,0,n.options,!0)),i=Gt(n.el,n.options,q),a=10;return t?e.clientX<i.left-a||e.clientY<r.top&&e.clientX<r.right:e.clientY<i.top-a||e.clientY<r.bottom&&e.clientX<r.left}function Gn(e,t,n){var r=V(Nt(n.el,n.options.draggable)),i=Gt(n.el,n.options,q),a=10;return t?e.clientX>i.right+a||e.clientY>r.bottom&&e.clientX>r.left:e.clientY>i.bottom+a||e.clientX>r.right&&e.clientY>r.top}function Kn(e,t,n,r,i,a,o,s){var c=r?e.clientY:e.clientX,l=r?n.height:n.width,u=r?n.top:n.left,d=r?n.bottom:n.right,f=!1;if(!o){if(s&&Cn<l*i){if(!xn&&(bn===1?c>u+l*a/2:c<d-l*a/2)&&(xn=!0),xn)f=!0;else if(bn===1?c<u+Cn:c>d-Cn)return-bn}else if(c>u+l*(1-i)/2&&c<d-l*(1-i)/2)return qn(t)}return f||=o,f&&(c<u+l*a/2||c>d-l*a/2)?c>u+l/2?1:-1:0}function qn(e){return Pt(G)<Pt(e)?1:-1}function Jn(e){for(var t=e.tagName+e.className+e.src+e.href+e.textContent,n=t.length,r=0;n--;)r+=t.charCodeAt(n);return r.toString(36)}function Yn(e){En.length=0;for(var t=e.getElementsByTagName(`input`),n=t.length;n--;){var r=t[n];r.checked&&En.push(r)}}function Xn(e){return setTimeout(e,0)}function Zn(e){return clearTimeout(e)}Dn&&L(document,`touchmove`,function(e){(Q.active||ln)&&e.cancelable&&e.preventDefault()}),Q.utils={on:L,off:R,css:B,find:kt,is:function(e,t){return!!Et(e,t,e,!1)},extend:Rt,throttle:Vt,closest:Et,toggleClass:z,clone:Wt,index:Pt,nextTick:Xn,cancelNextTick:Zn,detectDirection:Mn,getChild:Mt,expando:H},Q.get=function(e){return e[H]},Q.mount=function(){var e=[...arguments];e[0].constructor===Array&&(e=e[0]),e.forEach(function(e){if(!e.prototype||!e.prototype.constructor)throw`Sortable: Mounted plugin must be a constructor function, not ${{}.toString.call(e)}`;e.utils&&(Q.utils=lt(lt({},Q.utils),e.utils)),Zt.mount(e)})},Q.create=function(e,t){return new Q(e,t)},Q.version=ht;var $=[],Qn,$n,er=!1,tr,nr,rr,ir;function ar(){function e(){for(var e in this.defaults={scroll:!0,forceAutoScrollFallback:!1,scrollSensitivity:30,scrollSpeed:10,bubbleScroll:!0},this)e.charAt(0)===`_`&&typeof this[e]==`function`&&(this[e]=this[e].bind(this))}return e.prototype={dragStarted:function(e){var t=e.originalEvent;this.sortable.nativeDraggable?L(document,`dragover`,this._handleAutoScroll):this.options.supportPointer?L(document,`pointermove`,this._handleFallbackAutoScroll):t.touches?L(document,`touchmove`,this._handleFallbackAutoScroll):L(document,`mousemove`,this._handleFallbackAutoScroll)},dragOverCompleted:function(e){var t=e.originalEvent;!this.options.dragOverBubble&&!t.rootEl&&this._handleAutoScroll(t)},drop:function(){this.sortable.nativeDraggable?R(document,`dragover`,this._handleAutoScroll):(R(document,`pointermove`,this._handleFallbackAutoScroll),R(document,`touchmove`,this._handleFallbackAutoScroll),R(document,`mousemove`,this._handleFallbackAutoScroll)),sr(),or(),Ht()},nulling:function(){rr=$n=Qn=er=ir=tr=nr=null,$.length=0},_handleFallbackAutoScroll:function(e){this._handleAutoScroll(e,!0)},_handleAutoScroll:function(e,t){var n=this,r=(e.touches?e.touches[0]:e).clientX,i=(e.touches?e.touches[0]:e).clientY,a=document.elementFromPoint(r,i);if(rr=e,t||this.options.forceAutoScrollFallback||vt||_t||bt){cr(e,this.options,a,t);var o=Lt(a,!0);er&&(!ir||r!==tr||i!==nr)&&(ir&&sr(),ir=setInterval(function(){var a=Lt(document.elementFromPoint(r,i),!0);a!==o&&(o=a,or()),cr(e,n.options,a,t)},10),tr=r,nr=i)}else{if(!this.options.bubbleScroll||Lt(a,!0)===At()){or();return}cr(e,this.options,Lt(a,!1),!1)}}},st(e,{pluginName:`scroll`,initializeByDefault:!0})}function or(){$.forEach(function(e){clearInterval(e.pid)}),$=[]}function sr(){clearInterval(ir)}var cr=Vt(function(e,t,n,r){if(t.scroll){var i=(e.touches?e.touches[0]:e).clientX,a=(e.touches?e.touches[0]:e).clientY,o=t.scrollSensitivity,s=t.scrollSpeed,c=At(),l=!1,u;$n!==n&&($n=n,or(),Qn=t.scroll,u=t.scrollFn,Qn===!0&&(Qn=Lt(n,!0)));var d=0,f=Qn;do{var p=f,m=V(p),h=m.top,g=m.bottom,_=m.left,v=m.right,y=m.width,b=m.height,x=void 0,S=void 0,C=p.scrollWidth,w=p.scrollHeight,T=B(p),E=p.scrollLeft,D=p.scrollTop;p===c?(x=y<C&&(T.overflowX===`auto`||T.overflowX===`scroll`||T.overflowX===`visible`),S=b<w&&(T.overflowY===`auto`||T.overflowY===`scroll`||T.overflowY===`visible`)):(x=y<C&&(T.overflowX===`auto`||T.overflowX===`scroll`),S=b<w&&(T.overflowY===`auto`||T.overflowY===`scroll`));var O=x&&(Math.abs(v-i)<=o&&E+y<C)-(Math.abs(_-i)<=o&&!!E),ee=S&&(Math.abs(g-a)<=o&&D+b<w)-(Math.abs(h-a)<=o&&!!D);if(!$[d])for(var k=0;k<=d;k++)$[k]||($[k]={});($[d].vx!=O||$[d].vy!=ee||$[d].el!==p)&&($[d].el=p,$[d].vx=O,$[d].vy=ee,clearInterval($[d].pid),(O!=0||ee!=0)&&(l=!0,$[d].pid=setInterval(function(){r&&this.layer===0&&Q.active._onTouchMove(rr);var t=$[this.layer].vy?$[this.layer].vy*s:0,n=$[this.layer].vx?$[this.layer].vx*s:0;(typeof u!=`function`||u.call(Q.dragged.parentNode[H],n,t,e,rr,$[this.layer].el)===`continue`)&&Ut($[this.layer].el,n,t)}.bind({layer:d}),24))),d++}while(t.bubbleScroll&&f!==c&&(f=Lt(f,!1)));er=l}},30),lr=function(e){var t=e.originalEvent,n=e.putSortable,r=e.dragEl,i=e.activeSortable,a=e.dispatchSortableEvent,o=e.hideGhostForTarget,s=e.unhideGhostForTarget;if(t){var c=n||i;o();var l=t.changedTouches&&t.changedTouches.length?t.changedTouches[0]:t,u=document.elementFromPoint(l.clientX,l.clientY);s(),c&&!c.el.contains(u)&&(a(`spill`),this.onSpill({dragEl:r,putSortable:n}))}};function ur(){}ur.prototype={startIndex:null,dragStart:function(e){var t=e.oldDraggableIndex;this.startIndex=t},onSpill:function(e){var t=e.dragEl,n=e.putSortable;this.sortable.captureAnimationState(),n&&n.captureAnimationState();var r=Mt(this.sortable.el,this.startIndex,this.options);r?this.sortable.el.insertBefore(t,r):this.sortable.el.appendChild(t),this.sortable.animateAll(),n&&n.animateAll()},drop:lr},st(ur,{pluginName:`revertOnSpill`});function dr(){}dr.prototype={onSpill:function(e){var t=e.dragEl,n=e.putSortable||this.sortable;n.captureAnimationState(),t.parentNode&&t.parentNode.removeChild(t),n.animateAll()},drop:lr},st(dr,{pluginName:`removeOnSpill`}),Q.mount(new ar),Q.mount(dr,ur);var fr=e=>Array.from(e.dataTransfer?.types??[]).includes(`Files`),pr=e=>{let t=e?.closest?.(`[data-item-id]`);return t?Number(t.dataset.itemId):null},mr=({item:e})=>{let t=e.current;return t?.hasThumbnail?F(`img`,{class:`thumb`,src:N.thumbnailUrl(e.id,t.n),alt:``,loading:`lazy`}):F(`span`,{class:`thumb thumb-ext ext-${t?.ext??`none`}`,children:(t?.ext??`?`).toUpperCase()})},hr=e=>{let t=ke(null),[n,r]=M(null),i=ke(e);return i.current=e,Oe(()=>{if(!t.current||!e.editable)return;let n=Q.create(t.current,{handle:`.handle`,animation:120,forceFallback:!0,fallbackTolerance:4,onEnd:e=>{let{oldIndex:t,newIndex:n,item:r,from:a}=e;if(t===void 0||n===void 0||t===n)return;a.removeChild(r),a.insertBefore(r,a.children[t]??null);let o=[...i.current.items],[s]=o.splice(t,1);o.splice(n,0,s),i.current.onReorder(s,n===0?null:o[n-1].id)}});return()=>n.destroy()},[e.editable]),F(`div`,{class:`list-wrap${n===`list`?` drop-list`:``}`,onDragOver:t=>{e.editable&&fr(t)&&(t.preventDefault(),t.dataTransfer.dropEffect=`copy`,r(pr(t.target)??`list`))},onDragLeave:e=>{e.currentTarget.contains(e.relatedTarget)||r(null)},onDrop:t=>{if(!e.editable||!fr(t))return;t.preventDefault(),r(null);let n=Array.from(t.dataTransfer?.files??[]);if(!n.length)return;let i=pr(t.target);e.onDropFiles(n,i===null?null:e.items.find(e=>e.id===i)??null)},children:[F(`ul`,{class:`items`,ref:t,children:e.items.map(t=>F(`li`,{"data-item-id":t.id,class:[`item`,t.id===e.selectedId?`selected`:``,n===t.id?`drop-row`:``,`status-${t.status}`].join(` `),onClick:n=>{n.target.closest(`select, a, button, .handle`)||e.onSelect(t.id)},children:[e.editable&&F(`span`,{class:`handle`,title:`Drag to reorder`,"aria-label":`Drag to reorder`,children:`⠿`}),F(mr,{item:t}),F(`span`,{class:`title`,children:[F(`span`,{class:`name`,children:t.title}),t.needsConfirm&&F(`span`,{class:`badge warn`,children:`printed?`}),F(`span`,{class:`meta`,children:[t.current?F(S,{children:[`v`,t.current.n,t.versionCount>1?`/${t.versionCount}`:``,` · `,t.current.ext.toUpperCase(),` ·`,` `,qe(t.current.size)]}):`no file`,F(`span`,{class:`when`,children:[` · `,F(`time`,{title:Xe(t.createdAt),children:Ye(t.createdAt)})]})]})]}),e.editable?F(`select`,{class:`status status-${t.status}`,value:t.status,"aria-label":`Status`,onChange:n=>e.onStatus(t,n.currentTarget.value),children:ze.map(e=>F(`option`,{value:e,children:e},e))}):F(`button`,{class:`small`,onClick:()=>e.onRestore(t),children:`Restore`}),e.onSend&&e.editable&&F(`button`,{class:`icon`,disabled:!t.sendable,title:t.sendable?`Send to Bambuddy`:`Bambuddy cannot slice STEP files`,"aria-label":`Send to Bambuddy`,onClick:()=>e.onSend(t),children:`➜`}),t.current&&F(`a`,{class:`icon`,href:N.downloadUrl(t.id,t.current.n),title:`Download`,"aria-label":`Download`,children:`⇩`})]},t.id))}),e.editable&&F(`p`,{class:`dropzone`,children:`⇪ Drop STL, 3MF, STEP, OBJ or ZIP files here. Drop one file on a row to add a new version.`})]})},gr=({queues:e,currentId:t,onSelect:n,onChanged:r})=>{let[i,a]=M(!1),[o,s]=M(``),[c,l]=M(!1),u=e.find(e=>e.id===t)??null,d=async()=>{let e=o.trim();if(!e)return a(!1);try{let t=await N.createQueue({name:e});s(``),a(!1),r(t.id)}catch(e){I(P(e),`error`)}};return F(`nav`,{class:`queuebar`,"aria-label":`Queues`,children:[F(`div`,{class:`tabs`,role:`tablist`,children:e.map(e=>F(`button`,{role:`tab`,"aria-selected":e.id===t,class:`tab${e.id===t?` active`:``}`,onClick:()=>n(e.id),children:[e.name,` `,F(`span`,{class:`count`,children:e.counts.queued})]},e.id))}),F(`select`,{class:`tabs-select`,"aria-label":`Queue`,value:t??``,onChange:e=>n(Number(e.currentTarget.value)),children:e.map(e=>F(`option`,{value:e.id,children:[e.name,` (`,e.counts.queued,`)`]},e.id))}),i?F(`form`,{class:`inline-form`,onSubmit:e=>{e.preventDefault(),d()},children:[F(`input`,{autoFocus:!0,placeholder:`Queue name`,value:o,onInput:e=>s(e.currentTarget.value),onKeyDown:e=>e.key===`Escape`&&a(!1)}),F(`button`,{type:`submit`,class:`small`,children:`Add`})]}):F(`button`,{class:`small`,onClick:()=>a(!0),title:`New queue`,children:`+ Queue`}),u&&F(`div`,{class:`settings`,children:[F(`button`,{class:`icon`,"aria-expanded":c,title:`Queue settings`,"aria-label":`Queue settings`,onClick:()=>l(!c),children:`⚙`}),c&&F(`div`,{class:`menu`,role:`dialog`,"aria-label":`Settings of ${u.name}`,children:[F(`form`,{class:`inline-form`,onSubmit:e=>{e.preventDefault();let t=e.currentTarget.elements.namedItem(`qname`).value.trim();t&&t!==u.name&&N.patchQueue(u.id,{name:t}).then(()=>r()).catch(e=>I(P(e),`error`))},children:[F(`input`,{name:`qname`,defaultValue:u.name,"aria-label":`Queue name`}),F(`button`,{type:`submit`,class:`small`,children:`Rename`})]}),F(`label`,{class:`check`,children:[F(`input`,{type:`checkbox`,checked:u.autoStatus,onChange:e=>N.patchQueue(u.id,{autoStatus:e.currentTarget.checked}).then(()=>r()).catch(e=>I(P(e),`error`))}),`Bambuddy prints set the status automatically`]}),F(`button`,{class:`danger small`,disabled:e.length<=1,title:e.length<=1?`The last queue cannot be deleted`:void 0,onClick:()=>{confirm(`Delete the queue "${u.name}"? Only an empty queue (trash included) can be deleted.`)&&N.deleteQueue(u.id).then(()=>{l(!1),r(e.find(e=>e.id!==u.id)?.id)}).catch(e=>I(P(e),`error`))},children:`Delete queue`})]})]})]})},_r=e=>e.event===`print_complete`?`finished`:e.event===`print_failed`?`failed`:e.event,vr=({events:e,onResolved:t})=>{let[n,r]=M(!1),[i,a]=M(null),[o,s]=M(null);if(e.length===0)return null;let c=()=>{i===null&&N.items({}).then(a).catch(e=>I(P(e),`error`))},l=(e,n,r)=>{s(e.id),N.assignEvent(e.id,n).then(()=>{I(r,`ok`),t()}).catch(e=>I(P(e),`error`)).finally(()=>s(null))};return F(`section`,{class:`unmatched`,"aria-label":`Unmatched prints`,children:[F(`button`,{class:`unmatched-head`,"aria-expanded":n,onClick:()=>r(!n),children:[`⚠ `,e.length,` print`,e.length===1?``:`s`,` could not be matched — `,n?`hide`:`review`]}),n&&F(`ul`,{class:`events`,children:e.map(e=>F(`li`,{class:`event event-${e.event}`,children:[F(`div`,{children:[F(`b`,{children:e.filename??`(no name)`}),` `,_r(e),e.printer?` on ${e.printer}`:``,` `,F(`time`,{class:`muted`,title:Xe(e.receivedAt),children:Ye(e.receivedAt)})]}),F(`div`,{class:`event-actions`,children:[e.candidates.map(t=>F(`button`,{class:`small`,disabled:o===e.id,onClick:()=>l(e,{itemId:t.id},`"${t.title}" updated from the print`),children:[`It was “`,t.title,`”`,` `,F(`span`,{class:`muted`,children:[`(`,t.filename?`${t.filename} · `:``,t.queueName,`, `,t.status,`)`]})]},t.id)),F(`select`,{"aria-label":`Another item`,disabled:o===e.id,onFocus:c,onMouseDown:c,value:``,onChange:t=>{let n=Number(t.currentTarget.value),r=i?.find(e=>e.id===n);r&&l(e,{itemId:n},`"${r.title}" updated from the print`)},children:[F(`option`,{value:``,children:e.candidates.length?`Another item…`:`It was…`}),(i??[]).map(e=>F(`option`,{value:e.id,children:[e.title,` (`,e.status,`)`]},e.id))]}),F(`button`,{class:`small`,disabled:o===e.id,onClick:()=>l(e,{ignore:!0},`Ignored`),children:`Not from the backlog`})]})]},e.id))})]})},yr={get:e=>{try{return localStorage.getItem(`print-backlog.${e}`)}catch{return null}},set:(e,t)=>{try{localStorage.setItem(`print-backlog.${e}`,t)}catch{}}};me(F(()=>{let[e,t]=M(null),[n,r]=M([]),[i,a]=M(Number(yr.get(`queue`))||null),[o,s]=M(yr.get(`view`)??`queued`),[c,l]=M(``),[u,d]=M([]),[f,p]=M(null),[m,h]=M(0),[g,_]=M(null),[v,y]=M(null),[b,x]=M([]),C=ke(null),w=je(async e=>{let t=await N.queues();r(t),a(n=>{let r=e??n;return t.some(e=>e.id===r)?r:t[0]?.id??null})},[]),T=je(async()=>{if(i===null)return;let e=await N.items({queue:i,status:o===`all`||o===`trash`?void 0:o,trash:o===`trash`,q:c.trim()||void 0});d(e)},[i,o,c]),E=je(()=>N.openEvents().then(x).catch(()=>{}),[]),D=je(()=>{T().catch(e=>I(P(e),`error`)),w().catch(e=>I(P(e),`error`)),E()},[T,w,E]);Oe(()=>{E();let e=setInterval(()=>{E(),w().catch(()=>{}),T().catch(()=>{})},6e4);return()=>clearInterval(e)},[E,w,T]);let O=e=>N.sendToBambuddy(e.id).then(t=>{I(t.duplicate?`Bambuddy already had "${e.title}"`:`Sent "${e.title}" to Bambuddy`,`ok`),h(e=>e+1),D()}).catch(e=>I(P(e),`error`));Oe(()=>{Promise.all([N.me(),w()]).then(([e])=>t(e)).catch(e=>y(P(e)))},[]),Oe(()=>{let e=setTimeout(()=>T().catch(e=>I(P(e),`error`)),c?200:0);return()=>clearTimeout(e)},[T]),Oe(()=>{i&&yr.set(`queue`,String(i)),yr.set(`view`,o)},[i,o]);let ee=async e=>{if(i&&e.length){_(0);try{let t=await N.uploadItems(i,e,_);I(`Added ${t.items.length} item${t.items.length===1?``:`s`}`,`ok`),t.skipped.length&&I(`Not imported from ZIP: ${t.skipped.slice(0,5).join(`, `)}${t.skipped.length>5?` …`:``}`,`info`),o!==`queued`&&o!==`all`&&s(`queued`),D()}catch(e){I(P(e),`error`)}finally{_(null)}}},k=async(e,t)=>{_(0);try{let n=await N.uploadVersion(e.id,t,void 0,_);I(n.duplicate?`"${e.title}": same file as version ${n.version.n}, nothing new stored`:`"${e.title}": version ${n.version.n} added`,n.duplicate?`info`:`ok`),h(e=>e+1),D()}catch(e){I(P(e),`error`)}finally{_(null)}},te=(e,t)=>{t&&e.length===1?confirm(`Add "${e[0].name}" as a new version of "${t.title}"?`)&&k(t,e[0]):ee(e)},ne=(e,t)=>{d(n=>n.map(n=>n.id===e.id?{...n,status:t}:n)),N.patchItem(e.id,{status:t}).then(()=>{h(e=>e+1),D()}).catch(e=>{I(P(e),`error`),D()})},re=(e,t)=>{d(n=>{let r=n.filter(t=>t.id!==e.id),i=t===null?0:r.findIndex(e=>e.id===t)+1;return[...r.slice(0,i),e,...r.slice(i)]}),N.patchItem(e.id,{move:{afterId:t}}).catch(e=>I(P(e),`error`)).finally(()=>void T())};if(v)return F(`main`,{class:`fatal`,children:[`Print Backlog could not start: `,v]});let ie=n.find(e=>e.id===i)??null,ae=[...ze.map(e=>({id:e,label:e,count:ie?.counts[e]})),{id:`all`,label:`all`},{id:`trash`,label:`trash`}];return F(S,{children:[F(`header`,{class:`top`,children:[F(`h1`,{children:`Print Backlog`}),F(`span`,{class:`muted`,children:e?.user})]}),F(gr,{queues:n,currentId:i,onSelect:e=>{a(e),p(null)},onChanged:e=>void w(e).then(()=>T())}),F(`div`,{class:`layout${f?` with-panel`:``}`,children:[F(`main`,{children:[F(`div`,{class:`toolbar`,children:[F(`div`,{class:`views`,role:`tablist`,"aria-label":`Filter by status`,children:ae.map(e=>F(`button`,{role:`tab`,"aria-selected":o===e.id,class:`chip status-${e.id}${o===e.id?` active`:``}`,onClick:()=>s(e.id),children:[e.label,e.count!==void 0&&F(`span`,{class:`count`,children:e.count})]},e.id))}),F(`input`,{type:`search`,class:`search`,placeholder:`Filter by title`,"aria-label":`Filter by title`,value:c,onInput:e=>l(e.currentTarget.value)}),o!==`trash`&&F(S,{children:[F(`button`,{onClick:()=>C.current?.click(),disabled:g!==null,children:`Add files`}),F(`input`,{ref:C,type:`file`,multiple:!0,hidden:!0,accept:`.stl,.3mf,.step,.stp,.obj,.zip`,onChange:e=>{let t=Array.from(e.currentTarget.files??[]);e.currentTarget.value=``,ee(t)}}),i&&u.length>0&&F(`a`,{class:`button`,href:N.exportUrl(i,o===`all`?void 0:o),title:`Download the current version of every item in this view as one ZIP`,children:`Export ZIP`})]})]}),g!==null&&F(`div`,{class:`progress`,role:`progressbar`,"aria-valuenow":Math.round(g*100),"aria-valuemin":0,"aria-valuemax":100,children:F(`div`,{style:{width:`${Math.round(g*100)}%`}})}),u.length===0&&F(`p`,{class:`empty`,children:o===`trash`?`The trash is empty.`:c?`Nothing matches the filter.`:`Nothing ${o===`all`?``:o} here yet.`}),F(vr,{events:b,onResolved:()=>{h(e=>e+1),D()}}),F(hr,{items:u,onSend:e?.bambuddy?O:void 0,selectedId:f,editable:o!==`trash`,onSelect:p,onStatus:ne,onReorder:re,onRestore:e=>N.restoreItem(e.id).then(()=>{I(`"${e.title}" restored`,`ok`),D()}).catch(e=>I(P(e),`error`)),onDropFiles:te})]}),f!==null&&F(at,{itemId:f,queues:n,revision:m,onClose:()=>p(null),onChanged:D,onUploadVersion:(e,t)=>void k(e,t),bambuddy:e?.bambuddy??!1})]}),F(nt,{})]})},{}),document.getElementById(`app`));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
:root{--bg:#f8fafc;--surface:#fff;--fg:#0f172a;--muted:#64748b;--line:#e2e8f0;--accent:#2563eb;--accent-soft:#dbeafe;--danger:#dc2626;--queued:#2563eb;--skipped:#64748b;--done:#16a34a;--error:#dc2626;--warn:#d97706;--radius:8px;color:var(--fg);background:var(--bg);font-family:system-ui,-apple-system,Segoe UI,sans-serif;font-size:15px}@media (prefers-color-scheme:dark){:root{--bg:#0b1120;--surface:#111a2e;--fg:#e2e8f0;--muted:#94a3b8;--line:#1e293b;--accent:#60a5fa;--accent-soft:#1e3a5f;--danger:#f87171;--queued:#60a5fa;--skipped:#94a3b8;--done:#4ade80;--error:#f87171;--warn:#fbbf24}}*{box-sizing:border-box}body{background:var(--bg);margin:0}h1{margin:0;font-size:1.15rem}h2{overflow-wrap:anywhere;margin:0;font-size:1.1rem}h3{margin:1rem 0 .5rem;font-size:.95rem}a{color:var(--accent)}.muted{color:var(--muted);font-size:.85rem}button,.button,select,input,textarea{font:inherit;color:inherit}button,.button{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);cursor:pointer;white-space:nowrap;padding:.4rem .8rem;text-decoration:none}button:hover,.button:hover{border-color:var(--accent)}button:disabled{opacity:.5;cursor:default}button.small{padding:.2rem .6rem;font-size:.85rem}button.icon,a.icon{background:0 0;border:none;padding:.2rem .4rem;font-size:1.1rem;text-decoration:none}button.danger{color:var(--danger);border-color:var(--danger)}input,select,textarea{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);max-width:100%;padding:.35rem .5rem}:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.top{justify-content:space-between;align-items:baseline;padding:.8rem 1rem .4rem;display:flex}.queuebar{border-bottom:1px solid var(--line);flex-wrap:wrap;align-items:center;gap:.5rem;padding:0 1rem;display:flex}.tabs{gap:.2rem;display:flex;overflow-x:auto}.tab{background:0 0;border:none;border-bottom:2px solid #0000;border-radius:0;padding:.5rem .7rem}.tab.active{border-bottom-color:var(--accent);font-weight:600}.tabs-select{display:none}.count{color:var(--muted);margin-left:.35rem;font-size:.75rem}.inline-form{gap:.3rem;display:flex}.settings{margin-left:auto;position:relative}.menu{z-index:10;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);gap:.6rem;min-width:17rem;padding:.7rem;display:grid;position:absolute;top:100%;right:0;box-shadow:0 8px 24px #00000026}.check{align-items:center;gap:.4rem;font-size:.9rem;display:flex}.layout{grid-template-columns:minmax(0,1fr);max-width:80rem;margin:0 auto;display:grid}.layout.with-panel{grid-template-columns:minmax(0,1fr) minmax(20rem,26rem)}main{min-width:0;padding:.8rem 1rem 2rem}.toolbar{flex-wrap:wrap;align-items:center;gap:.5rem;margin-bottom:.7rem;display:flex}.views{flex-wrap:wrap;gap:.3rem;display:flex}.search{flex:10rem;min-width:8rem}.chip{border-radius:999px;padding:.2rem .7rem;font-size:.85rem}.chip.active{background:var(--accent-soft);border-color:var(--accent)}.chip.status-queued.active{border-color:var(--queued)}.chip.status-done.active{border-color:var(--done)}.chip.status-skipped.active{border-color:var(--skipped)}.chip.status-error.active{border-color:var(--error)}.progress{background:var(--line);border-radius:2px;height:4px;margin-bottom:.6rem;overflow:hidden}.progress>div{background:var(--accent);height:100%;transition:width .15s}.empty{color:var(--muted);text-align:center;padding:1.5rem 0 .5rem}.list-wrap{border-radius:var(--radius);border:2px dashed #0000;transition:border-color .1s}.list-wrap.drop-list{border-color:var(--accent);background:var(--accent-soft)}.items{margin:0;padding:0;list-style:none}.item{background:var(--surface);border:1px solid var(--line);border-left:4px solid var(--queued);border-radius:var(--radius);cursor:pointer;align-items:center;gap:.6rem;margin-bottom:.35rem;padding:.45rem .5rem;display:flex}.item.status-done{border-left-color:var(--done)}.item.status-skipped{border-left-color:var(--skipped);opacity:.8}.item.status-error{border-left-color:var(--error)}.item.selected{outline:2px solid var(--accent)}.item.drop-row{outline:2px dashed var(--accent);background:var(--accent-soft)}.item.sortable-chosen{box-shadow:0 6px 18px #0000002e}.item.sortable-ghost{opacity:.35}.handle{cursor:grab;color:var(--muted);touch-action:none;-webkit-user-select:none;user-select:none;padding:0 .15rem;font-size:1.1rem}.thumb{object-fit:cover;background:var(--bg);border-radius:6px;flex:none;width:44px;height:44px}.thumb-ext{color:var(--muted);border:1px solid var(--line);place-items:center;font-size:.65rem;font-weight:700;display:grid}.title{flex-direction:column;flex:1;min-width:0;display:flex}.name{text-overflow:ellipsis;white-space:nowrap;font-weight:500;overflow:hidden}.meta{color:var(--muted);font-size:.8rem}.badge{border:1px solid var(--line);color:var(--muted);border-radius:999px;margin-left:.4rem;padding:0 .4rem;font-size:.7rem;display:inline-block}.badge.warn{border-color:var(--warn);color:var(--warn)}select.status{padding:.2rem .3rem;font-size:.85rem}select.status-queued{color:var(--queued)}select.status-done{color:var(--done)}select.status-skipped{color:var(--skipped)}select.status-error{color:var(--error)}.dropzone{text-align:center;color:var(--muted);border:1px dashed var(--line);border-radius:var(--radius);margin:.3rem 0 0;padding:1rem .5rem;font-size:.85rem}.panel{border-left:1px solid var(--line);background:var(--surface);min-width:0;max-height:100vh;padding:.8rem 1rem 2rem;position:sticky;top:0;overflow-y:auto}.panel-head,.section-head{justify-content:space-between;align-items:center;gap:.5rem;display:flex}.section-head h3{margin-right:auto}.preview{object-fit:contain;border-radius:var(--radius);background:var(--bg);width:100%;max-height:14rem;margin:.6rem 0}.field{gap:.25rem;margin:.6rem 0;display:grid}.field>span{color:var(--muted);font-size:.8rem}.field input,.field textarea,.field select{width:100%}.status-row{flex-wrap:wrap;gap:.3rem;display:flex}.reason,.source{font-size:.85rem}.versions,.history{margin:0;padding:0;list-style:none}.versions li{border:1px solid var(--line);border-radius:var(--radius);margin-bottom:.4rem;padding:.5rem .6rem}.versions li.current{border-color:var(--accent)}.version-head{overflow-wrap:anywhere}.row-actions{align-items:center;gap:.7rem;font-size:.85rem;display:flex}.history li{border-bottom:1px solid var(--line);padding:.25rem 0;font-size:.85rem}.history time{color:var(--muted)}.panel-foot{margin-top:1.2rem}.toasts{z-index:20;gap:.4rem;width:min(32rem,100vw - 2rem);display:grid;position:fixed;bottom:1rem;left:50%;transform:translate(-50%)}.toast{background:var(--surface);border:1px solid var(--line);border-left:4px solid var(--accent);border-radius:var(--radius);padding:.6rem .8rem;font-size:.9rem;box-shadow:0 6px 18px #00000026}.toast-ok{border-left-color:var(--done)}.toast-error{border-left-color:var(--error)}.fatal{color:var(--error);padding:2rem 1rem}@media (width<=760px){.tabs{display:none}.tabs-select{flex:1;margin:.4rem 0;display:block}.layout.with-panel{grid-template-columns:minmax(0,1fr)}.panel{z-index:15;border-left:none;max-height:none;position:fixed;inset:0}.meta .when{display:none}.settings{margin-left:0}.menu{min-width:min(17rem,100vw - 2rem);left:auto;right:0}}
|
|
1
|
+
:root{--bg:#f8fafc;--surface:#fff;--fg:#0f172a;--muted:#64748b;--line:#e2e8f0;--accent:#2563eb;--accent-soft:#dbeafe;--danger:#dc2626;--queued:#2563eb;--skipped:#64748b;--done:#16a34a;--error:#dc2626;--warn:#d97706;--radius:8px;color:var(--fg);background:var(--bg);font-family:system-ui,-apple-system,Segoe UI,sans-serif;font-size:15px}@media (prefers-color-scheme:dark){:root{--bg:#0b1120;--surface:#111a2e;--fg:#e2e8f0;--muted:#94a3b8;--line:#1e293b;--accent:#60a5fa;--accent-soft:#1e3a5f;--danger:#f87171;--queued:#60a5fa;--skipped:#94a3b8;--done:#4ade80;--error:#f87171;--warn:#fbbf24}}*{box-sizing:border-box}body{background:var(--bg);margin:0}h1{margin:0;font-size:1.15rem}h2{overflow-wrap:anywhere;margin:0;font-size:1.1rem}h3{margin:1rem 0 .5rem;font-size:.95rem}a{color:var(--accent)}.muted{color:var(--muted);font-size:.85rem}button,.button,select,input,textarea{font:inherit;color:inherit}button,.button{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);cursor:pointer;white-space:nowrap;padding:.4rem .8rem;text-decoration:none}button:hover,.button:hover{border-color:var(--accent)}button:disabled{opacity:.5;cursor:default}button.small{padding:.2rem .6rem;font-size:.85rem}button.icon,a.icon{background:0 0;border:none;padding:.2rem .4rem;font-size:1.1rem;text-decoration:none}button.danger{color:var(--danger);border-color:var(--danger)}input,select,textarea{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);max-width:100%;padding:.35rem .5rem}:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.top{justify-content:space-between;align-items:baseline;padding:.8rem 1rem .4rem;display:flex}.queuebar{border-bottom:1px solid var(--line);flex-wrap:wrap;align-items:center;gap:.5rem;padding:0 1rem;display:flex}.tabs{gap:.2rem;display:flex;overflow-x:auto}.tab{background:0 0;border:none;border-bottom:2px solid #0000;border-radius:0;padding:.5rem .7rem}.tab.active{border-bottom-color:var(--accent);font-weight:600}.tabs-select{display:none}.count{color:var(--muted);margin-left:.35rem;font-size:.75rem}.inline-form{gap:.3rem;display:flex}.settings{margin-left:auto;position:relative}.menu{z-index:10;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);gap:.6rem;min-width:17rem;padding:.7rem;display:grid;position:absolute;top:100%;right:0;box-shadow:0 8px 24px #00000026}.check{align-items:center;gap:.4rem;font-size:.9rem;display:flex}.layout{grid-template-columns:minmax(0,1fr);max-width:80rem;margin:0 auto;display:grid}.layout.with-panel{grid-template-columns:minmax(0,1fr) minmax(20rem,26rem)}main{min-width:0;padding:.8rem 1rem 2rem}.toolbar{flex-wrap:wrap;align-items:center;gap:.5rem;margin-bottom:.7rem;display:flex}.views{flex-wrap:wrap;gap:.3rem;display:flex}.search{flex:10rem;min-width:8rem}.chip{border-radius:999px;padding:.2rem .7rem;font-size:.85rem}.chip.active{background:var(--accent-soft);border-color:var(--accent)}.chip.status-queued.active{border-color:var(--queued)}.chip.status-done.active{border-color:var(--done)}.chip.status-skipped.active{border-color:var(--skipped)}.chip.status-error.active{border-color:var(--error)}.progress{background:var(--line);border-radius:2px;height:4px;margin-bottom:.6rem;overflow:hidden}.progress>div{background:var(--accent);height:100%;transition:width .15s}.empty{color:var(--muted);text-align:center;padding:1.5rem 0 .5rem}.list-wrap{border-radius:var(--radius);border:2px dashed #0000;transition:border-color .1s}.list-wrap.drop-list{border-color:var(--accent);background:var(--accent-soft)}.items{margin:0;padding:0;list-style:none}.item{background:var(--surface);border:1px solid var(--line);border-left:4px solid var(--queued);border-radius:var(--radius);cursor:pointer;align-items:center;gap:.6rem;margin-bottom:.35rem;padding:.45rem .5rem;display:flex}.item.status-done{border-left-color:var(--done)}.item.status-skipped{border-left-color:var(--skipped);opacity:.8}.item.status-error{border-left-color:var(--error)}.item.selected{outline:2px solid var(--accent)}.item.drop-row{outline:2px dashed var(--accent);background:var(--accent-soft)}.item.sortable-chosen{box-shadow:0 6px 18px #0000002e}.item.sortable-ghost{opacity:.35}.handle{cursor:grab;color:var(--muted);touch-action:none;-webkit-user-select:none;user-select:none;padding:0 .15rem;font-size:1.1rem}.thumb{object-fit:cover;background:var(--bg);border-radius:6px;flex:none;width:44px;height:44px}.thumb-ext{color:var(--muted);border:1px solid var(--line);place-items:center;font-size:.65rem;font-weight:700;display:grid}.title{flex-direction:column;flex:1;min-width:0;display:flex}.name{text-overflow:ellipsis;white-space:nowrap;font-weight:500;overflow:hidden}.meta{color:var(--muted);font-size:.8rem}.badge{border:1px solid var(--line);color:var(--muted);border-radius:999px;margin-left:.4rem;padding:0 .4rem;font-size:.7rem;display:inline-block}.badge.warn{border-color:var(--warn);color:var(--warn)}select.status{padding:.2rem .3rem;font-size:.85rem}select.status-queued{color:var(--queued)}select.status-done{color:var(--done)}select.status-skipped{color:var(--skipped)}select.status-error{color:var(--error)}.dropzone{text-align:center;color:var(--muted);border:1px dashed var(--line);border-radius:var(--radius);margin:.3rem 0 0;padding:1rem .5rem;font-size:.85rem}.panel{border-left:1px solid var(--line);background:var(--surface);min-width:0;max-height:100vh;padding:.8rem 1rem 2rem;position:sticky;top:0;overflow-y:auto}.panel-head,.section-head{justify-content:space-between;align-items:center;gap:.5rem;display:flex}.section-head h3{margin-right:auto}.preview{object-fit:contain;border-radius:var(--radius);background:var(--bg);width:100%;max-height:14rem;margin:.6rem 0}.field{gap:.25rem;margin:.6rem 0;display:grid}.field>span{color:var(--muted);font-size:.8rem}.field input,.field textarea,.field select{width:100%}.status-row{flex-wrap:wrap;gap:.3rem;display:flex}.reason,.source{font-size:.85rem}.versions,.history{margin:0;padding:0;list-style:none}.versions li{border:1px solid var(--line);border-radius:var(--radius);margin-bottom:.4rem;padding:.5rem .6rem}.versions li.current{border-color:var(--accent)}.version-head{overflow-wrap:anywhere}.row-actions{align-items:center;gap:.7rem;font-size:.85rem;display:flex}.history li{border-bottom:1px solid var(--line);padding:.25rem 0;font-size:.85rem}.history time{color:var(--muted)}.panel-foot{margin-top:1.2rem}.toasts{z-index:20;gap:.4rem;width:min(32rem,100vw - 2rem);display:grid;position:fixed;bottom:1rem;left:50%;transform:translate(-50%)}.toast{background:var(--surface);border:1px solid var(--line);border-left:4px solid var(--accent);border-radius:var(--radius);padding:.6rem .8rem;font-size:.9rem;box-shadow:0 6px 18px #00000026}.toast-ok{border-left-color:var(--done)}.toast-error{border-left-color:var(--error)}.fatal{color:var(--error);padding:2rem 1rem}@media (width<=760px){.tabs{display:none}.tabs-select{flex:1;margin:.4rem 0;display:block}.layout.with-panel{grid-template-columns:minmax(0,1fr)}.panel{z-index:15;border-left:none;max-height:none;position:fixed;inset:0}.meta .when{display:none}.settings{margin-left:0}.menu{min-width:min(17rem,100vw - 2rem);left:auto;right:0}}.send{align-items:center;gap:.6rem;margin:.8rem 0;display:flex}.unmatched{border:1px solid var(--warn);border-radius:var(--radius);background:var(--surface);margin-bottom:.7rem}.unmatched-head{text-align:left;width:100%;color:var(--warn);background:0 0;border:none;font-weight:600}.events{margin:0;padding:0 .6rem .4rem;list-style:none}.event{border-top:1px solid var(--line);gap:.4rem;padding:.5rem 0;display:grid}.event-print_failed b{color:var(--error)}.event-actions{flex-wrap:wrap;align-items:center;gap:.4rem;display:flex}.event-actions select{max-width:16rem;font-size:.85rem}.title .badge{align-self:flex-start;margin-left:0}
|
package/dist/public/index.html
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
<meta name="color-scheme" content="light dark" />
|
|
7
7
|
<title>Print Backlog</title>
|
|
8
8
|
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
|
9
|
-
<script type="module" crossorigin src="/assets/index-
|
|
10
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-C4BbRvDB.js"></script>
|
|
10
|
+
<link rel="stylesheet" crossorigin href="/assets/index-D7yzmKDn.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
|
13
13
|
<div id="app"></div>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { HookAck, PrintEventView } from "../../shared/types.js";
|
|
2
|
+
import type { Sql } from "../db.js";
|
|
3
|
+
import { type Ctx } from "../http.js";
|
|
4
|
+
/**
|
|
5
|
+
* POST /hooks/bambuddy: store the event, then match it (docs/plan.md §3.9).
|
|
6
|
+
* - print_complete → done, print_failed → error, on exactly one `queued`
|
|
7
|
+
* item (in a queue with auto status) whose title or file name matches.
|
|
8
|
+
* - Several matches: left open, the candidates get the "printed?" badge.
|
|
9
|
+
* - No match: left open (Unmatched prints).
|
|
10
|
+
* - print_stopped and any other event: stored, ignored.
|
|
11
|
+
*/
|
|
12
|
+
export declare const bambuddyHook: (sql: Sql) => ({ body }: Ctx) => Promise<HookAck>;
|
|
13
|
+
/** GET /api/v1/print-events?open=1 (default): open events with candidates; open=0: the last 100 of all. */
|
|
14
|
+
export declare const listEvents: (sql: Sql) => ({ url }: Ctx) => Promise<PrintEventView[]>;
|
|
15
|
+
/**
|
|
16
|
+
* POST /api/v1/print-events/:id/assign: a person resolves an open event,
|
|
17
|
+
* either as one item (its status follows the event, as an automatic match
|
|
18
|
+
* would; recorded with the person's name) or as nothing of ours.
|
|
19
|
+
*/
|
|
20
|
+
export declare const assignEvent: (sql: Sql) => ({ params, body, user }: Ctx) => Promise<PrintEventView>;
|
|
21
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/server/api/events.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,OAAO,EAEP,cAAc,EACf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,KAAK,GAAG,EAAa,MAAM,YAAY,CAAC;AA+GjD;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,GACtB,KAAK,GAAG,MACF,UAAU,GAAG,KAAG,OAAO,CAAC,OAAO,CAsCrC,CAAC;AA6CJ,2GAA2G;AAC3G,eAAO,MAAM,UAAU,GACpB,KAAK,GAAG,MACF,SAAS,GAAG,KAAG,OAAO,CAAC,cAAc,EAAE,CAW7C,CAAC;AAOJ;;;;GAIG;AACH,eAAO,MAAM,WAAW,GACrB,KAAK,GAAG,MACF,wBAAwB,GAAG,KAAG,OAAO,CAAC,cAAc,CA2C1D,CAAC"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { HttpError } from "../http.js";
|
|
3
|
+
import { eventDetail, matchCandidates, statusForEvent, } from "../matching.js";
|
|
4
|
+
/**
|
|
5
|
+
* Bambuddy's "Webhook" notification provider, payload format "generic":
|
|
6
|
+
* {title, message, timestamp, source, event, printer, filename, status?,
|
|
7
|
+
* duration?, filament_grams?, reason?, …}. Only the fields the matching needs
|
|
8
|
+
* are typed; the whole payload is kept as it came.
|
|
9
|
+
*/
|
|
10
|
+
const payloadSchema = z
|
|
11
|
+
.object({
|
|
12
|
+
event: z.string().min(1).max(100),
|
|
13
|
+
filename: z.string().max(1000).optional(),
|
|
14
|
+
printer: z.string().max(200).optional(),
|
|
15
|
+
status: z.string().max(100).optional(),
|
|
16
|
+
})
|
|
17
|
+
.loose();
|
|
18
|
+
/**
|
|
19
|
+
* Items a print could be: not in the trash, with every version's file name.
|
|
20
|
+
* `autoOnly`: only `queued` items in queues with auto_status on (the
|
|
21
|
+
* automatic match); otherwise any status, any queue (offered to a person).
|
|
22
|
+
*/
|
|
23
|
+
const loadCandidates = async (db, autoOnly) => {
|
|
24
|
+
const rows = await db `
|
|
25
|
+
SELECT i.id, i.title, i.queue_id, q.name AS queue_name, i.status::text AS status,
|
|
26
|
+
coalesce(array_agg(v.filename) FILTER (WHERE v.id IS NOT NULL), '{}') AS filenames,
|
|
27
|
+
max(v.filename) FILTER (WHERE v.id = i.current_version_id) AS current_filename
|
|
28
|
+
FROM backlog.item i
|
|
29
|
+
JOIN backlog.queue q ON q.id = i.queue_id
|
|
30
|
+
LEFT JOIN backlog.version v ON v.item_id = i.id
|
|
31
|
+
WHERE i.deleted_at IS NULL
|
|
32
|
+
${autoOnly ? db `AND i.status = 'queued' AND q.auto_status` : db ``}
|
|
33
|
+
GROUP BY i.id, q.name
|
|
34
|
+
ORDER BY i.id
|
|
35
|
+
`;
|
|
36
|
+
return rows.map((r) => ({
|
|
37
|
+
id: Number(r.id),
|
|
38
|
+
title: r.title,
|
|
39
|
+
queueId: Number(r.queue_id),
|
|
40
|
+
queueName: r.queue_name,
|
|
41
|
+
status: r.status,
|
|
42
|
+
filenames: r.filenames,
|
|
43
|
+
filename: r.current_filename,
|
|
44
|
+
}));
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Apply a print to an item: the status the event sets (if any and if
|
|
48
|
+
* different), recorded in the history with the print's details. Locks the
|
|
49
|
+
* item row. Returns false when the item is gone or in the trash.
|
|
50
|
+
*/
|
|
51
|
+
const applyToItem = async (tx, itemId, event, payload, by, extra = {}) => {
|
|
52
|
+
const [item] = await tx `
|
|
53
|
+
SELECT status::text AS status, deleted_at FROM backlog.item WHERE id = ${itemId} FOR UPDATE
|
|
54
|
+
`;
|
|
55
|
+
if (!item || item.deleted_at)
|
|
56
|
+
return false;
|
|
57
|
+
const to = statusForEvent(event);
|
|
58
|
+
if (to && to !== item.status) {
|
|
59
|
+
await tx `
|
|
60
|
+
UPDATE backlog.item
|
|
61
|
+
SET status = ${to}::text::backlog.item_status, status_changed_at = now(), needs_confirm = false
|
|
62
|
+
WHERE id = ${itemId}
|
|
63
|
+
`;
|
|
64
|
+
await tx `
|
|
65
|
+
INSERT INTO backlog.status_event (item_id, from_status, to_status, by, source, detail)
|
|
66
|
+
VALUES (${itemId}, ${item.status}::text::backlog.item_status, ${to}::text::backlog.item_status, ${by}, 'webhook',
|
|
67
|
+
${tx.json({ event, ...eventDetail(payload), ...extra })})
|
|
68
|
+
`;
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
await tx `UPDATE backlog.item SET needs_confirm = false WHERE id = ${itemId}`;
|
|
72
|
+
}
|
|
73
|
+
return true;
|
|
74
|
+
};
|
|
75
|
+
/** Clear the "printed?" badge of the items that were candidates of a resolved event. */
|
|
76
|
+
const clearConfirm = async (tx, filename) => {
|
|
77
|
+
const ids = matchCandidates(filename, await loadCandidates(tx, true)).map((c) => c.id);
|
|
78
|
+
if (ids.length)
|
|
79
|
+
await tx `UPDATE backlog.item SET needs_confirm = false WHERE id IN ${tx(ids)}`;
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* POST /hooks/bambuddy: store the event, then match it (docs/plan.md §3.9).
|
|
83
|
+
* - print_complete → done, print_failed → error, on exactly one `queued`
|
|
84
|
+
* item (in a queue with auto status) whose title or file name matches.
|
|
85
|
+
* - Several matches: left open, the candidates get the "printed?" badge.
|
|
86
|
+
* - No match: left open (Unmatched prints).
|
|
87
|
+
* - print_stopped and any other event: stored, ignored.
|
|
88
|
+
*/
|
|
89
|
+
export const bambuddyHook = (sql) => async ({ body }) => {
|
|
90
|
+
const p = payloadSchema.parse(body);
|
|
91
|
+
const payload = body;
|
|
92
|
+
return sql.begin(async (tx) => {
|
|
93
|
+
const [row] = await tx `
|
|
94
|
+
INSERT INTO backlog.print_event (event, filename, printer, status, payload)
|
|
95
|
+
VALUES (${p.event}, ${p.filename ?? null}, ${p.printer ?? null}, ${p.status ?? null}, ${tx.json(payload)})
|
|
96
|
+
RETURNING id
|
|
97
|
+
`;
|
|
98
|
+
const id = Number(row.id);
|
|
99
|
+
const ignore = async () => {
|
|
100
|
+
await tx `UPDATE backlog.print_event SET resolution = 'ignored' WHERE id = ${id}`;
|
|
101
|
+
return { stored: true, id, resolution: "ignored", matchedItemId: null };
|
|
102
|
+
};
|
|
103
|
+
if (statusForEvent(p.event) === null)
|
|
104
|
+
return ignore();
|
|
105
|
+
const matches = matchCandidates(p.filename, await loadCandidates(tx, true));
|
|
106
|
+
if (matches.length === 1 &&
|
|
107
|
+
(await applyToItem(tx, matches[0].id, p.event, payload, "bambuddy"))) {
|
|
108
|
+
await tx `
|
|
109
|
+
UPDATE backlog.print_event SET matched_item_id = ${matches[0].id}, resolution = 'auto' WHERE id = ${id}
|
|
110
|
+
`;
|
|
111
|
+
return {
|
|
112
|
+
stored: true,
|
|
113
|
+
id,
|
|
114
|
+
resolution: "auto",
|
|
115
|
+
matchedItemId: matches[0].id,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
if (matches.length > 1)
|
|
119
|
+
await tx `UPDATE backlog.item SET needs_confirm = true WHERE id IN ${tx(matches.map((m) => m.id))}`;
|
|
120
|
+
return { stored: true, id, resolution: null, matchedItemId: null };
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
const toViews = async (db, rows) => {
|
|
124
|
+
const all = rows.some((r) => r.resolution === null)
|
|
125
|
+
? await loadCandidates(db, false)
|
|
126
|
+
: [];
|
|
127
|
+
return rows.map((r) => ({
|
|
128
|
+
id: Number(r.id),
|
|
129
|
+
receivedAt: r.received_at.toISOString(),
|
|
130
|
+
event: r.event,
|
|
131
|
+
filename: r.filename,
|
|
132
|
+
printer: r.printer,
|
|
133
|
+
status: r.status,
|
|
134
|
+
resolution: r.resolution,
|
|
135
|
+
matchedItemId: r.matched_item_id === null ? null : Number(r.matched_item_id),
|
|
136
|
+
candidates: r.resolution === null
|
|
137
|
+
? matchCandidates(r.filename, all).map(({ id, title, queueId, queueName, status, filename }) => ({
|
|
138
|
+
id,
|
|
139
|
+
title,
|
|
140
|
+
queueId,
|
|
141
|
+
queueName,
|
|
142
|
+
status,
|
|
143
|
+
filename,
|
|
144
|
+
}))
|
|
145
|
+
: [],
|
|
146
|
+
}));
|
|
147
|
+
};
|
|
148
|
+
const listQuery = z.object({ open: z.enum(["0", "1"]).optional() });
|
|
149
|
+
/** GET /api/v1/print-events?open=1 (default): open events with candidates; open=0: the last 100 of all. */
|
|
150
|
+
export const listEvents = (sql) => async ({ url }) => {
|
|
151
|
+
const open = listQuery.parse(Object.fromEntries(url.searchParams)).open !== "0";
|
|
152
|
+
const rows = await sql `
|
|
153
|
+
SELECT id, received_at, event, filename, printer, status, resolution, matched_item_id
|
|
154
|
+
FROM backlog.print_event
|
|
155
|
+
${open ? sql `WHERE resolution IS NULL` : sql ``}
|
|
156
|
+
ORDER BY received_at DESC, id DESC
|
|
157
|
+
LIMIT 100
|
|
158
|
+
`;
|
|
159
|
+
return toViews(sql, rows);
|
|
160
|
+
};
|
|
161
|
+
const assignBody = z.union([
|
|
162
|
+
z.object({ itemId: z.number().int().positive() }).strict(),
|
|
163
|
+
z.object({ ignore: z.literal(true) }).strict(),
|
|
164
|
+
]);
|
|
165
|
+
/**
|
|
166
|
+
* POST /api/v1/print-events/:id/assign: a person resolves an open event,
|
|
167
|
+
* either as one item (its status follows the event, as an automatic match
|
|
168
|
+
* would; recorded with the person's name) or as nothing of ours.
|
|
169
|
+
*/
|
|
170
|
+
export const assignEvent = (sql) => async ({ params, body, user }) => {
|
|
171
|
+
const id = Number(params.id);
|
|
172
|
+
if (!Number.isSafeInteger(id) || id <= 0)
|
|
173
|
+
throw new HttpError(400, "bad event id");
|
|
174
|
+
const a = assignBody.parse(body);
|
|
175
|
+
await sql.begin(async (tx) => {
|
|
176
|
+
const [ev] = await tx `
|
|
177
|
+
SELECT event, filename, payload, resolution FROM backlog.print_event WHERE id = ${id} FOR UPDATE
|
|
178
|
+
`;
|
|
179
|
+
if (!ev)
|
|
180
|
+
throw new HttpError(404, `print event ${id} not found`);
|
|
181
|
+
if (ev.resolution !== null)
|
|
182
|
+
throw new HttpError(409, `print event ${id} is already resolved (${ev.resolution})`);
|
|
183
|
+
if ("ignore" in a) {
|
|
184
|
+
await tx `UPDATE backlog.print_event SET resolution = 'ignored' WHERE id = ${id}`;
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
if (!(await applyToItem(tx, a.itemId, ev.event, ev.payload, user, {
|
|
188
|
+
assigned: true,
|
|
189
|
+
})))
|
|
190
|
+
throw new HttpError(404, `item ${a.itemId} not found (or in the trash)`);
|
|
191
|
+
await tx `UPDATE backlog.print_event SET matched_item_id = ${a.itemId}, resolution = 'manual' WHERE id = ${id}`;
|
|
192
|
+
}
|
|
193
|
+
await clearConfirm(tx, ev.filename);
|
|
194
|
+
});
|
|
195
|
+
const rows = await sql `
|
|
196
|
+
SELECT id, received_at, event, filename, printer, status, resolution, matched_item_id
|
|
197
|
+
FROM backlog.print_event WHERE id = ${id}
|
|
198
|
+
`;
|
|
199
|
+
return (await toViews(sql, rows))[0];
|
|
200
|
+
};
|
|
201
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../../src/server/api/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
-
import { type HistoryEntry, type Item, type ItemDetail, type UploadResult, type VersionUploadResult } from "../../shared/types.js";
|
|
1
|
+
import { type HistoryEntry, type Item, type ItemDetail, type SendResult, type UploadResult, type VersionUploadResult } from "../../shared/types.js";
|
|
2
2
|
import type { Sql } from "../db.js";
|
|
3
|
+
import { type BambuddyClient } from "../bambuddy.js";
|
|
3
4
|
import { type Ctx, HANDLED } from "../http.js";
|
|
4
5
|
import { FileStore } from "../storage.js";
|
|
5
6
|
export interface ItemsDeps {
|
|
6
7
|
sql: Sql;
|
|
7
8
|
store: FileStore;
|
|
9
|
+
/** Send to Bambuddy; null when BAMBUDDY_URL is not set */
|
|
10
|
+
sender?: {
|
|
11
|
+
client: BambuddyClient;
|
|
12
|
+
folder: string;
|
|
13
|
+
} | null;
|
|
8
14
|
}
|
|
9
15
|
/** GET /api/v1/items?queue=&status=&q=&trash=1 */
|
|
10
16
|
export declare const listItems: ({ sql }: ItemsDeps) => ({ url }: Ctx) => Promise<Item[]>;
|
|
@@ -46,4 +52,11 @@ export declare const versionThumbnail: ({ sql, store }: ItemsDeps) => ({ params,
|
|
|
46
52
|
* while it is sent. Items whose file is missing on disk are left out.
|
|
47
53
|
*/
|
|
48
54
|
export declare const exportQueue: ({ sql, store }: ItemsDeps) => ({ params, url, res, req }: Ctx) => Promise<typeof HANDLED>;
|
|
55
|
+
/**
|
|
56
|
+
* POST /api/v1/items/:id/send-to-bambuddy: upload the current version into
|
|
57
|
+
* Bambuddy's library folder (BAMBUDDY_FOLDER, created if missing). Bambuddy
|
|
58
|
+
* keeps one copy of identical content and says so (`duplicate`). Sending
|
|
59
|
+
* again uploads again. STEP is refused: Bambuddy cannot take it.
|
|
60
|
+
*/
|
|
61
|
+
export declare const sendToBambuddy: ({ sql, store, sender }: ItemsDeps) => ({ params }: Ctx) => Promise<SendResult>;
|
|
49
62
|
//# sourceMappingURL=items.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"items.d.ts","sourceRoot":"","sources":["../../../src/server/api/items.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,IAAI,EACT,KAAK,UAAU,EAEf,KAAK,YAAY,EAEjB,KAAK,mBAAmB,EACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,KAAK,GAAG,EAAE,OAAO,EAAa,MAAM,YAAY,CAAC;AAG1D,OAAO,EAEL,SAAS,EAKV,MAAM,eAAe,CAAC;AAWvB,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,GAAG,CAAC;IACT,KAAK,EAAE,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"items.d.ts","sourceRoot":"","sources":["../../../src/server/api/items.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,IAAI,EACT,KAAK,UAAU,EAEf,KAAK,UAAU,EACf,KAAK,YAAY,EAEjB,KAAK,mBAAmB,EACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,OAAO,EAAE,KAAK,cAAc,EAAiB,MAAM,gBAAgB,CAAC;AACpE,OAAO,EAAE,KAAK,GAAG,EAAE,OAAO,EAAa,MAAM,YAAY,CAAC;AAG1D,OAAO,EAEL,SAAS,EAKV,MAAM,eAAe,CAAC;AAWvB,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,GAAG,CAAC;IACT,KAAK,EAAE,SAAS,CAAC;IACjB,0DAA0D;IAC1D,MAAM,CAAC,EAAE;QAAE,MAAM,EAAE,cAAc,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC5D;AA4JD,kDAAkD;AAClD,eAAO,MAAM,SAAS,GACnB,SAAS,SAAS,MACZ,SAAS,GAAG,KAAG,OAAO,CAAC,IAAI,EAAE,CAgBnC,CAAC;AAEJ,4BAA4B;AAC5B,eAAO,MAAM,OAAO,GACjB,SAAS,SAAS,MAClB,YAAY,GAAG,KAAG,OAAO,CAAC,UAAU,CACA,CAAC;AAExC,gGAAgG;AAChG,eAAO,MAAM,WAAW,GACrB,SAAS,SAAS,MACZ,YAAY,GAAG,KAAG,OAAO,CAAC,YAAY,EAAE,CA4E9C,CAAC;AAmCJ,mEAAmE;AACnE,eAAO,MAAM,aAAa,GAAI,KAAK,MAAM,KAAG,MAA4B,CAAC;AA2DzE;;;;GAIG;AACH,eAAO,MAAM,WAAW,GACrB,gBAAgB,SAAS,MACnB,uBAAuB,GAAG,KAAG,OAAO,CAAC,YAAY,CAmDvD,CAAC;AAEJ;;;;GAIG;AACH,eAAO,MAAM,aAAa,GACvB,gBAAgB,SAAS,MACnB,uBAAuB,GAAG,KAAG,OAAO,CAAC,mBAAmB,CA8C9D,CAAC;AASJ,wFAAwF;AACxF,eAAO,MAAM,YAAY,GACtB,SAAS,SAAS,MACZ,kBAAkB,GAAG,KAAG,OAAO,CAAC,UAAU,CAgBhD,CAAC;AAEJ,oFAAoF;AACpF,eAAO,MAAM,eAAe,GACzB,gBAAgB,SAAS,MACnB,sBAAsB,GAAG,KAAG,OAAO,CAAC,OAAO,OAAO,CAgCxD,CAAC;AAEJ,kEAAkE;AAClE,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,KAAG,MAGrD,CAAC;AAmBF,2FAA2F;AAC3F,eAAO,MAAM,SAAS,GACnB,SAAS,SAAS,MACZ,wBAAwB,GAAG,KAAG,OAAO,CAAC,UAAU,CAuCtD,CAAC;AAEJ,oFAAoF;AACpF,eAAO,MAAM,UAAU,GACpB,SAAS,SAAS,MACZ,YAAY,GAAG,KAAG,OAAO,CAAC,IAAI,CAOpC,CAAC;AAEJ,oFAAoF;AACpF,eAAO,MAAM,WAAW,GACrB,SAAS,SAAS,MACZ,YAAY,GAAG,KAAG,OAAO,CAAC,IAAI,CAmBpC,CAAC;AAEJ,kFAAkF;AAClF,eAAO,MAAM,gBAAgB,GAC1B,gBAAgB,SAAS,MACnB,sBAAsB,GAAG,KAAG,OAAO,CAAC,OAAO,OAAO,CA0BxD,CAAC;AAMJ;;;;GAIG;AACH,eAAO,MAAM,WAAW,GACrB,gBAAgB,SAAS,MACnB,2BAA2B,GAAG,KAAG,OAAO,CAAC,OAAO,OAAO,CAmD7D,CAAC;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GACxB,wBAAwB,SAAS,MAC3B,YAAY,GAAG,KAAG,OAAO,CAAC,UAAU,CA4B1C,CAAC"}
|
package/dist/server/api/items.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { ITEM_STATUSES, } from "../../shared/types.js";
|
|
3
|
+
import { BambuddyError } from "../bambuddy.js";
|
|
3
4
|
import { HANDLED, HttpError } from "../http.js";
|
|
4
5
|
import { MAX_FILES, readMultipart } from "../multipart.js";
|
|
5
6
|
import { itemPosition } from "../positions.js";
|
|
@@ -124,7 +125,7 @@ export const getItem = ({ sql }) => ({ params }) => loadDetail(sql, idParam(para
|
|
|
124
125
|
/** GET /api/v1/items/:id/history: status changes, versions and matched prints, oldest first. */
|
|
125
126
|
export const itemHistory = ({ sql }) => async ({ params }) => {
|
|
126
127
|
const id = idParam(params.id);
|
|
127
|
-
await loadItem(sql, id);
|
|
128
|
+
const item = await loadItem(sql, id);
|
|
128
129
|
const [statuses, versions, prints] = await Promise.all([
|
|
129
130
|
sql `
|
|
130
131
|
SELECT at, by, source, from_status::text AS from_status, to_status::text AS to_status, detail
|
|
@@ -162,6 +163,16 @@ export const itemHistory = ({ sql }) => async ({ params }) => {
|
|
|
162
163
|
filename: p.filename,
|
|
163
164
|
resolution: p.resolution,
|
|
164
165
|
})),
|
|
166
|
+
// Only the last send is kept (bambuddy_sent_at).
|
|
167
|
+
...(item.bambuddySentAt && item.bambuddyFileId !== null
|
|
168
|
+
? [
|
|
169
|
+
{
|
|
170
|
+
kind: "sent",
|
|
171
|
+
at: item.bambuddySentAt,
|
|
172
|
+
fileId: item.bambuddyFileId,
|
|
173
|
+
},
|
|
174
|
+
]
|
|
175
|
+
: []),
|
|
165
176
|
];
|
|
166
177
|
return entries.sort((a, b) => a.at.localeCompare(b.at));
|
|
167
178
|
};
|
|
@@ -549,4 +560,41 @@ export const exportQueue = ({ sql, store }) => async ({ params, url, res, req })
|
|
|
549
560
|
});
|
|
550
561
|
return HANDLED;
|
|
551
562
|
};
|
|
563
|
+
/**
|
|
564
|
+
* POST /api/v1/items/:id/send-to-bambuddy: upload the current version into
|
|
565
|
+
* Bambuddy's library folder (BAMBUDDY_FOLDER, created if missing). Bambuddy
|
|
566
|
+
* keeps one copy of identical content and says so (`duplicate`). Sending
|
|
567
|
+
* again uploads again. STEP is refused: Bambuddy cannot take it.
|
|
568
|
+
*/
|
|
569
|
+
export const sendToBambuddy = ({ sql, store, sender }) => async ({ params }) => {
|
|
570
|
+
if (!sender)
|
|
571
|
+
throw new HttpError(409, "Send to Bambuddy is not configured (BAMBUDDY_URL)");
|
|
572
|
+
const id = idParam(params.id);
|
|
573
|
+
const item = await loadItem(sql, id);
|
|
574
|
+
if (item.deletedAt)
|
|
575
|
+
throw new HttpError(409, `item ${id} is in the trash`);
|
|
576
|
+
if (!item.current)
|
|
577
|
+
throw new HttpError(409, `item ${id} has no file`);
|
|
578
|
+
if (!item.sendable)
|
|
579
|
+
throw new HttpError(400, `.${item.current.ext} cannot be sent to Bambuddy (it slices STL, 3MF and OBJ)`);
|
|
580
|
+
const [v] = await sql `
|
|
581
|
+
SELECT stored_path FROM backlog.version WHERE item_id = ${id} AND n = ${item.current.n}
|
|
582
|
+
`;
|
|
583
|
+
if (!v || !(await store.exists(v.stored_path)))
|
|
584
|
+
throw new HttpError(410, "the file is missing on disk");
|
|
585
|
+
const folderId = await sender.client
|
|
586
|
+
.folderId(sender.folder)
|
|
587
|
+
.catch(upstream);
|
|
588
|
+
const r = await sender.client
|
|
589
|
+
.upload(store.absolute(v.stored_path), item.current.filename, folderId)
|
|
590
|
+
.catch(upstream);
|
|
591
|
+
await sql `UPDATE backlog.item SET bambuddy_file_id = ${r.fileId}, bambuddy_sent_at = now() WHERE id = ${id}`;
|
|
592
|
+
return { item: await loadDetail(sql, id), duplicate: r.duplicate };
|
|
593
|
+
};
|
|
594
|
+
/** A Bambuddy failure as our answer: 502 with Bambuddy's message. */
|
|
595
|
+
const upstream = (e) => {
|
|
596
|
+
if (e instanceof BambuddyError)
|
|
597
|
+
throw new HttpError(e.status, e.message);
|
|
598
|
+
throw e;
|
|
599
|
+
};
|
|
552
600
|
//# sourceMappingURL=items.js.map
|