diff --git a/CHANGES.rst b/CHANGES.rst index 9b5624647c..f2a2ecf0b5 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,7 @@ Changelog 2.3.0 (unreleased) ------------------ +- #2137 Dynamic Workflow Menu - #2139 Fix LabClerk cannot create partitions from received samples - #2130 Catalog mapping for Samples and Analyses - #2131 Allow to edit the analysis service sort keys in the services listing diff --git a/src/senaite/core/browser/contentmenu/configure.zcml b/src/senaite/core/browser/contentmenu/configure.zcml index a85ae435fd..222e5108fb 100644 --- a/src/senaite/core/browser/contentmenu/configure.zcml +++ b/src/senaite/core/browser/contentmenu/configure.zcml @@ -3,6 +3,16 @@ xmlns:five="http://namespaces.zope.org/five" i18n_domain="plone"> + + + {"use strict";var e={559:e=>{e.exports=jQuery}},t={};function n(r){var o=t[r];if(void 0!==o)return o.exports;var i=t[r]={exports:{}};return e[r](i,i.exports,n),i.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e=n(559),t=n.n(e);const r=function(){var e=this;e.baseUrl=t()("body").attr("data-i18ncatalogurl"),e.currentLanguage=t()("html").attr("lang")||"en",e.currentLanguage.split("-").length>1&&(e.currentLanguage=e.currentLanguage.split("-")[0]+"_"+e.currentLanguage.split("-")[1].toUpperCase()),e.storage=null,e.catalogs={},e.ttl=864e5,Date.now||(Date.now=function(){return(new Date).valueOf()});try{"localStorage"in window&&null!==window.localStorage&&"JSON"in window&&null!==window.JSON&&(e.storage=window.localStorage)}catch(e){}e.configure=function(t){for(var n in t)e[n]=t[n]},e._setCatalog=function(t,n,r){t in e.catalogs||(e.catalogs[t]={}),e.catalogs[t][n]=r},e._storeCatalog=function(t,n,r){var o=t+"-"+n;null!==e.storage&&null!==r&&(e.storage.setItem(o,JSON.stringify(r)),e.storage.setItem(o+"-updated",Date.now()))},e.getUrl=function(t,n){return e.baseUrl+"?domain="+t+"&language="+n},e.loadCatalog=function(n,r){if(void 0===r&&(r=e.currentLanguage),null!==e.storage){var o=n+"-"+r;if(o in e.storage&&Date.now()-parseInt(e.storage.getItem(o+"-updated"),10)=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function b(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=g(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0,o=function(){};return{s:o,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){s=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw i}}}}function g(e,t){if(e){if("string"==typeof e)return w(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?w(e,t):void 0}}function w(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n1&&void 0!==arguments[1])||arguments[1],n=e.closest(".field"),r="d-none";!1===t?n.classList.add(r):n.classList.remove(r)}},{key:"has_field_errors",value:function(e){return e.querySelectorAll(".is-invalid").length>0}},{key:"set_field_readonly",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;e.setAttribute("readonly","");var n=e.parentElement.querySelector("div.message");if(n)n.innerHTML=_t(t);else{var r=document.createElement("div");r.className="message text-secondary small",r.innerHTML=_t(t),e.parentElement.appendChild(r)}}},{key:"set_field_editable",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;e.removeAttribute("readonly");var n=e.parentElement.querySelector("div.message");if(n)n.innerHTML=_t(t);else{var r=document.createElement("div");r.className="message text-secondary small",r.innerHTML=_t(t),e.parentElement.appendChild(r)}}},{key:"set_field_error",value:function(e,t){e.classList.add("is-invalid");var n=e.parentElement.querySelector("div.invalid-feedback");if(n)n.innerHTML=_t(t);else{var r=document.createElement("div");r.className="invalid-feedback",r.innerHTML=_t(t),e.parentElement.appendChild(r)}}},{key:"remove_field_error",value:function(e){e.classList.remove("is-invalid");var t=e.parentElement.querySelector(".invalid-feedback");t&&t.remove()}},{key:"add_statusmessage",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"info",n=arguments.length>2?arguments[2]:void 0;n=n||{};var r=document.createElement("div"),o=n.title||"".concat(t.charAt(0).toUpperCase()+t.slice(1));r.innerHTML='\n \n '),r=r.firstElementChild;var i=document.getElementById("viewlet-above-content");if(n.flush){var a,s=b(i.querySelectorAll(".alert"));try{for(s.s();!(a=s.n()).done;){var u=a.value;u.remove()}}catch(e){s.e(e)}finally{s.f()}}return i.appendChild(r),r}},{key:"add_notification",value:function(e,t,n){n=n||{},n=Object.assign({animation:!0,autohide:!0,delay:5e3},n);var r=document.createElement("div");r.innerHTML='\n \n "),r=r.firstElementChild;var o=document.querySelector(".toast-container");return o||((o=document.createElement("div")).innerHTML='\n
\n
\n
\n
\n ',document.querySelector(".container-fluid").appendChild(o),o=o.querySelector(".toast-container")),o.appendChild(r),r}},{key:"update_form",value:function(e,n){var r,o=n.hide||[],i=n.show||[],a=n.readonly||[],s=n.editable||[],g=n.errors||[],w=n.messages||[],k=n.notifications||[],O=n.updates||[],E=n.html||[],S=n.attributes||[],j=b(g);try{for(j.s();!(r=j.n()).done;){var x,T,A=r.value,C=void 0,P=A;x=P.name,T=P.error,C=m(P,u);var R=this.get_form_field_by_name(e,x);R&&(T?this.set_field_error(R,T):this.remove_field_error(R))}}catch(e){j.e(e)}finally{j.f()}var N,L=b(w);try{for(L.s();!(N=L.n()).done;){var I=N.value,D=(C=void 0,I);q=D.message,M=D.level,C=m(D,l);var M=M||"info",q=q||"";this.add_statusmessage(q,M,C)}}catch(e){L.e(e)}finally{L.f()}var z,U=b(k);try{for(U.s();!(z=U.n()).done;){var B,H,F=z.value,J=(C=void 0,F);B=J.title,H=J.message,C=m(J,c);var $=this.add_notification(B,H,C);t()($).toast("show")}}catch(e){U.e(e)}finally{U.f()}var K,W=b(o);try{for(W.s();!(K=W.n()).done;){var X,G=K.value,Q=(C=void 0,G);X=Q.name,C=m(Q,f);var V=this.get_form_field_by_name(e,X);V&&this.toggle_field_visibility(V,!1)}}catch(e){W.e(e)}finally{W.f()}var Y,Z=b(i);try{for(Z.s();!(Y=Z.n()).done;){var ee,te=Y.value,ne=(C=void 0,te);ee=ne.name,C=m(ne,d);var re=this.get_form_field_by_name(e,ee);re&&this.toggle_field_visibility(re,!0)}}catch(e){Z.e(e)}finally{Z.f()}var oe,ie=b(a);try{for(ie.s();!(oe=ie.n()).done;){var ae,se,ue=oe.value,le=(C=void 0,ue);ae=le.name,se=le.message,C=m(le,h);var ce=this.get_form_field_by_name(e,ae);ce&&this.set_field_readonly(ce,se)}}catch(e){ie.e(e)}finally{ie.f()}var fe,de=b(s);try{for(de.s();!(fe=de.n()).done;){var he,pe,ye=fe.value,ve=(C=void 0,ye);he=ve.name,pe=ve.message,C=m(ve,p);var _e=this.get_form_field_by_name(e,he);_e&&this.set_field_editable(_e,pe)}}catch(e){de.e(e)}finally{de.f()}var me,be=b(O);try{for(be.s();!(me=be.n()).done;){var ge,we,ke=me.value,Oe=(C=void 0,ke);ge=Oe.name,we=Oe.value,C=m(Oe,y);var Ee=this.get_form_field_by_name(e,ge);Ee&&this.set_field_value(Ee,we)}}catch(e){be.e(e)}finally{be.f()}var Se,je=b(E);try{for(je.s();!(Se=je.n()).done;){var xe,Te,Ae=Se.value,Ce=(C=void 0,Ae);xe=Ce.selector,Te=Ce.html,C=m(Ce,v);var Pe=e.querySelector(xe);Pe&&(C.append?Pe.innerHTML=Pe.innerHTML+Te:Pe.innerHTML=Te)}}catch(e){je.e(e)}finally{je.f()}var Re,Ne=b(S);try{for(Ne.s();!(Re=Ne.n()).done;){var Le,Ie,De,Me=Re.value,qe=(C=void 0,Me);Le=qe.selector,Ie=qe.name,De=qe.value,C=m(qe,_);var ze=e.querySelector(Le);ze&&(null===De?ze.removeAttribute(Ie):ze.addAttribute(Ie,De))}}catch(e){Ne.e(e)}finally{Ne.f()}this.has_field_errors(e)?this.toggle_submit(e,!1):this.toggle_submit(e,!0)}},{key:"get_form_field_by_name",value:function(e,t){var n=e.querySelector("[name='".concat(t,"']")),r=e.querySelector("[name^='".concat(t,"']")),o=n||r||null;return null===o?null:o}},{key:"get_form_data",value:function(e){var t={};return new FormData(e).forEach((function(e,n){t[n]=e})),t}},{key:"get_form_fields",value:function(e){var t,n,r=[],o=b(this.config.field_selectors);try{for(o.s();!(t=o.n()).done;){var i,a=t.value,s=e.querySelectorAll(a);r=(i=r).concat.apply(i,function(e){if(Array.isArray(e))return w(e)}(n=s.values())||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(n)||g(n)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}())}}catch(e){o.e(e)}finally{o.f()}return r}},{key:"get_field_name",value:function(e){return e.name.split(":")[0]}},{key:"get_field_value",value:function(e){if(this.is_checkbox(e))return e.checked;if(this.is_select(e)){var t=e.selectedOptions;return Array.prototype.map.call(t,(function(e){return e.value}))}if(this.is_single_reference(e))return e.getAttribute("uid");if(this.is_multi_reference(e)){var n=e.getAttribute("uid");return 0==n.length?[]:n.split(",")}return e.value}},{key:"set_field_value",value:function(e,t){var n=t.selected||[],r=t.options||[];if(this.is_single_reference(e)){var o,i=b(n);try{for(i.s();!(o=i.n()).done;){var a=o.value;e.setAttribute("uid",a.value),e.value=a.title}}catch(e){i.e(e)}finally{i.f()}}else if(this.is_select(e)){if(0==n.length){var s=e.options[e.selected];s&&(n=[s.value])}e.options.length=0,r.sort((function(e,t){var n=e.title.toLowerCase(),r=t.title.toLowerCase();return null===e.value&&(n=""),null===t.value&&(r=""),nr?1:void 0}));var u,l=b(r);try{for(l.s();!(u=l.n()).done;){var c=u.value,f=document.createElement("option");f.value=c.value,f.innerHTML=c.title,-1!==n.indexOf(c.value)&&(f.selected=!0),e.appendChild(f)}}catch(e){l.e(e)}finally{l.f()}0==n.length&&(e.selectedIndex=0)}else this.is_checkbox(e)?e.checked=t:e.value=t}},{key:"modified",value:function(e){var t=new CustomEvent("modified",{detail:{field:e,form:e.form}});e.form.dispatchEvent(t)}},{key:"loading",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t=e?"ajaxStart":"ajaxStop",n=new CustomEvent(t);document.dispatchEvent(n)}},{key:"notify",value:function(e,t,n){var r={name:this.get_field_name(t),value:this.get_field_value(t)};this.ajax_send(e,r,n)}},{key:"ajax_send",value:function(e,t,n){var r=document.body.dataset.viewUrl,o="".concat(r,"/ajax_form/").concat(n),i=Object.assign({form:this.get_form_data(e)},t),a={method:"POST",credentials:"include",body:JSON.stringify(i),headers:{"Content-Type":"application/json","X-CSRF-TOKEN":document.querySelector("#protect-script").dataset.token}};return this.ajax_request(e,o,a)}},{key:"ajax_submit",value:function(e,t,n){for(var r=document.body.dataset.viewUrl,o="".concat(r,"/ajax_form/").concat(n),i=new FormData(e),a=0,s=Object.entries(t);a-1||(r=r.concat(i.target),this.handle_mutation(n,i))}}catch(e){o.e(e)}finally{o.f()}}},{key:"on_modified",value:function(e){var t=e.detail.form,n=e.detail.field;this.notify(t,n,"modified")}},{key:"on_submit",value:function(e){var t=this;e.preventDefault();var n={},r=e.currentTarget.closest("form"),o=e.submitter;o&&(n[o.name]=o.value,this.toggle_disable(o,!0)),this.ajax_submit(r,n,"submit").then((function(e){return t.toggle_disable(o,!1)}))}},{key:"on_blur",value:function(e){var t=e.currentTarget;this.modified(t)}},{key:"on_click",value:function(e){var t=e.currentTarget;this.modified(t)}},{key:"on_change",value:function(e){var t=e.currentTarget;this.modified(t)}}],r&&k(n.prototype,r),e}();var E=n(559),S=function(e,t){return function(){return e.apply(t,arguments)}};const j=function(){function e(){this.set_cookie=S(this.set_cookie,this),this.read_cookie=S(this.read_cookie,this),this.authenticator=S(this.authenticator,this)}return e.prototype.authenticator=function(){var e;return(e=E("input[name='_authenticator']").val())||(e=new URLSearchParams(window.location.search).get("_authenticator")),e},e.prototype.read_cookie=function(e){var t,n,r;for(e+="=",n=document.cookie.split(";"),r=0;r0&&void 0!==arguments[0]&&arguments[0];window.site.set_cookie(this.config.cookie_key,e),e?(this.el.classList.add("toggled"),this.maximize()):(this.el.classList.remove("toggled"),this.minimize())}},{key:"minimize",value:function(){this.el.classList.add("minimized")}},{key:"maximize",value:function(){this.el.classList.remove("minimized")}},{key:"on_click",value:function(e){clearTimeout(this.tid),this.toggle(!this.is_toggled())}},{key:"on_mouseenter",value:function(e){clearTimeout(this.tid),this.is_toggled()||(this.tid=setTimeout(this.maximize,this.config.timeout))}},{key:"on_mouseleave",value:function(e){clearTimeout(this.tid),this.is_toggled()||this.minimize()}}],n&&x(t.prototype,n),e}(),A=React;var C=n.n(A);function P(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,i=[],a=!0,s=!1;try{for(n=n.call(e);!(a=(r=n.next()).done)&&(i.push(r.value),!t||i.length!==t);a=!0);}catch(e){s=!0,o=e}finally{try{a||null==n.return||n.return()}finally{if(s)throw o}}return i}}(e,t)||function(e,t){if(e){if("string"==typeof e)return R(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?R(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function R(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){s=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw i}}}}function J(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0}},{key:"get_style",value:function(){return{minWidth:this.props.width||"400px",backgroundColor:"white",zIndex:999999}}},{key:"get_result_uid",value:function(e){return e.uid||"NO UID FOUND!"}},{key:"is_uid_selected",value:function(e){return this.props.uids.indexOf(e)>-1}},{key:"build_header_columns",value:function(){var e,t=[],n=F(this.get_columns());try{for(n.s();!(e=n.n()).done;){var r=e.value,o=r.label||r.title,i=r.width||"auto",a=r.align||"left";t.push(C().createElement("th",{className:"border-top-0",width:i,align:a},_t(o)))}}catch(e){n.e(e)}finally{n.f()}return t.push(C().createElement("th",{className:"border-top-0",width:"1"})),t}},{key:"build_rows",value:function(){var e=this,t=[];return this.get_results().forEach((function(n,r){var o=e.get_result_uid(n);t.push(C().createElement("tr",{uid:o,className:e.props.focused==r?"table-active":"",onClick:e.on_select},e.build_columns(n)))})),t}},{key:"build_columns",value:function(e){var t,n=[],r=this.props.searchterm||"",o=F(this.get_column_names());try{for(o.s();!(t=o.n()).done;){var i=e[t.value],a=this.highlight(i,r);n.push(C().createElement("td",{dangerouslySetInnerHTML:{__html:a}}))}}catch(e){o.e(e)}finally{o.f()}var s=e.uid,u=this.props.uids.indexOf(s)>-1;return n.push(C().createElement("td",null,u&&C().createElement("i",{class:"fas fa-link text-success"}))),n}},{key:"highlight",value:function(e,t){if(0==t.length)return e;try{var n=new RegExp(t,"gi");e=e.replaceAll(n,(function(e){return""+e+""}))}catch(e){}return e}},{key:"build_pages",value:function(){for(var e=[],t=1;t<=this.props.pages;t++){var n=["page-item"];this.props.page==t&&n.push("active"),e.push(C().createElement("li",{className:n.join(" ")},C().createElement("button",{className:"page-link",page:t,onClick:this.on_page},t)))}return e}},{key:"build_next_button",value:function(){var e=["page-item"];return this.props.next_url||e.push("disabled"),C().createElement("li",{className:e.join(" ")},C().createElement("button",{className:"page-link",onClick:this.on_next_page},"Next"))}},{key:"build_prev_button",value:function(){var e=["page-item"];return this.props.prev_url||e.push("disabled"),C().createElement("li",{className:e.join(" ")},C().createElement("button",{className:"page-link",onClick:this.on_prev_page},"Previous"))}},{key:"build_close_button",value:function(){return C().createElement("button",{className:"btn btn-sm btn-link",onClick:this.on_close},C().createElement("i",{class:"fas fa-window-close"}))}},{key:"on_select",value:function(e){e.preventDefault();var t=e.currentTarget.getAttribute("uid");this.props.on_select&&this.props.on_select(t)}},{key:"on_page",value:function(e){e.preventDefault();var t=e.currentTarget.getAttribute("page");t!=this.props.page&&this.props.on_page&&this.props.on_page(t)}},{key:"on_prev_page",value:function(e){e.preventDefault();var t=this.props.page;t<2||this.props.on_page&&this.props.on_page(t-1)}},{key:"on_next_page",value:function(e){e.preventDefault();var t=this.props.page;t+1>this.props.pages||this.props.on_page&&this.props.on_page(t+1)}},{key:"on_close",value:function(e){e.preventDefault(),this.props.on_clear&&this.props.on_clear()}},{key:"render",value:function(){return this.has_results()?C().createElement("div",{className:this.props.className,style:this.get_style()},C().createElement("div",{style:{position:"absolute",top:0,right:0}},this.build_close_button()),C().createElement("table",{className:"table table-sm table-hover small"},C().createElement("thead",null,C().createElement("tr",null,this.build_header_columns())),C().createElement("tbody",null,this.build_rows())),this.props.pages>1&&C().createElement("nav",null,C().createElement("ul",{className:"pagination pagination-sm justify-content-center"},this.build_prev_button(),this.build_pages(),this.build_next_button()))):null}}])&&$(t.prototype,n),a}(C().Component);function V(e){return V="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},V(e)}function Y(e,t){if(e){if("string"==typeof e)return Z(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Z(e,t):void 0}}function Z(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){s=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw i}}}}(this.get_selected_uids());try{for(n.s();!(e=n.n()).done;){var r=e.value;t.push(C().createElement("li",{uid:r},C().createElement("div",{className:"p-1 mb-1 mr-1 bg-light border rounded d-inline-block"},C().createElement("span",{dangerouslySetInnerHTML:{__html:this.render_display_template(r)}}),C().createElement("button",{uid:r,className:"btn btn-sm btn-link-danger",onClick:this.on_deselect},C().createElement("i",{className:"fas fa-times-circle"})))))}}catch(e){n.e(e)}finally{n.f()}return t}},{key:"on_deselect",value:function(e){e.preventDefault();var t=e.currentTarget.getAttribute("uid");this.props.on_deselect&&this.props.on_deselect(t)}},{key:"render",value:function(){return C().createElement("div",{className:"uidreferencewidget-references"},C().createElement("ul",{className:"list-unstyled list-group list-group-horizontal"},this.build_selected_items()),C().createElement("textarea",{className:"d-none",name:this.props.name,value:this.props.uids.join("\n")}))}}])&&ee(t.prototype,n),a}(C().Component);function ae(e){return ae="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},ae(e)}function se(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0}},{key:"make_query",value:function(e){return e=e||{},Object.assign({q:this.state.searchterm,limit:this.state.limit,complete:1},e,this.state.query)}},{key:"fetch_results",value:function(e){e=e||{};var t=this,n=this.make_query();this.toggle_loading(!0);var r=this.api.search(this.state.catalog,n,e);return r.then((function(e){t.set_results_data(e),t.toggle_loading(!1)})),r}},{key:"search",value:function(e){if(e||!(this.state.results.length>0))return this.state.searchterm=e||"",this.fetch_results();this.state.searchterm=""}},{key:"goto_page",value:function(e){e=parseInt(e);var t=parseInt(this.state.limit),n=e*t-t;return this.fetch_results({b_start:n})}},{key:"select",value:function(e){var t=[].concat(this.state.uids);return-1==t.indexOf(e)&&t.push(e),this.setState({uids:t}),t.length>0&&!this.state.multi_valued&&this.clear_results(),t}},{key:"select_focused",value:function(){var e=this.state.focused,t=this.state.results.at(e);if(t){var n=t.uid;-1==this.state.uids.indexOf(n)?this.select(n):this.deselect(n)}}},{key:"deselect",value:function(e){var t=[].concat(this.state.uids),n=t.indexOf(e);return n>-1&&t.splice(n,1),this.setState({uids:t}),t}},{key:"navigate_results",value:function(e){var t=this.state.page,n=this.state.pages,r=this.state.results,o=this.state.focused,i=this.state.searchterm;"up"==e?o>0?this.setState({focused:o-1}):(this.setState({focused:0}),t>1&&this.goto_page(t-1)):"down"==e?(0==this.state.results.length&&this.search(i),o0&&this.goto_page(t-1)):"right"==e&&(this.setState({focused:0}),t=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){s=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw i}}}}(n);try{for(o.s();!(t=o.n()).done;){var i=t.value;r[i.uid]=i}}catch(e){o.e(e)}finally{o.f()}this.setState({records:r,results:n,count:e.count||0,page:e.page||1,pages:e.pages||1,next_url:e.next||null,prev_url:e.previous||null})}},{key:"clear_results",value:function(){this.setState({results:[],count:0,page:1,pages:1,next_url:null,prev_url:null})}},{key:"on_keydown",value:function(e){27===e.keyCode&&this.clear_results()}},{key:"on_click",value:function(e){var t=this.props.root_el,n=e.target;t.contains(n)||this.clear_results()}},{key:"render",value:function(){return C().createElement("div",{className:"uidreferencewidget"},C().createElement(ie,{uids:this.state.uids,records:this.state.records,display_template:this.state.display_template,name:this.state.name,on_deselect:this.deselect}),C().createElement(B,{className:"form-control",name:"uidreference-search",disabled:this.is_disabled(),on_search:this.search,on_clear:this.clear_results,on_focus:this.search,on_arrow_key:this.navigate_results,on_enter:this.select_focused}),C().createElement(Q,{className:"position-absolute shadow border rounded bg-white mt-1 p-1",columns:this.state.columns,uids:this.state.uids,searchterm:this.state.searchterm,results:this.state.results,focused:this.state.focused,count:this.state.count,page:this.state.page,pages:this.state.pages,next_url:this.state.next_url,prev_url:this.state.prev_url,on_select:this.select,on_page:this.goto_page,on_clear:this.clear_results}))}}])&&ue(t.prototype,n),a}(C().Component);function pe(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){s=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw i}}}}(t);try{for(r.s();!(n=r.n()).done;){var o=n.value;e.push(C().createElement("option",{value:o},o))}}catch(e){r.e(e)}finally{r.f()}}return e}},{key:"render",value:function(){return C().createElement("select",{id:this.props.id,name:this.props.name,value:this.props.value,onChange:this.props.onChange},this.render_options())}}])&&me(t.prototype,n),a}(C().Component);function Oe(e){return Oe="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Oe(e)}function Ee(e,t){for(var n=0;n0),e}},{key:"render_element",value:function(){return this.is_location_selector()?C().createElement(ke,{id:this.props.id,name:this.props.name,value:this.props.value,locations:this.props.locations,onChange:this.props.onChange}):C().createElement("input",{type:"text",id:this.props.id,name:this.props.name,value:this.props.value,onChange:this.props.onChange})}},{key:"render",value:function(){return this.is_visible()?C().createElement("div",{class:"form-group form-row mb-2"},C().createElement("div",{class:"col input-group input-group-sm"},C().createElement("div",{class:"input-group-prepend"},C().createElement("label",{class:"input-group-text",for:this.props.id},this.props.label)),this.render_element())):C().createElement("input",{type:"hidden",id:this.props.id,name:this.props.name,value:this.props.value})}}])&&Ee(t.prototype,n),a}(C().Component);function Ae(e){return Ae="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Ae(e)}function Ce(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&(r[e].subdivision1=n[0].type);var o=Ue({},t.state.subdivisions1);o[e]=n.map((function(e){return e.name})).sort(),t.setState({subdivisions1:o,labels:r})})),n}},{key:"on_subdivision1_change",value:function(e,t){var n=this,r=this.api.fetch_subdivisions(t);return r.then((function(r){var o=Ue({},n.state.labels);r.length>0&&(o[e].subdivision2=r[0].type);var i=Ue({},n.state.subdivisions2);i[t]=r.map((function(e){return e.name})).sort(),n.setState({subdivisions2:i,labels:o})})),r}},{key:"render_items",value:function(){var e,t,n,r=[],o=this.state.items,i=function(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=Me(e))){n&&(e=n);var r=0,o=function(){};return{s:o,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){s=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw i}}}}(o.entries());try{for(i.s();!(e=i.n()).done;){var a=(t=e.value,n=2,function(e){if(Array.isArray(e))return e}(t)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,i=[],a=!0,s=!1;try{for(n=n.call(e);!(a=(r=n.next()).done)&&(i.push(r.value),!t||i.length!==t);a=!0);}catch(e){s=!0,o=e}finally{try{a||null==n.return||n.return()}finally{if(s)throw o}}return i}}(t,n)||Me(t,n)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),s=a[0],u=a[1],l="";o.length>1&&(l=C().createElement("strong",null,this.state.labels[u.type])),r.push(C().createElement("div",{class:"mb-2 pt-2"},l,C().createElement(Ie,{id:this.state.id,name:this.state.name,index:s,address_type:u.type,country:u.country,subdivision1:u.subdivision1,subdivision2:u.subdivision2,city:u.city,zip:u.zip,address:u.address,labels:this.state.labels,countries:this.state.countries,subdivisions1:this.state.subdivisions1,subdivisions2:this.state.subdivisions2,on_country_change:this.on_country_change,on_subdivision1_change:this.on_subdivision1_change})))}}catch(e){i.e(e)}finally{i.f()}return r}},{key:"render",value:function(){return C().createElement("div",{className:"addresswidget"},this.render_items())}}])&&He(t.prototype,n),a}(C().Component);function Xe(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=function(e,t){if(e){if("string"==typeof e)return Ge(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Ge(e,t):void 0}}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0,o=function(){};return{s:o,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){s=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw i}}}}function Ge(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n{"use strict";var e={559:e=>{e.exports=jQuery}},t={};function n(r){var o=t[r];if(void 0!==o)return o.exports;var i=t[r]={exports:{}};return e[r](i,i.exports,n),i.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e=n(559),t=n.n(e);const r=function(){var e=this;e.baseUrl=t()("body").attr("data-i18ncatalogurl"),e.currentLanguage=t()("html").attr("lang")||"en",e.currentLanguage.split("-").length>1&&(e.currentLanguage=e.currentLanguage.split("-")[0]+"_"+e.currentLanguage.split("-")[1].toUpperCase()),e.storage=null,e.catalogs={},e.ttl=864e5,Date.now||(Date.now=function(){return(new Date).valueOf()});try{"localStorage"in window&&null!==window.localStorage&&"JSON"in window&&null!==window.JSON&&(e.storage=window.localStorage)}catch(e){}e.configure=function(t){for(var n in t)e[n]=t[n]},e._setCatalog=function(t,n,r){t in e.catalogs||(e.catalogs[t]={}),e.catalogs[t][n]=r},e._storeCatalog=function(t,n,r){var o=t+"-"+n;null!==e.storage&&null!==r&&(e.storage.setItem(o,JSON.stringify(r)),e.storage.setItem(o+"-updated",Date.now()))},e.getUrl=function(t,n){return e.baseUrl+"?domain="+t+"&language="+n},e.loadCatalog=function(n,r){if(void 0===r&&(r=e.currentLanguage),null!==e.storage){var o=n+"-"+r;if(o in e.storage&&Date.now()-parseInt(e.storage.getItem(o+"-updated"),10)=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}function b(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=g(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0,o=function(){};return{s:o,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){s=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw i}}}}function g(e,t){if(e){if("string"==typeof e)return w(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?w(e,t):void 0}}function w(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n1&&void 0!==arguments[1])||arguments[1],n=e.closest(".field"),r="d-none";!1===t?n.classList.add(r):n.classList.remove(r)}},{key:"has_field_errors",value:function(e){return e.querySelectorAll(".is-invalid").length>0}},{key:"set_field_readonly",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;e.setAttribute("readonly","");var n=e.parentElement.querySelector("div.message");if(n)n.innerHTML=_t(t);else{var r=document.createElement("div");r.className="message text-secondary small",r.innerHTML=_t(t),e.parentElement.appendChild(r)}}},{key:"set_field_editable",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;e.removeAttribute("readonly");var n=e.parentElement.querySelector("div.message");if(n)n.innerHTML=_t(t);else{var r=document.createElement("div");r.className="message text-secondary small",r.innerHTML=_t(t),e.parentElement.appendChild(r)}}},{key:"set_field_error",value:function(e,t){e.classList.add("is-invalid");var n=e.parentElement.querySelector("div.invalid-feedback");if(n)n.innerHTML=_t(t);else{var r=document.createElement("div");r.className="invalid-feedback",r.innerHTML=_t(t),e.parentElement.appendChild(r)}}},{key:"remove_field_error",value:function(e){e.classList.remove("is-invalid");var t=e.parentElement.querySelector(".invalid-feedback");t&&t.remove()}},{key:"add_statusmessage",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"info",n=arguments.length>2?arguments[2]:void 0;n=n||{};var r=document.createElement("div"),o=n.title||"".concat(t.charAt(0).toUpperCase()+t.slice(1));r.innerHTML='\n \n '),r=r.firstElementChild;var i=document.getElementById("viewlet-above-content");if(n.flush){var a,s=b(i.querySelectorAll(".alert"));try{for(s.s();!(a=s.n()).done;){var u=a.value;u.remove()}}catch(e){s.e(e)}finally{s.f()}}return i.appendChild(r),r}},{key:"add_notification",value:function(e,t,n){n=n||{},n=Object.assign({animation:!0,autohide:!0,delay:5e3},n);var r=document.createElement("div");r.innerHTML='\n \n "),r=r.firstElementChild;var o=document.querySelector(".toast-container");return o||((o=document.createElement("div")).innerHTML='\n
\n
\n
\n
\n ',document.querySelector(".container-fluid").appendChild(o),o=o.querySelector(".toast-container")),o.appendChild(r),r}},{key:"update_form",value:function(e,n){var r,o=n.hide||[],i=n.show||[],a=n.readonly||[],s=n.editable||[],g=n.errors||[],w=n.messages||[],k=n.notifications||[],O=n.updates||[],E=n.html||[],S=n.attributes||[],j=b(g);try{for(j.s();!(r=j.n()).done;){var x,T,A=r.value,C=void 0,P=A;x=P.name,T=P.error,C=m(P,u);var R=this.get_form_field_by_name(e,x);R&&(T?this.set_field_error(R,T):this.remove_field_error(R))}}catch(e){j.e(e)}finally{j.f()}var N,L=b(w);try{for(L.s();!(N=L.n()).done;){var I=N.value,D=(C=void 0,I);q=D.message,M=D.level,C=m(D,l);var M=M||"info",q=q||"";this.add_statusmessage(q,M,C)}}catch(e){L.e(e)}finally{L.f()}var z,U=b(k);try{for(U.s();!(z=U.n()).done;){var B,H,F=z.value,J=(C=void 0,F);B=J.title,H=J.message,C=m(J,c);var $=this.add_notification(B,H,C);t()($).toast("show")}}catch(e){U.e(e)}finally{U.f()}var W,K=b(o);try{for(K.s();!(W=K.n()).done;){var X,G=W.value,Q=(C=void 0,G);X=Q.name,C=m(Q,f);var V=this.get_form_field_by_name(e,X);V&&this.toggle_field_visibility(V,!1)}}catch(e){K.e(e)}finally{K.f()}var Y,Z=b(i);try{for(Z.s();!(Y=Z.n()).done;){var ee,te=Y.value,ne=(C=void 0,te);ee=ne.name,C=m(ne,d);var re=this.get_form_field_by_name(e,ee);re&&this.toggle_field_visibility(re,!0)}}catch(e){Z.e(e)}finally{Z.f()}var oe,ie=b(a);try{for(ie.s();!(oe=ie.n()).done;){var ae,se,ue=oe.value,le=(C=void 0,ue);ae=le.name,se=le.message,C=m(le,h);var ce=this.get_form_field_by_name(e,ae);ce&&this.set_field_readonly(ce,se)}}catch(e){ie.e(e)}finally{ie.f()}var fe,de=b(s);try{for(de.s();!(fe=de.n()).done;){var he,pe,ye=fe.value,ve=(C=void 0,ye);he=ve.name,pe=ve.message,C=m(ve,p);var _e=this.get_form_field_by_name(e,he);_e&&this.set_field_editable(_e,pe)}}catch(e){de.e(e)}finally{de.f()}var me,be=b(O);try{for(be.s();!(me=be.n()).done;){var ge,we,ke=me.value,Oe=(C=void 0,ke);ge=Oe.name,we=Oe.value,C=m(Oe,y);var Ee=this.get_form_field_by_name(e,ge);Ee&&this.set_field_value(Ee,we)}}catch(e){be.e(e)}finally{be.f()}var Se,je=b(E);try{for(je.s();!(Se=je.n()).done;){var xe,Te,Ae=Se.value,Ce=(C=void 0,Ae);xe=Ce.selector,Te=Ce.html,C=m(Ce,v);var Pe=e.querySelector(xe);Pe&&(C.append?Pe.innerHTML=Pe.innerHTML+Te:Pe.innerHTML=Te)}}catch(e){je.e(e)}finally{je.f()}var Re,Ne=b(S);try{for(Ne.s();!(Re=Ne.n()).done;){var Le,Ie,De,Me=Re.value,qe=(C=void 0,Me);Le=qe.selector,Ie=qe.name,De=qe.value,C=m(qe,_);var ze=e.querySelector(Le);ze&&(null===De?ze.removeAttribute(Ie):ze.addAttribute(Ie,De))}}catch(e){Ne.e(e)}finally{Ne.f()}this.has_field_errors(e)?this.toggle_submit(e,!1):this.toggle_submit(e,!0)}},{key:"get_form_field_by_name",value:function(e,t){var n=e.querySelector("[name='".concat(t,"']")),r=e.querySelector("[name^='".concat(t,"']")),o=n||r||null;return null===o?null:o}},{key:"get_form_data",value:function(e){var t={};return new FormData(e).forEach((function(e,n){t[n]=e})),t}},{key:"get_form_fields",value:function(e){var t,n,r=[],o=b(this.config.field_selectors);try{for(o.s();!(t=o.n()).done;){var i,a=t.value,s=e.querySelectorAll(a);r=(i=r).concat.apply(i,function(e){if(Array.isArray(e))return w(e)}(n=s.values())||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(n)||g(n)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}())}}catch(e){o.e(e)}finally{o.f()}return r}},{key:"get_field_name",value:function(e){return e.name.split(":")[0]}},{key:"get_field_value",value:function(e){if(this.is_checkbox(e))return e.checked;if(this.is_select(e)){var t=e.selectedOptions;return Array.prototype.map.call(t,(function(e){return e.value}))}if(this.is_single_reference(e))return e.getAttribute("uid");if(this.is_multi_reference(e)){var n=e.getAttribute("uid");return 0==n.length?[]:n.split(",")}return e.value}},{key:"set_field_value",value:function(e,t){var n=t.selected||[],r=t.options||[];if(this.is_single_reference(e)){var o,i=b(n);try{for(i.s();!(o=i.n()).done;){var a=o.value;e.setAttribute("uid",a.value),e.value=a.title}}catch(e){i.e(e)}finally{i.f()}}else if(this.is_select(e)){if(0==n.length){var s=e.options[e.selected];s&&(n=[s.value])}e.options.length=0,r.sort((function(e,t){var n=e.title.toLowerCase(),r=t.title.toLowerCase();return null===e.value&&(n=""),null===t.value&&(r=""),nr?1:void 0}));var u,l=b(r);try{for(l.s();!(u=l.n()).done;){var c=u.value,f=document.createElement("option");f.value=c.value,f.innerHTML=c.title,-1!==n.indexOf(c.value)&&(f.selected=!0),e.appendChild(f)}}catch(e){l.e(e)}finally{l.f()}0==n.length&&(e.selectedIndex=0)}else this.is_checkbox(e)?e.checked=t:e.value=t}},{key:"modified",value:function(e){var t=new CustomEvent("modified",{detail:{field:e,form:e.form}});e.form.dispatchEvent(t)}},{key:"loading",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t=e?"ajaxStart":"ajaxStop",n=new CustomEvent(t);document.dispatchEvent(n)}},{key:"notify",value:function(e,t,n){var r={name:this.get_field_name(t),value:this.get_field_value(t)};this.ajax_send(e,r,n)}},{key:"ajax_send",value:function(e,t,n){var r=document.body.dataset.viewUrl,o="".concat(r,"/ajax_form/").concat(n),i=Object.assign({form:this.get_form_data(e)},t),a={method:"POST",credentials:"include",body:JSON.stringify(i),headers:{"Content-Type":"application/json","X-CSRF-TOKEN":document.querySelector("#protect-script").dataset.token}};return this.ajax_request(e,o,a)}},{key:"ajax_submit",value:function(e,t,n){for(var r=document.body.dataset.viewUrl,o="".concat(r,"/ajax_form/").concat(n),i=new FormData(e),a=0,s=Object.entries(t);a-1||(r=r.concat(i.target),this.handle_mutation(n,i))}}catch(e){o.e(e)}finally{o.f()}}},{key:"on_modified",value:function(e){var t=e.detail.form,n=e.detail.field;this.notify(t,n,"modified")}},{key:"on_submit",value:function(e){var t=this;e.preventDefault();var n={},r=e.currentTarget.closest("form"),o=e.submitter;o&&(n[o.name]=o.value,this.toggle_disable(o,!0)),this.ajax_submit(r,n,"submit").then((function(e){return t.toggle_disable(o,!1)}))}},{key:"on_blur",value:function(e){var t=e.currentTarget;this.modified(t)}},{key:"on_click",value:function(e){var t=e.currentTarget;this.modified(t)}},{key:"on_change",value:function(e){var t=e.currentTarget;this.modified(t)}}],r&&k(n.prototype,r),e}();var E=n(559),S=function(e,t){return function(){return e.apply(t,arguments)}};const j=function(){function e(){this.set_cookie=S(this.set_cookie,this),this.read_cookie=S(this.read_cookie,this),this.authenticator=S(this.authenticator,this)}return e.prototype.authenticator=function(){var e;return(e=E("input[name='_authenticator']").val())||(e=new URLSearchParams(window.location.search).get("_authenticator")),e},e.prototype.read_cookie=function(e){var t,n,r;for(e+="=",n=document.cookie.split(";"),r=0;r0&&void 0!==arguments[0]&&arguments[0];window.site.set_cookie(this.config.cookie_key,e),e?(this.el.classList.add("toggled"),this.maximize()):(this.el.classList.remove("toggled"),this.minimize())}},{key:"minimize",value:function(){this.el.classList.add("minimized")}},{key:"maximize",value:function(){this.el.classList.remove("minimized")}},{key:"on_click",value:function(e){clearTimeout(this.tid),this.toggle(!this.is_toggled())}},{key:"on_mouseenter",value:function(e){clearTimeout(this.tid),this.is_toggled()||(this.tid=setTimeout(this.maximize,this.config.timeout))}},{key:"on_mouseleave",value:function(e){clearTimeout(this.tid),this.is_toggled()||this.minimize()}}],n&&x(t.prototype,n),e}(),A=React;var C=n.n(A);function P(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,i=[],a=!0,s=!1;try{for(n=n.call(e);!(a=(r=n.next()).done)&&(i.push(r.value),!t||i.length!==t);a=!0);}catch(e){s=!0,o=e}finally{try{a||null==n.return||n.return()}finally{if(s)throw o}}return i}}(e,t)||function(e,t){if(e){if("string"==typeof e)return R(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?R(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function R(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){s=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw i}}}}function J(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0}},{key:"get_style",value:function(){return{minWidth:this.props.width||"400px",backgroundColor:"white",zIndex:999999}}},{key:"get_result_uid",value:function(e){return e.uid||"NO UID FOUND!"}},{key:"is_uid_selected",value:function(e){return this.props.uids.indexOf(e)>-1}},{key:"build_header_columns",value:function(){var e,t=[],n=F(this.get_columns());try{for(n.s();!(e=n.n()).done;){var r=e.value,o=r.label||r.title,i=r.width||"auto",a=r.align||"left";t.push(C().createElement("th",{className:"border-top-0",width:i,align:a},_t(o)))}}catch(e){n.e(e)}finally{n.f()}return t.push(C().createElement("th",{className:"border-top-0",width:"1"})),t}},{key:"build_rows",value:function(){var e=this,t=[];return this.get_results().forEach((function(n,r){var o=e.get_result_uid(n);t.push(C().createElement("tr",{uid:o,className:e.props.focused==r?"table-active":"",onClick:e.on_select},e.build_columns(n)))})),t}},{key:"build_columns",value:function(e){var t,n=[],r=this.props.searchterm||"",o=F(this.get_column_names());try{for(o.s();!(t=o.n()).done;){var i=e[t.value],a=this.highlight(i,r);n.push(C().createElement("td",{dangerouslySetInnerHTML:{__html:a}}))}}catch(e){o.e(e)}finally{o.f()}var s=e.uid,u=this.props.uids.indexOf(s)>-1;return n.push(C().createElement("td",null,u&&C().createElement("i",{class:"fas fa-link text-success"}))),n}},{key:"highlight",value:function(e,t){if(0==t.length)return e;try{var n=new RegExp(t,"gi");e=e.replaceAll(n,(function(e){return""+e+""}))}catch(e){}return e}},{key:"build_pages",value:function(){for(var e=[],t=1;t<=this.props.pages;t++){var n=["page-item"];this.props.page==t&&n.push("active"),e.push(C().createElement("li",{className:n.join(" ")},C().createElement("button",{className:"page-link",page:t,onClick:this.on_page},t)))}return e}},{key:"build_next_button",value:function(){var e=["page-item"];return this.props.next_url||e.push("disabled"),C().createElement("li",{className:e.join(" ")},C().createElement("button",{className:"page-link",onClick:this.on_next_page},"Next"))}},{key:"build_prev_button",value:function(){var e=["page-item"];return this.props.prev_url||e.push("disabled"),C().createElement("li",{className:e.join(" ")},C().createElement("button",{className:"page-link",onClick:this.on_prev_page},"Previous"))}},{key:"build_close_button",value:function(){return C().createElement("button",{className:"btn btn-sm btn-link",onClick:this.on_close},C().createElement("i",{class:"fas fa-window-close"}))}},{key:"on_select",value:function(e){e.preventDefault();var t=e.currentTarget.getAttribute("uid");this.props.on_select&&this.props.on_select(t)}},{key:"on_page",value:function(e){e.preventDefault();var t=e.currentTarget.getAttribute("page");t!=this.props.page&&this.props.on_page&&this.props.on_page(t)}},{key:"on_prev_page",value:function(e){e.preventDefault();var t=this.props.page;t<2||this.props.on_page&&this.props.on_page(t-1)}},{key:"on_next_page",value:function(e){e.preventDefault();var t=this.props.page;t+1>this.props.pages||this.props.on_page&&this.props.on_page(t+1)}},{key:"on_close",value:function(e){e.preventDefault(),this.props.on_clear&&this.props.on_clear()}},{key:"render",value:function(){return this.has_results()?C().createElement("div",{className:this.props.className,style:this.get_style()},C().createElement("div",{style:{position:"absolute",top:0,right:0}},this.build_close_button()),C().createElement("table",{className:"table table-sm table-hover small"},C().createElement("thead",null,C().createElement("tr",null,this.build_header_columns())),C().createElement("tbody",null,this.build_rows())),this.props.pages>1&&C().createElement("nav",null,C().createElement("ul",{className:"pagination pagination-sm justify-content-center"},this.build_prev_button(),this.build_pages(),this.build_next_button()))):null}}])&&$(t.prototype,n),a}(C().Component);function V(e){return V="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},V(e)}function Y(e,t){if(e){if("string"==typeof e)return Z(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Z(e,t):void 0}}function Z(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){s=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw i}}}}(this.get_selected_uids());try{for(n.s();!(e=n.n()).done;){var r=e.value;t.push(C().createElement("li",{uid:r},C().createElement("div",{className:"p-1 mb-1 mr-1 bg-light border rounded d-inline-block"},C().createElement("span",{dangerouslySetInnerHTML:{__html:this.render_display_template(r)}}),C().createElement("button",{uid:r,className:"btn btn-sm btn-link-danger",onClick:this.on_deselect},C().createElement("i",{className:"fas fa-times-circle"})))))}}catch(e){n.e(e)}finally{n.f()}return t}},{key:"on_deselect",value:function(e){e.preventDefault();var t=e.currentTarget.getAttribute("uid");this.props.on_deselect&&this.props.on_deselect(t)}},{key:"render",value:function(){return C().createElement("div",{className:"uidreferencewidget-references"},C().createElement("ul",{className:"list-unstyled list-group list-group-horizontal"},this.build_selected_items()),C().createElement("textarea",{className:"d-none",name:this.props.name,value:this.props.uids.join("\n")}))}}])&&ee(t.prototype,n),a}(C().Component);function ae(e){return ae="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},ae(e)}function se(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0}},{key:"make_query",value:function(e){return e=e||{},Object.assign({q:this.state.searchterm,limit:this.state.limit,complete:1},e,this.state.query)}},{key:"fetch_results",value:function(e){e=e||{};var t=this,n=this.make_query();this.toggle_loading(!0);var r=this.api.search(this.state.catalog,n,e);return r.then((function(e){t.set_results_data(e),t.toggle_loading(!1)})),r}},{key:"search",value:function(e){if(e||!(this.state.results.length>0))return this.state.searchterm=e||"",this.fetch_results();this.state.searchterm=""}},{key:"goto_page",value:function(e){e=parseInt(e);var t=parseInt(this.state.limit),n=e*t-t;return this.fetch_results({b_start:n})}},{key:"select",value:function(e){var t=[].concat(this.state.uids);return-1==t.indexOf(e)&&t.push(e),this.setState({uids:t}),t.length>0&&!this.state.multi_valued&&this.clear_results(),t}},{key:"select_focused",value:function(){var e=this.state.focused,t=this.state.results.at(e);if(t){var n=t.uid;-1==this.state.uids.indexOf(n)?this.select(n):this.deselect(n)}}},{key:"deselect",value:function(e){var t=[].concat(this.state.uids),n=t.indexOf(e);return n>-1&&t.splice(n,1),this.setState({uids:t}),t}},{key:"navigate_results",value:function(e){var t=this.state.page,n=this.state.pages,r=this.state.results,o=this.state.focused,i=this.state.searchterm;"up"==e?o>0?this.setState({focused:o-1}):(this.setState({focused:0}),t>1&&this.goto_page(t-1)):"down"==e?(0==this.state.results.length&&this.search(i),o0&&this.goto_page(t-1)):"right"==e&&(this.setState({focused:0}),t=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){s=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw i}}}}(n);try{for(o.s();!(t=o.n()).done;){var i=t.value;r[i.uid]=i}}catch(e){o.e(e)}finally{o.f()}this.setState({records:r,results:n,count:e.count||0,page:e.page||1,pages:e.pages||1,next_url:e.next||null,prev_url:e.previous||null})}},{key:"clear_results",value:function(){this.setState({results:[],count:0,page:1,pages:1,next_url:null,prev_url:null})}},{key:"on_keydown",value:function(e){27===e.keyCode&&this.clear_results()}},{key:"on_click",value:function(e){var t=this.props.root_el,n=e.target;t.contains(n)||this.clear_results()}},{key:"render",value:function(){return C().createElement("div",{className:"uidreferencewidget"},C().createElement(ie,{uids:this.state.uids,records:this.state.records,display_template:this.state.display_template,name:this.state.name,on_deselect:this.deselect}),C().createElement(B,{className:"form-control",name:"uidreference-search",disabled:this.is_disabled(),on_search:this.search,on_clear:this.clear_results,on_focus:this.search,on_arrow_key:this.navigate_results,on_enter:this.select_focused}),C().createElement(Q,{className:"position-absolute shadow border rounded bg-white mt-1 p-1",columns:this.state.columns,uids:this.state.uids,searchterm:this.state.searchterm,results:this.state.results,focused:this.state.focused,count:this.state.count,page:this.state.page,pages:this.state.pages,next_url:this.state.next_url,prev_url:this.state.prev_url,on_select:this.select,on_page:this.goto_page,on_clear:this.clear_results}))}}])&&ue(t.prototype,n),a}(C().Component);function pe(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){s=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw i}}}}(t);try{for(r.s();!(n=r.n()).done;){var o=n.value;e.push(C().createElement("option",{value:o},o))}}catch(e){r.e(e)}finally{r.f()}}return e}},{key:"render",value:function(){return C().createElement("select",{id:this.props.id,name:this.props.name,value:this.props.value,onChange:this.props.onChange},this.render_options())}}])&&me(t.prototype,n),a}(C().Component);function Oe(e){return Oe="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Oe(e)}function Ee(e,t){for(var n=0;n0),e}},{key:"render_element",value:function(){return this.is_location_selector()?C().createElement(ke,{id:this.props.id,name:this.props.name,value:this.props.value,locations:this.props.locations,onChange:this.props.onChange}):C().createElement("input",{type:"text",id:this.props.id,name:this.props.name,value:this.props.value,onChange:this.props.onChange})}},{key:"render",value:function(){return this.is_visible()?C().createElement("div",{class:"form-group form-row mb-2"},C().createElement("div",{class:"col input-group input-group-sm"},C().createElement("div",{class:"input-group-prepend"},C().createElement("label",{class:"input-group-text",for:this.props.id},this.props.label)),this.render_element())):C().createElement("input",{type:"hidden",id:this.props.id,name:this.props.name,value:this.props.value})}}])&&Ee(t.prototype,n),a}(C().Component);function Ae(e){return Ae="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Ae(e)}function Ce(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&(r[e].subdivision1=n[0].type);var o=Ue({},t.state.subdivisions1);o[e]=n.map((function(e){return e.name})).sort(),t.setState({subdivisions1:o,labels:r})})),n}},{key:"on_subdivision1_change",value:function(e,t){var n=this,r=this.api.fetch_subdivisions(t);return r.then((function(r){var o=Ue({},n.state.labels);r.length>0&&(o[e].subdivision2=r[0].type);var i=Ue({},n.state.subdivisions2);i[t]=r.map((function(e){return e.name})).sort(),n.setState({subdivisions2:i,labels:o})})),r}},{key:"render_items",value:function(){var e,t,n,r=[],o=this.state.items,i=function(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=Me(e))){n&&(e=n);var r=0,o=function(){};return{s:o,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){s=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw i}}}}(o.entries());try{for(i.s();!(e=i.n()).done;){var a=(t=e.value,n=2,function(e){if(Array.isArray(e))return e}(t)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,i=[],a=!0,s=!1;try{for(n=n.call(e);!(a=(r=n.next()).done)&&(i.push(r.value),!t||i.length!==t);a=!0);}catch(e){s=!0,o=e}finally{try{a||null==n.return||n.return()}finally{if(s)throw o}}return i}}(t,n)||Me(t,n)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),s=a[0],u=a[1],l="";o.length>1&&(l=C().createElement("strong",null,this.state.labels[u.type])),r.push(C().createElement("div",{class:"mb-2 pt-2"},l,C().createElement(Ie,{id:this.state.id,name:this.state.name,index:s,address_type:u.type,country:u.country,subdivision1:u.subdivision1,subdivision2:u.subdivision2,city:u.city,zip:u.zip,address:u.address,labels:this.state.labels,countries:this.state.countries,subdivisions1:this.state.subdivisions1,subdivisions2:this.state.subdivisions2,on_country_change:this.on_country_change,on_subdivision1_change:this.on_subdivision1_change})))}}catch(e){i.e(e)}finally{i.f()}return r}},{key:"render",value:function(){return C().createElement("div",{className:"addresswidget"},this.render_items())}}])&&He(t.prototype,n),a}(C().Component);function Xe(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=function(e,t){if(e){if("string"==typeof e)return Ge(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Ge(e,t):void 0}}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0,o=function(){};return{s:o,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return a=e.done,e},e:function(e){s=!0,i=e},f:function(){try{a||null==n.return||n.return()}finally{if(s)throw i}}}}function Ge(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","/* i18n integration. This is forked from jarn.jsi18n\n *\n * This is a singleton.\n * Configuration is done on the body tag data-i18ncatalogurl attribute\n * \n *\n * Or, it'll default to \"/plonejsi18n\"\n */\n\nimport $ from \"jquery\";\n\n\nvar I18N = function() {\n var self = this;\n self.baseUrl = $('body').attr('data-i18ncatalogurl');\n self.currentLanguage = $('html').attr('lang') || 'en';\n\n // Fix for country specific languages\n if (self.currentLanguage.split('-').length > 1) {\n self.currentLanguage = self.currentLanguage.split('-')[0] + '_' + self.currentLanguage.split('-')[1].toUpperCase();\n }\n\n self.storage = null;\n self.catalogs = {};\n self.ttl = 24 * 3600 * 1000;\n\n // Internet Explorer 8 does not know Date.now() which is used in e.g. loadCatalog, so we \"define\" it\n if (!Date.now) {\n Date.now = function() {\n return new Date().valueOf();\n };\n }\n\n try {\n if ('localStorage' in window && window.localStorage !== null && 'JSON' in window && window.JSON !== null) {\n self.storage = window.localStorage;\n }\n } catch (e) {}\n\n self.configure = function(config) {\n for (var key in config){\n self[key] = config[key];\n }\n };\n\n self._setCatalog = function (domain, language, catalog) {\n if (domain in self.catalogs) {\n self.catalogs[domain][language] = catalog;\n } else {\n self.catalogs[domain] = {};\n self.catalogs[domain][language] = catalog;\n }\n };\n\n self._storeCatalog = function (domain, language, catalog) {\n var key = domain + '-' + language;\n if (self.storage !== null && catalog !== null) {\n self.storage.setItem(key, JSON.stringify(catalog));\n self.storage.setItem(key + '-updated', Date.now());\n }\n };\n\n self.getUrl = function(domain, language) {\n return self.baseUrl + '?domain=' + domain + '&language=' + language;\n };\n\n self.loadCatalog = function (domain, language) {\n if (language === undefined) {\n language = self.currentLanguage;\n }\n if (self.storage !== null) {\n var key = domain + '-' + language;\n if (key in self.storage) {\n if ((Date.now() - parseInt(self.storage.getItem(key + '-updated'), 10)) < self.ttl) {\n var catalog = JSON.parse(self.storage.getItem(key));\n self._setCatalog(domain, language, catalog);\n return;\n }\n }\n }\n if (!self.baseUrl) {\n return;\n }\n $.getJSON(self.getUrl(domain, language), function (catalog) {\n if (catalog === null) {\n return;\n }\n self._setCatalog(domain, language, catalog);\n self._storeCatalog(domain, language, catalog);\n });\n };\n\n self.MessageFactory = function (domain, language) {\n language = language || self.currentLanguage;\n return function translate (msgid, keywords) {\n var msgstr;\n if ((domain in self.catalogs) && (language in self.catalogs[domain]) && (msgid in self.catalogs[domain][language])) {\n msgstr = self.catalogs[domain][language][msgid];\n } else {\n msgstr = msgid;\n }\n if (keywords) {\n var regexp, keyword;\n for (keyword in keywords) {\n if (keywords.hasOwnProperty(keyword)) {\n regexp = new RegExp('\\\\$\\\\{' + keyword + '\\\\}', 'g');\n msgstr = msgstr.replace(regexp, keywords[keyword]);\n }\n }\n }\n return msgstr;\n };\n };\n};\n\nexport default I18N;\n","import I18N from \"./components/i18n.js\";\n\n// SENAITE message factory\nvar t = null;\nexport var _t = (msgid, keywords) => {\n if (t === null) {\n let i18n = new I18N();\n console.debug(\"*** Loading `senaite.core` i18n MessageFactory ***\");\n i18n.loadCatalog(\"senaite.core\")\n t = i18n.MessageFactory(\"senaite.core\")\n }\n return t(msgid, keywords);\n}\n\n// Plone message factory\nvar p = null;\nexport var _p = (msgid, keywords) => {\n if (p === null) {\n let i18n = new I18N();\n console.debug(\"*** Loading `plone` i18n MessageFactory ***\");\n i18n.loadCatalog(\"plone\")\n p = i18n.MessageFactory(\"plone\")\n }\n return p(msgid, keywords);\n}\n","/* SENAITE Edit Form Handler\n *\n * This code handles field changes in edit forms and updates others according to\n * the changes with the help of adapters.\n *\n */\n\n// needed for Bootstrap toasts\nimport $ from \"jquery\";\n\n\nclass EditForm {\n\n constructor(config) {\n this.config = Object.assign({\n \"form_selectors\": [],\n \"field_selectors\": []\n }, config);\n\n this.hooked_fields = [];\n\n // bind event handlers\n this.on_mutated = this.on_mutated.bind(this);\n this.on_modified = this.on_modified.bind(this);\n this.on_submit = this.on_submit.bind(this);\n this.on_blur = this.on_blur.bind(this);\n this.on_click = this.on_click.bind(this);\n this.on_change = this.on_change.bind(this);\n this.init_forms();\n }\n\n /**\n * Initialize all form elements given by the config\n */\n init_forms() {\n let selectors = this.config.form_selectors;\n for (const selector of selectors) {\n let form = document.querySelector(selector);\n if (form && form.tagName === \"FORM\") {\n this.setup_form(form);\n this.watch_form(form);\n }\n }\n }\n\n /**\n * Trigger `initialized` event on the form element\n */\n setup_form(form) {\n console.debug(`EditForm::setup_form(${form})`);\n this.ajax_send(form, {}, \"initialized\");\n }\n\n /**\n * Bind event handlers on form fields to monitor changes\n */\n watch_form(form) {\n console.debug(`EditForm::watch_form(${form})`);\n let fields = this.get_form_fields(form);\n for (const field of fields) {\n this.hook_field(field)\n }\n // observe DOM mutations in form\n this.observe_mutations(form);\n // bind custom form event handlers\n form.addEventListener(\"modified\", this.on_modified);\n form.addEventListener(\"mutated\", this.on_mutated);\n if (form.hasAttribute(\"ajax-submit\")) {\n form.addEventListener(\"submit\", this.on_submit);\n }\n }\n\n /**\n * Bind event handlers to field\n */\n hook_field(field) {\n // return immediately if the fields is already hooked\n if (this.hooked_fields.indexOf(field) !== -1) {\n // console.debug(`Field '${field.name}' is already hooked`);\n return\n }\n if (this.is_button(field) || this.is_input_button(field)) {\n // bind click event\n field.addEventListener(\"click\", this.on_click);\n }\n else if (this.is_text(field) || this.is_textarea(field) || this.is_select(field)) {\n // bind change event\n field.addEventListener(\"change\", this.on_change);\n }\n else if (this.is_radio(field) || this.is_checkbox(field)) {\n // bind click event\n field.addEventListener(\"click\", this.on_click);\n } else {\n // bind blur event\n field.addEventListener(\"blur\", this.on_blur);\n }\n // console.debug(`Hooked field '${field.name}'`);\n // remember hooked fields\n this.hooked_fields = this.hooked_fields.concat(field);\n }\n\n /**\n * Initialize a DOM mutation observer to rebind dynamic added fields,\n * e.g. for records field etc.\n */\n observe_mutations(form) {\n let observer = new MutationObserver(function(mutations) {\n let event = new CustomEvent(\"mutated\", {\n detail: {\n form: form,\n mutations: mutations\n }\n });\n form.dispatchEvent(event);\n });\n // observe the form with all contained elements\n observer.observe(form, {\n childList: true,\n subtree: true\n });\n }\n\n /**\n * Handle a single DOM mutation\n */\n handle_mutation(form, mutation) {\n let target = mutation.target;\n let parent = target.closest(\".field\");\n let added = mutation.addedNodes;\n let removed = mutation.removedNodes;\n let selectors = this.config.field_selectors;\n // handle picklist widget\n if (this.is_multiple_select(target)) {\n return this.notify(form, target, \"modified\");\n }\n // hook new fields, e.g. when the records field \"More\" button was clicked\n if (added && target.ELEMENT_NODE) {\n for (const field of target.querySelectorAll(selectors)) {\n this.hook_field(field);\n }\n }\n }\n\n /**\n * toggles the submit button\n */\n toggle_submit(form, toggle) {\n let btn = form.querySelector(\"input[type='submit']\");\n btn.disabled = !toggle;\n }\n\n /**\n * toggles the display of the field with the `d-none` class\n */\n toggle_field_visibility(field, toggle=true) {\n let parent = field.closest(\".field\");\n let css_class = \"d-none\";\n if (toggle === false) {\n parent.classList.add(css_class);\n } else {\n parent.classList.remove(css_class);\n }\n }\n\n /**\n * check if fields have errors\n */\n has_field_errors(form) {\n let fields_with_errors = form.querySelectorAll(\".is-invalid\");\n if (fields_with_errors.length > 0) {\n return true;\n }\n return false;\n }\n\n /**\n * set field readonly\n */\n set_field_readonly(field, message=null) {\n field.setAttribute(\"readonly\", \"\");\n let existing_message = field.parentElement.querySelector(\"div.message\");\n if (existing_message) {\n existing_message.innerHTML = _t(message)\n } else {\n let div = document.createElement(\"div\");\n div.className = \"message text-secondary small\";\n div.innerHTML = _t(message);\n field.parentElement.appendChild(div);\n }\n }\n\n /**\n * set field editable\n */\n set_field_editable(field, message=null) {\n field.removeAttribute(\"readonly\");\n let existing_message = field.parentElement.querySelector(\"div.message\");\n if (existing_message) {\n existing_message.innerHTML = _t(message)\n } else {\n let div = document.createElement(\"div\");\n div.className = \"message text-secondary small\";\n div.innerHTML = _t(message);\n field.parentElement.appendChild(div);\n }\n }\n\n /**\n * set field error\n */\n set_field_error(field, message) {\n field.classList.add(\"is-invalid\");\n let existing_message = field.parentElement.querySelector(\"div.invalid-feedback\");\n if (existing_message) {\n existing_message.innerHTML = _t(message)\n } else {\n let div = document.createElement(\"div\");\n div.className = \"invalid-feedback\";\n div.innerHTML = _t(message);\n field.parentElement.appendChild(div);\n }\n }\n\n /**\n * remove field error\n */\n remove_field_error(field) {\n field.classList.remove(\"is-invalid\")\n let msg = field.parentElement.querySelector(\".invalid-feedback\");\n if (msg) {\n msg.remove();\n }\n }\n\n /**\n * add a status message\n * @param {string} message the message to display in the alert\n * @param {string} level one of \"info\", \"success\", \"warning\", \"danger\"\n * @param {object} options additional options to control the behavior\n * - option {string} title: alert title in bold\n * - option {string} flush: remove previous alerts\n */\n add_statusmessage(message, level=\"info\", options) {\n options = options || {};\n let el = document.createElement(\"div\");\n let title = options.title || `${level.charAt(0).toUpperCase() + level.slice(1)}`;\n el.innerHTML = `\n
\n ${title}\n ${_t(message)}\n \n
\n `\n el = el.firstElementChild\n let parent = document.getElementById(\"viewlet-above-content\");\n\n // clear put previous alerts\n if (options.flush) {\n for (let el of parent.querySelectorAll(\".alert\")) {\n el.remove();\n }\n }\n parent.appendChild(el);\n return el;\n }\n\n /**\n * add a notification message\n */\n add_notification(title, message, options) {\n options = options || {};\n options = Object.assign({\n animation: true,\n autohide: true,\n delay: 5000,\n }, options)\n let el = document.createElement(\"div\");\n el.innerHTML = `\n
\n
\n ${title.charAt(0).toUpperCase() + title.slice(1)}\n \n
\n
\n ${_t(message)}\n
\n
\n `\n el = el.firstElementChild;\n let parent = document.querySelector(\".toast-container\");\n if (!parent) {\n parent = document.createElement(\"div\");\n parent.innerHTML = `\n
\n
\n
\n
\n `\n let wrapper = document.querySelector(\".container-fluid\");\n wrapper.appendChild(parent);\n parent = parent.querySelector(\".toast-container\");\n }\n parent.appendChild(el);\n return el;\n }\n\n /**\n * update the form with the response from the server\n */\n update_form(form, data) {\n console.info(\"*** UPDATE FORM ***\", data)\n\n let hide = data.hide || [];\n let show = data.show || [];\n let readonly = data.readonly || [];\n let editable = data.editable || [];\n let errors = data.errors || [];\n let messages = data.messages || [];\n let notifications = data.notifications || [];\n let updates = data.updates || [];\n let html = data.html || [];\n let attributes = data.attributes || [];\n\n // render field errors\n for (const record of errors) {\n let name, error, rest;\n ({name, error, ...rest} = record);\n let el = this.get_form_field_by_name(form, name);\n if (!el) continue;\n if (error) {\n this.set_field_error(el, error);\n } else {\n this.remove_field_error(el);\n }\n }\n\n // render status messages\n for (const record of messages) {\n let name, error, rest;\n ({message, level, ...rest} = record);\n let level = level || \"info\";\n let message = message || \"\";\n this.add_statusmessage(message, level, rest);\n }\n\n // render notification messages\n for (const record of notifications) {\n let title, message, rest;\n ({title, message, ...rest} = record);\n let el = this.add_notification(title, message, rest);\n $(el).toast(\"show\");\n }\n\n // hide fields\n for (const record of hide) {\n let name, rest;\n ({name, ...rest} = record);\n let el = this.get_form_field_by_name(form, name);\n if (!el) continue;\n this.toggle_field_visibility(el, false);\n }\n\n // show fields\n for (const record of show) {\n let name, rest;\n ({name, ...rest} = record);\n let el = this.get_form_field_by_name(form, name);\n if (!el) continue;\n this.toggle_field_visibility(el, true);\n }\n\n // readonly fields\n for (const record of readonly) {\n let name, message, rest;\n ({name, message, ...rest} = record);\n let el = this.get_form_field_by_name(form, name);\n if (!el) continue;\n this.set_field_readonly(el, message);\n }\n\n // editable fields\n for (const record of editable) {\n let name, message, rest;\n ({name, message, ...rest} = record);\n let el = this.get_form_field_by_name(form, name);\n if (!el) continue;\n this.set_field_editable(el, message);\n }\n\n // updated fields\n for (const record of updates) {\n let name, value, rest;\n ({name, value, ...rest} = record);\n let el = this.get_form_field_by_name(form, name);\n if (!el) continue;\n this.set_field_value(el, value);\n }\n\n // html\n for (const record of html) {\n let selector, html, rest;\n ({selector, html, ...rest} = record);\n let el = form.querySelector(selector);\n if (!el) continue;\n if (rest.append) {\n el.innerHTML = el.innerHTML + html;\n } else {\n el.innerHTML = html;\n }\n }\n\n // set attribute to an element\n for (const record of attributes) {\n let selector, name, value, rest;\n ({selector, name, value, ...rest} = record);\n let el = form.querySelector(selector);\n if (!el) continue;\n if (value === null) {\n el.removeAttribute(name);\n } else {\n el.addAttribute(name, value);\n }\n }\n\n // disallow submit when field errors are present\n if (this.has_field_errors(form)) {\n this.toggle_submit(form, false);\n } else {\n this.toggle_submit(form, true);\n }\n }\n\n /**\n * return a form field by name\n */\n get_form_field_by_name(form, name) {\n // get the first element that matches the name\n let exact = form.querySelector(`[name='${name}']`);\n let fuzzy = form.querySelector(`[name^='${name}']`);\n let field = exact || fuzzy || null;\n if (field === null) {\n return null;\n }\n return field;\n }\n\n /**\n * return a dictionary of all the form values\n */\n get_form_data(form) {\n let data = {};\n let form_data = new FormData(form);\n form_data.forEach(function(value, key) {\n data[key] = value;\n });\n return data;\n }\n\n /**\n * Return form fields for the given selectors of the config\n */\n get_form_fields(form) {\n console.debug(`EditForm::get_form_fields(${form})`);\n let fields = [];\n let selectors = this.config.field_selectors;\n for (const selector of selectors) {\n let nodes = form.querySelectorAll(selector);\n fields = fields.concat(...nodes.values())\n }\n return fields\n }\n\n /**\n * returns the name of the field w/o ZPublisher converter\n */\n get_field_name(field) {\n let name = field.name;\n return name.split(\":\")[0];\n }\n\n /**\n * return the value of the form field\n */\n get_field_value(field) {\n if (this.is_checkbox(field)) {\n // returns true/false for checkboxes\n return field.checked;\n } else if (this.is_select(field)) {\n // returns a list of selected option\n let selected = field.selectedOptions;\n return Array.prototype.map.call(selected, (option) => option.value)\n } else if (this.is_single_reference(field)) {\n // returns the value of the `uid` attribute\n return field.getAttribute(\"uid\");\n } else if (this.is_multi_reference(field)) {\n // returns the value of the `uid` attribute and splits it on `,`\n let uids = field.getAttribute(\"uid\");\n if (uids.length == 0) return [];\n return uids.split(\",\");\n }\n // return the plain field value\n return field.value;\n }\n\n /**\n * set the value of the form field\n */\n set_field_value(field, value) {\n // for reference/select fields\n let selected = value.selected || [];\n let options = value.options || [];\n\n // set reference value\n if (this.is_single_reference(field)) {\n for (const item of selected) {\n field.setAttribute(\"uid\", item.value);\n field.value = item.title;\n }\n }\n // set select field\n else if (this.is_select(field)) {\n if (selected.length == 0) {\n let old_selected = field.options[field.selected];\n if (old_selected) {\n selected = [old_selected.value];\n }\n }\n // remove all options\n field.options.length = 0;\n // sort options\n options.sort((a, b) => {\n let _a = a.title.toLowerCase();\n let _b = b.title.toLowerCase();\n if (a.value === null) _a = \"\";\n if (b.value === null) _b = \"\";\n if (_a < _b) return -1;\n if (_a > _b) return 1;\n });\n // build new options\n for (const option of options) {\n let el = document.createElement(\"option\");\n el.value = option.value;\n el.innerHTML = option.title;\n // select item if the value is in the selected array\n if (selected.indexOf(option.value) !== -1) {\n el.selected = true;\n }\n field.appendChild(el);\n }\n // select first item\n if (selected.length == 0) {\n field.selectedIndex = 0;\n }\n }\n // set checkbox value\n else if (this.is_checkbox(field)) {\n field.checked = value;\n }\n // set other field values\n else {\n field.value = value;\n }\n }\n\n\n /**\n * trigger `modified` event on the form\n */\n modified(el) {\n let event = new CustomEvent(\"modified\", {\n detail: {\n field: el,\n form: el.form\n }\n });\n // dispatch the event on the element\n el.form.dispatchEvent(event);\n }\n\n /**\n * trigger ajax loading events\n */\n loading(toggle=true) {\n let event_type = toggle ? \"ajaxStart\" : \"ajaxStop\";\n let event = new CustomEvent(event_type);\n document.dispatchEvent(event);\n }\n\n /**\n * notify a field change to the server ajax endpoint\n */\n notify(form, field, endpoint) {\n let data = {\n name: this.get_field_name(field),\n value: this.get_field_value(field),\n }\n this.ajax_send(form, data, endpoint);\n }\n\n /**\n * send application/json to the server\n */\n ajax_send(form, data, endpoint) {\n let view_url = document.body.dataset.viewUrl;\n let ajax_url = `${view_url}/ajax_form/${endpoint}`;\n\n let payload = Object.assign({\n \"form\": this.get_form_data(form)\n }, data)\n\n console.debug(\"EditForm::ajax_send --> \", payload)\n\n let init = {\n method: \"POST\",\n credentials: \"include\",\n body: JSON.stringify(payload),\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-CSRF-TOKEN\": document.querySelector(\"#protect-script\").dataset.token\n },\n }\n\n return this.ajax_request(form, ajax_url, init);\n }\n\n /**\n * send multipart/form-data to the server\n */\n ajax_submit(form, data, endpoint) {\n let view_url = document.body.dataset.viewUrl;\n let ajax_url = `${view_url}/ajax_form/${endpoint}`;\n\n let payload = new FormData(form);\n\n // update form data\n for(let [key, value] of Object.entries(data)) {\n payload.set(key, value);\n }\n\n console.debug(\"EditForm::ajax_submit --> \", payload)\n\n let init = {\n method: \"POST\",\n body: payload,\n }\n\n return this.ajax_request(form, ajax_url, init);\n }\n\n\n /**\n * execute ajax request\n */\n ajax_request(form, url, init) {\n // send ajax request to server\n this.loading(true);\n let request = new Request(url, init);\n return fetch(request)\n .then((response) => {\n if (!response.ok) {\n return Promise.reject(response);\n }\n return response.json();\n })\n .then((data) => {\n console.debug(\"EditForm::ajax_request --> \", data);\n this.update_form(form, data);\n this.loading(false);\n })\n .catch((error) => {\n console.error(error);\n this.loading(false);\n });\n }\n\n /**\n * Toggle element disable\n */\n toggle_disable(el, toggle) {\n if (el) {\n el.disabled = toggle;\n }\n }\n\n /**\n * Checks if the element is a textarea field\n */\n is_textarea(el) {\n return el.tagName == \"TEXTAREA\";\n }\n\n /**\n * Checks if the elment is a select field\n */\n is_select(el) {\n return el.tagName == \"SELECT\";\n }\n\n /**\n * Checks if the element is a multiple select field\n */\n is_multiple_select(el) {\n return this.is_select(el) && el.hasAttribute(\"multiple\");\n }\n\n /**\n * Checks if the element is an input field\n */\n is_input(el) {\n return el.tagName === \"INPUT\";\n }\n\n /**\n * Checks if the element is an input[type='text'] field\n */\n is_text(el) {\n return this.is_input(el) && el.type === \"text\";\n }\n\n /**\n * Checks if the element is a button field\n */\n is_button(el) {\n return el.tagName === \"BUTTON\";\n }\n\n /**\n * Checks if the element is an input[type='button'] field\n */\n is_input_button(el) {\n return this.is_input(el) && el.type === \"button\";\n }\n\n /**\n * Checks if the element is an input[type='checkbox'] field\n */\n is_checkbox(el) {\n return this.is_input(el) && el.type === \"checkbox\";\n }\n\n /**\n * Checks if the element is an input[type='radio'] field\n */\n is_radio(el) {\n return this.is_input(el) && el.type === \"radio\";\n }\n\n /**\n * Checks if the element is a SENAITE reference field\n */\n is_reference(el) {\n return el.classList.contains(\"referencewidget\");\n }\n\n /**\n * Checks if the element is a SENAITE single-reference field\n */\n is_single_reference(el) {\n return this.is_reference(el) && el.getAttribute(\"multivalued\") == \"0\";\n }\n\n /**\n * Checks if the element is a SENAITE multi-reference field\n */\n is_multi_reference(el) {\n return this.is_reference(el) && el.getAttribute(\"multivalued\") == \"1\";\n }\n\n /**\n * event handler for `mutated` event\n */\n on_mutated(event) {\n console.debug(\"EditForm::on_mutated\");\n let form = event.detail.form;\n let mutations = event.detail.mutations;\n // reduce multiple mutations on the same node to one\n let seen = [];\n for (const mutation of mutations) {\n if (seen.indexOf(mutation.target) > -1) {\n continue;\n }\n seen = seen.concat(mutation.target);\n this.handle_mutation(form, mutation);\n }\n }\n\n /**\n * event handler for `modified` event\n */\n on_modified(event) {\n console.debug(\"EditForm::on_modified\");\n let form = event.detail.form;\n let field = event.detail.field;\n this.notify(form, field, \"modified\");\n }\n\n /**\n * event handler for `submit` event\n */\n on_submit(event) {\n console.debug(\"EditForm::on_submit\");\n event.preventDefault();\n let data = {}\n let form = event.currentTarget.closest(\"form\");\n // NOTE: submit input field not included in request form data!\n let submitter = event.submitter;\n if (submitter) {\n data[submitter.name] = submitter.value;\n // disable submit button during ajax call\n this.toggle_disable(submitter, true);\n }\n this.ajax_submit(form, data, \"submit\")\n .then((response) =>\n // enable submit button after ajax call again\n this.toggle_disable(submitter, false));\n }\n\n /**\n * event handler for `blur` event\n */\n on_blur(event) {\n console.debug(\"EditForm::on_blur\");\n let el = event.currentTarget;\n this.modified(el);\n }\n\n /**\n * event handler for `click` event\n */\n on_click(event) {\n console.debug(\"EditForm::on_click\");\n let el = event.currentTarget;\n this.modified(el);\n }\n\n /**\n * event handler for `change` event\n */\n on_change(event) {\n console.debug(\"EditForm::on_change\");\n let el = event.currentTarget;\n this.modified(el);\n }\n\n}\n\nexport default EditForm;\n","\n/* Please use this command to compile this file into the parent `js` directory:\n coffee --no-header -w -o ../ -c site.coffee\n */\nvar Site,\n bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };\n\nSite = (function() {\n\n /**\n * Creates a new instance of Site\n */\n function Site() {\n this.set_cookie = bind(this.set_cookie, this);\n this.read_cookie = bind(this.read_cookie, this);\n this.authenticator = bind(this.authenticator, this);\n // console.debug(\"Site::init\");\n }\n\n\n /**\n * Returns the authenticator value\n */\n\n Site.prototype.authenticator = function() {\n var auth, url_params;\n auth = $(\"input[name='_authenticator']\").val();\n if (!auth) {\n url_params = new URLSearchParams(window.location.search);\n auth = url_params.get(\"_authenticator\");\n }\n return auth;\n };\n\n\n /**\n * Reads a cookie value\n * @param {name} the name of the cookie\n */\n\n Site.prototype.read_cookie = function(name) {\n var c, ca, i;\n // console.debug(\"Site::read_cookie:\" + name);\n name = name + '=';\n ca = document.cookie.split(';');\n i = 0;\n while (i < ca.length) {\n c = ca[i];\n while (c.charAt(0) === ' ') {\n c = c.substring(1);\n }\n if (c.indexOf(name) === 0) {\n return c.substring(name.length, c.length);\n }\n i++;\n }\n return null;\n };\n\n\n /**\n * Sets a cookie value\n * @param {name} the name of the cookie\n * @param {value} the value of the cookie\n */\n\n Site.prototype.set_cookie = function(name, value) {\n var d, expires;\n // console.debug(\"Site::set_cookie:name=\" + name + \", value=\" + value);\n d = new Date;\n d.setTime(d.getTime() + 1 * 24 * 60 * 60 * 1000);\n expires = 'expires=' + d.toUTCString();\n document.cookie = name + '=' + value + ';' + expires + ';path=/';\n };\n\n return Site;\n\n})();\n\nexport default Site;\n","/* SENAITE Sidebar\n *\n * The sidebar shows when the mouse enters and hides when the mouse leaves the\n * HTML element.\n *\n * It keeps open when the toggle button was clicked.\n */\n\nclass Sidebar{\n\n constructor(config) {\n\n this.config = Object.assign({\n \"el\": \"sidebar\",\n \"toggle_el\": \"sidebar-header\",\n \"cookie_key\": \"sidebar-toggle\",\n \"timeout\": 1000,\n }, config);\n\n // Timer ID\n this.tid = null;\n\n // Bind \"this\" context when called\n this.maximize = this.maximize.bind(this);\n this.minimize = this.minimize.bind(this);\n this.on_click = this.on_click.bind(this);\n this.on_mouseenter = this.on_mouseenter.bind(this)\n this.on_mouseleave = this.on_mouseleave.bind(this);\n\n // toggle button handler\n this.toggle_el = document.getElementById(this.config.toggle_el);\n if (this.toggle_el) {\n this.toggle_el.addEventListener(\"click\", this.on_click);\n }\n\n // sidebar view/hide handler\n this.el = document.getElementById(this.config.el);\n if (this.el) {\n this.el.addEventListener(\"mouseenter\", this.on_mouseenter);\n this.el.addEventListener(\"mouseleave\", this.on_mouseleave);\n\n if (this.is_toggled()) {\n this.el.classList.remove(\"minimized\");\n this.el.classList.add(\"toggled\");\n }\n }\n\n return this;\n }\n\n is_toggled() {\n return window.site.read_cookie(this.config.cookie_key) == \"true\";\n }\n\n toggle(toggle=false) {\n window.site.set_cookie(this.config.cookie_key, toggle)\n if (toggle) {\n this.el.classList.add(\"toggled\")\n this.maximize();\n } else {\n this.el.classList.remove(\"toggled\")\n this.minimize();\n }\n }\n\n minimize() {\n this.el.classList.add(\"minimized\");\n }\n\n maximize() {\n this.el.classList.remove(\"minimized\");\n }\n\n on_click(event) {\n // console.debug(\"Sidebar::on_click:event=\", event)\n clearTimeout(this.tid);\n this.toggle(!this.is_toggled());\n }\n\n on_mouseenter(event) {\n // console.debug(\"Sidebar::on_mouseenter:event=\", event)\n clearTimeout(this.tid);\n if (this.is_toggled()) return\n this.tid = setTimeout(this.maximize, this.config.timeout);\n }\n\n on_mouseleave(event) {\n // console.debug(\"Sidebar::on_mouseleave:event=\", event)\n clearTimeout(this.tid);\n if (this.is_toggled()) return\n this.minimize();\n // console.debug(\"Clearing sidebar timeout\", this.tid);\n }\n}\n\nexport default Sidebar;\n","const __WEBPACK_NAMESPACE_OBJECT__ = React;","const __WEBPACK_NAMESPACE_OBJECT__ = ReactDOM;","class ReferenceWidgetAPI {\n\n constructor(props) {\n console.debug(\"ReferenceWidgetAPI::constructor\")\n this.api_url = props.api_url;\n this.on_api_error = props.on_api_error || function(response) {};\n return this;\n }\n\n get_api_url(endpoint) {\n return `${this.api_url}/${endpoint}#${location.search}`\n }\n\n /*\n * Fetch Ajax API resource from the server\n *\n * @param {string} endpoint\n * @param {object} options\n * @returns {Promise}\n */\n get_json(endpoint, options) {\n var data, init, method, on_api_error, request, url;\n if (options == null) {\n options = {};\n }\n method = options.method || \"POST\";\n data = JSON.stringify(options.data) || \"{}\";\n on_api_error = this.on_api_error;\n url = this.get_api_url(endpoint);\n init = {\n method: method,\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-CSRF-TOKEN\": this.get_csrf_token()\n },\n body: method === \"POST\" ? data : null,\n credentials: \"include\"\n };\n console.info(\"ReferenceWidgetAPI::fetch:endpoint=\" + endpoint + \" init=\", init);\n request = new Request(url, init);\n return fetch(request).then(function(response) {\n if (!response.ok) {\n return Promise.reject(response);\n }\n return response;\n }).then(function(response) {\n return response.json();\n }).catch(function(response) {\n on_api_error(response);\n return response;\n });\n }\n\n search(catalog, query, params) {\n params = params || {};\n let url = `search?catalog=${catalog}`;\n for(let [key, value] of Object.entries(query)) {\n // handle arrays as repeating parameters\n if (Array.isArray(value)) {\n value.forEach( (item) => {\n url += `&${key}=${item}`;\n });\n continue;\n }\n // workaround for path queries\n if (key == \"path\") {\n value = value.query || null;\n if (value.depth !== null) {\n url += `&depth=${value.depth}`;\n }\n }\n if (value) {\n url += `&${key}=${value}`;\n }\n }\n for(let [key, value] of Object.entries(params)) {\n url += `&${key}=${value}`;\n }\n console.debug(\"ReferenceWidgetAPI::search:url=\", url);\n return this.get_json(url, {method: \"GET\"});\n }\n\n /*\n * Get the plone.protect CSRF token\n * Note: The fields won't save w/o that token set\n */\n get_csrf_token() {\n return document.querySelector(\"#protect-script\").dataset.token;\n };\n\n}\n\nexport default ReferenceWidgetAPI;\n","import React from \"react\";\nimport ReactDOM from \"react-dom\";\n\n\nclass ReferenceField extends React.Component {\n\n constructor(props) {\n super(props);\n\n this.state = {}\n\n // React reference to the input field\n // https://reactjs.org/docs/react-api.html#reactcreateref\n this.input_field_ref = React.createRef();\n\n // bind event handlers\n this.on_focus = this.on_focus.bind(this);\n this.on_blur = this.on_blur.bind(this);\n this.on_change = this.on_change.bind(this);\n this.on_keydown = this.on_keydown.bind(this);\n this.on_keypress = this.on_keypress.bind(this);\n this.on_clear_click = this.on_clear_click.bind(this);\n this.on_search_click = this.on_search_click.bind(this);\n }\n\n /*\n * Returns the search value from the input field\n */\n get_search_value() {\n return this.input_field_ref.current.value;\n }\n\n /*\n * Handler when the search field get focused\n */\n on_focus(event) {\n console.debug(\"ReferenceField::on_focus\");\n if (this.props.on_focus) {\n let value = this.get_search_value() || null;\n this.props.on_focus(value);\n }\n }\n\n /*\n * Handler when the search field lost focus\n */\n on_blur(event) {\n console.debug(\"ReferenceField::on_blur\");\n if (this.props.on_blur) {\n let value = this.get_search_value();\n this.props.on_blur(value);\n }\n }\n\n /*\n * Handler when the search value changed\n */\n on_change(event) {\n event.preventDefault();\n let value = this.get_search_value();\n console.debug(\"ReferenceField::on_change:value: \", value);\n if (this.props.on_search) {\n this.props.on_search(value);\n }\n }\n\n /*\n * Handler for keydown events in the search field\n *\n */\n on_keydown(event) {\n // backspace\n if (event.which == 8) {\n if (this.get_search_value() == \"\") {\n this.props.on_clear();\n }\n }\n\n // down arrow\n if (event.which == 40) {\n if (this.props.on_arrow_key) {\n this.props.on_arrow_key(\"down\");\n }\n }\n // up arrow\n if (event.which == 38) {\n if (this.props.on_arrow_key) {\n this.props.on_arrow_key(\"up\");\n }\n }\n\n // left arrow\n if (event.which == 37) {\n if (this.props.on_arrow_key) {\n this.props.on_arrow_key(\"left\");\n }\n }\n\n // right arrow\n if (event.which == 39) {\n if (this.props.on_arrow_key) {\n this.props.on_arrow_key(\"right\");\n }\n }\n }\n\n /*\n * Handler for keypress events in the search field\n *\n */\n on_keypress(event) {\n if (event.which == 13) {\n console.debug(\"ReferenceField::on_keypress:ENTER\");\n // prevent form submission when clicking ENTER\n event.preventDefault();\n if (this.props.on_enter) {\n this.props.on_enter();\n }\n\n }\n }\n\n on_clear_click(event) {\n event.preventDefault();\n if (this.props.on_clear) {\n let value = this.get_search_value();\n this.props.on_clear(value);\n // clear the input field\n this.input_field_ref.current.value = \"\"\n }\n }\n\n on_search_click(event) {\n event.preventDefault();\n if (this.props.on_search) {\n let value = this.get_search_value();\n this.props.on_search(value);\n }\n }\n\n render() {\n return (\n
\n
\n \n
\n \n \n
\n
\n
\n );\n }\n}\n\nexport default ReferenceField;\n","import React from \"react\";\nimport ReactDOM from \"react-dom\";\n\n\nclass ReferenceResults extends React.Component {\n\n constructor(props) {\n super(props);\n\n // bind event handlers\n this.on_select = this.on_select.bind(this);\n this.on_page = this.on_page.bind(this);\n this.on_prev_page = this.on_prev_page.bind(this);\n this.on_next_page = this.on_next_page.bind(this);\n this.on_close = this.on_close.bind(this);\n }\n\n /*\n * Return the header columns config\n *\n * @returns {Array} of column config objects\n */\n get_columns() {\n return this.props.columns || [];\n }\n\n /*\n * Return only the (field-)names of the columns config\n *\n * @returns {Array} of column names\n */\n get_column_names() {\n let columns = this.get_columns();\n return columns.map((column) => {\n return column.name;\n });\n }\n\n /*\n * Return only the labels of the columns config\n *\n * @returns {Array} of column labels\n */\n get_column_labels() {\n let columns = this.get_columns();\n return columns.map((column) => { return column.label });\n }\n\n /*\n * Return the search results\n *\n * @returns {Array} of result objects (items of `senaite.jsonapi` response)\n */\n get_results() {\n return this.props.results || [];\n }\n\n /*\n * Checks if results are available\n *\n * @returns {Boolean} true if there are results, false otherwise\n */\n has_results() {\n return this.get_results().length > 0;\n }\n\n /*\n * Returns the style object for the dropdown table\n *\n * @returns {Object} of ReactJS CSS styles\n */\n get_style() {\n return {\n minWidth: this.props.width || \"400px\",\n backgroundColor: \"white\",\n zIndex: 999999\n }\n }\n\n /*\n * Returns the UID of a result object\n *\n * @returns {String} UID of the result\n */\n get_result_uid(result) {\n return result.uid || \"NO UID FOUND!\";\n }\n\n /*\n * Checks wehter the UID is already in the list of selected UIDs\n *\n * @returns {Boolean} true if the UID is already selected, false otherwise\n */\n is_uid_selected(uid) {\n return this.props.uids.indexOf(uid) > -1;\n }\n\n /*\n * Build Header columns\n *\n * @returns {Array} of ... columns\n */\n build_header_columns() {\n let columns = [];\n for (let column of this.get_columns()) {\n let label = column.label || column.title;\n let width = column.width || \"auto\";\n let align = column.align || \"left\";\n columns.push(\n \n {_t(label)}\n \n );\n }\n // Append additional column for usage state\n columns.push(\n \n )\n return columns;\n }\n\n /*\n * Build table rows\n *\n * @returns {Array} of ... rows\n */\n build_rows() {\n let rows = [];\n let results = this.get_results();\n results.forEach((result, index) => {\n let uid = this.get_result_uid(result);\n rows.push(\n \n {this.build_columns(result)}\n \n );\n });\n return rows\n }\n\n /*\n * Build Header columns\n *\n * @returns {Array} of ... columns\n */\n build_columns(result) {\n let columns = []\n let searchterm = this.props.searchterm || \"\";\n for (let name of this.get_column_names()) {\n let value = result[name];\n let highlighted = this.highlight(value, searchterm);\n columns.push(\n \n );\n }\n let uid = result.uid;\n let used = this.props.uids.indexOf(uid) > -1;\n columns.push(\n {used && }\n );\n return columns;\n }\n\n /*\n * Highlight any found match of the searchterm in the text\n *\n * @returns {String} highlighted text\n */\n highlight(text, searchterm) {\n if (searchterm.length == 0) return text;\n try {\n let rx = new RegExp(searchterm, \"gi\");\n text = text.replaceAll(rx, (m) => {\n return \"\"+m+\"\";\n });\n } catch (error) {\n // pass\n }\n return text\n }\n\n /*\n * Build pagination
  • ...
  • items\n *\n * @returns {Array} Pagination JSX\n */\n build_pages() {\n let pages = [];\n for (let page=1; page <= this.props.pages; page++) {\n let cls = [\"page-item\"];\n if (this.props.page == page) cls.push(\"active\");\n pages.push(\n
  • \n \n
  • \n );\n }\n return pages;\n }\n\n /*\n * Build pagination next button\n *\n * @returns {Array} Next button JSX\n */\n build_next_button() {\n let cls = [\"page-item\"]\n if (!this.props.next_url) cls.push(\"disabled\")\n return (\n
  • \n \n
  • \n )\n }\n\n /*\n * Build pagination previous button\n *\n * @returns {Array} Previous button JSX\n */\n build_prev_button() {\n let cls = [\"page-item\"]\n if (!this.props.prev_url) cls.push(\"disabled\")\n return (\n
  • \n \n
  • \n )\n }\n\n /*\n * Build results dropdown close button\n *\n * @returns {Array} Close button JSX\n */\n build_close_button() {\n return (\n \n )\n }\n\n /*\n * Event handler when a result was selected\n */\n on_select(event) {\n event.preventDefault();\n let target = event.currentTarget;\n let uid = target.getAttribute(\"uid\")\n console.debug(\"ReferenceResults::on_select:event=\", event);\n if (this.props.on_select) {\n this.props.on_select(uid);\n }\n }\n\n /*\n * Event handler when a page was clicked\n */\n on_page(event) {\n event.preventDefault();\n let target = event.currentTarget;\n let page = target.getAttribute(\"page\")\n console.debug(\"ReferenceResults::on_page:event=\", event);\n if (page == this.props.page) {\n return;\n }\n if (this.props.on_page) {\n this.props.on_page(page);\n }\n }\n\n /*\n * Event handler when the pagination previous button was clicked\n */\n on_prev_page(event) {\n event.preventDefault();\n console.debug(\"ReferenceResults::on_prev_page:event=\", event);\n let page = this.props.page;\n if (page < 2) {\n console.warn(\"No previous pages available!\");\n return;\n }\n if (this.props.on_page) {\n this.props.on_page(page - 1);\n }\n }\n\n /*\n * Event handler when the pagination next button was clicked\n */\n on_next_page(event) {\n event.preventDefault();\n console.debug(\"ReferenceResults::on_next_page:event=\", event);\n let page = this.props.page;\n if (page + 1 > this.props.pages) {\n console.warn(\"No next pages available!\");\n return;\n }\n if (this.props.on_page) {\n this.props.on_page(page + 1);\n }\n }\n\n /*\n * Event handler when the dropdown close button was clicked\n */\n on_close(event) {\n event.preventDefault();\n console.debug(\"ReferenceResults::on_close:event=\", event);\n if (this.props.on_clear) {\n this.props.on_clear();\n }\n }\n\n /*\n * Render the reference results selection\n */\n render() {\n if (!this.has_results()) {\n return null;\n }\n return (\n
    \n
    \n {this.build_close_button()}\n
    \n \n \n \n {this.build_header_columns()}\n \n \n \n {this.build_rows()}\n \n
    \n {this.props.pages > 1 &&\n \n }\n
    \n );\n }\n}\n\nexport default ReferenceResults;\n","import React from \"react\";\nimport ReactDOM from \"react-dom\";\n\n\nclass References extends React.Component {\n\n constructor(props) {\n super(props);\n\n this.on_deselect = this.on_deselect.bind(this);\n }\n\n get_selected_uids() {\n return this.props.uids || [];\n }\n\n /*\n * Simple template interpolation that replaces ${...} placeholders\n * with any found value from the context object.\n *\n * https://stackoverflow.com/questions/29182244/convert-a-string-to-a-template-string\n */\n interpolate(template, context) {\n for(let [key, value] of Object.entries(context)) {\n template = template.replace(new RegExp('\\\\$\\\\{' + key + '\\\\}', 'g'), value)\n }\n return template;\n }\n\n render_display_template(uid) {\n let template = this.props.display_template;\n let context = this.props.records[uid];\n if (!context) return uid;\n return this.interpolate(template, context);\n }\n\n build_selected_items() {\n let items = [];\n let selected_uids = this.get_selected_uids();\n\n for (let uid of selected_uids) {\n items.push(\n
  • \n
    \n \n \n
    \n\n
  • \n );\n }\n return items\n }\n\n on_deselect(event) {\n event.preventDefault();\n let target = event.currentTarget;\n let uid = target.getAttribute(\"uid\");\n console.debug(\"References::on_deselect: Remove UID\", uid);\n if (this.props.on_deselect) {\n this.props.on_deselect(uid);\n }\n }\n\n render() {\n return (\n
    \n
      \n {this.build_selected_items()}\n
    \n {/* submitted in form */}\n \n
    \n );\n }\n}\n\nexport default References;\n","import React from \"react\"\nimport ReactDOM from \"react-dom\"\n\nimport ReferenceWidgetAPI from \"./api.js\"\nimport ReferenceField from \"./components/ReferenceField.js\"\nimport ReferenceResults from \"./components/ReferenceResults.js\"\nimport References from \"./components/References.js\"\n\n\nclass UIDReferenceWidgetController extends React.Component {\n\n constructor(props) {\n super(props);\n\n // Internal state\n this.state = {\n results: [], // `items` list of search results coming from `senaite.jsonapi`\n searchterm: \"\", // the search term that was entered by the user\n loading: false, // loading flag when searching for results\n count: 0, // count of results (coming from `senaite.jsonapi`)\n page: 1, // current page (coming from `senaite.jsonapi`)\n pages: 1, // number of pages (coming from `senaite.jsonapi`)\n next_url: null, // next page API URL (coming from `senaite.jsonapi`)\n prev_url: null, // previous page API URL (coming from `senaite.jsonapi`)\n b_start: 1, // batch start for pagination (see `senaite.jsonapi.batch`)\n focused: 0, // current result that has the focus\n }\n\n // Root input HTML element\n let el = props.root_el;\n\n // Data keys located at the root element\n // -> initial values are set from the widget class\n const data_keys = [\n \"id\",\n \"name\",\n \"uids\",\n \"api_url\",\n \"records\",\n \"catalog\",\n \"query\",\n \"columns\",\n \"display_template\",\n \"limit\",\n \"multi_valued\",\n \"disabled\",\n \"readonly\",\n ]\n\n // Query data keys and set state with parsed JSON value\n for (let key of data_keys) {\n let value = el.dataset[key];\n this.state[key] = this.parse_json(value);\n }\n\n // Initialize communication API with the API URL\n this.api = new ReferenceWidgetAPI({\n api_url: this.state.api_url,\n });\n\n // Bind callbacks to current context\n this.search = this.search.bind(this);\n this.goto_page = this.goto_page.bind(this);\n this.clear_results = this.clear_results.bind(this);\n this.select = this.select.bind(this);\n this.select_focused = this.select_focused.bind(this);\n this.deselect = this.deselect.bind(this);\n this.navigate_results = this.navigate_results.bind(this);\n this.on_keydown = this.on_keydown.bind(this);\n this.on_click = this.on_click.bind(this);\n\n // dev only\n window.widget = this;\n\n return this\n }\n\n componentDidMount() {\n // Bind event listeners of the document\n document.addEventListener(\"keydown\", this.on_keydown, false);\n document.addEventListener(\"click\", this.on_click, false)\n }\n\n componentWillUnmount() {\n // Remove event listeners of the document\n document.removeEventListener(\"keydown\", this.on_keydown, false);\n document.removeEventListener(\"click\", this.on_click, false);\n }\n\n /*\n * JSON parse the given value\n *\n * @param {String} value: The JSON value to parse\n */\n parse_json(value) {\n try {\n return JSON.parse(value)\n } catch (error) {\n console.error(`Could not parse \"${value}\" to JSON`);\n }\n }\n\n is_disabled() {\n if (this.state.disabled) {\n return true;\n }\n if (this.state.readonly) {\n return true;\n }\n if (!this.state.multi_valued && this.state.uids.length > 0) {\n return true;\n }\n return false;\n }\n\n /*\n * Create a query object for the API\n *\n * This method prepares a query from the current state variables,\n * which can be used to call the `api.search` method.\n *\n * @param {Object} options: Additional options to add to the query\n * @returns {Object} The query object\n */\n make_query(options) {\n options = options || {};\n return Object.assign({\n q: this.state.searchterm,\n limit: this.state.limit,\n complete: 1,\n }, options, this.state.query);\n }\n\n /*\n * Execute a search query and set the results to the state\n *\n * @param {Object} url_params: Additional search params for the API search URL\n * @returns {Promise}\n */\n fetch_results(url_params) {\n url_params = url_params || {};\n // prepare the server request\n let self = this;\n let query = this.make_query();\n this.toggle_loading(true);\n let promise = this.api.search(this.state.catalog, query, url_params);\n promise.then(function(data) {\n console.debug(\"ReferenceWidgetController::fetch_results:GOT DATA: \", data);\n self.set_results_data(data);\n self.toggle_loading(false);\n });\n return promise;\n }\n\n /*\n * Execute a search for the given searchterm\n *\n * @param {String} searchterm: The value entered into the search field\n * @returns {Promise}\n */\n search(searchterm) {\n if (!searchterm && this.state.results.length > 0) {\n this.state.searchterm = \"\";\n return;\n }\n console.debug(\"ReferenceWidgetController::search:searchterm:\", searchterm);\n // set the searchterm directly to avoid re-rendering\n this.state.searchterm = searchterm || \"\";\n return this.fetch_results();\n }\n\n /*\n * Fetch results of a page\n *\n * @param {Integer} page: The page to fetch\n * @returns {Promise}\n */\n goto_page(page) {\n page = parseInt(page);\n let limit = parseInt(this.state.limit)\n // calculate the beginning of the page\n // Note: this is the count of previous items that are excluded\n let b_start = page * limit - limit;\n return this.fetch_results({b_start: b_start});\n }\n\n /*\n * Add the UID of a search result to the state\n *\n * @param {String} uid: The selected UID\n * @returns {Array} uids: current selected UIDs\n */\n select(uid) {\n console.debug(\"ReferenceWidgetController::select:uid:\", uid);\n // create a copy of the selected UIDs\n let uids = [].concat(this.state.uids);\n // Add the new UID if it is not selected yet\n if (uids.indexOf(uid) == -1) {\n uids.push(uid);\n }\n this.setState({uids: uids});\n if (uids.length > 0 && !this.state.multi_valued) {\n this.clear_results();\n }\n return uids;\n }\n\n /*\n * Add/remove the focused result\n *\n */\n select_focused() {\n console.debug(\"ReferenceWidgetController::select_focused\");\n let focused = this.state.focused;\n let result = this.state.results.at(focused);\n if (result) {\n let uid = result.uid;\n if (this.state.uids.indexOf(uid) == -1) {\n this.select(uid);\n } else {\n this.deselect(uid);\n }\n }\n }\n\n /*\n * Remove the UID of a reference from the state\n *\n * @param {String} uid: The selected UID\n * @returns {Array} uids: current selected UIDs\n */\n deselect(uid) {\n console.debug(\"ReferenceWidgetController::deselect:uid:\", uid);\n let uids = [].concat(this.state.uids);\n let pos = uids.indexOf(uid);\n if (pos > -1) {\n uids.splice(pos, 1);\n }\n this.setState({uids: uids});\n return uids;\n }\n\n /*\n * Navigate the results either up or down\n *\n * @param {String} direction: either up or down\n */\n navigate_results(direction) {\n let page = this.state.page;\n let pages = this.state.pages;\n let results = this.state.results;\n let focused = this.state.focused;\n let searchterm = this.state.searchterm;\n\n console.debug(\"ReferenceWidgetController::navigate_results:focused:\", focused);\n\n if (direction == \"up\") {\n if (focused > 0) {\n this.setState({focused: focused - 1});\n } else {\n this.setState({focused: 0});\n if (page > 1) {\n this.goto_page(page - 1);\n }\n }\n }\n\n else if (direction == \"down\") {\n if (this.state.results.length == 0) {\n this.search(searchterm);\n }\n if (focused < results.length - 1) {\n this.setState({focused: focused + 1});\n } else {\n this.setState({focused: 0});\n if (page < pages) {\n this.goto_page(page + 1);\n }\n }\n }\n\n else if (direction == \"left\") {\n this.setState({focused: 0});\n if (page > 0) {\n this.goto_page(page - 1);\n }\n }\n\n else if (direction == \"right\") {\n this.setState({focused: 0});\n if (page < pages) {\n this.goto_page(page + 1);\n }\n }\n }\n\n /*\n * Toggle loading state\n *\n * @param {Boolean} toggle: The loading state to set\n * @returns {Boolean} toggle: The current loading state\n */\n toggle_loading(toggle) {\n if (toggle == null) {\n toggle = false;\n }\n this.setState({\n loading: toggle\n });\n return toggle;\n }\n\n /*\n * Set results data coming from `senaite.jsonapi`\n *\n * @param {Object} data: JSON search result object returned from `senaite.jsonapi`\n */\n set_results_data(data) {\n data = data || {};\n let items = data.items || [];\n\n let records = Object.assign(this.state.records, {})\n // update state records\n for (let item of items) {\n let uid = item.uid;\n records[uid] = item;\n }\n\n this.setState({\n records: records,\n results: items,\n count: data.count || 0,\n page: data.page || 1,\n pages: data.pages || 1,\n next_url: data.next || null,\n prev_url: data.previous || null,\n });\n }\n\n /*\n * Clear results from the state\n */\n clear_results() {\n this.setState({\n results: [],\n count: 0,\n page: 1,\n pages: 1,\n next_url: null,\n prev_url: null,\n });\n }\n\n /*\n * ReactJS event handler for keydown event\n */\n on_keydown(event){\n // clear results when ESC key is pressed\n if(event.keyCode === 27) {\n this.clear_results();\n }\n }\n\n /*\n * ReactJS event handler for click events\n */\n on_click(event) {\n // clear results when clicked outside of the widget\n let widget = this.props.root_el;\n let target = event.target;\n if (!widget.contains(target)) {\n this.clear_results();\n }\n }\n\n render() {\n return (\n
    \n \n \n \n
    \n );\n }\n}\n\nexport default UIDReferenceWidgetController;\n","class AddressWidgetAPI {\n\n constructor(props) {\n console.debug(\"AddressWidgetAPI::constructor\")\n this.portal_url = props.portal_url;\n this.on_api_error = props.on_api_error || function(response) {};\n return this;\n }\n\n get_url(endpoint) {\n return `${this.portal_url}/${endpoint}`\n }\n\n /*\n * Fetch JSON resource from the server\n *\n * @param {string} endpoint\n * @param {object} options\n * @returns {Promise}\n */\n get_json(endpoint, options) {\n var data, init, method, on_api_error, request, url;\n if (options == null) {\n options = {};\n }\n method = options.method || \"POST\";\n data = JSON.stringify(options.data) || \"{}\";\n on_api_error = this.on_api_error;\n url = this.get_url(endpoint);\n init = {\n method: method,\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-CSRF-TOKEN\": this.get_csrf_token()\n },\n body: method === \"POST\" ? data : null,\n credentials: \"include\"\n };\n console.info(\"AddressWidgetAPI::fetch:endpoint=\" + endpoint + \" init=\", init);\n request = new Request(url, init);\n return fetch(request).then(function(response) {\n if (!response.ok) {\n return Promise.reject(response);\n }\n return response;\n }).then(function(response) {\n return response.json();\n }).catch(function(response) {\n on_api_error(response);\n return response;\n });\n }\n\n fetch_subdivisions(parent) {\n let url = `geo_subdivisions`\n console.debug(\"AddressWidgetAPI::fetch_subdivisions:url=\", url);\n let options = {\n method: \"POST\",\n data: {\n \"parent\": parent,\n }\n }\n return this.get_json(url, options)\n }\n\n /*\n * Get the plone.protect CSRF token\n */\n get_csrf_token() {\n return document.querySelector(\"#protect-script\").dataset.token;\n };\n\n}\n\nexport default AddressWidgetAPI;\n","import React from \"react\";\nimport ReactDOM from \"react-dom\";\n\n\nclass LocationSelector extends React.Component {\n\n constructor(props) {\n super(props);\n }\n\n render_options() {\n let options = [];\n let locations = this.props.locations;\n options.push(\n \n );\n if (Array.isArray(locations)) {\n for (let location of locations) {\n options.push(\n \n )\n }\n }\n return options;\n }\n\n render() {\n return (\n \n {this.render_options()}\n \n );\n }\n}\n\nexport default LocationSelector;\n","import React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport LocationSelector from \"./LocationSelector.js\";\n\n\nclass AddressField extends React.Component {\n\n constructor(props) {\n super(props);\n }\n\n is_location_selector() {\n return Array.isArray(this.props.locations);\n }\n\n is_visible() {\n let visible = true;\n if (this.is_location_selector()) {\n visible = this.props.locations.length > 0;\n }\n return visible;\n }\n\n render_element() {\n if (this.is_location_selector()) {\n return (\n \n )\n } else {\n return (\n \n )\n }\n }\n\n render() {\n if (!this.is_visible()) {\n return (\n \n )\n }\n return (\n
    \n
    \n
    \n \n
    \n {this.render_element()}\n
    \n
    \n );\n }\n}\n\nexport default AddressField;\n","import React from \"react\";\nimport ReactDOM from \"react-dom\";\n\nimport AddressField from \"./AddressField.js\";\n\n\nclass Address extends React.Component {\n\n constructor(props) {\n super(props);\n this.state = {\n country: props.country,\n subdivision1: props.subdivision1,\n subdivision2: props.subdivision2,\n city: props.city,\n zip: props.zip,\n address: props.address,\n address_type: props.address_type,\n }\n\n // Event handlers\n this.on_country_change = this.on_country_change.bind(this);\n this.on_subdivision1_change = this.on_subdivision1_change.bind(this);\n this.on_subdivision2_change = this.on_subdivision2_change.bind(this);\n this.on_city_change = this.on_city_change.bind(this);\n this.on_zip_change = this.on_zip_change.bind(this);\n this.on_address_change = this.on_address_change.bind(this);\n }\n\n force_array(value) {\n if (!Array.isArray(value)) {\n value = [];\n }\n return value;\n }\n\n /**\n * Returns the list of first-level subdivisions of the current country,\n * sorted alphabetically\n */\n get_subdivisions1() {\n let country = this.state.country;\n return this.force_array(this.props.subdivisions1[country]);\n }\n\n /**\n * Returns the list of subdivisions of the current first-level subdivision,\n * sorted sorted alphabetically\n */\n get_subdivisions2() {\n let subdivision1 = this.state.subdivision1;\n return this.force_array(this.props.subdivisions2[subdivision1]);\n }\n\n get_label(key) {\n let country = this.state.country;\n let label = this.props.labels[country];\n if (label != null && label.constructor == Object && key in label) {\n label = label[key];\n } else {\n label = this.props.labels[key];\n }\n return label;\n }\n\n /** Event triggered when the value for Country selector changes. Updates the\n * selector of subdivisions (e.g. states) with the list of top-level\n * subdivisions for the selected country\n */\n on_country_change(event) {\n let value = event.currentTarget.value;\n console.debug(`Address::on_country_change: ${value}`);\n if (this.props.on_country_change) {\n this.props.on_country_change(value);\n }\n this.setState({\n country: value,\n subdivision1: \"\",\n subdivision2: \"\",\n });\n }\n\n /** Event triggered when the value for the Country first-level subdivision\n * (e.g. state) selector changes. Updates the selector of subdivisions (e.g.\n * districts) for the selected subdivision and country\n */\n on_subdivision1_change(event) {\n let value = event.currentTarget.value;\n console.debug(`Address::on_subdivision1_change: ${value}`);\n if (this.props.on_subdivision1_change) {\n let country = this.state.country\n this.props.on_subdivision1_change(country, value);\n }\n this.setState({\n subdivision1: value,\n subdivision2: \"\",\n });\n }\n\n /** Event triggered when the value for the second-level subdivision (e.g.\n * district) selector changes\n */\n on_subdivision2_change(event) {\n let value = event.currentTarget.value;\n console.debug(`Address::on_subdivision2_change: ${value}`);\n if (this.props.on_subdivision2_change) {\n this.props.on_subdivision2_change(value);\n }\n this.setState({subdivision2: value});\n }\n\n /** Event triggered when the value for the address field changes\n */\n on_address_change(event) {\n let value = event.currentTarget.value;\n this.setState({address: value});\n }\n\n /** Event triggered when the value for the zip field changes\n */\n on_zip_change(event) {\n let value = event.currentTarget.value;\n this.setState({zip: value});\n }\n\n /** Event triggered when the value for the city field changes\n */\n on_city_change(event) {\n let value = event.currentTarget.value;\n this.setState({city: value});\n }\n\n get_input_id(subfield) {\n let id = this.props.id;\n let index = this.props.index;\n return `${id}-${index}-${subfield}`\n }\n\n get_input_name(subfield) {\n let name = this.props.name;\n let index = this.props.index;\n return `${name}.${index}.${subfield}`\n }\n\n render() {\n return (\n
    \n \n\n \n\n \n\n \n\n \n\n \n\n \n\n
    \n );\n }\n\n}\n\nexport default Address;","import React from \"react\"\nimport ReactDOM from \"react-dom\"\n\nimport AddressWidgetAPI from \"./api.js\"\nimport Address from \"./components/Address.js\"\n\n\nclass AddressWidgetController extends React.Component {\n\n constructor(props) {\n super(props);\n\n // Root input HTML element\n let el = props.root_el;\n\n this.state = {};\n\n // Data keys located at the root element\n // -> initial values are set from the widget class\n const data_keys = [\n \"id\",\n \"name\",\n \"items\",\n \"portal_url\",\n \"labels\",\n \"countries\",\n \"subdivisions1\",\n \"subdivisions2\",\n ];\n\n // Query data keys and set state with parsed JSON value\n for (let key of data_keys) {\n let value = el.dataset[key];\n this.state[key] = this.parse_json(value);\n }\n\n // Initialize communication API with the API URL\n this.api = new AddressWidgetAPI({\n portal_url: this.state.portal_url,\n });\n\n // Bind callbacks to current context\n this.on_country_change = this.on_country_change.bind(this);\n this.on_subdivision1_change = this.on_subdivision1_change.bind(this);\n\n return this;\n }\n\n parse_json(value) {\n try {\n return JSON.parse(value);\n } catch (error) {\n console.error(`Could not parse \"${value}\" to JSON`);\n }\n }\n\n /**\n * Event triggered when the user selects a country. Function fetches and\n * updates the geo mapping with the first level subdivisions for the selected\n * country if are not up-to-date yet. It also updates the label for the first\n * level subdivision in accordance.\n */\n on_country_change(country) {\n console.debug(`widget::on_country_change: ${country}`);\n let self = this;\n let promise = this.api.fetch_subdivisions(country);\n promise.then(function(data){\n\n // Update the label with the type of 1st-level subdivisions\n let labels = {...self.state.labels};\n if (data.length > 0) {\n labels[country][\"subdivision1\"] = data[0].type;\n }\n\n // Create a copy instead of modifying the existing dict from state var\n let subdivisions = {...self.state.subdivisions1};\n\n // Only interested in names, sorted alphabetically\n subdivisions[country] = data.map((x) => x.name).sort();\n\n // Update current state with the changes\n self.setState({\n subdivisions1: subdivisions,\n labels: labels,\n });\n });\n return promise;\n }\n\n /**\n * Event triggered when the user selects a first-level subdivision of a\n * country. Function fetches and updates the geo mapping with the second level\n * subdivisions for the selected subdivision if are not up-to-date. It also\n * updates the label for the second level subdivision in accordance.\n */\n on_subdivision1_change(country, subdivision) {\n console.debug(`widget::on_subdivision1_change: ${country}, ${subdivision}`);\n let self = this;\n let promise = this.api.fetch_subdivisions(subdivision);\n promise.then(function(data){\n\n // Update the label with the type of 1st-level subdivisions\n let labels = {...self.state.labels};\n if (data.length > 0) {\n labels[country][\"subdivision2\"] = data[0].type;\n }\n\n // Create a copy instead of modifying the existing dict from state var\n let subdivisions = {...self.state.subdivisions2};\n\n // Only interested in names, sorted alphabetically\n subdivisions[subdivision] = data.map((x) => x.name).sort();\n\n // Update current state with the changes\n self.setState({\n subdivisions2: subdivisions,\n labels: labels,\n });\n });\n return promise;\n }\n\n render_items() {\n let html_items = [];\n let items = this.state.items;\n for (const [index, item] of items.entries()) {\n let section_title = \"\";\n if (items.length > 1) {\n // Only render the title if more than one address\n section_title = (\n {this.state.labels[item.type]}\n )\n }\n\n html_items.push(\n
    \n {section_title}\n \n
    \n );\n }\n return html_items;\n }\n\n render() {\n return (\n
    \n {this.render_items()}\n
    \n );\n }\n}\n\nexport default AddressWidgetController;\n","import $ from \"jquery\";\nimport I18N from \"./components/i18n.js\";\nimport {i18n, _t, _p} from \"./i18n-wrapper.js\"\nimport EditForm from \"./components/editform.js\"\nimport Site from \"./components/site.js\"\nimport Sidebar from \"./components/sidebar.js\"\nimport UIDReferenceWidgetController from \"./widgets/uidreferencewidget/widget.js\"\nimport AddressWidgetController from \"./widgets/addresswidget/widget.js\"\n\n\ndocument.addEventListener(\"DOMContentLoaded\", () => {\n console.debug(\"*** SENAITE CORE JS LOADED ***\");\n\n // Initialize i18n message factories\n window.i18n = new I18N();\n window._t = _t;\n window._p = _p;\n\n // BBB: set global `portal_url` variable\n window.portal_url = document.body.dataset.portalUrl\n\n // TinyMCE\n tinymce.init({\n height: 300,\n paste_data_images: true,\n selector: \"textarea.mce_editable,div.ArchetypesRichWidget textarea,textarea[name='form.widgets.IRichTextBehavior.text'],textarea.richTextWidget\",\n plugins: [\"paste\", \"link\", \"fullscreen\", \"table\", \"code\"],\n content_css : \"/++plone++senaite.core.static/bundles/main.css\",\n })\n // /TinyMCE\n\n // Initialize Site\n window.site = new Site();\n\n // Initialize Sidebar\n window.sidebar = new Sidebar({\n \"el\": \"sidebar\",\n });\n\n // Ajax Edit Form Handler\n var form = new EditForm({\n form_selectors: [\n \"form[name='edit_form']\",\n \"form.senaite-ajax-form\",\n ],\n field_selectors: [\n \"input[type='text']\",\n \"input[type='number']\",\n \"input[type='checkbox']\",\n \"input[type='radio']\",\n \"input[type='file']\",\n \"select\",\n \"textarea\",\n ]\n })\n\n // Init Tooltips\n $(function () {\n $(\"[data-toggle='tooltip']\").tooltip();\n $(\"select.selectpicker\").selectpicker();\n });\n\n // Widgets\n window.widgets = {};\n // Referencewidgets\n var ref_widgets = document.getElementsByClassName(\"senaite-uidreference-widget-input\");\n for (let widget of ref_widgets) {\n let id = widget.dataset.id;\n let controller = ReactDOM.render(, widget);\n window.widgets[id] = controller;\n }\n // AddressWidget\n var address_widgets = document.getElementsByClassName(\"senaite-address-widget-input\");\n for (let widget of address_widgets) {\n let id = widget.dataset.id;\n let controller = ReactDOM.render(, widget);\n window.widgets[id] = controller;\n }\n});\n"],"names":["module","exports","jQuery","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","n","getter","__esModule","d","a","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","self","this","baseUrl","$","attr","currentLanguage","split","length","toUpperCase","storage","catalogs","ttl","Date","now","valueOf","window","localStorage","JSON","e","configure","config","_setCatalog","domain","language","catalog","_storeCatalog","setItem","stringify","getUrl","loadCatalog","parseInt","getItem","parse","MessageFactory","msgid","keywords","msgstr","regexp","keyword","RegExp","replace","t","_t","i18n","I18N","p","_p","EditForm","assign","hooked_fields","on_mutated","bind","on_modified","on_submit","on_blur","on_click","on_change","init_forms","form_selectors","selector","form","document","querySelector","tagName","setup_form","watch_form","ajax_send","get_form_fields","field","hook_field","observe_mutations","addEventListener","hasAttribute","indexOf","is_button","is_input_button","is_text","is_textarea","is_select","is_radio","is_checkbox","concat","MutationObserver","mutations","event","CustomEvent","detail","dispatchEvent","observe","childList","subtree","mutation","target","added","closest","addedNodes","selectors","removedNodes","field_selectors","is_multiple_select","notify","ELEMENT_NODE","querySelectorAll","toggle","disabled","parent","css_class","classList","add","remove","message","setAttribute","existing_message","parentElement","innerHTML","div","createElement","className","appendChild","removeAttribute","msg","level","options","el","title","charAt","slice","firstElementChild","getElementById","flush","animation","autohide","delay","data","hide","show","readonly","editable","errors","messages","notifications","updates","html","attributes","name","error","record","rest","get_form_field_by_name","set_field_error","remove_field_error","add_statusmessage","add_notification","toast","toggle_field_visibility","set_field_readonly","set_field_editable","value","set_field_value","append","addAttribute","has_field_errors","toggle_submit","exact","fuzzy","FormData","forEach","fields","nodes","values","checked","selected","selectedOptions","Array","map","option","is_single_reference","getAttribute","is_multi_reference","uids","item","old_selected","sort","b","_a","toLowerCase","_b","selectedIndex","event_type","endpoint","get_field_name","get_field_value","view_url","body","dataset","viewUrl","ajax_url","payload","get_form_data","init","method","credentials","headers","token","ajax_request","entries","set","url","loading","request","Request","fetch","then","response","ok","json","Promise","reject","update_form","is_input","type","contains","is_reference","seen","handle_mutation","preventDefault","currentTarget","submitter","toggle_disable","ajax_submit","modified","fn","me","apply","arguments","Site","set_cookie","read_cookie","authenticator","auth","val","URLSearchParams","location","search","c","ca","i","cookie","substring","expires","setTime","getTime","toUTCString","Sidebar","tid","maximize","minimize","on_mouseenter","on_mouseleave","toggle_el","is_toggled","site","cookie_key","clearTimeout","setTimeout","timeout","React","ReactDOM","ReferenceWidgetAPI","props","api_url","on_api_error","get_api_url","get_csrf_token","query","params","isArray","depth","get_json","ReferenceField","state","input_field_ref","on_focus","on_keydown","on_keypress","on_clear_click","on_search_click","current","get_search_value","on_search","which","on_clear","on_arrow_key","on_enter","ref","onKeyDown","onKeyPress","onChange","onFocus","onBlur","placeholder","style","maxWidth","class","onClick","ReferenceResults","on_select","on_page","on_prev_page","on_next_page","on_close","columns","get_columns","column","label","results","get_results","minWidth","width","backgroundColor","zIndex","result","uid","align","push","rows","index","get_result_uid","focused","build_columns","searchterm","get_column_names","highlighted","highlight","dangerouslySetInnerHTML","__html","used","text","rx","replaceAll","m","pages","page","cls","join","next_url","prev_url","has_results","get_style","position","top","right","build_close_button","build_header_columns","build_rows","build_prev_button","build_pages","build_next_button","References","on_deselect","template","context","display_template","records","interpolate","items","get_selected_uids","render_display_template","build_selected_items","UIDReferenceWidgetController","count","b_start","root_el","parse_json","api","goto_page","clear_results","select","select_focused","deselect","navigate_results","widget","removeEventListener","multi_valued","q","limit","complete","url_params","make_query","toggle_loading","promise","set_results_data","fetch_results","setState","at","pos","splice","direction","next","previous","keyCode","is_disabled","AddressWidgetAPI","portal_url","get_url","LocationSelector","locations","id","render_options","AddressField","visible","is_location_selector","is_visible","for","render_element","Address","country","subdivision1","subdivision2","city","zip","address","address_type","on_country_change","on_subdivision1_change","on_subdivision2_change","on_city_change","on_zip_change","on_address_change","force_array","subdivisions1","subdivisions2","labels","constructor","subfield","get_input_id","get_input_name","countries","get_label","get_subdivisions1","get_subdivisions2","AddressWidgetController","fetch_subdivisions","subdivisions","x","subdivision","html_items","section_title","render_items","portalUrl","tinymce","height","paste_data_images","plugins","content_css","sidebar","tooltip","selectpicker","widgets","getElementsByClassName","controller","render"],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"main.js","mappings":"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","sources":["webpack:///external var \"jQuery\"","webpack:///webpack/bootstrap","webpack:///webpack/runtime/compat get default export","webpack:///webpack/runtime/define property getters","webpack:///webpack/runtime/hasOwnProperty shorthand","webpack:///./components/i18n.js","webpack:///./i18n-wrapper.js","webpack:///./components/editform.js","webpack:///./components/site.js","webpack:///./components/sidebar.js","webpack:///external var \"React\"","webpack:///external var \"ReactDOM\"","webpack:///./widgets/uidreferencewidget/api.js","webpack:///./widgets/uidreferencewidget/components/ReferenceField.js","webpack:///./widgets/uidreferencewidget/components/ReferenceResults.js","webpack:///./widgets/uidreferencewidget/components/References.js","webpack:///./widgets/uidreferencewidget/widget.js","webpack:///./widgets/addresswidget/api.js","webpack:///./widgets/addresswidget/components/LocationSelector.js","webpack:///./widgets/addresswidget/components/AddressField.js","webpack:///./widgets/addresswidget/components/Address.js","webpack:///./widgets/addresswidget/widget.js","webpack:///./senaite.core.js"],"sourcesContent":["module.exports = jQuery;","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","/* i18n integration. This is forked from jarn.jsi18n\n *\n * This is a singleton.\n * Configuration is done on the body tag data-i18ncatalogurl attribute\n * \n *\n * Or, it'll default to \"/plonejsi18n\"\n */\n\nimport $ from \"jquery\";\n\n\nvar I18N = function() {\n var self = this;\n self.baseUrl = $('body').attr('data-i18ncatalogurl');\n self.currentLanguage = $('html').attr('lang') || 'en';\n\n // Fix for country specific languages\n if (self.currentLanguage.split('-').length > 1) {\n self.currentLanguage = self.currentLanguage.split('-')[0] + '_' + self.currentLanguage.split('-')[1].toUpperCase();\n }\n\n self.storage = null;\n self.catalogs = {};\n self.ttl = 24 * 3600 * 1000;\n\n // Internet Explorer 8 does not know Date.now() which is used in e.g. loadCatalog, so we \"define\" it\n if (!Date.now) {\n Date.now = function() {\n return new Date().valueOf();\n };\n }\n\n try {\n if ('localStorage' in window && window.localStorage !== null && 'JSON' in window && window.JSON !== null) {\n self.storage = window.localStorage;\n }\n } catch (e) {}\n\n self.configure = function(config) {\n for (var key in config){\n self[key] = config[key];\n }\n };\n\n self._setCatalog = function (domain, language, catalog) {\n if (domain in self.catalogs) {\n self.catalogs[domain][language] = catalog;\n } else {\n self.catalogs[domain] = {};\n self.catalogs[domain][language] = catalog;\n }\n };\n\n self._storeCatalog = function (domain, language, catalog) {\n var key = domain + '-' + language;\n if (self.storage !== null && catalog !== null) {\n self.storage.setItem(key, JSON.stringify(catalog));\n self.storage.setItem(key + '-updated', Date.now());\n }\n };\n\n self.getUrl = function(domain, language) {\n return self.baseUrl + '?domain=' + domain + '&language=' + language;\n };\n\n self.loadCatalog = function (domain, language) {\n if (language === undefined) {\n language = self.currentLanguage;\n }\n if (self.storage !== null) {\n var key = domain + '-' + language;\n if (key in self.storage) {\n if ((Date.now() - parseInt(self.storage.getItem(key + '-updated'), 10)) < self.ttl) {\n var catalog = JSON.parse(self.storage.getItem(key));\n self._setCatalog(domain, language, catalog);\n return;\n }\n }\n }\n if (!self.baseUrl) {\n return;\n }\n $.getJSON(self.getUrl(domain, language), function (catalog) {\n if (catalog === null) {\n return;\n }\n self._setCatalog(domain, language, catalog);\n self._storeCatalog(domain, language, catalog);\n });\n };\n\n self.MessageFactory = function (domain, language) {\n language = language || self.currentLanguage;\n return function translate (msgid, keywords) {\n var msgstr;\n if ((domain in self.catalogs) && (language in self.catalogs[domain]) && (msgid in self.catalogs[domain][language])) {\n msgstr = self.catalogs[domain][language][msgid];\n } else {\n msgstr = msgid;\n }\n if (keywords) {\n var regexp, keyword;\n for (keyword in keywords) {\n if (keywords.hasOwnProperty(keyword)) {\n regexp = new RegExp('\\\\$\\\\{' + keyword + '\\\\}', 'g');\n msgstr = msgstr.replace(regexp, keywords[keyword]);\n }\n }\n }\n return msgstr;\n };\n };\n};\n\nexport default I18N;\n","import I18N from \"./components/i18n.js\";\n\n// SENAITE message factory\nvar t = null;\nexport var _t = (msgid, keywords) => {\n if (t === null) {\n let i18n = new I18N();\n console.debug(\"*** Loading `senaite.core` i18n MessageFactory ***\");\n i18n.loadCatalog(\"senaite.core\")\n t = i18n.MessageFactory(\"senaite.core\")\n }\n return t(msgid, keywords);\n}\n\n// Plone message factory\nvar p = null;\nexport var _p = (msgid, keywords) => {\n if (p === null) {\n let i18n = new I18N();\n console.debug(\"*** Loading `plone` i18n MessageFactory ***\");\n i18n.loadCatalog(\"plone\")\n p = i18n.MessageFactory(\"plone\")\n }\n return p(msgid, keywords);\n}\n","/* SENAITE Edit Form Handler\n *\n * This code handles field changes in edit forms and updates others according to\n * the changes with the help of adapters.\n *\n */\n\n// needed for Bootstrap toasts\nimport $ from \"jquery\";\n\n\nclass EditForm {\n\n constructor(config) {\n this.config = Object.assign({\n \"form_selectors\": [],\n \"field_selectors\": []\n }, config);\n\n this.hooked_fields = [];\n\n // bind event handlers\n this.on_mutated = this.on_mutated.bind(this);\n this.on_modified = this.on_modified.bind(this);\n this.on_submit = this.on_submit.bind(this);\n this.on_blur = this.on_blur.bind(this);\n this.on_click = this.on_click.bind(this);\n this.on_change = this.on_change.bind(this);\n this.init_forms();\n }\n\n /**\n * Initialize all form elements given by the config\n */\n init_forms() {\n let selectors = this.config.form_selectors;\n for (const selector of selectors) {\n let form = document.querySelector(selector);\n if (form && form.tagName === \"FORM\") {\n this.setup_form(form);\n this.watch_form(form);\n }\n }\n }\n\n /**\n * Trigger `initialized` event on the form element\n */\n setup_form(form) {\n console.debug(`EditForm::setup_form(${form})`);\n this.ajax_send(form, {}, \"initialized\");\n }\n\n /**\n * Bind event handlers on form fields to monitor changes\n */\n watch_form(form) {\n console.debug(`EditForm::watch_form(${form})`);\n let fields = this.get_form_fields(form);\n for (const field of fields) {\n this.hook_field(field)\n }\n // observe DOM mutations in form\n this.observe_mutations(form);\n // bind custom form event handlers\n form.addEventListener(\"modified\", this.on_modified);\n form.addEventListener(\"mutated\", this.on_mutated);\n if (form.hasAttribute(\"ajax-submit\")) {\n form.addEventListener(\"submit\", this.on_submit);\n }\n }\n\n /**\n * Bind event handlers to field\n */\n hook_field(field) {\n // return immediately if the fields is already hooked\n if (this.hooked_fields.indexOf(field) !== -1) {\n // console.debug(`Field '${field.name}' is already hooked`);\n return\n }\n if (this.is_button(field) || this.is_input_button(field)) {\n // bind click event\n field.addEventListener(\"click\", this.on_click);\n }\n else if (this.is_text(field) || this.is_textarea(field) || this.is_select(field)) {\n // bind change event\n field.addEventListener(\"change\", this.on_change);\n }\n else if (this.is_radio(field) || this.is_checkbox(field)) {\n // bind click event\n field.addEventListener(\"click\", this.on_click);\n } else {\n // bind blur event\n field.addEventListener(\"blur\", this.on_blur);\n }\n // console.debug(`Hooked field '${field.name}'`);\n // remember hooked fields\n this.hooked_fields = this.hooked_fields.concat(field);\n }\n\n /**\n * Initialize a DOM mutation observer to rebind dynamic added fields,\n * e.g. for records field etc.\n */\n observe_mutations(form) {\n let observer = new MutationObserver(function(mutations) {\n let event = new CustomEvent(\"mutated\", {\n detail: {\n form: form,\n mutations: mutations\n }\n });\n form.dispatchEvent(event);\n });\n // observe the form with all contained elements\n observer.observe(form, {\n childList: true,\n subtree: true\n });\n }\n\n /**\n * Handle a single DOM mutation\n */\n handle_mutation(form, mutation) {\n let target = mutation.target;\n let parent = target.closest(\".field\");\n let added = mutation.addedNodes;\n let removed = mutation.removedNodes;\n let selectors = this.config.field_selectors;\n // handle picklist widget\n if (this.is_multiple_select(target)) {\n return this.notify(form, target, \"modified\");\n }\n // hook new fields, e.g. when the records field \"More\" button was clicked\n if (added && target.ELEMENT_NODE) {\n for (const field of target.querySelectorAll(selectors)) {\n this.hook_field(field);\n }\n }\n }\n\n /**\n * toggles the submit button\n */\n toggle_submit(form, toggle) {\n let btn = form.querySelector(\"input[type='submit']\");\n btn.disabled = !toggle;\n }\n\n /**\n * toggles the display of the field with the `d-none` class\n */\n toggle_field_visibility(field, toggle=true) {\n let parent = field.closest(\".field\");\n let css_class = \"d-none\";\n if (toggle === false) {\n parent.classList.add(css_class);\n } else {\n parent.classList.remove(css_class);\n }\n }\n\n /**\n * check if fields have errors\n */\n has_field_errors(form) {\n let fields_with_errors = form.querySelectorAll(\".is-invalid\");\n if (fields_with_errors.length > 0) {\n return true;\n }\n return false;\n }\n\n /**\n * set field readonly\n */\n set_field_readonly(field, message=null) {\n field.setAttribute(\"readonly\", \"\");\n let existing_message = field.parentElement.querySelector(\"div.message\");\n if (existing_message) {\n existing_message.innerHTML = _t(message)\n } else {\n let div = document.createElement(\"div\");\n div.className = \"message text-secondary small\";\n div.innerHTML = _t(message);\n field.parentElement.appendChild(div);\n }\n }\n\n /**\n * set field editable\n */\n set_field_editable(field, message=null) {\n field.removeAttribute(\"readonly\");\n let existing_message = field.parentElement.querySelector(\"div.message\");\n if (existing_message) {\n existing_message.innerHTML = _t(message)\n } else {\n let div = document.createElement(\"div\");\n div.className = \"message text-secondary small\";\n div.innerHTML = _t(message);\n field.parentElement.appendChild(div);\n }\n }\n\n /**\n * set field error\n */\n set_field_error(field, message) {\n field.classList.add(\"is-invalid\");\n let existing_message = field.parentElement.querySelector(\"div.invalid-feedback\");\n if (existing_message) {\n existing_message.innerHTML = _t(message)\n } else {\n let div = document.createElement(\"div\");\n div.className = \"invalid-feedback\";\n div.innerHTML = _t(message);\n field.parentElement.appendChild(div);\n }\n }\n\n /**\n * remove field error\n */\n remove_field_error(field) {\n field.classList.remove(\"is-invalid\")\n let msg = field.parentElement.querySelector(\".invalid-feedback\");\n if (msg) {\n msg.remove();\n }\n }\n\n /**\n * add a status message\n * @param {string} message the message to display in the alert\n * @param {string} level one of \"info\", \"success\", \"warning\", \"danger\"\n * @param {object} options additional options to control the behavior\n * - option {string} title: alert title in bold\n * - option {string} flush: remove previous alerts\n */\n add_statusmessage(message, level=\"info\", options) {\n options = options || {};\n let el = document.createElement(\"div\");\n let title = options.title || `${level.charAt(0).toUpperCase() + level.slice(1)}`;\n el.innerHTML = `\n
    \n ${title}\n ${_t(message)}\n \n
    \n `\n el = el.firstElementChild\n let parent = document.getElementById(\"viewlet-above-content\");\n\n // clear put previous alerts\n if (options.flush) {\n for (let el of parent.querySelectorAll(\".alert\")) {\n el.remove();\n }\n }\n parent.appendChild(el);\n return el;\n }\n\n /**\n * add a notification message\n */\n add_notification(title, message, options) {\n options = options || {};\n options = Object.assign({\n animation: true,\n autohide: true,\n delay: 5000,\n }, options)\n let el = document.createElement(\"div\");\n el.innerHTML = `\n
    \n
    \n ${title.charAt(0).toUpperCase() + title.slice(1)}\n \n
    \n
    \n ${_t(message)}\n
    \n
    \n `\n el = el.firstElementChild;\n let parent = document.querySelector(\".toast-container\");\n if (!parent) {\n parent = document.createElement(\"div\");\n parent.innerHTML = `\n
    \n
    \n
    \n
    \n `\n let wrapper = document.querySelector(\".container-fluid\");\n wrapper.appendChild(parent);\n parent = parent.querySelector(\".toast-container\");\n }\n parent.appendChild(el);\n return el;\n }\n\n /**\n * update the form with the response from the server\n */\n update_form(form, data) {\n console.info(\"*** UPDATE FORM ***\", data)\n\n let hide = data.hide || [];\n let show = data.show || [];\n let readonly = data.readonly || [];\n let editable = data.editable || [];\n let errors = data.errors || [];\n let messages = data.messages || [];\n let notifications = data.notifications || [];\n let updates = data.updates || [];\n let html = data.html || [];\n let attributes = data.attributes || [];\n\n // render field errors\n for (const record of errors) {\n let name, error, rest;\n ({name, error, ...rest} = record);\n let el = this.get_form_field_by_name(form, name);\n if (!el) continue;\n if (error) {\n this.set_field_error(el, error);\n } else {\n this.remove_field_error(el);\n }\n }\n\n // render status messages\n for (const record of messages) {\n let name, error, rest;\n ({message, level, ...rest} = record);\n let level = level || \"info\";\n let message = message || \"\";\n this.add_statusmessage(message, level, rest);\n }\n\n // render notification messages\n for (const record of notifications) {\n let title, message, rest;\n ({title, message, ...rest} = record);\n let el = this.add_notification(title, message, rest);\n $(el).toast(\"show\");\n }\n\n // hide fields\n for (const record of hide) {\n let name, rest;\n ({name, ...rest} = record);\n let el = this.get_form_field_by_name(form, name);\n if (!el) continue;\n this.toggle_field_visibility(el, false);\n }\n\n // show fields\n for (const record of show) {\n let name, rest;\n ({name, ...rest} = record);\n let el = this.get_form_field_by_name(form, name);\n if (!el) continue;\n this.toggle_field_visibility(el, true);\n }\n\n // readonly fields\n for (const record of readonly) {\n let name, message, rest;\n ({name, message, ...rest} = record);\n let el = this.get_form_field_by_name(form, name);\n if (!el) continue;\n this.set_field_readonly(el, message);\n }\n\n // editable fields\n for (const record of editable) {\n let name, message, rest;\n ({name, message, ...rest} = record);\n let el = this.get_form_field_by_name(form, name);\n if (!el) continue;\n this.set_field_editable(el, message);\n }\n\n // updated fields\n for (const record of updates) {\n let name, value, rest;\n ({name, value, ...rest} = record);\n let el = this.get_form_field_by_name(form, name);\n if (!el) continue;\n this.set_field_value(el, value);\n }\n\n // html\n for (const record of html) {\n let selector, html, rest;\n ({selector, html, ...rest} = record);\n let el = form.querySelector(selector);\n if (!el) continue;\n if (rest.append) {\n el.innerHTML = el.innerHTML + html;\n } else {\n el.innerHTML = html;\n }\n }\n\n // set attribute to an element\n for (const record of attributes) {\n let selector, name, value, rest;\n ({selector, name, value, ...rest} = record);\n let el = form.querySelector(selector);\n if (!el) continue;\n if (value === null) {\n el.removeAttribute(name);\n } else {\n el.addAttribute(name, value);\n }\n }\n\n // disallow submit when field errors are present\n if (this.has_field_errors(form)) {\n this.toggle_submit(form, false);\n } else {\n this.toggle_submit(form, true);\n }\n }\n\n /**\n * return a form field by name\n */\n get_form_field_by_name(form, name) {\n // get the first element that matches the name\n let exact = form.querySelector(`[name='${name}']`);\n let fuzzy = form.querySelector(`[name^='${name}']`);\n let field = exact || fuzzy || null;\n if (field === null) {\n return null;\n }\n return field;\n }\n\n /**\n * return a dictionary of all the form values\n */\n get_form_data(form) {\n let data = {};\n let form_data = new FormData(form);\n form_data.forEach(function(value, key) {\n data[key] = value;\n });\n return data;\n }\n\n /**\n * Return form fields for the given selectors of the config\n */\n get_form_fields(form) {\n console.debug(`EditForm::get_form_fields(${form})`);\n let fields = [];\n let selectors = this.config.field_selectors;\n for (const selector of selectors) {\n let nodes = form.querySelectorAll(selector);\n fields = fields.concat(...nodes.values())\n }\n return fields\n }\n\n /**\n * returns the name of the field w/o ZPublisher converter\n */\n get_field_name(field) {\n let name = field.name;\n return name.split(\":\")[0];\n }\n\n /**\n * return the value of the form field\n */\n get_field_value(field) {\n if (this.is_checkbox(field)) {\n // returns true/false for checkboxes\n return field.checked;\n } else if (this.is_select(field)) {\n // returns a list of selected option\n let selected = field.selectedOptions;\n return Array.prototype.map.call(selected, (option) => option.value)\n } else if (this.is_single_reference(field)) {\n // returns the value of the `uid` attribute\n return field.getAttribute(\"uid\");\n } else if (this.is_multi_reference(field)) {\n // returns the value of the `uid` attribute and splits it on `,`\n let uids = field.getAttribute(\"uid\");\n if (uids.length == 0) return [];\n return uids.split(\",\");\n }\n // return the plain field value\n return field.value;\n }\n\n /**\n * set the value of the form field\n */\n set_field_value(field, value) {\n // for reference/select fields\n let selected = value.selected || [];\n let options = value.options || [];\n\n // set reference value\n if (this.is_single_reference(field)) {\n for (const item of selected) {\n field.setAttribute(\"uid\", item.value);\n field.value = item.title;\n }\n }\n // set select field\n else if (this.is_select(field)) {\n if (selected.length == 0) {\n let old_selected = field.options[field.selected];\n if (old_selected) {\n selected = [old_selected.value];\n }\n }\n // remove all options\n field.options.length = 0;\n // sort options\n options.sort((a, b) => {\n let _a = a.title.toLowerCase();\n let _b = b.title.toLowerCase();\n if (a.value === null) _a = \"\";\n if (b.value === null) _b = \"\";\n if (_a < _b) return -1;\n if (_a > _b) return 1;\n });\n // build new options\n for (const option of options) {\n let el = document.createElement(\"option\");\n el.value = option.value;\n el.innerHTML = option.title;\n // select item if the value is in the selected array\n if (selected.indexOf(option.value) !== -1) {\n el.selected = true;\n }\n field.appendChild(el);\n }\n // select first item\n if (selected.length == 0) {\n field.selectedIndex = 0;\n }\n }\n // set checkbox value\n else if (this.is_checkbox(field)) {\n field.checked = value;\n }\n // set other field values\n else {\n field.value = value;\n }\n }\n\n\n /**\n * trigger `modified` event on the form\n */\n modified(el) {\n let event = new CustomEvent(\"modified\", {\n detail: {\n field: el,\n form: el.form\n }\n });\n // dispatch the event on the element\n el.form.dispatchEvent(event);\n }\n\n /**\n * trigger ajax loading events\n */\n loading(toggle=true) {\n let event_type = toggle ? \"ajaxStart\" : \"ajaxStop\";\n let event = new CustomEvent(event_type);\n document.dispatchEvent(event);\n }\n\n /**\n * notify a field change to the server ajax endpoint\n */\n notify(form, field, endpoint) {\n let data = {\n name: this.get_field_name(field),\n value: this.get_field_value(field),\n }\n this.ajax_send(form, data, endpoint);\n }\n\n /**\n * send application/json to the server\n */\n ajax_send(form, data, endpoint) {\n let view_url = document.body.dataset.viewUrl;\n let ajax_url = `${view_url}/ajax_form/${endpoint}`;\n\n let payload = Object.assign({\n \"form\": this.get_form_data(form)\n }, data)\n\n console.debug(\"EditForm::ajax_send --> \", payload)\n\n let init = {\n method: \"POST\",\n credentials: \"include\",\n body: JSON.stringify(payload),\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-CSRF-TOKEN\": document.querySelector(\"#protect-script\").dataset.token\n },\n }\n\n return this.ajax_request(form, ajax_url, init);\n }\n\n /**\n * send multipart/form-data to the server\n */\n ajax_submit(form, data, endpoint) {\n let view_url = document.body.dataset.viewUrl;\n let ajax_url = `${view_url}/ajax_form/${endpoint}`;\n\n let payload = new FormData(form);\n\n // update form data\n for(let [key, value] of Object.entries(data)) {\n payload.set(key, value);\n }\n\n console.debug(\"EditForm::ajax_submit --> \", payload)\n\n let init = {\n method: \"POST\",\n body: payload,\n }\n\n return this.ajax_request(form, ajax_url, init);\n }\n\n\n /**\n * execute ajax request\n */\n ajax_request(form, url, init) {\n // send ajax request to server\n this.loading(true);\n let request = new Request(url, init);\n return fetch(request)\n .then((response) => {\n if (!response.ok) {\n return Promise.reject(response);\n }\n return response.json();\n })\n .then((data) => {\n console.debug(\"EditForm::ajax_request --> \", data);\n this.update_form(form, data);\n this.loading(false);\n })\n .catch((error) => {\n console.error(error);\n this.loading(false);\n });\n }\n\n /**\n * Toggle element disable\n */\n toggle_disable(el, toggle) {\n if (el) {\n el.disabled = toggle;\n }\n }\n\n /**\n * Checks if the element is a textarea field\n */\n is_textarea(el) {\n return el.tagName == \"TEXTAREA\";\n }\n\n /**\n * Checks if the elment is a select field\n */\n is_select(el) {\n return el.tagName == \"SELECT\";\n }\n\n /**\n * Checks if the element is a multiple select field\n */\n is_multiple_select(el) {\n return this.is_select(el) && el.hasAttribute(\"multiple\");\n }\n\n /**\n * Checks if the element is an input field\n */\n is_input(el) {\n return el.tagName === \"INPUT\";\n }\n\n /**\n * Checks if the element is an input[type='text'] field\n */\n is_text(el) {\n return this.is_input(el) && el.type === \"text\";\n }\n\n /**\n * Checks if the element is a button field\n */\n is_button(el) {\n return el.tagName === \"BUTTON\";\n }\n\n /**\n * Checks if the element is an input[type='button'] field\n */\n is_input_button(el) {\n return this.is_input(el) && el.type === \"button\";\n }\n\n /**\n * Checks if the element is an input[type='checkbox'] field\n */\n is_checkbox(el) {\n return this.is_input(el) && el.type === \"checkbox\";\n }\n\n /**\n * Checks if the element is an input[type='radio'] field\n */\n is_radio(el) {\n return this.is_input(el) && el.type === \"radio\";\n }\n\n /**\n * Checks if the element is a SENAITE reference field\n */\n is_reference(el) {\n return el.classList.contains(\"referencewidget\");\n }\n\n /**\n * Checks if the element is a SENAITE single-reference field\n */\n is_single_reference(el) {\n return this.is_reference(el) && el.getAttribute(\"multivalued\") == \"0\";\n }\n\n /**\n * Checks if the element is a SENAITE multi-reference field\n */\n is_multi_reference(el) {\n return this.is_reference(el) && el.getAttribute(\"multivalued\") == \"1\";\n }\n\n /**\n * event handler for `mutated` event\n */\n on_mutated(event) {\n console.debug(\"EditForm::on_mutated\");\n let form = event.detail.form;\n let mutations = event.detail.mutations;\n // reduce multiple mutations on the same node to one\n let seen = [];\n for (const mutation of mutations) {\n if (seen.indexOf(mutation.target) > -1) {\n continue;\n }\n seen = seen.concat(mutation.target);\n this.handle_mutation(form, mutation);\n }\n }\n\n /**\n * event handler for `modified` event\n */\n on_modified(event) {\n console.debug(\"EditForm::on_modified\");\n let form = event.detail.form;\n let field = event.detail.field;\n this.notify(form, field, \"modified\");\n }\n\n /**\n * event handler for `submit` event\n */\n on_submit(event) {\n console.debug(\"EditForm::on_submit\");\n event.preventDefault();\n let data = {}\n let form = event.currentTarget.closest(\"form\");\n // NOTE: submit input field not included in request form data!\n let submitter = event.submitter;\n if (submitter) {\n data[submitter.name] = submitter.value;\n // disable submit button during ajax call\n this.toggle_disable(submitter, true);\n }\n this.ajax_submit(form, data, \"submit\")\n .then((response) =>\n // enable submit button after ajax call again\n this.toggle_disable(submitter, false));\n }\n\n /**\n * event handler for `blur` event\n */\n on_blur(event) {\n console.debug(\"EditForm::on_blur\");\n let el = event.currentTarget;\n this.modified(el);\n }\n\n /**\n * event handler for `click` event\n */\n on_click(event) {\n console.debug(\"EditForm::on_click\");\n let el = event.currentTarget;\n this.modified(el);\n }\n\n /**\n * event handler for `change` event\n */\n on_change(event) {\n console.debug(\"EditForm::on_change\");\n let el = event.currentTarget;\n this.modified(el);\n }\n\n}\n\nexport default EditForm;\n","\n/* Please use this command to compile this file into the parent `js` directory:\n coffee --no-header -w -o ../ -c site.coffee\n */\nvar Site,\n bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };\n\nSite = (function() {\n\n /**\n * Creates a new instance of Site\n */\n function Site() {\n this.set_cookie = bind(this.set_cookie, this);\n this.read_cookie = bind(this.read_cookie, this);\n this.authenticator = bind(this.authenticator, this);\n // console.debug(\"Site::init\");\n }\n\n\n /**\n * Returns the authenticator value\n */\n\n Site.prototype.authenticator = function() {\n var auth, url_params;\n auth = $(\"input[name='_authenticator']\").val();\n if (!auth) {\n url_params = new URLSearchParams(window.location.search);\n auth = url_params.get(\"_authenticator\");\n }\n return auth;\n };\n\n\n /**\n * Reads a cookie value\n * @param {name} the name of the cookie\n */\n\n Site.prototype.read_cookie = function(name) {\n var c, ca, i;\n // console.debug(\"Site::read_cookie:\" + name);\n name = name + '=';\n ca = document.cookie.split(';');\n i = 0;\n while (i < ca.length) {\n c = ca[i];\n while (c.charAt(0) === ' ') {\n c = c.substring(1);\n }\n if (c.indexOf(name) === 0) {\n return c.substring(name.length, c.length);\n }\n i++;\n }\n return null;\n };\n\n\n /**\n * Sets a cookie value\n * @param {name} the name of the cookie\n * @param {value} the value of the cookie\n */\n\n Site.prototype.set_cookie = function(name, value) {\n var d, expires;\n // console.debug(\"Site::set_cookie:name=\" + name + \", value=\" + value);\n d = new Date;\n d.setTime(d.getTime() + 1 * 24 * 60 * 60 * 1000);\n expires = 'expires=' + d.toUTCString();\n document.cookie = name + '=' + value + ';' + expires + ';path=/';\n };\n\n return Site;\n\n})();\n\nexport default Site;\n","/* SENAITE Sidebar\n *\n * The sidebar shows when the mouse enters and hides when the mouse leaves the\n * HTML element.\n *\n * It keeps open when the toggle button was clicked.\n */\n\nclass Sidebar{\n\n constructor(config) {\n\n this.config = Object.assign({\n \"el\": \"sidebar\",\n \"toggle_el\": \"sidebar-header\",\n \"cookie_key\": \"sidebar-toggle\",\n \"timeout\": 1000,\n }, config);\n\n // Timer ID\n this.tid = null;\n\n // Bind \"this\" context when called\n this.maximize = this.maximize.bind(this);\n this.minimize = this.minimize.bind(this);\n this.on_click = this.on_click.bind(this);\n this.on_mouseenter = this.on_mouseenter.bind(this)\n this.on_mouseleave = this.on_mouseleave.bind(this);\n\n // toggle button handler\n this.toggle_el = document.getElementById(this.config.toggle_el);\n if (this.toggle_el) {\n this.toggle_el.addEventListener(\"click\", this.on_click);\n }\n\n // sidebar view/hide handler\n this.el = document.getElementById(this.config.el);\n if (this.el) {\n this.el.addEventListener(\"mouseenter\", this.on_mouseenter);\n this.el.addEventListener(\"mouseleave\", this.on_mouseleave);\n\n if (this.is_toggled()) {\n this.el.classList.remove(\"minimized\");\n this.el.classList.add(\"toggled\");\n }\n }\n\n return this;\n }\n\n is_toggled() {\n return window.site.read_cookie(this.config.cookie_key) == \"true\";\n }\n\n toggle(toggle=false) {\n window.site.set_cookie(this.config.cookie_key, toggle)\n if (toggle) {\n this.el.classList.add(\"toggled\")\n this.maximize();\n } else {\n this.el.classList.remove(\"toggled\")\n this.minimize();\n }\n }\n\n minimize() {\n this.el.classList.add(\"minimized\");\n }\n\n maximize() {\n this.el.classList.remove(\"minimized\");\n }\n\n on_click(event) {\n // console.debug(\"Sidebar::on_click:event=\", event)\n clearTimeout(this.tid);\n this.toggle(!this.is_toggled());\n }\n\n on_mouseenter(event) {\n // console.debug(\"Sidebar::on_mouseenter:event=\", event)\n clearTimeout(this.tid);\n if (this.is_toggled()) return\n this.tid = setTimeout(this.maximize, this.config.timeout);\n }\n\n on_mouseleave(event) {\n // console.debug(\"Sidebar::on_mouseleave:event=\", event)\n clearTimeout(this.tid);\n if (this.is_toggled()) return\n this.minimize();\n // console.debug(\"Clearing sidebar timeout\", this.tid);\n }\n}\n\nexport default Sidebar;\n","const __WEBPACK_NAMESPACE_OBJECT__ = React;","const __WEBPACK_NAMESPACE_OBJECT__ = ReactDOM;","class ReferenceWidgetAPI {\n\n constructor(props) {\n console.debug(\"ReferenceWidgetAPI::constructor\")\n this.api_url = props.api_url;\n this.on_api_error = props.on_api_error || function(response) {};\n return this;\n }\n\n get_api_url(endpoint) {\n return `${this.api_url}/${endpoint}#${location.search}`\n }\n\n /*\n * Fetch Ajax API resource from the server\n *\n * @param {string} endpoint\n * @param {object} options\n * @returns {Promise}\n */\n get_json(endpoint, options) {\n var data, init, method, on_api_error, request, url;\n if (options == null) {\n options = {};\n }\n method = options.method || \"POST\";\n data = JSON.stringify(options.data) || \"{}\";\n on_api_error = this.on_api_error;\n url = this.get_api_url(endpoint);\n init = {\n method: method,\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-CSRF-TOKEN\": this.get_csrf_token()\n },\n body: method === \"POST\" ? data : null,\n credentials: \"include\"\n };\n console.info(\"ReferenceWidgetAPI::fetch:endpoint=\" + endpoint + \" init=\", init);\n request = new Request(url, init);\n return fetch(request).then(function(response) {\n if (!response.ok) {\n return Promise.reject(response);\n }\n return response;\n }).then(function(response) {\n return response.json();\n }).catch(function(response) {\n on_api_error(response);\n return response;\n });\n }\n\n search(catalog, query, params) {\n params = params || {};\n let url = `search?catalog=${catalog}`;\n for(let [key, value] of Object.entries(query)) {\n // handle arrays as repeating parameters\n if (Array.isArray(value)) {\n value.forEach( (item) => {\n url += `&${key}=${item}`;\n });\n continue;\n }\n // workaround for path queries\n if (key == \"path\") {\n value = value.query || null;\n if (value.depth !== null) {\n url += `&depth=${value.depth}`;\n }\n }\n if (value) {\n url += `&${key}=${value}`;\n }\n }\n for(let [key, value] of Object.entries(params)) {\n url += `&${key}=${value}`;\n }\n console.debug(\"ReferenceWidgetAPI::search:url=\", url);\n return this.get_json(url, {method: \"GET\"});\n }\n\n /*\n * Get the plone.protect CSRF token\n * Note: The fields won't save w/o that token set\n */\n get_csrf_token() {\n return document.querySelector(\"#protect-script\").dataset.token;\n };\n\n}\n\nexport default ReferenceWidgetAPI;\n","import React from \"react\";\nimport ReactDOM from \"react-dom\";\n\n\nclass ReferenceField extends React.Component {\n\n constructor(props) {\n super(props);\n\n this.state = {}\n\n // React reference to the input field\n // https://reactjs.org/docs/react-api.html#reactcreateref\n this.input_field_ref = React.createRef();\n\n // bind event handlers\n this.on_focus = this.on_focus.bind(this);\n this.on_blur = this.on_blur.bind(this);\n this.on_change = this.on_change.bind(this);\n this.on_keydown = this.on_keydown.bind(this);\n this.on_keypress = this.on_keypress.bind(this);\n this.on_clear_click = this.on_clear_click.bind(this);\n this.on_search_click = this.on_search_click.bind(this);\n }\n\n /*\n * Returns the search value from the input field\n */\n get_search_value() {\n return this.input_field_ref.current.value;\n }\n\n /*\n * Handler when the search field get focused\n */\n on_focus(event) {\n console.debug(\"ReferenceField::on_focus\");\n if (this.props.on_focus) {\n let value = this.get_search_value() || null;\n this.props.on_focus(value);\n }\n }\n\n /*\n * Handler when the search field lost focus\n */\n on_blur(event) {\n console.debug(\"ReferenceField::on_blur\");\n if (this.props.on_blur) {\n let value = this.get_search_value();\n this.props.on_blur(value);\n }\n }\n\n /*\n * Handler when the search value changed\n */\n on_change(event) {\n event.preventDefault();\n let value = this.get_search_value();\n console.debug(\"ReferenceField::on_change:value: \", value);\n if (this.props.on_search) {\n this.props.on_search(value);\n }\n }\n\n /*\n * Handler for keydown events in the search field\n *\n */\n on_keydown(event) {\n // backspace\n if (event.which == 8) {\n if (this.get_search_value() == \"\") {\n this.props.on_clear();\n }\n }\n\n // down arrow\n if (event.which == 40) {\n if (this.props.on_arrow_key) {\n this.props.on_arrow_key(\"down\");\n }\n }\n // up arrow\n if (event.which == 38) {\n if (this.props.on_arrow_key) {\n this.props.on_arrow_key(\"up\");\n }\n }\n\n // left arrow\n if (event.which == 37) {\n if (this.props.on_arrow_key) {\n this.props.on_arrow_key(\"left\");\n }\n }\n\n // right arrow\n if (event.which == 39) {\n if (this.props.on_arrow_key) {\n this.props.on_arrow_key(\"right\");\n }\n }\n }\n\n /*\n * Handler for keypress events in the search field\n *\n */\n on_keypress(event) {\n if (event.which == 13) {\n console.debug(\"ReferenceField::on_keypress:ENTER\");\n // prevent form submission when clicking ENTER\n event.preventDefault();\n if (this.props.on_enter) {\n this.props.on_enter();\n }\n\n }\n }\n\n on_clear_click(event) {\n event.preventDefault();\n if (this.props.on_clear) {\n let value = this.get_search_value();\n this.props.on_clear(value);\n // clear the input field\n this.input_field_ref.current.value = \"\"\n }\n }\n\n on_search_click(event) {\n event.preventDefault();\n if (this.props.on_search) {\n let value = this.get_search_value();\n this.props.on_search(value);\n }\n }\n\n render() {\n return (\n
    \n
    \n \n
    \n \n \n
    \n
    \n
    \n );\n }\n}\n\nexport default ReferenceField;\n","import React from \"react\";\nimport ReactDOM from \"react-dom\";\n\n\nclass ReferenceResults extends React.Component {\n\n constructor(props) {\n super(props);\n\n // bind event handlers\n this.on_select = this.on_select.bind(this);\n this.on_page = this.on_page.bind(this);\n this.on_prev_page = this.on_prev_page.bind(this);\n this.on_next_page = this.on_next_page.bind(this);\n this.on_close = this.on_close.bind(this);\n }\n\n /*\n * Return the header columns config\n *\n * @returns {Array} of column config objects\n */\n get_columns() {\n return this.props.columns || [];\n }\n\n /*\n * Return only the (field-)names of the columns config\n *\n * @returns {Array} of column names\n */\n get_column_names() {\n let columns = this.get_columns();\n return columns.map((column) => {\n return column.name;\n });\n }\n\n /*\n * Return only the labels of the columns config\n *\n * @returns {Array} of column labels\n */\n get_column_labels() {\n let columns = this.get_columns();\n return columns.map((column) => { return column.label });\n }\n\n /*\n * Return the search results\n *\n * @returns {Array} of result objects (items of `senaite.jsonapi` response)\n */\n get_results() {\n return this.props.results || [];\n }\n\n /*\n * Checks if results are available\n *\n * @returns {Boolean} true if there are results, false otherwise\n */\n has_results() {\n return this.get_results().length > 0;\n }\n\n /*\n * Returns the style object for the dropdown table\n *\n * @returns {Object} of ReactJS CSS styles\n */\n get_style() {\n return {\n minWidth: this.props.width || \"400px\",\n backgroundColor: \"white\",\n zIndex: 999999\n }\n }\n\n /*\n * Returns the UID of a result object\n *\n * @returns {String} UID of the result\n */\n get_result_uid(result) {\n return result.uid || \"NO UID FOUND!\";\n }\n\n /*\n * Checks wehter the UID is already in the list of selected UIDs\n *\n * @returns {Boolean} true if the UID is already selected, false otherwise\n */\n is_uid_selected(uid) {\n return this.props.uids.indexOf(uid) > -1;\n }\n\n /*\n * Build Header columns\n *\n * @returns {Array} of ... columns\n */\n build_header_columns() {\n let columns = [];\n for (let column of this.get_columns()) {\n let label = column.label || column.title;\n let width = column.width || \"auto\";\n let align = column.align || \"left\";\n columns.push(\n \n {_t(label)}\n \n );\n }\n // Append additional column for usage state\n columns.push(\n \n )\n return columns;\n }\n\n /*\n * Build table rows\n *\n * @returns {Array} of ... rows\n */\n build_rows() {\n let rows = [];\n let results = this.get_results();\n results.forEach((result, index) => {\n let uid = this.get_result_uid(result);\n rows.push(\n \n {this.build_columns(result)}\n \n );\n });\n return rows\n }\n\n /*\n * Build Header columns\n *\n * @returns {Array} of ... columns\n */\n build_columns(result) {\n let columns = []\n let searchterm = this.props.searchterm || \"\";\n for (let name of this.get_column_names()) {\n let value = result[name];\n let highlighted = this.highlight(value, searchterm);\n columns.push(\n \n );\n }\n let uid = result.uid;\n let used = this.props.uids.indexOf(uid) > -1;\n columns.push(\n {used && }\n );\n return columns;\n }\n\n /*\n * Highlight any found match of the searchterm in the text\n *\n * @returns {String} highlighted text\n */\n highlight(text, searchterm) {\n if (searchterm.length == 0) return text;\n try {\n let rx = new RegExp(searchterm, \"gi\");\n text = text.replaceAll(rx, (m) => {\n return \"\"+m+\"\";\n });\n } catch (error) {\n // pass\n }\n return text\n }\n\n /*\n * Build pagination
  • ...
  • items\n *\n * @returns {Array} Pagination JSX\n */\n build_pages() {\n let pages = [];\n for (let page=1; page <= this.props.pages; page++) {\n let cls = [\"page-item\"];\n if (this.props.page == page) cls.push(\"active\");\n pages.push(\n
  • \n \n
  • \n );\n }\n return pages;\n }\n\n /*\n * Build pagination next button\n *\n * @returns {Array} Next button JSX\n */\n build_next_button() {\n let cls = [\"page-item\"]\n if (!this.props.next_url) cls.push(\"disabled\")\n return (\n
  • \n \n
  • \n )\n }\n\n /*\n * Build pagination previous button\n *\n * @returns {Array} Previous button JSX\n */\n build_prev_button() {\n let cls = [\"page-item\"]\n if (!this.props.prev_url) cls.push(\"disabled\")\n return (\n
  • \n \n
  • \n )\n }\n\n /*\n * Build results dropdown close button\n *\n * @returns {Array} Close button JSX\n */\n build_close_button() {\n return (\n \n )\n }\n\n /*\n * Event handler when a result was selected\n */\n on_select(event) {\n event.preventDefault();\n let target = event.currentTarget;\n let uid = target.getAttribute(\"uid\")\n console.debug(\"ReferenceResults::on_select:event=\", event);\n if (this.props.on_select) {\n this.props.on_select(uid);\n }\n }\n\n /*\n * Event handler when a page was clicked\n */\n on_page(event) {\n event.preventDefault();\n let target = event.currentTarget;\n let page = target.getAttribute(\"page\")\n console.debug(\"ReferenceResults::on_page:event=\", event);\n if (page == this.props.page) {\n return;\n }\n if (this.props.on_page) {\n this.props.on_page(page);\n }\n }\n\n /*\n * Event handler when the pagination previous button was clicked\n */\n on_prev_page(event) {\n event.preventDefault();\n console.debug(\"ReferenceResults::on_prev_page:event=\", event);\n let page = this.props.page;\n if (page < 2) {\n console.warn(\"No previous pages available!\");\n return;\n }\n if (this.props.on_page) {\n this.props.on_page(page - 1);\n }\n }\n\n /*\n * Event handler when the pagination next button was clicked\n */\n on_next_page(event) {\n event.preventDefault();\n console.debug(\"ReferenceResults::on_next_page:event=\", event);\n let page = this.props.page;\n if (page + 1 > this.props.pages) {\n console.warn(\"No next pages available!\");\n return;\n }\n if (this.props.on_page) {\n this.props.on_page(page + 1);\n }\n }\n\n /*\n * Event handler when the dropdown close button was clicked\n */\n on_close(event) {\n event.preventDefault();\n console.debug(\"ReferenceResults::on_close:event=\", event);\n if (this.props.on_clear) {\n this.props.on_clear();\n }\n }\n\n /*\n * Render the reference results selection\n */\n render() {\n if (!this.has_results()) {\n return null;\n }\n return (\n
    \n
    \n {this.build_close_button()}\n
    \n \n \n \n {this.build_header_columns()}\n \n \n \n {this.build_rows()}\n \n
    \n {this.props.pages > 1 &&\n \n }\n
    \n );\n }\n}\n\nexport default ReferenceResults;\n","import React from \"react\";\nimport ReactDOM from \"react-dom\";\n\n\nclass References extends React.Component {\n\n constructor(props) {\n super(props);\n\n this.on_deselect = this.on_deselect.bind(this);\n }\n\n get_selected_uids() {\n return this.props.uids || [];\n }\n\n /*\n * Simple template interpolation that replaces ${...} placeholders\n * with any found value from the context object.\n *\n * https://stackoverflow.com/questions/29182244/convert-a-string-to-a-template-string\n */\n interpolate(template, context) {\n for(let [key, value] of Object.entries(context)) {\n template = template.replace(new RegExp('\\\\$\\\\{' + key + '\\\\}', 'g'), value)\n }\n return template;\n }\n\n render_display_template(uid) {\n let template = this.props.display_template;\n let context = this.props.records[uid];\n if (!context) return uid;\n return this.interpolate(template, context);\n }\n\n build_selected_items() {\n let items = [];\n let selected_uids = this.get_selected_uids();\n\n for (let uid of selected_uids) {\n items.push(\n
  • \n
    \n \n \n
    \n\n
  • \n );\n }\n return items\n }\n\n on_deselect(event) {\n event.preventDefault();\n let target = event.currentTarget;\n let uid = target.getAttribute(\"uid\");\n console.debug(\"References::on_deselect: Remove UID\", uid);\n if (this.props.on_deselect) {\n this.props.on_deselect(uid);\n }\n }\n\n render() {\n return (\n
    \n
      \n {this.build_selected_items()}\n
    \n {/* submitted in form */}\n \n
    \n );\n }\n}\n\nexport default References;\n","import React from \"react\"\nimport ReactDOM from \"react-dom\"\n\nimport ReferenceWidgetAPI from \"./api.js\"\nimport ReferenceField from \"./components/ReferenceField.js\"\nimport ReferenceResults from \"./components/ReferenceResults.js\"\nimport References from \"./components/References.js\"\n\n\nclass UIDReferenceWidgetController extends React.Component {\n\n constructor(props) {\n super(props);\n\n // Internal state\n this.state = {\n results: [], // `items` list of search results coming from `senaite.jsonapi`\n searchterm: \"\", // the search term that was entered by the user\n loading: false, // loading flag when searching for results\n count: 0, // count of results (coming from `senaite.jsonapi`)\n page: 1, // current page (coming from `senaite.jsonapi`)\n pages: 1, // number of pages (coming from `senaite.jsonapi`)\n next_url: null, // next page API URL (coming from `senaite.jsonapi`)\n prev_url: null, // previous page API URL (coming from `senaite.jsonapi`)\n b_start: 1, // batch start for pagination (see `senaite.jsonapi.batch`)\n focused: 0, // current result that has the focus\n }\n\n // Root input HTML element\n let el = props.root_el;\n\n // Data keys located at the root element\n // -> initial values are set from the widget class\n const data_keys = [\n \"id\",\n \"name\",\n \"uids\",\n \"api_url\",\n \"records\",\n \"catalog\",\n \"query\",\n \"columns\",\n \"display_template\",\n \"limit\",\n \"multi_valued\",\n \"disabled\",\n \"readonly\",\n ]\n\n // Query data keys and set state with parsed JSON value\n for (let key of data_keys) {\n let value = el.dataset[key];\n this.state[key] = this.parse_json(value);\n }\n\n // Initialize communication API with the API URL\n this.api = new ReferenceWidgetAPI({\n api_url: this.state.api_url,\n });\n\n // Bind callbacks to current context\n this.search = this.search.bind(this);\n this.goto_page = this.goto_page.bind(this);\n this.clear_results = this.clear_results.bind(this);\n this.select = this.select.bind(this);\n this.select_focused = this.select_focused.bind(this);\n this.deselect = this.deselect.bind(this);\n this.navigate_results = this.navigate_results.bind(this);\n this.on_keydown = this.on_keydown.bind(this);\n this.on_click = this.on_click.bind(this);\n\n // dev only\n window.widget = this;\n\n return this\n }\n\n componentDidMount() {\n // Bind event listeners of the document\n document.addEventListener(\"keydown\", this.on_keydown, false);\n document.addEventListener(\"click\", this.on_click, false)\n }\n\n componentWillUnmount() {\n // Remove event listeners of the document\n document.removeEventListener(\"keydown\", this.on_keydown, false);\n document.removeEventListener(\"click\", this.on_click, false);\n }\n\n /*\n * JSON parse the given value\n *\n * @param {String} value: The JSON value to parse\n */\n parse_json(value) {\n try {\n return JSON.parse(value)\n } catch (error) {\n console.error(`Could not parse \"${value}\" to JSON`);\n }\n }\n\n is_disabled() {\n if (this.state.disabled) {\n return true;\n }\n if (this.state.readonly) {\n return true;\n }\n if (!this.state.multi_valued && this.state.uids.length > 0) {\n return true;\n }\n return false;\n }\n\n /*\n * Create a query object for the API\n *\n * This method prepares a query from the current state variables,\n * which can be used to call the `api.search` method.\n *\n * @param {Object} options: Additional options to add to the query\n * @returns {Object} The query object\n */\n make_query(options) {\n options = options || {};\n return Object.assign({\n q: this.state.searchterm,\n limit: this.state.limit,\n complete: 1,\n }, options, this.state.query);\n }\n\n /*\n * Execute a search query and set the results to the state\n *\n * @param {Object} url_params: Additional search params for the API search URL\n * @returns {Promise}\n */\n fetch_results(url_params) {\n url_params = url_params || {};\n // prepare the server request\n let self = this;\n let query = this.make_query();\n this.toggle_loading(true);\n let promise = this.api.search(this.state.catalog, query, url_params);\n promise.then(function(data) {\n console.debug(\"ReferenceWidgetController::fetch_results:GOT DATA: \", data);\n self.set_results_data(data);\n self.toggle_loading(false);\n });\n return promise;\n }\n\n /*\n * Execute a search for the given searchterm\n *\n * @param {String} searchterm: The value entered into the search field\n * @returns {Promise}\n */\n search(searchterm) {\n if (!searchterm && this.state.results.length > 0) {\n this.state.searchterm = \"\";\n return;\n }\n console.debug(\"ReferenceWidgetController::search:searchterm:\", searchterm);\n // set the searchterm directly to avoid re-rendering\n this.state.searchterm = searchterm || \"\";\n return this.fetch_results();\n }\n\n /*\n * Fetch results of a page\n *\n * @param {Integer} page: The page to fetch\n * @returns {Promise}\n */\n goto_page(page) {\n page = parseInt(page);\n let limit = parseInt(this.state.limit)\n // calculate the beginning of the page\n // Note: this is the count of previous items that are excluded\n let b_start = page * limit - limit;\n return this.fetch_results({b_start: b_start});\n }\n\n /*\n * Add the UID of a search result to the state\n *\n * @param {String} uid: The selected UID\n * @returns {Array} uids: current selected UIDs\n */\n select(uid) {\n console.debug(\"ReferenceWidgetController::select:uid:\", uid);\n // create a copy of the selected UIDs\n let uids = [].concat(this.state.uids);\n // Add the new UID if it is not selected yet\n if (uids.indexOf(uid) == -1) {\n uids.push(uid);\n }\n this.setState({uids: uids});\n if (uids.length > 0 && !this.state.multi_valued) {\n this.clear_results();\n }\n return uids;\n }\n\n /*\n * Add/remove the focused result\n *\n */\n select_focused() {\n console.debug(\"ReferenceWidgetController::select_focused\");\n let focused = this.state.focused;\n let result = this.state.results.at(focused);\n if (result) {\n let uid = result.uid;\n if (this.state.uids.indexOf(uid) == -1) {\n this.select(uid);\n } else {\n this.deselect(uid);\n }\n }\n }\n\n /*\n * Remove the UID of a reference from the state\n *\n * @param {String} uid: The selected UID\n * @returns {Array} uids: current selected UIDs\n */\n deselect(uid) {\n console.debug(\"ReferenceWidgetController::deselect:uid:\", uid);\n let uids = [].concat(this.state.uids);\n let pos = uids.indexOf(uid);\n if (pos > -1) {\n uids.splice(pos, 1);\n }\n this.setState({uids: uids});\n return uids;\n }\n\n /*\n * Navigate the results either up or down\n *\n * @param {String} direction: either up or down\n */\n navigate_results(direction) {\n let page = this.state.page;\n let pages = this.state.pages;\n let results = this.state.results;\n let focused = this.state.focused;\n let searchterm = this.state.searchterm;\n\n console.debug(\"ReferenceWidgetController::navigate_results:focused:\", focused);\n\n if (direction == \"up\") {\n if (focused > 0) {\n this.setState({focused: focused - 1});\n } else {\n this.setState({focused: 0});\n if (page > 1) {\n this.goto_page(page - 1);\n }\n }\n }\n\n else if (direction == \"down\") {\n if (this.state.results.length == 0) {\n this.search(searchterm);\n }\n if (focused < results.length - 1) {\n this.setState({focused: focused + 1});\n } else {\n this.setState({focused: 0});\n if (page < pages) {\n this.goto_page(page + 1);\n }\n }\n }\n\n else if (direction == \"left\") {\n this.setState({focused: 0});\n if (page > 0) {\n this.goto_page(page - 1);\n }\n }\n\n else if (direction == \"right\") {\n this.setState({focused: 0});\n if (page < pages) {\n this.goto_page(page + 1);\n }\n }\n }\n\n /*\n * Toggle loading state\n *\n * @param {Boolean} toggle: The loading state to set\n * @returns {Boolean} toggle: The current loading state\n */\n toggle_loading(toggle) {\n if (toggle == null) {\n toggle = false;\n }\n this.setState({\n loading: toggle\n });\n return toggle;\n }\n\n /*\n * Set results data coming from `senaite.jsonapi`\n *\n * @param {Object} data: JSON search result object returned from `senaite.jsonapi`\n */\n set_results_data(data) {\n data = data || {};\n let items = data.items || [];\n\n let records = Object.assign(this.state.records, {})\n // update state records\n for (let item of items) {\n let uid = item.uid;\n records[uid] = item;\n }\n\n this.setState({\n records: records,\n results: items,\n count: data.count || 0,\n page: data.page || 1,\n pages: data.pages || 1,\n next_url: data.next || null,\n prev_url: data.previous || null,\n });\n }\n\n /*\n * Clear results from the state\n */\n clear_results() {\n this.setState({\n results: [],\n count: 0,\n page: 1,\n pages: 1,\n next_url: null,\n prev_url: null,\n });\n }\n\n /*\n * ReactJS event handler for keydown event\n */\n on_keydown(event){\n // clear results when ESC key is pressed\n if(event.keyCode === 27) {\n this.clear_results();\n }\n }\n\n /*\n * ReactJS event handler for click events\n */\n on_click(event) {\n // clear results when clicked outside of the widget\n let widget = this.props.root_el;\n let target = event.target;\n if (!widget.contains(target)) {\n this.clear_results();\n }\n }\n\n render() {\n return (\n
    \n \n \n \n
    \n );\n }\n}\n\nexport default UIDReferenceWidgetController;\n","class AddressWidgetAPI {\n\n constructor(props) {\n console.debug(\"AddressWidgetAPI::constructor\")\n this.portal_url = props.portal_url;\n this.on_api_error = props.on_api_error || function(response) {};\n return this;\n }\n\n get_url(endpoint) {\n return `${this.portal_url}/${endpoint}`\n }\n\n /*\n * Fetch JSON resource from the server\n *\n * @param {string} endpoint\n * @param {object} options\n * @returns {Promise}\n */\n get_json(endpoint, options) {\n var data, init, method, on_api_error, request, url;\n if (options == null) {\n options = {};\n }\n method = options.method || \"POST\";\n data = JSON.stringify(options.data) || \"{}\";\n on_api_error = this.on_api_error;\n url = this.get_url(endpoint);\n init = {\n method: method,\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-CSRF-TOKEN\": this.get_csrf_token()\n },\n body: method === \"POST\" ? data : null,\n credentials: \"include\"\n };\n console.info(\"AddressWidgetAPI::fetch:endpoint=\" + endpoint + \" init=\", init);\n request = new Request(url, init);\n return fetch(request).then(function(response) {\n if (!response.ok) {\n return Promise.reject(response);\n }\n return response;\n }).then(function(response) {\n return response.json();\n }).catch(function(response) {\n on_api_error(response);\n return response;\n });\n }\n\n fetch_subdivisions(parent) {\n let url = `geo_subdivisions`\n console.debug(\"AddressWidgetAPI::fetch_subdivisions:url=\", url);\n let options = {\n method: \"POST\",\n data: {\n \"parent\": parent,\n }\n }\n return this.get_json(url, options)\n }\n\n /*\n * Get the plone.protect CSRF token\n */\n get_csrf_token() {\n return document.querySelector(\"#protect-script\").dataset.token;\n };\n\n}\n\nexport default AddressWidgetAPI;\n","import React from \"react\";\nimport ReactDOM from \"react-dom\";\n\n\nclass LocationSelector extends React.Component {\n\n constructor(props) {\n super(props);\n }\n\n render_options() {\n let options = [];\n let locations = this.props.locations;\n options.push(\n \n );\n if (Array.isArray(locations)) {\n for (let location of locations) {\n options.push(\n \n )\n }\n }\n return options;\n }\n\n render() {\n return (\n \n {this.render_options()}\n \n );\n }\n}\n\nexport default LocationSelector;\n","import React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport LocationSelector from \"./LocationSelector.js\";\n\n\nclass AddressField extends React.Component {\n\n constructor(props) {\n super(props);\n }\n\n is_location_selector() {\n return Array.isArray(this.props.locations);\n }\n\n is_visible() {\n let visible = true;\n if (this.is_location_selector()) {\n visible = this.props.locations.length > 0;\n }\n return visible;\n }\n\n render_element() {\n if (this.is_location_selector()) {\n return (\n \n )\n } else {\n return (\n \n )\n }\n }\n\n render() {\n if (!this.is_visible()) {\n return (\n \n )\n }\n return (\n
    \n
    \n
    \n \n
    \n {this.render_element()}\n
    \n
    \n );\n }\n}\n\nexport default AddressField;\n","import React from \"react\";\nimport ReactDOM from \"react-dom\";\n\nimport AddressField from \"./AddressField.js\";\n\n\nclass Address extends React.Component {\n\n constructor(props) {\n super(props);\n this.state = {\n country: props.country,\n subdivision1: props.subdivision1,\n subdivision2: props.subdivision2,\n city: props.city,\n zip: props.zip,\n address: props.address,\n address_type: props.address_type,\n }\n\n // Event handlers\n this.on_country_change = this.on_country_change.bind(this);\n this.on_subdivision1_change = this.on_subdivision1_change.bind(this);\n this.on_subdivision2_change = this.on_subdivision2_change.bind(this);\n this.on_city_change = this.on_city_change.bind(this);\n this.on_zip_change = this.on_zip_change.bind(this);\n this.on_address_change = this.on_address_change.bind(this);\n }\n\n force_array(value) {\n if (!Array.isArray(value)) {\n value = [];\n }\n return value;\n }\n\n /**\n * Returns the list of first-level subdivisions of the current country,\n * sorted alphabetically\n */\n get_subdivisions1() {\n let country = this.state.country;\n return this.force_array(this.props.subdivisions1[country]);\n }\n\n /**\n * Returns the list of subdivisions of the current first-level subdivision,\n * sorted sorted alphabetically\n */\n get_subdivisions2() {\n let subdivision1 = this.state.subdivision1;\n return this.force_array(this.props.subdivisions2[subdivision1]);\n }\n\n get_label(key) {\n let country = this.state.country;\n let label = this.props.labels[country];\n if (label != null && label.constructor == Object && key in label) {\n label = label[key];\n } else {\n label = this.props.labels[key];\n }\n return label;\n }\n\n /** Event triggered when the value for Country selector changes. Updates the\n * selector of subdivisions (e.g. states) with the list of top-level\n * subdivisions for the selected country\n */\n on_country_change(event) {\n let value = event.currentTarget.value;\n console.debug(`Address::on_country_change: ${value}`);\n if (this.props.on_country_change) {\n this.props.on_country_change(value);\n }\n this.setState({\n country: value,\n subdivision1: \"\",\n subdivision2: \"\",\n });\n }\n\n /** Event triggered when the value for the Country first-level subdivision\n * (e.g. state) selector changes. Updates the selector of subdivisions (e.g.\n * districts) for the selected subdivision and country\n */\n on_subdivision1_change(event) {\n let value = event.currentTarget.value;\n console.debug(`Address::on_subdivision1_change: ${value}`);\n if (this.props.on_subdivision1_change) {\n let country = this.state.country\n this.props.on_subdivision1_change(country, value);\n }\n this.setState({\n subdivision1: value,\n subdivision2: \"\",\n });\n }\n\n /** Event triggered when the value for the second-level subdivision (e.g.\n * district) selector changes\n */\n on_subdivision2_change(event) {\n let value = event.currentTarget.value;\n console.debug(`Address::on_subdivision2_change: ${value}`);\n if (this.props.on_subdivision2_change) {\n this.props.on_subdivision2_change(value);\n }\n this.setState({subdivision2: value});\n }\n\n /** Event triggered when the value for the address field changes\n */\n on_address_change(event) {\n let value = event.currentTarget.value;\n this.setState({address: value});\n }\n\n /** Event triggered when the value for the zip field changes\n */\n on_zip_change(event) {\n let value = event.currentTarget.value;\n this.setState({zip: value});\n }\n\n /** Event triggered when the value for the city field changes\n */\n on_city_change(event) {\n let value = event.currentTarget.value;\n this.setState({city: value});\n }\n\n get_input_id(subfield) {\n let id = this.props.id;\n let index = this.props.index;\n return `${id}-${index}-${subfield}`\n }\n\n get_input_name(subfield) {\n let name = this.props.name;\n let index = this.props.index;\n return `${name}.${index}.${subfield}`\n }\n\n render() {\n return (\n
    \n \n\n \n\n \n\n \n\n \n\n \n\n \n\n
    \n );\n }\n\n}\n\nexport default Address;","import React from \"react\"\nimport ReactDOM from \"react-dom\"\n\nimport AddressWidgetAPI from \"./api.js\"\nimport Address from \"./components/Address.js\"\n\n\nclass AddressWidgetController extends React.Component {\n\n constructor(props) {\n super(props);\n\n // Root input HTML element\n let el = props.root_el;\n\n this.state = {};\n\n // Data keys located at the root element\n // -> initial values are set from the widget class\n const data_keys = [\n \"id\",\n \"name\",\n \"items\",\n \"portal_url\",\n \"labels\",\n \"countries\",\n \"subdivisions1\",\n \"subdivisions2\",\n ];\n\n // Query data keys and set state with parsed JSON value\n for (let key of data_keys) {\n let value = el.dataset[key];\n this.state[key] = this.parse_json(value);\n }\n\n // Initialize communication API with the API URL\n this.api = new AddressWidgetAPI({\n portal_url: this.state.portal_url,\n });\n\n // Bind callbacks to current context\n this.on_country_change = this.on_country_change.bind(this);\n this.on_subdivision1_change = this.on_subdivision1_change.bind(this);\n\n return this;\n }\n\n parse_json(value) {\n try {\n return JSON.parse(value);\n } catch (error) {\n console.error(`Could not parse \"${value}\" to JSON`);\n }\n }\n\n /**\n * Event triggered when the user selects a country. Function fetches and\n * updates the geo mapping with the first level subdivisions for the selected\n * country if are not up-to-date yet. It also updates the label for the first\n * level subdivision in accordance.\n */\n on_country_change(country) {\n console.debug(`widget::on_country_change: ${country}`);\n let self = this;\n let promise = this.api.fetch_subdivisions(country);\n promise.then(function(data){\n\n // Update the label with the type of 1st-level subdivisions\n let labels = {...self.state.labels};\n if (data.length > 0) {\n labels[country][\"subdivision1\"] = data[0].type;\n }\n\n // Create a copy instead of modifying the existing dict from state var\n let subdivisions = {...self.state.subdivisions1};\n\n // Only interested in names, sorted alphabetically\n subdivisions[country] = data.map((x) => x.name).sort();\n\n // Update current state with the changes\n self.setState({\n subdivisions1: subdivisions,\n labels: labels,\n });\n });\n return promise;\n }\n\n /**\n * Event triggered when the user selects a first-level subdivision of a\n * country. Function fetches and updates the geo mapping with the second level\n * subdivisions for the selected subdivision if are not up-to-date. It also\n * updates the label for the second level subdivision in accordance.\n */\n on_subdivision1_change(country, subdivision) {\n console.debug(`widget::on_subdivision1_change: ${country}, ${subdivision}`);\n let self = this;\n let promise = this.api.fetch_subdivisions(subdivision);\n promise.then(function(data){\n\n // Update the label with the type of 1st-level subdivisions\n let labels = {...self.state.labels};\n if (data.length > 0) {\n labels[country][\"subdivision2\"] = data[0].type;\n }\n\n // Create a copy instead of modifying the existing dict from state var\n let subdivisions = {...self.state.subdivisions2};\n\n // Only interested in names, sorted alphabetically\n subdivisions[subdivision] = data.map((x) => x.name).sort();\n\n // Update current state with the changes\n self.setState({\n subdivisions2: subdivisions,\n labels: labels,\n });\n });\n return promise;\n }\n\n render_items() {\n let html_items = [];\n let items = this.state.items;\n for (const [index, item] of items.entries()) {\n let section_title = \"\";\n if (items.length > 1) {\n // Only render the title if more than one address\n section_title = (\n {this.state.labels[item.type]}\n )\n }\n\n html_items.push(\n
    \n {section_title}\n \n
    \n );\n }\n return html_items;\n }\n\n render() {\n return (\n
    \n {this.render_items()}\n
    \n );\n }\n}\n\nexport default AddressWidgetController;\n","import $ from \"jquery\";\nimport I18N from \"./components/i18n.js\";\nimport {i18n, _t, _p} from \"./i18n-wrapper.js\"\nimport EditForm from \"./components/editform.js\"\nimport Site from \"./components/site.js\"\nimport Sidebar from \"./components/sidebar.js\"\nimport UIDReferenceWidgetController from \"./widgets/uidreferencewidget/widget.js\"\nimport AddressWidgetController from \"./widgets/addresswidget/widget.js\"\n\n\ndocument.addEventListener(\"DOMContentLoaded\", () => {\n console.debug(\"*** SENAITE CORE JS LOADED ***\");\n\n // Initialize i18n message factories\n window.i18n = new I18N();\n window._t = _t;\n window._p = _p;\n\n // BBB: set global `portal_url` variable\n window.portal_url = document.body.dataset.portalUrl\n\n // TinyMCE\n tinymce.init({\n height: 300,\n paste_data_images: true,\n selector: \"textarea.mce_editable,div.ArchetypesRichWidget textarea,textarea[name='form.widgets.IRichTextBehavior.text'],textarea.richTextWidget\",\n plugins: [\"paste\", \"link\", \"fullscreen\", \"table\", \"code\"],\n content_css : \"/++plone++senaite.core.static/bundles/main.css\",\n })\n // /TinyMCE\n\n // Initialize Site\n window.site = new Site();\n\n // Initialize Sidebar\n window.sidebar = new Sidebar({\n \"el\": \"sidebar\",\n });\n\n // Ajax Edit Form Handler\n var form = new EditForm({\n form_selectors: [\n \"form[name='edit_form']\",\n \"form.senaite-ajax-form\",\n ],\n field_selectors: [\n \"input[type='text']\",\n \"input[type='number']\",\n \"input[type='checkbox']\",\n \"input[type='radio']\",\n \"input[type='file']\",\n \"select\",\n \"textarea\",\n ]\n })\n\n // Init Tooltips\n $(function () {\n $(\"[data-toggle='tooltip']\").tooltip();\n $(\"select.selectpicker\").selectpicker();\n });\n\n // Widgets\n window.widgets = {};\n // Referencewidgets\n var ref_widgets = document.getElementsByClassName(\"senaite-uidreference-widget-input\");\n for (let widget of ref_widgets) {\n let id = widget.dataset.id;\n let controller = ReactDOM.render(, widget);\n window.widgets[id] = controller;\n }\n // AddressWidget\n var address_widgets = document.getElementsByClassName(\"senaite-address-widget-input\");\n for (let widget of address_widgets) {\n let id = widget.dataset.id;\n let controller = ReactDOM.render(, widget);\n window.widgets[id] = controller;\n }\n\n // Workflow Menu Update for Ajax Transitions\n // https://github.com/senaite/senaite.app.listing/pull/87\n document.body.addEventListener(\"listing:submit\", (event) => {\n let menu = document.getElementById(\"plone-contentmenu-workflow\");\n // return immediately if no workflow menu is present\n if (menu === null ) {\n return false;\n }\n // get the base url from the `data-base-url` attribute\n let base_url = document.body.dataset.baseUrl;\n if (base_url === undefined) {\n // fallback to the current location URL\n base_url = location.href.split(\"#\")[0].split(\"?\")[0];\n }\n const request = new Request(base_url + \"/menu/workflow_menu\");\n fetch(request)\n .then((response) => {\n // we might get a 404 e.g. for WS /manage_results, but this is actually\n // desired. Otherwise, we would update the WF menu of the WS ...\n if (response.ok) {\n return response.text();\n }\n })\n .then((html) => {\n if (!html) {\n return;\n }\n let parser = new DOMParser();\n let doc = parser.parseFromString(html, \"text/html\");\n let el = doc.body.firstChild;\n menu.replaceWith(el);\n })\n });\n\n});\n"],"names":["module","exports","jQuery","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","undefined","__webpack_modules__","n","getter","__esModule","d","a","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","self","this","baseUrl","$","attr","currentLanguage","split","length","toUpperCase","storage","catalogs","ttl","Date","now","valueOf","window","localStorage","JSON","e","configure","config","_setCatalog","domain","language","catalog","_storeCatalog","setItem","stringify","getUrl","loadCatalog","parseInt","getItem","parse","MessageFactory","msgid","keywords","msgstr","regexp","keyword","RegExp","replace","t","_t","i18n","I18N","p","_p","EditForm","assign","hooked_fields","on_mutated","bind","on_modified","on_submit","on_blur","on_click","on_change","init_forms","form_selectors","selector","form","document","querySelector","tagName","setup_form","watch_form","ajax_send","get_form_fields","field","hook_field","observe_mutations","addEventListener","hasAttribute","indexOf","is_button","is_input_button","is_text","is_textarea","is_select","is_radio","is_checkbox","concat","MutationObserver","mutations","event","CustomEvent","detail","dispatchEvent","observe","childList","subtree","mutation","target","added","closest","addedNodes","selectors","removedNodes","field_selectors","is_multiple_select","notify","ELEMENT_NODE","querySelectorAll","toggle","disabled","parent","css_class","classList","add","remove","message","setAttribute","existing_message","parentElement","innerHTML","div","createElement","className","appendChild","removeAttribute","msg","level","options","el","title","charAt","slice","firstElementChild","getElementById","flush","animation","autohide","delay","data","hide","show","readonly","editable","errors","messages","notifications","updates","html","attributes","name","error","record","rest","get_form_field_by_name","set_field_error","remove_field_error","add_statusmessage","add_notification","toast","toggle_field_visibility","set_field_readonly","set_field_editable","value","set_field_value","append","addAttribute","has_field_errors","toggle_submit","exact","fuzzy","FormData","forEach","fields","nodes","values","checked","selected","selectedOptions","Array","map","option","is_single_reference","getAttribute","is_multi_reference","uids","item","old_selected","sort","b","_a","toLowerCase","_b","selectedIndex","event_type","endpoint","get_field_name","get_field_value","view_url","body","dataset","viewUrl","ajax_url","payload","get_form_data","init","method","credentials","headers","token","ajax_request","entries","set","url","loading","request","Request","fetch","then","response","ok","json","Promise","reject","update_form","is_input","type","contains","is_reference","seen","handle_mutation","preventDefault","currentTarget","submitter","toggle_disable","ajax_submit","modified","fn","me","apply","arguments","Site","set_cookie","read_cookie","authenticator","auth","val","URLSearchParams","location","search","c","ca","i","cookie","substring","expires","setTime","getTime","toUTCString","Sidebar","tid","maximize","minimize","on_mouseenter","on_mouseleave","toggle_el","is_toggled","site","cookie_key","clearTimeout","setTimeout","timeout","React","ReactDOM","ReferenceWidgetAPI","props","api_url","on_api_error","get_api_url","get_csrf_token","query","params","isArray","depth","get_json","ReferenceField","state","input_field_ref","on_focus","on_keydown","on_keypress","on_clear_click","on_search_click","current","get_search_value","on_search","which","on_clear","on_arrow_key","on_enter","ref","onKeyDown","onKeyPress","onChange","onFocus","onBlur","placeholder","style","maxWidth","class","onClick","ReferenceResults","on_select","on_page","on_prev_page","on_next_page","on_close","columns","get_columns","column","label","results","get_results","minWidth","width","backgroundColor","zIndex","result","uid","align","push","rows","index","get_result_uid","focused","build_columns","searchterm","get_column_names","highlighted","highlight","dangerouslySetInnerHTML","__html","used","text","rx","replaceAll","m","pages","page","cls","join","next_url","prev_url","has_results","get_style","position","top","right","build_close_button","build_header_columns","build_rows","build_prev_button","build_pages","build_next_button","References","on_deselect","template","context","display_template","records","interpolate","items","get_selected_uids","render_display_template","build_selected_items","UIDReferenceWidgetController","count","b_start","root_el","parse_json","api","goto_page","clear_results","select","select_focused","deselect","navigate_results","widget","removeEventListener","multi_valued","q","limit","complete","url_params","make_query","toggle_loading","promise","set_results_data","fetch_results","setState","at","pos","splice","direction","next","previous","keyCode","is_disabled","AddressWidgetAPI","portal_url","get_url","LocationSelector","locations","id","render_options","AddressField","visible","is_location_selector","is_visible","for","render_element","Address","country","subdivision1","subdivision2","city","zip","address","address_type","on_country_change","on_subdivision1_change","on_subdivision2_change","on_city_change","on_zip_change","on_address_change","force_array","subdivisions1","subdivisions2","labels","constructor","subfield","get_input_id","get_input_name","countries","get_label","get_subdivisions1","get_subdivisions2","AddressWidgetController","fetch_subdivisions","subdivisions","x","subdivision","html_items","section_title","render_items","portalUrl","tinymce","height","paste_data_images","plugins","content_css","sidebar","tooltip","selectpicker","widgets","getElementsByClassName","controller","render","menu","base_url","href","DOMParser","parseFromString","firstChild","replaceWith"],"sourceRoot":""} \ No newline at end of file diff --git a/webpack/app/senaite.core.js b/webpack/app/senaite.core.js index 55db1a37fd..6aa7991e32 100644 --- a/webpack/app/senaite.core.js +++ b/webpack/app/senaite.core.js @@ -76,4 +76,39 @@ document.addEventListener("DOMContentLoaded", () => { let controller = ReactDOM.render(, widget); window.widgets[id] = controller; } + + // Workflow Menu Update for Ajax Transitions + // https://github.com/senaite/senaite.app.listing/pull/87 + document.body.addEventListener("listing:submit", (event) => { + let menu = document.getElementById("plone-contentmenu-workflow"); + // return immediately if no workflow menu is present + if (menu === null ) { + return false; + } + // get the base url from the `data-base-url` attribute + let base_url = document.body.dataset.baseUrl; + if (base_url === undefined) { + // fallback to the current location URL + base_url = location.href.split("#")[0].split("?")[0]; + } + const request = new Request(base_url + "/menu/workflow_menu"); + fetch(request) + .then((response) => { + // we might get a 404 when the current page URL ends with a view, e.g. + // `WS-ID/manage_results` or `CLIENT-ID/multi_results` etc. + if (response.ok) { + return response.text(); + } + }) + .then((html) => { + if (!html) { + return; + } + let parser = new DOMParser(); + let doc = parser.parseFromString(html, "text/html"); + let el = doc.body.firstChild; + menu.replaceWith(el); + }) + }); + });