diff --git a/js/dist/common/common.js b/js/dist/common/common.js index 7eafe1dee..71b255b1d 100644 --- a/js/dist/common/common.js +++ b/js/dist/common/common.js @@ -1,2 +1,2 @@ -(self.webpackChunkflarum_core=self.webpackChunkflarum_core||[]).push([[661],{5873:(t,e,n)=>{"use strict";n.d(e,{Z:()=>j});var r=n(2122),s=n(6156),i=n(7037),a=n(5462),o=n(8864),u=n(2003),c=n(2058),l=n(877),h=n(4993),d=n(7794),p=n(2231),f=n(7963),v=n(2839),Z=n(3214),b=n(1252),y=n(2660),g=n(4371),w=n(6583),A=n(4693),N=n(2242),k=n(6437),C=n(442),x=n(2919),E=n(6250),T=n(8696),D=n(7757),B=n.n(D),S=n(2137),O=n(8292),R=function(){function t(){this.modal=null}var e=t.prototype;return e.show=function(){var t=(0,S.Z)(B().mark((function t(e,n){var r;return B().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(e.prototype instanceof O.Z){t.next=10;break}if("function"!=typeof e){t.next=8;break}return t.next=4,e();case 4:r=t.sent,e=r.default,t.next=10;break;case 8:throw console.error("The ModalManager can only show Modals"),new Error("The ModalManager can only show Modals");case 10:if(!e.init){t.next=13;break}throw console.error("The componentClass parameter must be a modal class, not a modal instance. Whichever extension triggered this modal should be updated to comply with beta 14."),new Error("The componentClass parameter must be a modal class, not a modal instance. Whichever extension triggered this modal should be updated to comply with beta 14.");case 13:clearTimeout(this.closeTimeout),this.modal={componentClass:e,attrs:n},m.redraw.sync();case 16:case"end":return t.stop()}}),t,this)})));return function(e,n){return t.apply(this,arguments)}}(),e.close=function(){var t=this;this.modal&&(this.closeTimeout=setTimeout((function(){t.modal=null,m.redraw()})))},t}(),I=n(6150),P=function(){function t(){(0,s.Z)(this,"activeAlerts",{}),(0,s.Z)(this,"alertId",0)}var e=t.prototype;return e.getActiveAlerts=function(){return this.activeAlerts},e.show=function(t,e,n){var r,s=I.Z,i={};if(1==arguments.length?r=t:2==arguments.length?(i=t,r=e):3==arguments.length&&(s=t,i=e,r=n),i===I.Z||i instanceof I.Z)throw console.error("The AlertManager can only show Alerts. Whichever extension triggered this alert should be updated to comply with beta 14."),new Error("The AlertManager can only show Alerts. Whichever extension triggered this alert should be updated to comply with beta 14.");return this.activeAlerts[++this.alertId]={children:r,attrs:i,componentClass:s},m.redraw(),this.alertId},e.dismiss=function(t){t&&t in this.activeAlerts&&(delete this.activeAlerts[t],m.redraw())},e.clear=function(){this.activeAlerts={},m.redraw()},t}();function M(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n=t.length?{done:!0}:{done:!1,value:t[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}return(n=t[Symbol.iterator]()).next.bind(n)}((0,E.Z)(s.extend));!(r=i()).done;)r.value.extend(e,{name:n,exports:s})}))},e.mount=function(t){var e=this;void 0===t&&(t=""),m.mount(document.getElementById("modal"),{view:function(){return o.Z.component({state:e.modal})}}),m.mount(document.getElementById("alerts"),{view:function(){return u.Z.component({state:e.alerts})}}),this.drawer=new f.Z,m.route(document.getElementById("content"),t+"/",(0,v.Z)(this.routes,t));var n=new b.Z((function(t){var e=$("#app"),n=e.offset().top;e.toggleClass("affix",t>=n).toggleClass("scrolled",t>n),$(".App-header").toggleClass("navbar-fixed-top",t>=n)}));n.start(),n.update(),$((function(){$("body").addClass("ontouchstart"in window?"touch":"no-touch")})),(0,y.Z)()},e.preloadedApiDocument=function(){if(this.data.apiDocument&&window.location.href===this.initialRoute){var t=this.store.pushPayload(this.data.apiDocument);return this.data.apiDocument=null,t}return null},e.screen=function(){return getComputedStyle(document.documentElement).getPropertyValue("--flarum-screen")},e.setTitle=function(t){this.title=t,this.updateTitle()},e.setTitleCount=function(t){this.titleCount=t,this.updateTitle()},e.updateTitle=function(){var t=this.titleCount?"("+this.titleCount+") ":"",e=this.title&&m.route.get()!==this.forum.attribute("basePath")+"/"?this.title+" - ":"",n=this.forum.attribute("title");document.title=t+e+n},e.request=function(t){var e=this,n=(0,r.Z)({},t);if(n.background=n.background||!0,(0,g.extend)(n,"config",(function(t,n){return n.setRequestHeader("X-CSRF-Token",e.session.csrfToken)})),"GET"!==n.method&&"POST"!==n.method){var s=n.method;(0,g.extend)(n,"config",(function(t,e){return e.setRequestHeader("X-HTTP-Method-Override",s)})),n.method="POST"}n.deserialize=n.deserialize||function(t){return t},n.errorHandler=n.errorHandler||function(t){throw t};var i=n.extract;return n.extract=function(t){var e;e=i?i(t.responseText):t.responseText||null;var r=t.status;if(r<200||r>299)throw new Z.Z(r,e,n,t);if(t.getResponseHeader){var s=t.getResponseHeader("X-CSRF-Token");s&&(app.session.csrfToken=s)}try{return JSON.parse(e)}catch(r){throw new Z.Z(500,e,n,t)}},this.requestErrorAlert&&this.alerts.dismiss(this.requestErrorAlert),m.request(n).then((function(t){return t}),(function(t){var r;switch(t.status){case 422:r=t.response.errors.map((function(t){return[t.detail,m("br",null)]})).reduce((function(t,e){return t.concat(e)}),[]).slice(0,-1);break;case 401:case 403:r=app.translator.trans("core.lib.error.permission_denied_message");break;case 404:case 410:r=app.translator.trans("core.lib.error.not_found_message");break;case 429:r=app.translator.trans("core.lib.error.rate_limit_exceeded_message");break;default:r=app.translator.trans("core.lib.error.generic_message")}var s=app.forum.attribute("debug"),i=t.response&&t.response.errors,o=Array.isArray(i)&&i[0]&&i[0].detail&&i.map((function(t){return decodeURI(t.detail)}));t.alert={type:"error",content:r,controls:s&&[m(a.Z,{className:"Button Button--link",onclick:e.showDebug.bind(e,t,o)},"Debug")]};try{n.errorHandler(t)}catch(t){if(s&&t.xhr){var u,c=t.options,l=c.method,h=c.url,d=t.xhr.status,p=void 0===d?"":d;console.group(l+" "+h+" "+p),(u=console).error.apply(u,o||[t]),console.groupEnd()}e.requestErrorAlert=e.alerts.show(t.alert,t.alert.content)}return Promise.reject(t)}))},e.showDebug=function(t,e){this.alerts.dismiss(this.requestErrorAlert),this.modal.show(c.Z,{error:t,formattedError:e})},e.route=function(t,e){void 0===e&&(e={});var n=this.routes[t];if(!n)throw new Error("Route '"+t+"' does not exist");var r=n.path.replace(/:([^\/]+)/g,(function(t,n){return(0,p.Z)(e,n)}));for(var s in e)e.hasOwnProperty(s)&&!e[s]&&delete e[s];var i=m.buildQueryString(e);return(""===m.route.prefix?this.forum.attribute("basePath"):"")+r+(i?"?"+i:"")},t}()},6366:(t,e,n)=>{"use strict";n.d(e,{Z:()=>i});var r=n(2122),s=n(6156),i=function(){function t(){(0,s.Z)(this,"element",void 0),(0,s.Z)(this,"attrs",void 0)}var e=t.prototype;return e.oninit=function(t){this.setAttrs(t.attrs)},e.oncreate=function(t){this.element=t.dom},e.onbeforeupdate=function(t){this.setAttrs(t.attrs)},e.$=function(t){function e(e){return t.apply(this,arguments)}return e.toString=function(){return t.toString()},e}((function(t){var e=$(this.element);return t?e.find(t):e})),t.component=function(t,e){void 0===t&&(t={}),void 0===e&&(e=null);var n=(0,r.Z)({},t);return m(this,n,e)},e.setAttrs=function(t){if(void 0===t&&(t={}),this.constructor.initAttrs(t),t){if("children"in t)throw new Error("["+this.constructor.name+'] The "children" attribute of attrs should never be used. Either pass children in as the vnode children or rename the attribute');if("tag"in t)throw new Error("["+this.constructor.name+'] You cannot use the "tag" attribute name with Mithril 2.')}this.attrs=t},t.initAttrs=function(t){},t}()},8866:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(2122),s=function(){function t(t,e){void 0===t&&(t={}),void 0===e&&(e=null),this.data=t,this.freshness=new Date,this.exists=!1,this.store=e}var e=t.prototype;return e.id=function(){return this.data.id},e.attribute=function(t){return this.data.attributes[t]},e.pushData=function(e){for(var n in e)if("object"==typeof e[n])for(var r in this.data[n]=this.data[n]||{},e[n])e[n][r]instanceof t&&(e[n][r]={data:t.getIdentifier(e[n][r])}),this.data[n][r]=e[n][r];else this.data[n]=e[n];this.freshness=new Date},e.pushAttributes=function(t){this.pushData({attributes:t})},e.save=function(e,n){var s=this;void 0===n&&(n={});var i={type:this.data.type,id:this.data.id,attributes:e};if(e.relationships){for(var a in i.relationships={},e.relationships){var o=e.relationships[a];i.relationships[a]={data:o instanceof Array?o.map(t.getIdentifier):t.getIdentifier(o)}}delete e.relationships}var u=this.copyData();this.pushData(i);var c={data:i};return n.meta&&(c.meta=n.meta),app.request((0,r.Z)({method:this.exists?"PATCH":"POST",url:app.forum.attribute("apiUrl")+this.apiEndpoint(),body:c},n)).then((function(t){return s.store.data[t.data.type]=s.store.data[t.data.type]||{},s.store.data[t.data.type][t.data.id]=s,s.store.pushPayload(t)}),(function(t){throw s.pushData(u),m.redraw(),t}))},e.delete=function(t,e){var n=this;return void 0===e&&(e={}),this.exists?app.request((0,r.Z)({method:"DELETE",url:app.forum.attribute("apiUrl")+this.apiEndpoint(),body:t},e)).then((function(){n.exists=!1,n.store.remove(n)})):Promise.resolve()},e.apiEndpoint=function(){return"/"+this.data.type+(this.exists?"/"+this.data.id:"")},e.copyData=function(){return JSON.parse(JSON.stringify(this.data))},t.attribute=function(t,e){return function(){var n=this.data.attributes&&this.data.attributes[t];return e?e(n):n}},t.hasOne=function(t){return function(){if(this.data.relationships){var e=this.data.relationships[t];if(e)return app.store.getById(e.data.type,e.data.id)}return!1}},t.hasMany=function(t){return function(){if(this.data.relationships){var e=this.data.relationships[t];if(e)return e.data.map((function(t){return app.store.getById(t.type,t.id)}))}return!1}},t.transformDate=function(t){return t?new Date(t):null},t.getIdentifier=function(t){return{type:t.data.type,id:t.data.id}},t}()},7794:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(2122),s=function(){function t(t,e){this.user=t,this.csrfToken=e}var e=t.prototype;return e.login=function(t,e){return void 0===e&&(e={}),app.request((0,r.Z)({method:"POST",url:app.forum.attribute("baseUrl")+"/login",body:t},e))},e.logout=function(){window.location=app.forum.attribute("baseUrl")+"/logout?token="+this.csrfToken},t}()},4993:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(2122),s=function(){function t(t){this.data={},this.models=t}var e=t.prototype;return e.pushPayload=function(t){t.included&&t.included.map(this.pushObject.bind(this));var e=t.data instanceof Array?t.data.map(this.pushObject.bind(this)):this.pushObject(t.data);return e.payload=t,e},e.pushObject=function(t){if(!this.models[t.type])return null;var e=this.data[t.type]=this.data[t.type]||{};return e[t.id]?e[t.id].pushData(t):e[t.id]=this.createRecord(t.type,t),e[t.id].exists=!0,e[t.id]},e.find=function(t,e,n,s){void 0===n&&(n={}),void 0===s&&(s={});var i=n,a=app.forum.attribute("apiUrl")+"/"+t;return e instanceof Array?a+="?filter[id]="+e.join(","):"object"==typeof e?i=e:e&&(a+="/"+e),app.request((0,r.Z)({method:"GET",url:a,params:i},s)).then(this.pushPayload.bind(this))},e.getById=function(t,e){return this.data[t]&&this.data[t][e]},e.getBy=function(t,e,n){return this.all(t).filter((function(t){return t[e]()===n}))[0]},e.all=function(t){var e=this.data[t];return e?Object.keys(e).map((function(t){return e[t]})):[]},e.remove=function(t){delete this.data[t.data.type][t.id()]},e.createRecord=function(t,e){return void 0===e&&(e={}),e.type=e.type||t,new this.models[t](e,this)},t}()},877:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(2122),s=n(3131),i=n(2231),a=function(){function t(){this.translations={},this.locale=null}var e=t.prototype;return e.addTranslations=function(t){(0,r.Z)(this.translations,t)},e.trans=function(t,e){var n=this.translations[t];return n?this.apply(n,e||{}):t},e.transChoice=function(t,e,n){var r=this.translations[t];return r?(e=parseInt(e,10),r=this.pluralize(r,e),this.apply(r,n||{})):t},e.apply=function(t,e){if("user"in e){var n=(0,i.Z)(e,"user");e.username||(e.username=(0,s.Z)(n))}t=t.split(new RegExp("({[a-z0-9_]+}|)","gi"));var r=[],a=[r];return t.forEach((function(t){var n=t.match(new RegExp("{([a-z0-9_]+)}|<(/?)([a-z0-9_]+)>","i"));if(n){if(n[1])a[0].push(e[n[1]]);else if(n[3])if(n[2]){var r,s=a[0].splice(0,a[0].length);(r=a[0]).push.apply(r,m.fragment(s).children),a.shift()}else{var i=e[n[3]]||{tag:n[3],children:[]};a[0].push(i),a.unshift(i.children||i)}}else a[0].push(t)})),r.filter((function(t){return t}))},e.pluralize=function(t,e){var n=this,r=new RegExp(/^\w+\: +(.+)$/),s=new RegExp(/^\s*((\{\s*(\-?\d+[\s*,\s*\-?\d+]*)\s*\})|([\[\]])\s*(-Inf|\-?\d+)\s*,\s*(\+?Inf|\-?\d+)\s*([\[\]]))\s?(.+?)$/),i=new RegExp(/^\s*(\{\s*(\-?\d+[\s*,\s*\-?\d+]*)\s*\})|([\[\]])\s*(-Inf|\-?\d+)\s*,\s*(\+?Inf|\-?\d+)\s*([\[\]])/),a=[],o=[];return t.split("|").forEach((function(t){if(s.test(t)){var e=t.match(s);o[e[0]]=e[e.length-1]}else if(r.test(t)){var n=t.match(r);a.push(n[1])}else a.push(t)})),o.forEach((function(t,r){if(i.test(r)){var s=r.match(i);if(s[1]){var a=s[2].split(",");for(var u in a)if(e==a[u])return o[r]}else{var c=n.convertNumber(s[4]),l=n.convertNumber(s[5]);if(("["===s[3]?e>=c:e>c)&&("]"===s[6]?e<=l:e3&&(e=e.split("_")[0]),e){case"bo":case"dz":case"id":case"ja":case"jv":case"ka":case"km":case"kn":case"ko":case"ms":case"th":case"vi":case"zh":return 0;case"af":case"az":case"bn":case"bg":case"ca":case"da":case"de":case"el":case"en":case"eo":case"es":case"et":case"eu":case"fa":case"fi":case"fo":case"fur":case"fy":case"gl":case"gu":case"ha":case"he":case"hu":case"is":case"it":case"ku":case"lb":case"ml":case"mn":case"mr":case"nah":case"nb":case"ne":case"nl":case"nn":case"no":case"om":case"or":case"pa":case"pap":case"ps":case"pt":case"so":case"sq":case"sv":case"sw":case"ta":case"te":case"tk":case"tr":case"ur":case"zu":return 1==t?0:1;case"am":case"bh":case"fil":case"fr":case"gun":case"hi":case"ln":case"mg":case"nso":case"xbr":case"ti":case"wa":return 0===t||1==t?0:1;case"be":case"bs":case"hr":case"ru":case"sr":case"uk":return t%10==1&&t%100!=11?0:t%10>=2&&t%10<=4&&(t%100<10||t%100>=20)?1:2;case"cs":case"sk":return 1==t?0:t>=2&&t<=4?1:2;case"ga":return 1==t?0:2==t?1:2;case"lt":return t%10==1&&t%100!=11?0:t%10>=2&&(t%100<10||t%100>=20)?1:2;case"sl":return t%100==1?0:t%100==2?1:t%100==3||t%100==4?2:3;case"mk":return t%10==1?0:1;case"mt":return 1==t?0:0===t||t%100>1&&t%100<11?1:t%100>10&&t%100<20?2:3;case"lv":return 0===t?0:t%10==1&&t%100!=11?1:2;case"pl":return 1==t?0:t%10>=2&&t%10<=4&&(t%100<12||t%100>14)?1:2;case"cy":return 1==t?0:2==t?1:8==t||11==t?2:3;case"ro":return 1==t?0:0===t||t%100>0&&t%100<20?1:2;case"ar":return 0===t?0:1==t?1:2==t?2:t>=3&&t<=10?3:t>=11&&t<=99?4:5;default:return 0}},t}()},1834:(t,e,n)=>{"use strict";n.d(e,{Z:()=>kt});var r=n(4371),s=n(7794),i=n(4993),a=n(4967);const o={handlers:null,getHandlers:function(t){return this.handlers=this.handlers||{},this.handlers[t]=this.handlers[t]||[],this.handlers[t]},trigger:function(t){for(var e=this,n=arguments.length,r=new Array(n>1?n-1:0),s=1;s1?n-1:0),s=1;s{"use strict";n.d(e,{Z:()=>c});var r=n(2122),s=n(1788),i=n(6366),a=n(5462),o=n(1698),u=n(2231),c=function(t){function e(){return t.apply(this,arguments)||this}return(0,s.Z)(e,t),e.prototype.view=function(t){var e=(0,r.Z)({},this.attrs),n=(0,u.Z)(e,"type");e.className="Alert Alert--"+n+" "+(e.className||"");var s=(0,u.Z)(e,"content")||t.children,i=(0,u.Z)(e,"controls")||[],c=(0,u.Z)(e,"dismissible"),l=(0,u.Z)(e,"ondismiss"),h=[];return(c||void 0===c)&&h.push(m(a.Z,{icon:"fas fa-times",className:"Button Button--link Button--icon Alert-dismiss",onclick:l})),m("div",e,m("span",{className:"Alert-body"},s),m("ul",{className:"Alert-controls"},(0,o.Z)(i.concat(h))))},e}(i.Z)},2003:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(2122),s=n(1788),i=n(6366),a=(n(6150),function(t){function e(){return t.apply(this,arguments)||this}(0,s.Z)(e,t);var n=e.prototype;return n.oninit=function(e){t.prototype.oninit.call(this,e),this.state=this.attrs.state},n.view=function(){var t=this;return m("div",{className:"AlertManager"},Object.entries(this.state.getActiveAlerts()).map((function(e){var n=e[0],s=e[1];return m("div",{className:"AlertManager-alert"},m(s.componentClass,(0,r.Z)({},s.attrs,{ondismiss:t.state.dismiss.bind(t.state,n)}),s.children))})))},e}(i.Z))},7262:(t,e,n)=>{"use strict";n.d(e,{Z:()=>u});var r=n(2122),s=n(1788),i=n(6366),a=n(5052),o=n(2231),u=function(t){function e(){return t.apply(this,arguments)||this}(0,s.Z)(e,t);var n=e.prototype;return n.view=function(){var t=(0,r.Z)({},this.attrs),e=(0,o.Z)(t,"type"),n=(0,o.Z)(t,"icon");return t.className="Badge "+(e?"Badge--"+e:"")+" "+(t.className||""),t.title=(0,o.Z)(t,"label")||"",m("span",t,n?(0,a.Z)(n,{className:"Badge-icon"}):m.trust(" "))},n.oncreate=function(e){t.prototype.oncreate.call(this,e),this.attrs.label&&this.$().tooltip()},e}(i.Z)},5462:(t,e,n)=>{"use strict";n.d(e,{Z:()=>h});var r=n(2122),s=n(1788),i=n(6366),a=n(5052),o=n(1749),u=n(2231),c=n(8165),l=n(2232),h=function(t){function e(){return t.apply(this,arguments)||this}(0,s.Z)(e,t);var n=e.prototype;return n.view=function(t){var e=(0,r.Z)({},this.attrs);e.type=e.type||"button",e.title&&!t.children&&(e["aria-label"]=e.title),"object"==typeof e.title&&(e.title=(0,c.Z)(e.title)),!e.title&&t.children&&(e.title=(0,c.Z)(t.children));var n=(0,u.Z)(e,"icon"),s=(0,u.Z)(e,"loading");return(e.disabled||s)&&delete e.onclick,e.className=(0,o.Z)([e.className,n&&"hasIcon",(e.disabled||s)&&"disabled",s&&"loading"]),m("button",e,this.getButtonContent(t.children))},n.getButtonContent=function(t){var e=this.attrs.icon;return[e&&!0!==e?(0,a.Z)(e,{className:"Button-icon"}):"",t?m("span",{className:"Button-label"},t):"",this.attrs.loading?m(l.Z,{size:"tiny",className:"LoadingIndicator--inline"}):""]},e}(i.Z)},9699:(t,e,n)=>{"use strict";n.d(e,{Z:()=>c});var r=n(1788),s=n(6366),i=n(2232),a=n(5052),o=n(1749),u=n(9194),c=function(t){function e(){return t.apply(this,arguments)||this}(0,r.Z)(e,t);var n=e.prototype;return n.view=function(t){"0"===this.attrs.state&&(this.attrs.state=!1);var e=(0,o.Z)(["Checkbox",this.attrs.state?"on":"off",this.attrs.className,this.attrs.loading&&"loading",this.attrs.disabled&&"disabled"]);return m("label",{className:e},m("input",{type:"checkbox",checked:this.attrs.state,disabled:this.attrs.disabled,onchange:(0,u.Z)("checked",this.onchange.bind(this))}),m("div",{className:"Checkbox-display"},this.getDisplay()),t.children)},n.getDisplay=function(){return this.attrs.loading?m(i.Z,{size:"tiny"}):(0,a.Z)(this.attrs.state?"fas fa-check":"fas fa-times")},n.onchange=function(t){this.attrs.onchange&&this.attrs.onchange(t,this)},e}(s.Z)},8777:(t,e,n)=>{"use strict";n.d(e,{Z:()=>o});var r=n(1788),s=n(6366),i=n(5052),a=n(1698),o=function(t){function e(){return t.apply(this,arguments)||this}(0,r.Z)(e,t),e.initAttrs=function(t){t.className=t.className||"",t.buttonClassName=t.buttonClassName||"",t.menuClassName=t.menuClassName||"",t.label=t.label||"",t.caretIcon=void 0!==t.caretIcon?t.caretIcon:"fas fa-caret-down",t.accessibleToggleLabel=t.accessibleToggleLabel||app.translator.trans("core.lib.dropdown.toggle_dropdown_accessible_label")};var n=e.prototype;return n.oninit=function(e){t.prototype.oninit.call(this,e),this.showing=!1},n.view=function(t){var e=t.children?(0,a.Z)(t.children):[];return m("div",{className:"ButtonGroup Dropdown dropdown "+this.attrs.className+" itemCount"+e.length+(this.showing?" open":"")},this.getButton(t.children),this.getMenu(e))},n.oncreate=function(e){var n=this;t.prototype.oncreate.call(this,e),this.$().on("shown.bs.dropdown",(function(){n.showing=!0,n.attrs.onshow&&n.attrs.onshow(),m.redraw();var t=n.$(".Dropdown-menu"),e=t.hasClass("Dropdown-menu--right");t.removeClass("Dropdown-menu--top Dropdown-menu--right"),t.toggleClass("Dropdown-menu--top",t.offset().top+t.height()>$(window).scrollTop()+$(window).height()),t.offset().top<0&&t.removeClass("Dropdown-menu--top"),t.toggleClass("Dropdown-menu--right",e||t.offset().left+t.width()>$(window).scrollLeft()+$(window).width())})),this.$().on("hidden.bs.dropdown",(function(){n.showing=!1,n.attrs.onhide&&n.attrs.onhide(),m.redraw()}))},n.getButton=function(t){return m("button",{className:"Dropdown-toggle "+this.attrs.buttonClassName,"aria-haspopup":"menu","aria-label":this.attrs.accessibleToggleLabel,"data-toggle":"dropdown",onclick:this.attrs.onclick},this.getButtonContent(t))},n.getButtonContent=function(t){return[this.attrs.icon?(0,i.Z)(this.attrs.icon,{className:"Button-icon"}):"",m("span",{className:"Button-label"},this.attrs.label),this.attrs.caretIcon?(0,i.Z)(this.attrs.caretIcon,{className:"Button-caret"}):""]},n.getMenu=function(t){return m("ul",{className:"Dropdown-menu dropdown-menu "+this.attrs.menuClassName},t)},e}(s.Z)},9226:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(1788),s=n(6366),i=n(1698),a=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.prototype.view=function(t){return m("fieldset",{className:this.attrs.className},m("legend",null,this.attrs.label),m("ul",null,(0,i.Z)(t.children)))},e}(s.Z)},512:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(1788),s=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.initAttrs=function(e){t.initAttrs.call(this,e),e.group&&(e.icon=e.group.icon(),e.style={backgroundColor:e.group.color()},e.label=void 0===e.label?e.group.nameSingular():e.label,e.type="group--"+e.group.id(),delete e.group)},e}(n(7262).Z)},9236:(t,e,n)=>{"use strict";n.d(e,{Z:()=>o});var r=n(9756),s=n(1788),i=n(6366),a=n(2231),o=function(t){function e(){return t.apply(this,arguments)||this}return(0,s.Z)(e,t),e.prototype.view=function(t){var e=t.attrs,n=e.options,s=void 0===n?{}:n,i=(0,r.Z)(e,["options"]);i.href=i.href||"";var o=t.children||{tag:"#",children:t.text};return i.external?m("a",i,o):(i.href===m.route.get()&&("replace"in s||(s.replace=!0)),(0,a.Z)(i,"force")&&("state"in s||(s.state={}),"key"in s.state||(s.state.key=Date.now())),i.options=s,m(m.route.Link,i,o))},e}(i.Z)},7971:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(1788),s=n(5462),i=n(9236),a=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.initAttrs=function(e){t.initAttrs.call(this,e),e.active=this.isActive(e),void 0===e.force&&(e.force=!0)},e.prototype.view=function(e){var n=t.prototype.view.call(this,e);return n.tag=i.Z,n.attrs.active=String(n.attrs.active),n},e.isActive=function(t){return void 0!==t.active?t.active:m.route.get()===t.href},e}(s.Z)},2232:(t,e,n)=>{"use strict";n.d(e,{Z:()=>o});var r=n(2122),s=n(1788),i=n(6366),a=n(1035),o=function(t){function e(){return t.apply(this,arguments)||this}(0,s.Z)(e,t);var n=e.prototype;return n.view=function(){var t=(0,r.Z)({},this.attrs);return t.className="LoadingIndicator "+(t.className||""),delete t.size,m("div",t,m.trust(" "))},n.oncreate=function(e){t.prototype.oncreate.call(this,e);var n={zIndex:"auto",color:this.$().css("color")};switch(this.attrs.size){case"large":(0,r.Z)(n,{lines:10,length:8,width:4,radius:8});break;case"tiny":(0,r.Z)(n,{lines:8,length:2,width:2,radius:3});break;default:(0,r.Z)(n,{lines:8,length:4,width:3,radius:5})}new a.$(n).spin(this.element)},e}(i.Z)},8292:(t,e,n)=>{"use strict";n.d(e,{Z:()=>c});var r=n(3349),s=n(1788),i=n(6156),a=n(6366),o=n(6150),u=n(5462),c=function(t){function e(){for(var e,n=arguments.length,s=new Array(n),a=0;a{"use strict";n.d(e,{Z:()=>i});var r=n(2122),s=n(1788),i=function(t){function e(){return t.apply(this,arguments)||this}(0,s.Z)(e,t);var n=e.prototype;return n.view=function(){var t=this.attrs.state.modal;return m("div",{className:"ModalManager modal fade"},t?t.componentClass.component((0,r.Z)({},t.attrs,{animateShow:this.animateShow.bind(this),animateHide:this.animateHide.bind(this),state:this.attrs.state})):"")},n.oncreate=function(e){t.prototype.oncreate.call(this,e),this.$().on("hidden.bs.modal",this.attrs.state.close.bind(this.attrs.state))},n.animateShow=function(t){var e=!!this.attrs.state.modal.componentClass.isDismissible;this.$().hasClass("in")?t():this.$().one("shown.bs.modal",t).modal({backdrop:e||"static",keyboard:e}).modal("show")},n.animateHide=function(){this.$().modal("hide")},e}(n(6366).Z)},7330:(t,e,n)=>{"use strict";n.d(e,{Z:()=>o});var r=n(1788),s=n(6366),i=n(5462),a=n(7971),o=function(t){function e(){return t.apply(this,arguments)||this}(0,r.Z)(e,t);var n=e.prototype;return n.view=function(){var t=app,e=t.history,n=t.pane;return m("div",{className:"Navigation ButtonGroup "+(this.attrs.className||""),onmouseenter:n&&n.show.bind(n),onmouseleave:n&&n.onmouseleave.bind(n)},e.canGoBack()?[this.getBackButton(),this.getPaneButton()]:this.getDrawerButton())},n.getBackButton=function(){var t=app.history,e=t.getPrevious()||{};return a.Z.component({className:"Button Navigation-back Button--icon",href:t.backUrl(),icon:"fas fa-chevron-left",title:e.title,onclick:function(e){e.shiftKey||e.ctrlKey||e.metaKey||2===e.which||(e.preventDefault(),t.back())}})},n.getPaneButton=function(){var t=app.pane;return t&&t.active?i.Z.component({className:"Button Button--icon Navigation-pin"+(t.pinned?" active":""),onclick:t.togglePinned.bind(t),icon:"fas fa-thumbtack"}):""},n.getDrawerButton=function(){if(!this.attrs.drawer)return"";var t=app.drawer,e=app.session.user;return i.Z.component({className:"Button Button--icon Navigation-drawer"+(e&&e.newNotificationCount()?" new":""),onclick:function(e){e.stopPropagation(),t.show()},icon:"fas fa-bars"})},e}(s.Z)},3340:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(1788),s=n(6366),i=n(8696),a=function(t){function e(){return t.apply(this,arguments)||this}(0,r.Z)(e,t);var n=e.prototype;return n.oninit=function(e){t.prototype.oninit.call(this,e),app.previous=app.current,app.current=new i.Z(this.constructor,{routeName:this.attrs.routeName}),app.drawer.hide(),app.modal.close(),this.bodyClass="",this.scrollTopOnCreate=!0,this.useBrowserScrollRestoration=!0},n.oncreate=function(e){t.prototype.oncreate.call(this,e),this.bodyClass&&$("#app").addClass(this.bodyClass),this.scrollTopOnCreate&&$(window).scrollTop(0),"scrollRestoration"in history&&(history.scrollRestoration=this.useBrowserScrollRestoration?"auto":"manual")},n.onremove=function(){this.bodyClass&&$("#app").removeClass(this.bodyClass)},e}(s.Z)},4389:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(1788),s=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.prototype.view=function(){return m("div",{className:"Placeholder"},m("p",null,this.attrs.text))},e}(n(6366).Z)},2058:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(1788),s=function(t){function e(){return t.apply(this,arguments)||this}(0,r.Z)(e,t);var n=e.prototype;return n.className=function(){return"RequestErrorModal Modal--large"},n.title=function(){return this.attrs.error.xhr?this.attrs.error.xhr.status+" "+this.attrs.error.xhr.statusText:""},n.content=function(){var t,e=this.attrs,n=e.error,r=e.formattedError;if(r)t=r.join("\n\n");else try{var s=n.response||JSON.parse(n.responseText);t=JSON.stringify(s,null,2)}catch(e){t=n.responseText}return m("div",{className:"Modal-body"},m("pre",null,this.attrs.error.options.method," ",this.attrs.error.options.url,m("br",null),m("br",null),t))},e}(n(8292).Z)},8112:(t,e,n)=>{"use strict";n.d(e,{Z:()=>o});var r=n(1788),s=n(6366),i=n(5052),a=n(9194),o=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.prototype.view=function(){var t=this.attrs,e=t.options,n=t.onchange,r=t.value,s=t.disabled;return m("span",{className:"Select"},m("select",{className:"Select-input FormControl",onchange:n?(0,a.Z)("value",n.bind(this)):void 0,value:r,disabled:s},Object.keys(e).map((function(t){return m("option",{value:t},e[t])}))),(0,i.Z)("fas fa-sort",{className:"Select-caret"}))},e}(s.Z)},6317:(t,e,n)=>{"use strict";n.d(e,{Z:()=>o});var r=n(1788),s=n(8777),i=n(5052);function a(t){var e=t.tag;return("string"!=typeof e||"a"===e||"button"===e)&&("initAttrs"in e&&e.initAttrs(t.attrs),"isActive"in e?e.isActive(t.attrs):t.attrs.active)}var o=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.initAttrs=function(e){e.caretIcon=void 0!==e.caretIcon?e.caretIcon:"fas fa-sort",t.initAttrs.call(this,e),e.className+=" Dropdown--select"},e.prototype.getButtonContent=function(t){var e=t.find(a),n=e&&e.children||this.attrs.defaultLabel;return n instanceof Array&&(n=n[0]),[m("span",{className:"Button-label"},n),(0,i.Z)(this.attrs.caretIcon,{className:"Button-caret"})]},e}(s.Z)},2939:(t,e,n)=>{"use strict";n.d(e,{Z:()=>i});var r=n(1788),s=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.prototype.view=function(){return m("li",{className:"Dropdown-separator"})},e}(n(6366).Z);s.isListItem=!0;const i=s},1342:(t,e,n)=>{"use strict";n.d(e,{Z:()=>u});var r=n(2122),s=n(1788),i=n(8777),a=n(5462),o=n(5052),u=function(t){function e(){return t.apply(this,arguments)||this}(0,s.Z)(e,t),e.initAttrs=function(e){t.initAttrs.call(this,e),e.className+=" Dropdown--split",e.menuClassName+=" Dropdown-menu--right"};var n=e.prototype;return n.getButton=function(t){var e=this.getFirstChild(t),n=(0,r.Z)({},e.attrs);return n.className=(n.className||"")+" SplitDropdown-button Button "+this.attrs.buttonClassName,[a.Z.component(n,e.children),m("button",{className:"Dropdown-toggle Button Button--icon "+this.attrs.buttonClassName,"aria-haspopup":"menu","aria-label":this.attrs.accessibleToggleLabel,"data-toggle":"dropdown"},(0,o.Z)(this.attrs.icon,{className:"Button-icon"}),(0,o.Z)("fas fa-caret-down",{className:"Button-caret"}))]},n.getFirstChild=function(t){for(var e=t;e instanceof Array;)e=e[0];return e},e}(i.Z)},4435:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(1788),s=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.initAttrs=function(e){t.initAttrs.call(this,e),e.className=(e.className||"")+" Checkbox--switch"},e.prototype.getDisplay=function(){return this.attrs.loading?t.prototype.getDisplay.call(this):""},e}(n(9699).Z)},4371:(t,e,n)=>{"use strict";n.r(e),n.d(e,{extend:()=>s,override:()=>i});var r=n(2122);function s(t,e,n){var s=t[e];t[e]=function(){for(var t=arguments.length,e=new Array(t),r=0;r{"use strict";n.d(e,{Z:()=>s});var r=n(2122);function s(t,e){void 0===e&&(e={}),e.className="Avatar "+(e.className||"");var n="",s="undefined"===e.title||e.title;if(s||delete e.title,t){var i=t.displayName()||"?",a=t.avatarUrl();if(s&&(e.title=e.title||i),a)return m("img",(0,r.Z)({},e,{src:a,alt:""}));n=i.charAt(0).toUpperCase(),e.style={background:t.color()}}return m("span",e,n)}},7693:(t,e,n)=>{"use strict";n.d(e,{Z:()=>i});var r=n(7484),s=n.n(r);function i(t){var e=s()(t),n=e.format(),r=e.format("LLLL");return m("time",{pubdate:!0,datetime:n},r)}},4910:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(6646);function s(t,e,n){if(!e&&!n)return t;var s=e instanceof RegExp?e:new RegExp(e,"gi"),i=t,a=0;return n&&(e&&(a=Math.max(0,t.search(s)-n/2)),i=(0,r.truncate)(i,n,a)),i=$("
").text(i).html(),e&&(i=i.replace(s,"$&")),m.trust(i)}},7603:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(7484),s=n.n(r),i=n(9090);function a(t){var e=s()(t),n=e.format(),r=e.format("LLLL"),a=(0,i.Z)(t);return m("time",{pubdate:!0,datetime:n,title:r,"data-humantime":!0},a)}},5052:(t,e,n)=>{"use strict";function r(t,e){return void 0===e&&(e={}),e.className="icon "+t+" "+(e.className||""),m("i",e)}n.d(e,{Z:()=>r})},1698:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(2939),s=n(1749);function i(t){return t.tag===r.Z}function a(t){return t instanceof Array||(t=[t]),function(t){var e,n=[];return t.filter(Boolean).forEach((function(r,s){(!i(r)||e&&!i(e)&&s!==t.length-1)&&(e=r,n.push(r))})),n}(t).map((function(t){var e=t.tag&&t.tag.isListItem,n=t.tag&&t.tag.isActive&&t.tag.isActive(t.attrs),r=t.attrs&&t.attrs.itemClassName||t.itemClassName;return e&&(t.attrs=t.attrs||{},t.attrs.key=t.attrs.key||t.itemName,t.key=t.attrs.key),e?t:m("li",{className:(0,s.Z)([r,t.itemName&&"item-"+t.itemName,n&&"active"]),key:t.attrs&&t.attrs.key||t.itemName},t)}))}},5589:(t,e,n)=>{"use strict";function r(t){if(2===t.length)return app.translator.trans("core.lib.series.two_text",{first:t[0],second:t[1]});if(t.length>=3){var e=t.slice(1,t.length-1).reduce((function(t,e){return t.concat([e,app.translator.trans("core.lib.series.glue_text")])}),[]).slice(0,-1);return app.translator.trans("core.lib.series.three_text",{first:t[0],second:e,third:t[t.length-1]})}return t}n.d(e,{Z:()=>r})},947:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(5052);function s(t){if(t.lastSeenAt()&&t.isOnline())return m("span",{className:"UserOnline"},(0,r.Z)("fas fa-circle"))}},3131:(t,e,n)=>{"use strict";function r(t){var e=t&&t.displayName()||app.translator.trans("core.lib.username.deleted_text");return m("span",{className:"username"},e)}n.d(e,{Z:()=>r})},2633:(t,e,n)=>{"use strict";n.d(e,{U:()=>r});var r={};n.r(r),n.d(r,{Model:()=>l,PostTypes:()=>d,Routes:()=>p}),n(4352),n(5436),n(270),n(5377),n(9737),n(8852),n(6278),n(8294),n(5314);var s=n(4110),i=n.n(s),a=n(6176),o=n.n(a),u=n(8119),c=n(6156),l=function(){function t(t,e){void 0===e&&(e=null),(0,c.Z)(this,"type",void 0),(0,c.Z)(this,"attributes",[]),(0,c.Z)(this,"hasOnes",[]),(0,c.Z)(this,"hasManys",[]),this.type=t,this.model=e}var e=t.prototype;return e.attribute=function(t){return this.attributes.push(t),this},e.hasOne=function(t){return this.hasOnes.push(t),this},e.hasMany=function(t){return this.hasManys.push(t),this},e.extend=function(t,e){this.model&&(t.store.models[this.type]=this.model);var n=t.store.models[this.type];this.attributes.forEach((function(t){return n.prototype[t]=n.attribute(t)})),this.hasOnes.forEach((function(t){return n.prototype[t]=n.hasOne(t)})),this.hasManys.forEach((function(t){return n.prototype[t]=n.hasMany(t)}))},t}(),h=n(2122),d=function(){function t(){(0,c.Z)(this,"postComponents",{})}var e=t.prototype;return e.add=function(t,e){return this.postComponents[t]=e,this},e.extend=function(t,e){(0,h.Z)(t.postComponents,this.postComponents)},t}(),p=function(){function t(){(0,c.Z)(this,"routes",{})}var e=t.prototype;return e.add=function(t,e,n){return this.routes[t]={path:e,component:n},this},e.extend=function(t,e){(0,h.Z)(t.routes,this.routes)},t}();dayjs.extend(i()),dayjs.extend(o()),(0,u.Z)(window)},2242:(t,e,n)=>{"use strict";n.d(e,{Z:()=>c});var r=n(2122),s=n(1788),i=n(8866),a=n(876),o=n(7037),u=n(7262),c=function(t){function e(){return t.apply(this,arguments)||this}return(0,s.Z)(e,t),e}(i.Z);(0,r.Z)(c.prototype,{title:i.Z.attribute("title"),slug:i.Z.attribute("slug"),createdAt:i.Z.attribute("createdAt",i.Z.transformDate),user:i.Z.hasOne("user"),firstPost:i.Z.hasOne("firstPost"),lastPostedAt:i.Z.attribute("lastPostedAt",i.Z.transformDate),lastPostedUser:i.Z.hasOne("lastPostedUser"),lastPost:i.Z.hasOne("lastPost"),lastPostNumber:i.Z.attribute("lastPostNumber"),commentCount:i.Z.attribute("commentCount"),replyCount:(0,a.Z)("commentCount",(function(t){return Math.max(0,t-1)})),posts:i.Z.hasMany("posts"),mostRelevantPost:i.Z.hasOne("mostRelevantPost"),lastReadAt:i.Z.attribute("lastReadAt",i.Z.transformDate),lastReadPostNumber:i.Z.attribute("lastReadPostNumber"),isUnread:(0,a.Z)("unreadCount",(function(t){return!!t})),isRead:(0,a.Z)("unreadCount",(function(t){return app.session.user&&!t})),hiddenAt:i.Z.attribute("hiddenAt",i.Z.transformDate),hiddenUser:i.Z.hasOne("hiddenUser"),isHidden:(0,a.Z)("hiddenAt",(function(t){return!!t})),canReply:i.Z.attribute("canReply"),canRename:i.Z.attribute("canRename"),canHide:i.Z.attribute("canHide"),canDelete:i.Z.attribute("canDelete"),removePost:function(t){var e=this.data.relationships,n=e&&e.posts;n&&n.data.some((function(e,r){if(t===e.id)return n.data.splice(r,1),!0}))},unreadCount:function(){var t=app.session.user;if(t&&t.markedAllAsReadAt(){"use strict";n.d(e,{Z:()=>s});var r=n(1788),s=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.prototype.apiEndpoint=function(){return"/"},e}(n(8866).Z)},442:(t,e,n)=>{"use strict";n.d(e,{Z:()=>o});var r=n(2122),s=n(1788),i=n(8866),a=function(t){function e(){return t.apply(this,arguments)||this}return(0,s.Z)(e,t),e}(i.Z);(0,r.Z)(a.prototype,{nameSingular:i.Z.attribute("nameSingular"),namePlural:i.Z.attribute("namePlural"),color:i.Z.attribute("color"),icon:i.Z.attribute("icon"),isHidden:i.Z.attribute("isHidden")}),a.ADMINISTRATOR_ID="1",a.GUEST_ID="2",a.MEMBER_ID="3";const o=a},2919:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(2122),s=n(1788),i=n(8866),a=function(t){function e(){return t.apply(this,arguments)||this}return(0,s.Z)(e,t),e}(i.Z);(0,r.Z)(a.prototype,{contentType:i.Z.attribute("contentType"),content:i.Z.attribute("content"),createdAt:i.Z.attribute("createdAt",i.Z.transformDate),isRead:i.Z.attribute("isRead"),user:i.Z.hasOne("user"),fromUser:i.Z.hasOne("fromUser"),subject:i.Z.hasOne("subject")})},6437:(t,e,n)=>{"use strict";n.d(e,{Z:()=>u});var r=n(2122),s=n(1788),i=n(8866),a=n(876),o=n(6646),u=function(t){function e(){return t.apply(this,arguments)||this}return(0,s.Z)(e,t),e}(i.Z);(0,r.Z)(u.prototype,{number:i.Z.attribute("number"),discussion:i.Z.hasOne("discussion"),createdAt:i.Z.attribute("createdAt",i.Z.transformDate),user:i.Z.hasOne("user"),contentType:i.Z.attribute("contentType"),content:i.Z.attribute("content"),contentHtml:i.Z.attribute("contentHtml"),contentPlain:(0,a.Z)("contentHtml",o.getPlainContent),editedAt:i.Z.attribute("editedAt",i.Z.transformDate),editedUser:i.Z.hasOne("editedUser"),isEdited:(0,a.Z)("editedAt",(function(t){return!!t})),hiddenAt:i.Z.attribute("hiddenAt",i.Z.transformDate),hiddenUser:i.Z.hasOne("hiddenUser"),isHidden:(0,a.Z)("hiddenAt",(function(t){return!!t})),canEdit:i.Z.attribute("canEdit"),canHide:i.Z.attribute("canHide"),canDelete:i.Z.attribute("canDelete")})},4693:(t,e,n)=>{"use strict";n.d(e,{Z:()=>l});var r=n(2122),s=n(1788),i=n(8866),a=n(3849),o=n(7037),u=n(876),c=n(512),l=function(t){function e(){return t.apply(this,arguments)||this}return(0,s.Z)(e,t),e}(i.Z);(0,r.Z)(l.prototype,{username:i.Z.attribute("username"),slug:i.Z.attribute("slug"),displayName:i.Z.attribute("displayName"),email:i.Z.attribute("email"),isEmailConfirmed:i.Z.attribute("isEmailConfirmed"),password:i.Z.attribute("password"),avatarUrl:i.Z.attribute("avatarUrl"),preferences:i.Z.attribute("preferences"),groups:i.Z.hasMany("groups"),joinTime:i.Z.attribute("joinTime",i.Z.transformDate),lastSeenAt:i.Z.attribute("lastSeenAt",i.Z.transformDate),markedAllAsReadAt:i.Z.attribute("markedAllAsReadAt",i.Z.transformDate),unreadNotificationCount:i.Z.attribute("unreadNotificationCount"),newNotificationCount:i.Z.attribute("newNotificationCount"),discussionCount:i.Z.attribute("discussionCount"),commentCount:i.Z.attribute("commentCount"),canEdit:i.Z.attribute("canEdit"),canEditCredentials:i.Z.attribute("canEditCredentials"),canEditGroups:i.Z.attribute("canEditGroups"),canDelete:i.Z.attribute("canDelete"),avatarColor:null,color:(0,u.Z)("username","avatarUrl","avatarColor",(function(t,e,n){return n?"rgb("+n.join(", ")+")":e?(this.calculateAvatarColor(),""):"#"+(0,a.Z)(t)})),isOnline:function(){return dayjs().subtract(5,"minutes").isBefore(this.lastSeenAt())},badges:function(){var t=new o.Z,e=this.groups();return e&&e.forEach((function(e){t.add("group"+e.id(),c.Z.component({group:e}))})),t},calculateAvatarColor:function(){var t=new Image,e=this;t.onload=function(){var t=new ColorThief;e.avatarColor=t.getColor(this),e.freshness=new Date,m.redraw()},t.crossOrigin="anonymous",t.src=this.avatarUrl()},savePreferences:function(t){var e=this.preferences();return(0,r.Z)(e,t),this.save({preferences:e})}})},4965:(t,e,n)=>{"use strict";n.d(e,{Z:()=>u});var r=n(7757),s=n.n(r),i=n(2137),a=n(2122),o=n(6156),u=function(){function t(t,e){(0,o.Z)(this,"component",void 0),(0,o.Z)(this,"routeName",void 0),this.component=t,this.routeName=e}var e=t.prototype;return e.makeKey=function(){return this.routeName+JSON.stringify(m.route.param())},e.makeAttrs=function(t){return(0,a.Z)({},t.attrs,{routeName:this.routeName})},e.onmatch=function(){var t=(0,i.Z)(s().mark((function t(e,n,r){var i;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if("function"!=typeof this.component.component){t.next=4;break}return t.abrupt("return",this.component);case 4:return t.next=6,this.component();case 6:return i=t.sent,t.abrupt("return",i.default);case 8:case"end":return t.stop()}}),t,this)})));return function(e,n,r){return t.apply(this,arguments)}}(),e.render=function(t){return[(0,a.Z)({},t,{attrs:this.makeAttrs(t),key:this.makeKey()})]},t}()},8696:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(9668),s=function(){function t(t,e){void 0===e&&(e={}),this.type=t,this.data=e}var e=t.prototype;return e.matches=function(t,e){var n=this;return void 0===e&&(e={}),!!(0,r.Z)(this.type,t)&&Object.keys(e).every((function(t){return n.data[t]===e[t]}))},e.get=function(t){return this.data[t]},e.set=function(t,e){this.data[t]=e},t}()},4967:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(6156),s=n(6496),i=n.n(s),a=function(){function t(t,e){(0,r.Z)(this,"el",void 0),this.el=document.createElement("textarea"),this.build(t,e)}var e=t.prototype;return e.build=function(t,e){var n=this;this.el.className=e.classNames.join(" "),this.el.disabled=e.disabled,this.el.placeholder=e.placeholder,this.el.value=e.value;var r=function(t){e.inputListeners.forEach((function(t){t()})),t.redraw=!1};this.el.oninput=function(t){e.oninput(n.el.value),r(t)},this.el.onclick=r,this.el.onkeyup=r,this.el.addEventListener("keydown",(function(t){(t.metaKey||t.ctrlKey)&&"Enter"===t.key&&e.onsubmit()})),t.append(this.el)},e.setValue=function(t){$(this.el).val(t).trigger("input"),this.el.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))},e.moveCursorTo=function(t){this.setSelectionRange(t,t)},e.getSelectionRange=function(){return[this.el.selectionStart,this.el.selectionEnd]},e.getLastNChars=function(t){return this.el.value.slice(Math.max(0,this.el.selectionStart-t),this.el.selectionStart)},e.insertAtCursor=function(t){this.insertAt(this.el.selectionStart,t)},e.insertAt=function(t,e){this.insertBetween(t,t,e)},e.insertBetween=function(t,e,n){var r=this.el.value,s=r.slice(0,t),i=r.slice(e);this.setValue(""+s+n+i),this.moveCursorTo(t+n.length)},e.replaceBeforeCursor=function(t,e){this.insertBetween(t,this.el.selectionStart,e)},e.setSelectionRange=function(t,e){this.el.setSelectionRange(t,e),this.focus()},e.getCaretCoordinates=function(t){var e=i()(this.el,t);return{top:e.top-this.el.scrollTop,left:e.left}},e.disabled=function(t){this.el.disabled=t},e.focus=function(){this.el.focus()},e.destroy=function(){this.el.remove()},t}()},7963:(t,e,n)=>{"use strict";n.d(e,{Z:()=>r});var r=function(){function t(){var t=this;$("#content").click((function(e){t.isOpen()&&(e.preventDefault(),t.hide())}))}var e=t.prototype;return e.isOpen=function(){return $("#app").hasClass("drawerOpen")},e.hide=function(){var t=$("#app");if(t.hasClass("drawerOpen")){var e=$("#drawer");e.css("visibility","visible").one("transitionend",(function(){return e.css("visibility","")})),t.removeClass("drawerOpen"),this.$backdrop&&this.$backdrop.remove()}},e.show=function(){var t=this;$("#app").addClass("drawerOpen"),this.$backdrop=$("
").addClass("drawer-backdrop fade").appendTo("body").click((function(){return t.hide()})),setTimeout((function(){return t.$backdrop.addClass("in")}))},t}()},7037:(t,e,n)=>{"use strict";n.d(e,{Z:()=>i});var r=n(6156),s=function(t,e){(0,r.Z)(this,"content",void 0),(0,r.Z)(this,"priority",void 0),(0,r.Z)(this,"key",void 0),this.content=t,this.priority=e},i=function(){function t(){(0,r.Z)(this,"items",{})}var e=t.prototype;return e.isEmpty=function(){for(var t in this.items)if(this.items.hasOwnProperty(t))return!1;return!0},e.has=function(t){return!!this.items[t]},e.get=function(t){return this.items[t].content},e.add=function(t,e,n){return void 0===n&&(n=0),this.items[t]=new s(e,n),this},e.replace=function(t,e,n){return void 0===e&&(e=null),void 0===n&&(n=null),this.items[t]&&(null!==e&&(this.items[t].content=e),null!==n&&(this.items[t].priority=n)),this},e.remove=function(t){return delete this.items[t],this},e.merge=function(t){for(var e in t.items)t.items.hasOwnProperty(e)&&t.items[e]instanceof s&&(this.items[e]=t.items[e]);return this},e.toArray=function(){var t=[];for(var e in this.items)this.items.hasOwnProperty(e)&&this.items[e]instanceof s&&(this.items[e].content=Object(this.items[e].content),this.items[e].content.itemName=e,t.push(this.items[e]),this.items[e].key=t.length);return t.sort((function(t,e){return t.priority===e.priority?t.key-e.key:t.priority>e.priority?-1:1})).map((function(t){return t.content}))},t}()},3214:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(6156),s=function(t,e,n,s){(0,r.Z)(this,"status",void 0),(0,r.Z)(this,"options",void 0),(0,r.Z)(this,"xhr",void 0),(0,r.Z)(this,"responseText",void 0),(0,r.Z)(this,"response",void 0),(0,r.Z)(this,"alert",void 0),this.status=t,this.responseText=e,this.options=n,this.xhr=s;try{this.response=JSON.parse(e)}catch(t){this.response=null}this.alert=null}},1252:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},s=function(){function t(t){this.callback=t,this.ticking=!1}var e=t.prototype;return e.loop=function(){var t=this;this.ticking||(r((function(){t.update(),t.ticking=!1})),this.ticking=!0)},e.update=function(){this.callback(window.pageYOffset)},e.start=function(){this.active||window.addEventListener("scroll",this.active=this.loop.bind(this),{passive:!0})},e.stop=function(){window.removeEventListener("scroll",this.active),this.active=null},t}()},9015:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(5922);const s=n.n(r)()},8932:(t,e,n)=>{"use strict";n.d(e,{Z:()=>r});var r=function(){function t(){for(var t=arguments.length,e=new Array(t),n=0;n{"use strict";function r(t){return t>=1e6?Math.floor(t/1e6)+app.translator.trans("core.lib.number_suffix.mega_text"):t>=1e3?(t/1e3).toFixed(1)+app.translator.trans("core.lib.number_suffix.kilo_text"):t.toString()}n.d(e,{Z:()=>r})},3927:(t,e,n)=>{"use strict";function r(t,e){var n=$(window),r=$(t).offset().top-n.scrollTop();e(),n.scrollTop($(t).offset().top-r)}n.d(e,{Z:()=>r})},1749:(t,e,n)=>{"use strict";n.d(e,{Z:()=>r});const r=n(6010).Z},876:(t,e,n)=>{"use strict";function r(){for(var t=arguments.length,e=new Array(t),n=0;nr})},2231:(t,e,n)=>{"use strict";function r(t,e){var n=t[e];return delete t[e],n}n.d(e,{Z:()=>r})},8165:(t,e,n)=>{"use strict";function r(t){return t instanceof Array?t.map((function(t){return r(t)})).join(""):"object"==typeof t&&null!==t?t.children?r(t.children):t.text:t}n.d(e,{Z:()=>r})},1068:(t,e,n)=>{"use strict";function r(t){return t.toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")}n.d(e,{Z:()=>r})},9090:(t,e,n)=>{"use strict";n.d(e,{Z:()=>i});var r=n(7484),s=n.n(r);function i(t){var e=s()(t),n=s()();return e.isAfter(n)&&(e=n),e.diff(s()())<-2592e6?e.year()===s()().year()?e.format("D MMM"):e.format("ll"):"5 days"}n(4110)},2660:(t,e,n)=>{"use strict";n.d(e,{Z:()=>i});var r=n(9090);function s(){$("[data-humantime]").each((function(){var t=$(this),e=(0,r.Z)(t.attr("datetime"));t.html(e)}))}function i(){setInterval(s,1e4)}},2839:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(4965);function s(t,e){void 0===e&&(e="");var n={};for(var s in t){var i=t[s];if("resolver"in i)n[e+i.path]=i.resolver;else{if(!("component"in i))throw new Error("Either a resolver or a component must be provided for the route ["+s+"]");var a="resolverClass"in i?i.resolverClass:r.Z;n[e+i.path]=new a(i.component,s)}}return n}},8119:(t,e,n)=>{"use strict";function r(t,e){var n="select"===t.tag?t.attrs.multi?"multi":"select":t.attrs.type;return t.attrs.onchange="multi"===n?function(){e([].slice.call(this.selectedOptions,(function(t){return t.value})))}:"select"===n?function(t){e(this.selectedOptions[0].value)}:"checkbox"===n?function(t){e(this.checked)}:t.attrs.oninput=function(t){e(this.value)},"select"===t.tag?t.children.forEach((function(t){t.attrs.value!==e()&&t.children[0]!==e()||(t.attrs.selected=!0)})):"checkbox"===n?t.attrs.checked=e():"radio"===n?t.attrs.checked=e()===t.attrs.value:t.attrs.value=e(),t.attrs.bidi=null,t}n.d(e,{Z:()=>i}),r.view=function(t,e,n){return r(e,e.attrs.bidi)};const s=r;function i(t){var e=t.m,n=function(t){for(var n=arguments.length,r=new Array(n>1?n-1:0),i=1;i{"use strict";n.d(e,{Z:()=>r});const r=function(t,e){var n=new RegExp("(\\w+\\/)?("+e+"|common)\\/");return new Proxy(t,{get:function(t,e){return t[e]||t[e.replace(n,"$1")]}})}},7769:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(2122);function s(t,e,n){void 0===e&&(e=null),void 0===n&&(n={});var s=(0,r.Z)({},n);s.state=s.state||{},s.state.key=Date.now(),m.route.set(t,e,s)}},3849:(t,e,n)=>{"use strict";function r(t){for(var e=0,n=0;nr})},9668:(t,e,n)=>{"use strict";function r(t,e){return t&&(t===e||t.prototype instanceof e)}n.d(e,{Z:()=>r})},9194:(t,e,n)=>{"use strict";n.d(e,{Z:()=>r});const r=function(t,e){return function(){e(this.getAttribute(t)||this[t])}}}}]); +(self.webpackChunkflarum_core=self.webpackChunkflarum_core||[]).push([[661],{5873:(t,e,n)=>{"use strict";n.d(e,{Z:()=>j});var r=n(2122),s=n(6156),i=n(7037),a=n(5462),o=n(8864),u=n(2003),c=n(2058),l=n(877),h=n(4993),d=n(7794),p=n(2231),f=n(7963),v=n(2839),Z=n(3214),b=n(1252),y=n(2660),g=n(4371),w=n(6583),A=n(4693),N=n(2242),k=n(6437),C=n(442),x=n(2919),E=n(6250),T=n(8696),D=n(7757),B=n.n(D),S=n(2137),O=n(8292),R=function(){function t(){this.modal=null}var e=t.prototype;return e.show=function(){var t=(0,S.Z)(B().mark((function t(e,n){var r;return B().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(e.prototype instanceof O.Z){t.next=10;break}if("function"!=typeof e){t.next=8;break}return t.next=4,e();case 4:r=t.sent,e=r.default,t.next=10;break;case 8:throw console.error("The ModalManager can only show Modals"),new Error("The ModalManager can only show Modals");case 10:if(!e.init){t.next=13;break}throw console.error("The componentClass parameter must be a modal class, not a modal instance. Whichever extension triggered this modal should be updated to comply with beta 14."),new Error("The componentClass parameter must be a modal class, not a modal instance. Whichever extension triggered this modal should be updated to comply with beta 14.");case 13:clearTimeout(this.closeTimeout),this.modal={componentClass:e,attrs:n},m.redraw.sync();case 16:case"end":return t.stop()}}),t,this)})));return function(e,n){return t.apply(this,arguments)}}(),e.close=function(){var t=this;this.modal&&(this.closeTimeout=setTimeout((function(){t.modal=null,m.redraw()})))},t}(),I=n(6150),P=function(){function t(){(0,s.Z)(this,"activeAlerts",{}),(0,s.Z)(this,"alertId",0)}var e=t.prototype;return e.getActiveAlerts=function(){return this.activeAlerts},e.show=function(t,e,n){var r,s=I.Z,i={};if(1==arguments.length?r=t:2==arguments.length?(i=t,r=e):3==arguments.length&&(s=t,i=e,r=n),i===I.Z||i instanceof I.Z)throw console.error("The AlertManager can only show Alerts. Whichever extension triggered this alert should be updated to comply with beta 14."),new Error("The AlertManager can only show Alerts. Whichever extension triggered this alert should be updated to comply with beta 14.");return this.activeAlerts[++this.alertId]={children:r,attrs:i,componentClass:s},m.redraw(),this.alertId},e.dismiss=function(t){t&&t in this.activeAlerts&&(delete this.activeAlerts[t],m.redraw())},e.clear=function(){this.activeAlerts={},m.redraw()},t}();function M(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,r=new Array(e);n=t.length?{done:!0}:{done:!1,value:t[r++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}return(n=t[Symbol.iterator]()).next.bind(n)}((0,E.Z)(s.extend));!(r=i()).done;)r.value.extend(e,{name:n,exports:s})}))},e.mount=function(t){var e=this;void 0===t&&(t=""),m.mount(document.getElementById("modal"),{view:function(){return o.Z.component({state:e.modal})}}),m.mount(document.getElementById("alerts"),{view:function(){return u.Z.component({state:e.alerts})}}),this.drawer=new f.Z,m.route(document.getElementById("content"),t+"/",(0,v.Z)(this.routes,t));var n=new b.Z((function(t){var e=$("#app"),n=e.offset().top;e.toggleClass("affix",t>=n).toggleClass("scrolled",t>n),$(".App-header").toggleClass("navbar-fixed-top",t>=n)}));n.start(),n.update(),$((function(){$("body").addClass("ontouchstart"in window?"touch":"no-touch")})),(0,y.Z)()},e.preloadedApiDocument=function(){if(this.data.apiDocument&&window.location.href===this.initialRoute){var t=this.store.pushPayload(this.data.apiDocument);return this.data.apiDocument=null,t}return null},e.screen=function(){return getComputedStyle(document.documentElement).getPropertyValue("--flarum-screen")},e.setTitle=function(t){this.title=t,this.updateTitle()},e.setTitleCount=function(t){this.titleCount=t,this.updateTitle()},e.updateTitle=function(){var t=this.titleCount?"("+this.titleCount+") ":"",e=this.title&&m.route.get()!==this.forum.attribute("basePath")+"/"?this.title+" - ":"",n=this.forum.attribute("title");document.title=t+e+n},e.request=function(t){var e=this,n=(0,r.Z)({},t);if(n.background=n.background||!0,(0,g.extend)(n,"config",(function(t,n){return n.setRequestHeader("X-CSRF-Token",e.session.csrfToken)})),"GET"!==n.method&&"POST"!==n.method){var s=n.method;(0,g.extend)(n,"config",(function(t,e){return e.setRequestHeader("X-HTTP-Method-Override",s)})),n.method="POST"}n.deserialize=n.deserialize||function(t){return t},n.errorHandler=n.errorHandler||function(t){throw t};var i=n.extract;return n.extract=function(t){var e;e=i?i(t.responseText):t.responseText||null;var r=t.status;if(r<200||r>299)throw new Z.Z(r,e,n,t);if(t.getResponseHeader){var s=t.getResponseHeader("X-CSRF-Token");s&&(app.session.csrfToken=s)}try{return JSON.parse(e)}catch(r){throw new Z.Z(500,e,n,t)}},this.requestErrorAlert&&this.alerts.dismiss(this.requestErrorAlert),m.request(n).then((function(t){return t}),(function(t){var r;switch(t.status){case 422:r=t.response.errors.map((function(t){return[t.detail,m("br",null)]})).reduce((function(t,e){return t.concat(e)}),[]).slice(0,-1);break;case 401:case 403:r=app.translator.trans("core.lib.error.permission_denied_message");break;case 404:case 410:r=app.translator.trans("core.lib.error.not_found_message");break;case 429:r=app.translator.trans("core.lib.error.rate_limit_exceeded_message");break;default:r=app.translator.trans("core.lib.error.generic_message")}var s=app.forum.attribute("debug"),i=t.response&&t.response.errors,o=Array.isArray(i)&&i[0]&&i[0].detail&&i.map((function(t){return decodeURI(t.detail)}));t.alert={type:"error",content:r,controls:s&&[m(a.Z,{className:"Button Button--link",onclick:e.showDebug.bind(e,t,o)},"Debug")]};try{n.errorHandler(t)}catch(t){if(s&&t.xhr){var u,c=t.options,l=c.method,h=c.url,d=t.xhr.status,p=void 0===d?"":d;console.group(l+" "+h+" "+p),(u=console).error.apply(u,o||[t]),console.groupEnd()}e.requestErrorAlert=e.alerts.show(t.alert,t.alert.content)}return Promise.reject(t)}))},e.showDebug=function(t,e){this.alerts.dismiss(this.requestErrorAlert),this.modal.show(c.Z,{error:t,formattedError:e})},e.route=function(t,e){void 0===e&&(e={});var n=this.routes[t];if(!n)throw new Error("Route '"+t+"' does not exist");var r=n.path.replace(/:([^\/]+)/g,(function(t,n){return(0,p.Z)(e,n)}));for(var s in e)e.hasOwnProperty(s)&&!e[s]&&delete e[s];var i=m.buildQueryString(e);return(""===m.route.prefix?this.forum.attribute("basePath"):"")+r+(i?"?"+i:"")},t}()},6366:(t,e,n)=>{"use strict";n.d(e,{Z:()=>i});var r=n(2122),s=n(6156),i=function(){function t(){(0,s.Z)(this,"element",void 0),(0,s.Z)(this,"attrs",void 0)}var e=t.prototype;return e.oninit=function(t){this.setAttrs(t.attrs)},e.oncreate=function(t){this.element=t.dom},e.onbeforeupdate=function(t){this.setAttrs(t.attrs)},e.$=function(t){function e(e){return t.apply(this,arguments)}return e.toString=function(){return t.toString()},e}((function(t){var e=$(this.element);return t?e.find(t):e})),t.component=function(t,e){void 0===t&&(t={}),void 0===e&&(e=null);var n=(0,r.Z)({},t);return m(this,n,e)},e.setAttrs=function(t){if(void 0===t&&(t={}),this.constructor.initAttrs(t),t){if("children"in t)throw new Error("["+this.constructor.name+'] The "children" attribute of attrs should never be used. Either pass children in as the vnode children or rename the attribute');if("tag"in t)throw new Error("["+this.constructor.name+'] You cannot use the "tag" attribute name with Mithril 2.')}this.attrs=t},t.initAttrs=function(t){},t}()},8866:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(2122),s=function(){function t(t,e){void 0===t&&(t={}),void 0===e&&(e=null),this.data=t,this.freshness=new Date,this.exists=!1,this.store=e}var e=t.prototype;return e.id=function(){return this.data.id},e.attribute=function(t){return this.data.attributes[t]},e.pushData=function(e){for(var n in e)if("object"==typeof e[n])for(var r in this.data[n]=this.data[n]||{},e[n])e[n][r]instanceof t&&(e[n][r]={data:t.getIdentifier(e[n][r])}),this.data[n][r]=e[n][r];else this.data[n]=e[n];this.freshness=new Date},e.pushAttributes=function(t){this.pushData({attributes:t})},e.save=function(e,n){var s=this;void 0===n&&(n={});var i={type:this.data.type,id:this.data.id,attributes:e};if(e.relationships){for(var a in i.relationships={},e.relationships){var o=e.relationships[a];i.relationships[a]={data:o instanceof Array?o.map(t.getIdentifier):t.getIdentifier(o)}}delete e.relationships}var u=this.copyData();this.pushData(i);var c={data:i};return n.meta&&(c.meta=n.meta),app.request((0,r.Z)({method:this.exists?"PATCH":"POST",url:app.forum.attribute("apiUrl")+this.apiEndpoint(),body:c},n)).then((function(t){return s.store.data[t.data.type]=s.store.data[t.data.type]||{},s.store.data[t.data.type][t.data.id]=s,s.store.pushPayload(t)}),(function(t){throw s.pushData(u),m.redraw(),t}))},e.delete=function(t,e){var n=this;return void 0===e&&(e={}),this.exists?app.request((0,r.Z)({method:"DELETE",url:app.forum.attribute("apiUrl")+this.apiEndpoint(),body:t},e)).then((function(){n.exists=!1,n.store.remove(n)})):Promise.resolve()},e.apiEndpoint=function(){return"/"+this.data.type+(this.exists?"/"+this.data.id:"")},e.copyData=function(){return JSON.parse(JSON.stringify(this.data))},t.attribute=function(t,e){return function(){var n=this.data.attributes&&this.data.attributes[t];return e?e(n):n}},t.hasOne=function(t){return function(){if(this.data.relationships){var e=this.data.relationships[t];if(e)return app.store.getById(e.data.type,e.data.id)}return!1}},t.hasMany=function(t){return function(){if(this.data.relationships){var e=this.data.relationships[t];if(e)return e.data.map((function(t){return app.store.getById(t.type,t.id)}))}return!1}},t.transformDate=function(t){return t?new Date(t):null},t.getIdentifier=function(t){return{type:t.data.type,id:t.data.id}},t}()},7794:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(2122),s=function(){function t(t,e){this.user=t,this.csrfToken=e}var e=t.prototype;return e.login=function(t,e){return void 0===e&&(e={}),app.request((0,r.Z)({method:"POST",url:app.forum.attribute("baseUrl")+"/login",body:t},e))},e.logout=function(){window.location=app.forum.attribute("baseUrl")+"/logout?token="+this.csrfToken},t}()},4993:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(2122),s=function(){function t(t){this.data={},this.models=t}var e=t.prototype;return e.pushPayload=function(t){t.included&&t.included.map(this.pushObject.bind(this));var e=t.data instanceof Array?t.data.map(this.pushObject.bind(this)):this.pushObject(t.data);return e.payload=t,e},e.pushObject=function(t){if(!this.models[t.type])return null;var e=this.data[t.type]=this.data[t.type]||{};return e[t.id]?e[t.id].pushData(t):e[t.id]=this.createRecord(t.type,t),e[t.id].exists=!0,e[t.id]},e.find=function(t,e,n,s){void 0===n&&(n={}),void 0===s&&(s={});var i=n,a=app.forum.attribute("apiUrl")+"/"+t;return e instanceof Array?a+="?filter[id]="+e.join(","):"object"==typeof e?i=e:e&&(a+="/"+e),app.request((0,r.Z)({method:"GET",url:a,params:i},s)).then(this.pushPayload.bind(this))},e.getById=function(t,e){return this.data[t]&&this.data[t][e]},e.getBy=function(t,e,n){return this.all(t).filter((function(t){return t[e]()===n}))[0]},e.all=function(t){var e=this.data[t];return e?Object.keys(e).map((function(t){return e[t]})):[]},e.remove=function(t){delete this.data[t.data.type][t.id()]},e.createRecord=function(t,e){return void 0===e&&(e={}),e.type=e.type||t,new this.models[t](e,this)},t}()},877:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(2122),s=n(3131),i=n(2231),a=function(){function t(){this.translations={},this.locale=null}var e=t.prototype;return e.addTranslations=function(t){(0,r.Z)(this.translations,t)},e.trans=function(t,e){var n=this.translations[t];return n?this.apply(n,e||{}):t},e.transChoice=function(t,e,n){var r=this.translations[t];return r?(e=parseInt(e,10),r=this.pluralize(r,e),this.apply(r,n||{})):t},e.apply=function(t,e){if("user"in e){var n=(0,i.Z)(e,"user");e.username||(e.username=(0,s.Z)(n))}t=t.split(new RegExp("({[a-z0-9_]+}|)","gi"));var r=[],a=[r];return t.forEach((function(t){var n=t.match(new RegExp("{([a-z0-9_]+)}|<(/?)([a-z0-9_]+)>","i"));if(n){if(n[1])a[0].push(e[n[1]]);else if(n[3])if(n[2]){var r,s=a[0].splice(0,a[0].length);(r=a[0]).push.apply(r,m.fragment(s).children),a.shift()}else{var i=e[n[3]]||{tag:n[3],children:[]};a[0].push(i),a.unshift(i.children||i)}}else a[0].push(t)})),r.filter((function(t){return t}))},e.pluralize=function(t,e){var n=this,r=new RegExp(/^\w+\: +(.+)$/),s=new RegExp(/^\s*((\{\s*(\-?\d+[\s*,\s*\-?\d+]*)\s*\})|([\[\]])\s*(-Inf|\-?\d+)\s*,\s*(\+?Inf|\-?\d+)\s*([\[\]]))\s?(.+?)$/),i=new RegExp(/^\s*(\{\s*(\-?\d+[\s*,\s*\-?\d+]*)\s*\})|([\[\]])\s*(-Inf|\-?\d+)\s*,\s*(\+?Inf|\-?\d+)\s*([\[\]])/),a=[],o=[];return t.split("|").forEach((function(t){if(s.test(t)){var e=t.match(s);o[e[0]]=e[e.length-1]}else if(r.test(t)){var n=t.match(r);a.push(n[1])}else a.push(t)})),o.forEach((function(t,r){if(i.test(r)){var s=r.match(i);if(s[1]){var a=s[2].split(",");for(var u in a)if(e==a[u])return o[r]}else{var c=n.convertNumber(s[4]),l=n.convertNumber(s[5]);if(("["===s[3]?e>=c:e>c)&&("]"===s[6]?e<=l:e3&&(e=e.split("_")[0]),e){case"bo":case"dz":case"id":case"ja":case"jv":case"ka":case"km":case"kn":case"ko":case"ms":case"th":case"vi":case"zh":return 0;case"af":case"az":case"bn":case"bg":case"ca":case"da":case"de":case"el":case"en":case"eo":case"es":case"et":case"eu":case"fa":case"fi":case"fo":case"fur":case"fy":case"gl":case"gu":case"ha":case"he":case"hu":case"is":case"it":case"ku":case"lb":case"ml":case"mn":case"mr":case"nah":case"nb":case"ne":case"nl":case"nn":case"no":case"om":case"or":case"pa":case"pap":case"ps":case"pt":case"so":case"sq":case"sv":case"sw":case"ta":case"te":case"tk":case"tr":case"ur":case"zu":return 1==t?0:1;case"am":case"bh":case"fil":case"fr":case"gun":case"hi":case"ln":case"mg":case"nso":case"xbr":case"ti":case"wa":return 0===t||1==t?0:1;case"be":case"bs":case"hr":case"ru":case"sr":case"uk":return t%10==1&&t%100!=11?0:t%10>=2&&t%10<=4&&(t%100<10||t%100>=20)?1:2;case"cs":case"sk":return 1==t?0:t>=2&&t<=4?1:2;case"ga":return 1==t?0:2==t?1:2;case"lt":return t%10==1&&t%100!=11?0:t%10>=2&&(t%100<10||t%100>=20)?1:2;case"sl":return t%100==1?0:t%100==2?1:t%100==3||t%100==4?2:3;case"mk":return t%10==1?0:1;case"mt":return 1==t?0:0===t||t%100>1&&t%100<11?1:t%100>10&&t%100<20?2:3;case"lv":return 0===t?0:t%10==1&&t%100!=11?1:2;case"pl":return 1==t?0:t%10>=2&&t%10<=4&&(t%100<12||t%100>14)?1:2;case"cy":return 1==t?0:2==t?1:8==t||11==t?2:3;case"ro":return 1==t?0:0===t||t%100>0&&t%100<20?1:2;case"ar":return 0===t?0:1==t?1:2==t?2:t>=3&&t<=10?3:t>=11&&t<=99?4:5;default:return 0}},t}()},1834:(t,e,n)=>{"use strict";n.d(e,{Z:()=>kt});var r=n(4371),s=n(7794),i=n(4993),a=n(4967);const o={handlers:null,getHandlers:function(t){return this.handlers=this.handlers||{},this.handlers[t]=this.handlers[t]||[],this.handlers[t]},trigger:function(t){for(var e=this,n=arguments.length,r=new Array(n>1?n-1:0),s=1;s1?n-1:0),s=1;s{"use strict";n.d(e,{Z:()=>c});var r=n(2122),s=n(1788),i=n(6366),a=n(5462),o=n(1698),u=n(2231),c=function(t){function e(){return t.apply(this,arguments)||this}return(0,s.Z)(e,t),e.prototype.view=function(t){var e=(0,r.Z)({},this.attrs),n=(0,u.Z)(e,"type");e.className="Alert Alert--"+n+" "+(e.className||"");var s=(0,u.Z)(e,"content")||t.children,i=(0,u.Z)(e,"controls")||[],c=(0,u.Z)(e,"dismissible"),l=(0,u.Z)(e,"ondismiss"),h=[];return(c||void 0===c)&&h.push(m(a.Z,{icon:"fas fa-times",className:"Button Button--link Button--icon Alert-dismiss",onclick:l})),m("div",e,m("span",{className:"Alert-body"},s),m("ul",{className:"Alert-controls"},(0,o.Z)(i.concat(h))))},e}(i.Z)},2003:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(2122),s=n(1788),i=n(6366),a=(n(6150),function(t){function e(){return t.apply(this,arguments)||this}(0,s.Z)(e,t);var n=e.prototype;return n.oninit=function(e){t.prototype.oninit.call(this,e),this.state=this.attrs.state},n.view=function(){var t=this;return m("div",{className:"AlertManager"},Object.entries(this.state.getActiveAlerts()).map((function(e){var n=e[0],s=e[1];return m("div",{className:"AlertManager-alert"},m(s.componentClass,(0,r.Z)({},s.attrs,{ondismiss:t.state.dismiss.bind(t.state,n)}),s.children))})))},e}(i.Z))},7262:(t,e,n)=>{"use strict";n.d(e,{Z:()=>u});var r=n(2122),s=n(1788),i=n(6366),a=n(5052),o=n(2231),u=function(t){function e(){return t.apply(this,arguments)||this}(0,s.Z)(e,t);var n=e.prototype;return n.view=function(){var t=(0,r.Z)({},this.attrs),e=(0,o.Z)(t,"type"),n=(0,o.Z)(t,"icon");return t.className="Badge "+(e?"Badge--"+e:"")+" "+(t.className||""),t.title=(0,o.Z)(t,"label")||"",m("span",t,n?(0,a.Z)(n,{className:"Badge-icon"}):m.trust(" "))},n.oncreate=function(e){t.prototype.oncreate.call(this,e),this.attrs.label&&this.$().tooltip()},e}(i.Z)},5462:(t,e,n)=>{"use strict";n.d(e,{Z:()=>h});var r=n(2122),s=n(1788),i=n(6366),a=n(5052),o=n(1749),u=n(2231),c=n(8165),l=n(2232),h=function(t){function e(){return t.apply(this,arguments)||this}(0,s.Z)(e,t);var n=e.prototype;return n.view=function(t){var e=(0,r.Z)({},this.attrs);e.type=e.type||"button",e.title&&!t.children&&(e["aria-label"]=e.title),"object"==typeof e.title&&(e.title=(0,c.Z)(e.title)),!e.title&&t.children&&(e.title=(0,c.Z)(t.children));var n=(0,u.Z)(e,"icon"),s=(0,u.Z)(e,"loading");return(e.disabled||s)&&delete e.onclick,e.className=(0,o.Z)([e.className,n&&"hasIcon",(e.disabled||s)&&"disabled",s&&"loading"]),m("button",e,this.getButtonContent(t.children))},n.getButtonContent=function(t){var e=this.attrs.icon;return[e&&!0!==e?(0,a.Z)(e,{className:"Button-icon"}):"",t?m("span",{className:"Button-label"},t):"",this.attrs.loading?m(l.Z,{size:"tiny",className:"LoadingIndicator--inline"}):""]},e}(i.Z)},9699:(t,e,n)=>{"use strict";n.d(e,{Z:()=>c});var r=n(1788),s=n(6366),i=n(2232),a=n(5052),o=n(1749),u=n(9194),c=function(t){function e(){return t.apply(this,arguments)||this}(0,r.Z)(e,t);var n=e.prototype;return n.view=function(t){"0"===this.attrs.state&&(this.attrs.state=!1);var e=(0,o.Z)(["Checkbox",this.attrs.state?"on":"off",this.attrs.className,this.attrs.loading&&"loading",this.attrs.disabled&&"disabled"]);return m("label",{className:e},m("input",{type:"checkbox",checked:this.attrs.state,disabled:this.attrs.disabled,onchange:(0,u.Z)("checked",this.onchange.bind(this))}),m("div",{className:"Checkbox-display"},this.getDisplay()),t.children)},n.getDisplay=function(){return this.attrs.loading?m(i.Z,{size:"tiny"}):(0,a.Z)(this.attrs.state?"fas fa-check":"fas fa-times")},n.onchange=function(t){this.attrs.onchange&&this.attrs.onchange(t,this)},e}(s.Z)},8777:(t,e,n)=>{"use strict";n.d(e,{Z:()=>o});var r=n(1788),s=n(6366),i=n(5052),a=n(1698),o=function(t){function e(){return t.apply(this,arguments)||this}(0,r.Z)(e,t),e.initAttrs=function(t){t.className=t.className||"",t.buttonClassName=t.buttonClassName||"",t.menuClassName=t.menuClassName||"",t.label=t.label||"",t.caretIcon=void 0!==t.caretIcon?t.caretIcon:"fas fa-caret-down",t.accessibleToggleLabel=t.accessibleToggleLabel||app.translator.trans("core.lib.dropdown.toggle_dropdown_accessible_label")};var n=e.prototype;return n.oninit=function(e){t.prototype.oninit.call(this,e),this.showing=!1},n.view=function(t){var e=t.children?(0,a.Z)(t.children):[];return m("div",{className:"ButtonGroup Dropdown dropdown "+this.attrs.className+" itemCount"+e.length+(this.showing?" open":"")},this.getButton(t.children),this.getMenu(e))},n.oncreate=function(e){var n=this;t.prototype.oncreate.call(this,e),this.$().on("shown.bs.dropdown",(function(){n.showing=!0,n.attrs.onshow&&n.attrs.onshow(),m.redraw();var t=n.$(".Dropdown-menu"),e=t.hasClass("Dropdown-menu--right");t.removeClass("Dropdown-menu--top Dropdown-menu--right"),t.toggleClass("Dropdown-menu--top",t.offset().top+t.height()>$(window).scrollTop()+$(window).height()),t.offset().top<0&&t.removeClass("Dropdown-menu--top"),t.toggleClass("Dropdown-menu--right",e||t.offset().left+t.width()>$(window).scrollLeft()+$(window).width())})),this.$().on("hidden.bs.dropdown",(function(){n.showing=!1,n.attrs.onhide&&n.attrs.onhide(),m.redraw()}))},n.getButton=function(t){return m("button",{className:"Dropdown-toggle "+this.attrs.buttonClassName,"aria-haspopup":"menu","aria-label":this.attrs.accessibleToggleLabel,"data-toggle":"dropdown",onclick:this.attrs.onclick},this.getButtonContent(t))},n.getButtonContent=function(t){return[this.attrs.icon?(0,i.Z)(this.attrs.icon,{className:"Button-icon"}):"",m("span",{className:"Button-label"},this.attrs.label),this.attrs.caretIcon?(0,i.Z)(this.attrs.caretIcon,{className:"Button-caret"}):""]},n.getMenu=function(t){return m("ul",{className:"Dropdown-menu dropdown-menu "+this.attrs.menuClassName},t)},e}(s.Z)},9226:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(1788),s=n(6366),i=n(1698),a=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.prototype.view=function(t){return m("fieldset",{className:this.attrs.className},m("legend",null,this.attrs.label),m("ul",null,(0,i.Z)(t.children)))},e}(s.Z)},512:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(1788),s=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.initAttrs=function(e){t.initAttrs.call(this,e),e.group&&(e.icon=e.group.icon(),e.style={backgroundColor:e.group.color()},e.label=void 0===e.label?e.group.nameSingular():e.label,e.type="group--"+e.group.id(),delete e.group)},e}(n(7262).Z)},9236:(t,e,n)=>{"use strict";n.d(e,{Z:()=>o});var r=n(9756),s=n(1788),i=n(6366),a=n(2231),o=function(t){function e(){return t.apply(this,arguments)||this}return(0,s.Z)(e,t),e.prototype.view=function(t){var e=t.attrs,n=e.options,s=void 0===n?{}:n,i=(0,r.Z)(e,["options"]);i.href=i.href||"";var o=t.children||{tag:"#",children:t.text};return i.external?m("a",i,o):(i.href===m.route.get()&&("replace"in s||(s.replace=!0)),(0,a.Z)(i,"force")&&("state"in s||(s.state={}),"key"in s.state||(s.state.key=Date.now())),i.options=s,m(m.route.Link,i,o))},e}(i.Z)},7971:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(1788),s=n(5462),i=n(9236),a=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.initAttrs=function(e){t.initAttrs.call(this,e),e.active=this.isActive(e),void 0===e.force&&(e.force=!0)},e.prototype.view=function(e){var n=t.prototype.view.call(this,e);return n.tag=i.Z,n.attrs.active=String(n.attrs.active),n},e.isActive=function(t){return void 0!==t.active?t.active:m.route.get()===t.href},e}(s.Z)},2232:(t,e,n)=>{"use strict";n.d(e,{Z:()=>o});var r=n(2122),s=n(1788),i=n(6366),a=n(1035),o=function(t){function e(){return t.apply(this,arguments)||this}(0,s.Z)(e,t);var n=e.prototype;return n.view=function(){var t=(0,r.Z)({},this.attrs);return t.className="LoadingIndicator "+(t.className||""),delete t.size,m("div",t,m.trust(" "))},n.oncreate=function(e){t.prototype.oncreate.call(this,e);var n={zIndex:"auto",color:this.$().css("color")};switch(this.attrs.size){case"large":(0,r.Z)(n,{lines:10,length:8,width:4,radius:8});break;case"tiny":(0,r.Z)(n,{lines:8,length:2,width:2,radius:3});break;default:(0,r.Z)(n,{lines:8,length:4,width:3,radius:5})}new a.$(n).spin(this.element)},e}(i.Z)},8292:(t,e,n)=>{"use strict";n.d(e,{Z:()=>c});var r=n(3349),s=n(1788),i=n(6156),a=n(6366),o=n(6150),u=n(5462),c=function(t){function e(){for(var e,n=arguments.length,s=new Array(n),a=0;a{"use strict";n.d(e,{Z:()=>i});var r=n(2122),s=n(1788),i=function(t){function e(){return t.apply(this,arguments)||this}(0,s.Z)(e,t);var n=e.prototype;return n.view=function(){var t=this.attrs.state.modal;return m("div",{className:"ModalManager modal fade"},t?t.componentClass.component((0,r.Z)({},t.attrs,{animateShow:this.animateShow.bind(this),animateHide:this.animateHide.bind(this),state:this.attrs.state})):"")},n.oncreate=function(e){t.prototype.oncreate.call(this,e),this.$().on("hidden.bs.modal",this.attrs.state.close.bind(this.attrs.state))},n.animateShow=function(t){var e=!!this.attrs.state.modal.componentClass.isDismissible;this.$().hasClass("in")?t():this.$().one("shown.bs.modal",t).modal({backdrop:e||"static",keyboard:e}).modal("show")},n.animateHide=function(){this.$().modal("hide")},e}(n(6366).Z)},7330:(t,e,n)=>{"use strict";n.d(e,{Z:()=>o});var r=n(1788),s=n(6366),i=n(5462),a=n(7971),o=function(t){function e(){return t.apply(this,arguments)||this}(0,r.Z)(e,t);var n=e.prototype;return n.view=function(){var t=app,e=t.history,n=t.pane;return m("div",{className:"Navigation ButtonGroup "+(this.attrs.className||""),onmouseenter:n&&n.show.bind(n),onmouseleave:n&&n.onmouseleave.bind(n)},e.canGoBack()?[this.getBackButton(),this.getPaneButton()]:this.getDrawerButton())},n.getBackButton=function(){var t=app.history,e=t.getPrevious()||{};return a.Z.component({className:"Button Navigation-back Button--icon",href:t.backUrl(),icon:"fas fa-chevron-left",title:e.title,onclick:function(e){e.shiftKey||e.ctrlKey||e.metaKey||2===e.which||(e.preventDefault(),t.back())}})},n.getPaneButton=function(){var t=app.pane;return t&&t.active?i.Z.component({className:"Button Button--icon Navigation-pin"+(t.pinned?" active":""),onclick:t.togglePinned.bind(t),icon:"fas fa-thumbtack"}):""},n.getDrawerButton=function(){if(!this.attrs.drawer)return"";var t=app.drawer,e=app.session.user;return i.Z.component({className:"Button Button--icon Navigation-drawer"+(e&&e.newNotificationCount()?" new":""),onclick:function(e){e.stopPropagation(),t.show()},icon:"fas fa-bars"})},e}(s.Z)},3340:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(1788),s=n(6366),i=n(8696),a=function(t){function e(){return t.apply(this,arguments)||this}(0,r.Z)(e,t);var n=e.prototype;return n.oninit=function(e){t.prototype.oninit.call(this,e),app.previous=app.current,app.current=new i.Z(this.constructor,{routeName:this.attrs.routeName}),app.drawer.hide(),app.modal.close(),this.bodyClass="",this.scrollTopOnCreate=!0,this.useBrowserScrollRestoration=!0},n.oncreate=function(e){t.prototype.oncreate.call(this,e),this.bodyClass&&$("#app").addClass(this.bodyClass),this.scrollTopOnCreate&&$(window).scrollTop(0),"scrollRestoration"in history&&(history.scrollRestoration=this.useBrowserScrollRestoration?"auto":"manual")},n.onremove=function(){this.bodyClass&&$("#app").removeClass(this.bodyClass)},e}(s.Z)},4389:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(1788),s=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.prototype.view=function(){return m("div",{className:"Placeholder"},m("p",null,this.attrs.text))},e}(n(6366).Z)},2058:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(1788),s=function(t){function e(){return t.apply(this,arguments)||this}(0,r.Z)(e,t);var n=e.prototype;return n.className=function(){return"RequestErrorModal Modal--large"},n.title=function(){return this.attrs.error.xhr?this.attrs.error.xhr.status+" "+this.attrs.error.xhr.statusText:""},n.content=function(){var t,e=this.attrs,n=e.error,r=e.formattedError;if(r)t=r.join("\n\n");else try{var s=n.response||JSON.parse(n.responseText);t=JSON.stringify(s,null,2)}catch(e){t=n.responseText}return m("div",{className:"Modal-body"},m("pre",null,this.attrs.error.options.method," ",this.attrs.error.options.url,m("br",null),m("br",null),t))},e}(n(8292).Z)},8112:(t,e,n)=>{"use strict";n.d(e,{Z:()=>o});var r=n(1788),s=n(6366),i=n(5052),a=n(9194),o=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.prototype.view=function(){var t=this.attrs,e=t.options,n=t.onchange,r=t.value,s=t.disabled;return m("span",{className:"Select"},m("select",{className:"Select-input FormControl",onchange:n?(0,a.Z)("value",n.bind(this)):void 0,value:r,disabled:s},Object.keys(e).map((function(t){return m("option",{value:t},e[t])}))),(0,i.Z)("fas fa-sort",{className:"Select-caret"}))},e}(s.Z)},6317:(t,e,n)=>{"use strict";n.d(e,{Z:()=>o});var r=n(1788),s=n(8777),i=n(5052);function a(t){var e=t.tag;return("string"!=typeof e||"a"===e||"button"===e)&&("initAttrs"in e&&e.initAttrs(t.attrs),"isActive"in e?e.isActive(t.attrs):t.attrs.active)}var o=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.initAttrs=function(e){e.caretIcon=void 0!==e.caretIcon?e.caretIcon:"fas fa-sort",t.initAttrs.call(this,e),e.className+=" Dropdown--select"},e.prototype.getButtonContent=function(t){var e=t.find(a),n=e&&e.children||this.attrs.defaultLabel;return n instanceof Array&&(n=n[0]),[m("span",{className:"Button-label"},n),(0,i.Z)(this.attrs.caretIcon,{className:"Button-caret"})]},e}(s.Z)},2939:(t,e,n)=>{"use strict";n.d(e,{Z:()=>i});var r=n(1788),s=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.prototype.view=function(){return m("li",{className:"Dropdown-separator"})},e}(n(6366).Z);s.isListItem=!0;const i=s},1342:(t,e,n)=>{"use strict";n.d(e,{Z:()=>u});var r=n(2122),s=n(1788),i=n(8777),a=n(5462),o=n(5052),u=function(t){function e(){return t.apply(this,arguments)||this}(0,s.Z)(e,t),e.initAttrs=function(e){t.initAttrs.call(this,e),e.className+=" Dropdown--split",e.menuClassName+=" Dropdown-menu--right"};var n=e.prototype;return n.getButton=function(t){var e=this.getFirstChild(t),n=(0,r.Z)({},e.attrs);return n.className=(n.className||"")+" SplitDropdown-button Button "+this.attrs.buttonClassName,[a.Z.component(n,e.children),m("button",{className:"Dropdown-toggle Button Button--icon "+this.attrs.buttonClassName,"aria-haspopup":"menu","aria-label":this.attrs.accessibleToggleLabel,"data-toggle":"dropdown"},(0,o.Z)(this.attrs.icon,{className:"Button-icon"}),(0,o.Z)("fas fa-caret-down",{className:"Button-caret"}))]},n.getFirstChild=function(t){for(var e=t;e instanceof Array;)e=e[0];return e},e}(i.Z)},4435:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(1788),s=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.initAttrs=function(e){t.initAttrs.call(this,e),e.className=(e.className||"")+" Checkbox--switch"},e.prototype.getDisplay=function(){return this.attrs.loading?t.prototype.getDisplay.call(this):""},e}(n(9699).Z)},4371:(t,e,n)=>{"use strict";n.r(e),n.d(e,{extend:()=>s,override:()=>i});var r=n(2122);function s(t,e,n){var s=t[e];t[e]=function(){for(var t=arguments.length,e=new Array(t),r=0;r{"use strict";n.d(e,{Z:()=>s});var r=n(2122);function s(t,e){void 0===e&&(e={}),e.className="Avatar "+(e.className||"");var n="",s="undefined"===e.title||e.title;if(s||delete e.title,t){var i=t.displayName()||"?",a=t.avatarUrl();if(s&&(e.title=e.title||i),a)return m("img",(0,r.Z)({},e,{src:a,alt:""}));n=i.charAt(0).toUpperCase(),e.style={background:t.color()}}return m("span",e,n)}},7693:(t,e,n)=>{"use strict";n.d(e,{Z:()=>i});var r=n(7484),s=n.n(r);function i(t){var e=s()(t),n=e.format(),r=e.format("LLLL");return m("time",{pubdate:!0,datetime:n},r)}},4910:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(6646);function s(t,e,n){if(!e&&!n)return t;var s=e instanceof RegExp?e:new RegExp(e,"gi"),i=t,a=0;return n&&(e&&(a=Math.max(0,t.search(s)-n/2)),i=(0,r.truncate)(i,n,a)),i=$("
").text(i).html(),e&&(i=i.replace(s,"$&")),m.trust(i)}},7603:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(7484),s=n.n(r),i=n(9090);function a(t){var e=s()(t),n=e.format(),r=e.format("LLLL"),a=(0,i.Z)(t);return m("time",{pubdate:!0,datetime:n,title:r,"data-humantime":!0},a)}},5052:(t,e,n)=>{"use strict";function r(t,e){return void 0===e&&(e={}),e.className="icon "+t+" "+(e.className||""),m("i",e)}n.d(e,{Z:()=>r})},1698:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(2939),s=n(1749);function i(t){return t.tag===r.Z}function a(t){return t instanceof Array||(t=[t]),function(t){var e,n=[];return t.filter(Boolean).forEach((function(r,s){(!i(r)||e&&!i(e)&&s!==t.length-1)&&(e=r,n.push(r))})),n}(t).map((function(t){var e=t.tag&&t.tag.isListItem,n=t.tag&&t.tag.isActive&&t.tag.isActive(t.attrs),r=t.attrs&&t.attrs.itemClassName||t.itemClassName;return e&&(t.attrs=t.attrs||{},t.attrs.key=t.attrs.key||t.itemName,t.key=t.attrs.key),e?t:m("li",{className:(0,s.Z)([r,t.itemName&&"item-"+t.itemName,n&&"active"]),key:t.attrs&&t.attrs.key||t.itemName},t)}))}},5589:(t,e,n)=>{"use strict";function r(t){if(2===t.length)return app.translator.trans("core.lib.series.two_text",{first:t[0],second:t[1]});if(t.length>=3){var e=t.slice(1,t.length-1).reduce((function(t,e){return t.concat([e,app.translator.trans("core.lib.series.glue_text")])}),[]).slice(0,-1);return app.translator.trans("core.lib.series.three_text",{first:t[0],second:e,third:t[t.length-1]})}return t}n.d(e,{Z:()=>r})},947:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(5052);function s(t){if(t.lastSeenAt()&&t.isOnline())return m("span",{className:"UserOnline"},(0,r.Z)("fas fa-circle"))}},3131:(t,e,n)=>{"use strict";function r(t){var e=t&&t.displayName()||app.translator.trans("core.lib.username.deleted_text");return m("span",{className:"username"},e)}n.d(e,{Z:()=>r})},2633:(t,e,n)=>{"use strict";n.d(e,{U:()=>r});var r={};n.r(r),n.d(r,{Model:()=>l,PostTypes:()=>d,Routes:()=>p}),n(4352),n(5436),n(270),n(5377),n(9737),n(8852),n(6278),n(8294),n(5314);var s=n(4110),i=n.n(s),a=n(6176),o=n.n(a),u=n(8119),c=n(6156),l=function(){function t(t,e){void 0===e&&(e=null),(0,c.Z)(this,"type",void 0),(0,c.Z)(this,"attributes",[]),(0,c.Z)(this,"hasOnes",[]),(0,c.Z)(this,"hasManys",[]),this.type=t,this.model=e}var e=t.prototype;return e.attribute=function(t){return this.attributes.push(t),this},e.hasOne=function(t){return this.hasOnes.push(t),this},e.hasMany=function(t){return this.hasManys.push(t),this},e.extend=function(t,e){this.model&&(t.store.models[this.type]=this.model);var n=t.store.models[this.type];this.attributes.forEach((function(t){return n.prototype[t]=n.attribute(t)})),this.hasOnes.forEach((function(t){return n.prototype[t]=n.hasOne(t)})),this.hasManys.forEach((function(t){return n.prototype[t]=n.hasMany(t)}))},t}(),h=n(2122),d=function(){function t(){(0,c.Z)(this,"postComponents",{})}var e=t.prototype;return e.add=function(t,e){return this.postComponents[t]=e,this},e.extend=function(t,e){(0,h.Z)(t.postComponents,this.postComponents)},t}(),p=function(){function t(){(0,c.Z)(this,"routes",{})}var e=t.prototype;return e.add=function(t,e,n){return this.routes[t]={path:e,component:n},this},e.extend=function(t,e){(0,h.Z)(t.routes,this.routes)},t}();dayjs.extend(i()),dayjs.extend(o()),(0,u.Z)(window)},2242:(t,e,n)=>{"use strict";n.d(e,{Z:()=>c});var r=n(2122),s=n(1788),i=n(8866),a=n(876),o=n(7037),u=n(7262),c=function(t){function e(){return t.apply(this,arguments)||this}return(0,s.Z)(e,t),e}(i.Z);(0,r.Z)(c.prototype,{title:i.Z.attribute("title"),slug:i.Z.attribute("slug"),createdAt:i.Z.attribute("createdAt",i.Z.transformDate),user:i.Z.hasOne("user"),firstPost:i.Z.hasOne("firstPost"),lastPostedAt:i.Z.attribute("lastPostedAt",i.Z.transformDate),lastPostedUser:i.Z.hasOne("lastPostedUser"),lastPost:i.Z.hasOne("lastPost"),lastPostNumber:i.Z.attribute("lastPostNumber"),commentCount:i.Z.attribute("commentCount"),replyCount:(0,a.Z)("commentCount",(function(t){return Math.max(0,t-1)})),posts:i.Z.hasMany("posts"),mostRelevantPost:i.Z.hasOne("mostRelevantPost"),lastReadAt:i.Z.attribute("lastReadAt",i.Z.transformDate),lastReadPostNumber:i.Z.attribute("lastReadPostNumber"),isUnread:(0,a.Z)("unreadCount",(function(t){return!!t})),isRead:(0,a.Z)("unreadCount",(function(t){return app.session.user&&!t})),hiddenAt:i.Z.attribute("hiddenAt",i.Z.transformDate),hiddenUser:i.Z.hasOne("hiddenUser"),isHidden:(0,a.Z)("hiddenAt",(function(t){return!!t})),canReply:i.Z.attribute("canReply"),canRename:i.Z.attribute("canRename"),canHide:i.Z.attribute("canHide"),canDelete:i.Z.attribute("canDelete"),removePost:function(t){var e=this.data.relationships,n=e&&e.posts;n&&n.data.some((function(e,r){if(t===e.id)return n.data.splice(r,1),!0}))},unreadCount:function(){var t=app.session.user;if(t&&t.markedAllAsReadAt(){"use strict";n.d(e,{Z:()=>s});var r=n(1788),s=function(t){function e(){return t.apply(this,arguments)||this}return(0,r.Z)(e,t),e.prototype.apiEndpoint=function(){return"/"},e}(n(8866).Z)},442:(t,e,n)=>{"use strict";n.d(e,{Z:()=>o});var r=n(2122),s=n(1788),i=n(8866),a=function(t){function e(){return t.apply(this,arguments)||this}return(0,s.Z)(e,t),e}(i.Z);(0,r.Z)(a.prototype,{nameSingular:i.Z.attribute("nameSingular"),namePlural:i.Z.attribute("namePlural"),color:i.Z.attribute("color"),icon:i.Z.attribute("icon"),isHidden:i.Z.attribute("isHidden")}),a.ADMINISTRATOR_ID="1",a.GUEST_ID="2",a.MEMBER_ID="3";const o=a},2919:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(2122),s=n(1788),i=n(8866),a=function(t){function e(){return t.apply(this,arguments)||this}return(0,s.Z)(e,t),e}(i.Z);(0,r.Z)(a.prototype,{contentType:i.Z.attribute("contentType"),content:i.Z.attribute("content"),createdAt:i.Z.attribute("createdAt",i.Z.transformDate),isRead:i.Z.attribute("isRead"),user:i.Z.hasOne("user"),fromUser:i.Z.hasOne("fromUser"),subject:i.Z.hasOne("subject")})},6437:(t,e,n)=>{"use strict";n.d(e,{Z:()=>u});var r=n(2122),s=n(1788),i=n(8866),a=n(876),o=n(6646),u=function(t){function e(){return t.apply(this,arguments)||this}return(0,s.Z)(e,t),e}(i.Z);(0,r.Z)(u.prototype,{number:i.Z.attribute("number"),discussion:i.Z.hasOne("discussion"),createdAt:i.Z.attribute("createdAt",i.Z.transformDate),user:i.Z.hasOne("user"),contentType:i.Z.attribute("contentType"),content:i.Z.attribute("content"),contentHtml:i.Z.attribute("contentHtml"),contentPlain:(0,a.Z)("contentHtml",o.getPlainContent),editedAt:i.Z.attribute("editedAt",i.Z.transformDate),editedUser:i.Z.hasOne("editedUser"),isEdited:(0,a.Z)("editedAt",(function(t){return!!t})),hiddenAt:i.Z.attribute("hiddenAt",i.Z.transformDate),hiddenUser:i.Z.hasOne("hiddenUser"),isHidden:(0,a.Z)("hiddenAt",(function(t){return!!t})),canEdit:i.Z.attribute("canEdit"),canHide:i.Z.attribute("canHide"),canDelete:i.Z.attribute("canDelete")})},4693:(t,e,n)=>{"use strict";n.d(e,{Z:()=>l});var r=n(2122),s=n(1788),i=n(8866),a=n(3849),o=n(7037),u=n(876),c=n(512),l=function(t){function e(){return t.apply(this,arguments)||this}return(0,s.Z)(e,t),e}(i.Z);(0,r.Z)(l.prototype,{username:i.Z.attribute("username"),slug:i.Z.attribute("slug"),displayName:i.Z.attribute("displayName"),email:i.Z.attribute("email"),isEmailConfirmed:i.Z.attribute("isEmailConfirmed"),password:i.Z.attribute("password"),avatarUrl:i.Z.attribute("avatarUrl"),preferences:i.Z.attribute("preferences"),groups:i.Z.hasMany("groups"),joinTime:i.Z.attribute("joinTime",i.Z.transformDate),lastSeenAt:i.Z.attribute("lastSeenAt",i.Z.transformDate),markedAllAsReadAt:i.Z.attribute("markedAllAsReadAt",i.Z.transformDate),unreadNotificationCount:i.Z.attribute("unreadNotificationCount"),newNotificationCount:i.Z.attribute("newNotificationCount"),discussionCount:i.Z.attribute("discussionCount"),commentCount:i.Z.attribute("commentCount"),canEdit:i.Z.attribute("canEdit"),canEditCredentials:i.Z.attribute("canEditCredentials"),canEditGroups:i.Z.attribute("canEditGroups"),canDelete:i.Z.attribute("canDelete"),avatarColor:null,color:(0,u.Z)("username","avatarUrl","avatarColor",(function(t,e,n){return n?"rgb("+n.join(", ")+")":e?(this.calculateAvatarColor(),""):"#"+(0,a.Z)(t)})),isOnline:function(){return dayjs().subtract(5,"minutes").isBefore(this.lastSeenAt())},badges:function(){var t=new o.Z,e=this.groups();return e&&e.forEach((function(e){t.add("group"+e.id(),c.Z.component({group:e}))})),t},calculateAvatarColor:function(){var t=new Image,e=this;t.onload=function(){var t=new ColorThief;e.avatarColor=t.getColor(this),e.freshness=new Date,m.redraw()},t.crossOrigin="anonymous",t.src=this.avatarUrl()},savePreferences:function(t){var e=this.preferences();return(0,r.Z)(e,t),this.save({preferences:e})}})},4965:(t,e,n)=>{"use strict";n.d(e,{Z:()=>u});var r=n(7757),s=n.n(r),i=n(2137),a=n(2122),o=n(6156),u=function(){function t(t,e){(0,o.Z)(this,"component",void 0),(0,o.Z)(this,"routeName",void 0),this.component=t,this.routeName=e}var e=t.prototype;return e.makeKey=function(){return this.routeName+JSON.stringify(m.route.param())},e.makeAttrs=function(t){return(0,a.Z)({},t.attrs,{routeName:this.routeName})},e.onmatch=function(){var t=(0,i.Z)(s().mark((function t(e,n,r){var i;return s().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if("function"!=typeof this.component.component){t.next=4;break}return t.abrupt("return",this.component);case 4:return t.next=6,this.component();case 6:return i=t.sent,t.abrupt("return",i.default);case 8:case"end":return t.stop()}}),t,this)})));return function(e,n,r){return t.apply(this,arguments)}}(),e.render=function(t){return[(0,a.Z)({},t,{attrs:this.makeAttrs(t),key:this.makeKey()})]},t}()},8696:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(9668),s=function(){function t(t,e){void 0===e&&(e={}),this.type=t,this.data=e}var e=t.prototype;return e.matches=function(t,e){var n=this;return void 0===e&&(e={}),!!(0,r.Z)(this.type,t)&&Object.keys(e).every((function(t){return n.data[t]===e[t]}))},e.get=function(t){return this.data[t]},e.set=function(t,e){this.data[t]=e},t}()},4967:(t,e,n)=>{"use strict";n.d(e,{Z:()=>a});var r=n(6156),s=n(6496),i=n.n(s),a=function(){function t(t,e){(0,r.Z)(this,"el",void 0),this.el=document.createElement("textarea"),this.build(t,e)}var e=t.prototype;return e.build=function(t,e){var n=this;this.el.className=e.classNames.join(" "),this.el.disabled=e.disabled,this.el.placeholder=e.placeholder,this.el.value=e.value;var r=function(t){e.inputListeners.forEach((function(t){t()})),t.redraw=!1};this.el.oninput=function(t){e.oninput(n.el.value),r(t)},this.el.onclick=r,this.el.onkeyup=r,this.el.addEventListener("keydown",(function(t){(t.metaKey||t.ctrlKey)&&"Enter"===t.key&&e.onsubmit()})),t.append(this.el)},e.setValue=function(t){$(this.el).val(t).trigger("input"),this.el.dispatchEvent(new CustomEvent("input",{bubbles:!0,cancelable:!0}))},e.moveCursorTo=function(t){this.setSelectionRange(t,t)},e.getSelectionRange=function(){return[this.el.selectionStart,this.el.selectionEnd]},e.getLastNChars=function(t){return this.el.value.slice(Math.max(0,this.el.selectionStart-t),this.el.selectionStart)},e.insertAtCursor=function(t){this.insertAt(this.el.selectionStart,t)},e.insertAt=function(t,e){this.insertBetween(t,t,e)},e.insertBetween=function(t,e,n){var r=this.el.value,s=r.slice(0,t),i=r.slice(e);this.setValue(""+s+n+i),this.moveCursorTo(t+n.length)},e.replaceBeforeCursor=function(t,e){this.insertBetween(t,this.el.selectionStart,e)},e.setSelectionRange=function(t,e){this.el.setSelectionRange(t,e),this.focus()},e.getCaretCoordinates=function(t){var e=i()(this.el,t);return{top:e.top-this.el.scrollTop,left:e.left}},e.disabled=function(t){this.el.disabled=t},e.focus=function(){this.el.focus()},e.destroy=function(){this.el.remove()},t}()},7963:(t,e,n)=>{"use strict";n.d(e,{Z:()=>r});var r=function(){function t(){var t=this;$("#content").click((function(e){t.isOpen()&&(e.preventDefault(),t.hide())}))}var e=t.prototype;return e.isOpen=function(){return $("#app").hasClass("drawerOpen")},e.hide=function(){var t=$("#app");if(t.hasClass("drawerOpen")){var e=$("#drawer");e.css("visibility","visible").one("transitionend",(function(){return e.css("visibility","")})),t.removeClass("drawerOpen"),this.$backdrop&&this.$backdrop.remove()}},e.show=function(){var t=this;$("#app").addClass("drawerOpen"),this.$backdrop=$("
").addClass("drawer-backdrop fade").appendTo("body").click((function(){return t.hide()})),setTimeout((function(){return t.$backdrop.addClass("in")}))},t}()},7037:(t,e,n)=>{"use strict";n.d(e,{Z:()=>i});var r=n(6156),s=function(t,e){(0,r.Z)(this,"content",void 0),(0,r.Z)(this,"priority",void 0),(0,r.Z)(this,"key",void 0),this.content=t,this.priority=e},i=function(){function t(){(0,r.Z)(this,"items",{})}var e=t.prototype;return e.isEmpty=function(){for(var t in this.items)if(this.items.hasOwnProperty(t))return!1;return!0},e.has=function(t){return!!this.items[t]},e.get=function(t){return this.items[t].content},e.add=function(t,e,n){return void 0===n&&(n=0),this.items[t]=new s(e,n),this},e.replace=function(t,e,n){return void 0===e&&(e=null),void 0===n&&(n=null),this.items[t]&&(null!==e&&(this.items[t].content=e),null!==n&&(this.items[t].priority=n)),this},e.remove=function(t){return delete this.items[t],this},e.merge=function(t){for(var e in t.items)t.items.hasOwnProperty(e)&&t.items[e]instanceof s&&(this.items[e]=t.items[e]);return this},e.toArray=function(){var t=[];for(var e in this.items)this.items.hasOwnProperty(e)&&this.items[e]instanceof s&&(this.items[e].content=Object(this.items[e].content),this.items[e].content.itemName=e,t.push(this.items[e]),this.items[e].key=t.length);return t.sort((function(t,e){return t.priority===e.priority?t.key-e.key:t.priority>e.priority?-1:1})).map((function(t){return t.content}))},t}()},3214:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(6156),s=function(t,e,n,s){(0,r.Z)(this,"status",void 0),(0,r.Z)(this,"options",void 0),(0,r.Z)(this,"xhr",void 0),(0,r.Z)(this,"responseText",void 0),(0,r.Z)(this,"response",void 0),(0,r.Z)(this,"alert",void 0),this.status=t,this.responseText=e,this.options=n,this.xhr=s;try{this.response=JSON.parse(e)}catch(t){this.response=null}this.alert=null}},1252:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame||function(t){return window.setTimeout(t,1e3/60)},s=function(){function t(t){this.callback=t,this.ticking=!1}var e=t.prototype;return e.loop=function(){var t=this;this.ticking||(r((function(){t.update(),t.ticking=!1})),this.ticking=!0)},e.update=function(){this.callback(window.pageYOffset)},e.start=function(){this.active||window.addEventListener("scroll",this.active=this.loop.bind(this),{passive:!0})},e.stop=function(){window.removeEventListener("scroll",this.active),this.active=null},t}()},9015:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(5922);const s=n.n(r)()},8932:(t,e,n)=>{"use strict";n.d(e,{Z:()=>r});var r=function(){function t(){for(var t=arguments.length,e=new Array(t),n=0;n{"use strict";function r(t){return t>=1e6?Math.floor(t/1e6)+app.translator.trans("core.lib.number_suffix.mega_text"):t>=1e3?(t/1e3).toFixed(1)+app.translator.trans("core.lib.number_suffix.kilo_text"):t.toString()}n.d(e,{Z:()=>r})},3927:(t,e,n)=>{"use strict";function r(t,e){var n=$(window),r=$(t).offset().top-n.scrollTop();e(),n.scrollTop($(t).offset().top-r)}n.d(e,{Z:()=>r})},1749:(t,e,n)=>{"use strict";n.d(e,{Z:()=>r});const r=n(6010).Z},876:(t,e,n)=>{"use strict";function r(){for(var t=arguments.length,e=new Array(t),n=0;nr})},2231:(t,e,n)=>{"use strict";function r(t,e){var n=t[e];return delete t[e],n}n.d(e,{Z:()=>r})},8165:(t,e,n)=>{"use strict";function r(t){return t instanceof Array?t.map((function(t){return r(t)})).join(""):"object"==typeof t&&null!==t?t.children?r(t.children):t.text:t}n.d(e,{Z:()=>r})},1068:(t,e,n)=>{"use strict";function r(t){return t.toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")}n.d(e,{Z:()=>r})},9090:(t,e,n)=>{"use strict";n.d(e,{Z:()=>i});var r=n(7484),s=n.n(r);function i(t){var e=s()(t),n=s()();return e.isAfter(n)&&(e=n),e.diff(s()())<-2592e6?e.year()===s()().year()?e.format("D MMM"):e.format("ll"):e.fromNow()}n(4110)},2660:(t,e,n)=>{"use strict";n.d(e,{Z:()=>i});var r=n(9090);function s(){$("[data-humantime]").each((function(){var t=$(this),e=(0,r.Z)(t.attr("datetime"));t.html(e)}))}function i(){setInterval(s,1e4)}},2839:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(4965);function s(t,e){void 0===e&&(e="");var n={};for(var s in t){var i=t[s];if("resolver"in i)n[e+i.path]=i.resolver;else{if(!("component"in i))throw new Error("Either a resolver or a component must be provided for the route ["+s+"]");var a="resolverClass"in i?i.resolverClass:r.Z;n[e+i.path]=new a(i.component,s)}}return n}},8119:(t,e,n)=>{"use strict";function r(t,e){var n="select"===t.tag?t.attrs.multi?"multi":"select":t.attrs.type;return t.attrs.onchange="multi"===n?function(){e([].slice.call(this.selectedOptions,(function(t){return t.value})))}:"select"===n?function(t){e(this.selectedOptions[0].value)}:"checkbox"===n?function(t){e(this.checked)}:t.attrs.oninput=function(t){e(this.value)},"select"===t.tag?t.children.forEach((function(t){t.attrs.value!==e()&&t.children[0]!==e()||(t.attrs.selected=!0)})):"checkbox"===n?t.attrs.checked=e():"radio"===n?t.attrs.checked=e()===t.attrs.value:t.attrs.value=e(),t.attrs.bidi=null,t}n.d(e,{Z:()=>i}),r.view=function(t,e,n){return r(e,e.attrs.bidi)};const s=r;function i(t){var e=t.m,n=function(t){for(var n=arguments.length,r=new Array(n>1?n-1:0),i=1;i{"use strict";n.d(e,{Z:()=>r});const r=function(t,e){var n=new RegExp("(\\w+\\/)?("+e+"|common)\\/");return new Proxy(t,{get:function(t,e){return t[e]||t[e.replace(n,"$1")]}})}},7769:(t,e,n)=>{"use strict";n.d(e,{Z:()=>s});var r=n(2122);function s(t,e,n){void 0===e&&(e=null),void 0===n&&(n={});var s=(0,r.Z)({},n);s.state=s.state||{},s.state.key=Date.now(),m.route.set(t,e,s)}},3849:(t,e,n)=>{"use strict";function r(t){for(var e=0,n=0;nr})},9668:(t,e,n)=>{"use strict";function r(t,e){return t&&(t===e||t.prototype instanceof e)}n.d(e,{Z:()=>r})},9194:(t,e,n)=>{"use strict";n.d(e,{Z:()=>r});const r=function(t,e){return function(){e(this.getAttribute(t)||this[t])}}}}]); //# sourceMappingURL=common.js.map \ No newline at end of file diff --git a/js/dist/common/common.js.map b/js/dist/common/common.js.map index 67b7cbd98..3888d2d27 100644 --- a/js/dist/common/common.js.map +++ b/js/dist/common/common.js.map @@ -1 +1 @@ -{"version":3,"sources":["webpack://@flarum/core/./src/common/states/ModalManagerState.js","webpack://@flarum/core/./src/common/states/AlertManagerState.ts","webpack://@flarum/core/./src/common/Application.js","webpack://@flarum/core/./src/common/Component.ts","webpack://@flarum/core/./src/common/Model.js","webpack://@flarum/core/./src/common/Session.js","webpack://@flarum/core/./src/common/Store.js","webpack://@flarum/core/./src/common/Translator.js","webpack://@flarum/core/./src/common/utils/evented.js","webpack://@flarum/core/./src/common/Fragment.ts","webpack://@flarum/core/./src/common/compat.js","webpack://@flarum/core/./src/common/utils/mixin.js","webpack://@flarum/core/./src/common/components/Alert.tsx","webpack://@flarum/core/./src/common/components/AlertManager.js","webpack://@flarum/core/./src/common/components/Badge.js","webpack://@flarum/core/./src/common/components/Button.js","webpack://@flarum/core/./src/common/components/Checkbox.js","webpack://@flarum/core/./src/common/components/Dropdown.js","webpack://@flarum/core/./src/common/components/FieldSet.js","webpack://@flarum/core/./src/common/components/GroupBadge.js","webpack://@flarum/core/./src/common/components/Link.js","webpack://@flarum/core/./src/common/components/LinkButton.js","webpack://@flarum/core/./src/common/components/LoadingIndicator.js","webpack://@flarum/core/./src/common/components/Modal.js","webpack://@flarum/core/./src/common/components/ModalManager.js","webpack://@flarum/core/./src/common/components/Navigation.js","webpack://@flarum/core/./src/common/components/Page.js","webpack://@flarum/core/./src/common/components/Placeholder.js","webpack://@flarum/core/./src/common/components/RequestErrorModal.js","webpack://@flarum/core/./src/common/components/Select.js","webpack://@flarum/core/./src/common/components/SelectDropdown.js","webpack://@flarum/core/./src/common/components/Separator.js","webpack://@flarum/core/./src/common/components/SplitDropdown.js","webpack://@flarum/core/./src/common/components/Switch.js","webpack://@flarum/core/./src/common/extend.js","webpack://@flarum/core/./src/common/helpers/avatar.tsx","webpack://@flarum/core/./src/common/helpers/fullTime.tsx","webpack://@flarum/core/./src/common/helpers/highlight.tsx","webpack://@flarum/core/./src/common/helpers/humanTime.tsx","webpack://@flarum/core/./src/common/helpers/icon.tsx","webpack://@flarum/core/./src/common/helpers/listItems.tsx","webpack://@flarum/core/./src/common/helpers/punctuateSeries.js","webpack://@flarum/core/./src/common/helpers/userOnline.tsx","webpack://@flarum/core/./src/common/helpers/username.tsx","webpack://@flarum/core/./src/common/extend/Model.js","webpack://@flarum/core/./src/common/extend/PostTypes.js","webpack://@flarum/core/./src/common/extend/Routes.js","webpack://@flarum/core/./src/common/index.js","webpack://@flarum/core/./src/common/models/Discussion.js","webpack://@flarum/core/./src/common/models/Forum.js","webpack://@flarum/core/./src/common/models/Group.js","webpack://@flarum/core/./src/common/models/Notification.js","webpack://@flarum/core/./src/common/models/Post.js","webpack://@flarum/core/./src/common/models/User.js","webpack://@flarum/core/./src/common/resolvers/DefaultResolver.ts","webpack://@flarum/core/./src/common/states/PageState.js","webpack://@flarum/core/./src/common/utils/BasicEditorDriver.ts","webpack://@flarum/core/./src/common/utils/Drawer.js","webpack://@flarum/core/./src/common/utils/ItemList.ts","webpack://@flarum/core/./src/common/utils/RequestError.ts","webpack://@flarum/core/./src/common/utils/ScrollListener.js","webpack://@flarum/core/./src/common/utils/Stream.js","webpack://@flarum/core/./src/common/utils/SubtreeRetainer.js","webpack://@flarum/core/./src/common/utils/abbreviateNumber.ts","webpack://@flarum/core/./src/common/utils/anchorScroll.js","webpack://@flarum/core/./src/common/utils/classList.ts","webpack://@flarum/core/./src/common/utils/computed.js","webpack://@flarum/core/./src/common/utils/extract.ts","webpack://@flarum/core/./src/common/utils/extractText.js","webpack://@flarum/core/./src/common/utils/formatNumber.ts","webpack://@flarum/core/./src/common/utils/humanTime.ts","webpack://@flarum/core/./src/common/utils/liveHumanTimes.ts","webpack://@flarum/core/./src/common/utils/mapRoutes.js","webpack://@flarum/core/./src/common/utils/bidi.js","webpack://@flarum/core/./src/common/utils/patchMithril.js","webpack://@flarum/core/./src/common/utils/proxifyCompat.ts","webpack://@flarum/core/./src/common/utils/setRouteWithForcedRefresh.ts","webpack://@flarum/core/./src/common/utils/stringToColor.ts","webpack://@flarum/core/./src/common/utils/subclassOf.js","webpack://@flarum/core/./src/common/utils/withAttr.ts"],"names":["ModalManagerState","this","modal","show","componentClass","attrs","prototype","Modal","componentResolver","console","error","Error","init","clearTimeout","closeTimeout","m","redraw","sync","close","setTimeout","AlertManagerState","getActiveAlerts","activeAlerts","arg1","arg2","arg3","children","Alert","arguments","length","alertId","dismiss","key","clear","Application","ItemList","Translator","Store","forums","Forum","users","User","discussions","Discussion","posts","Post","groups","Group","notifications","Notification","PageState","load","payload","data","translator","locale","boot","initializers","toArray","forEach","initializer","store","pushPayload","resources","forum","getById","session","Session","userId","csrfToken","mount","initialRoute","window","location","href","bootExtensions","extensions","Object","keys","name","extension","flattenDeep","extend","exports","basePath","document","getElementById","view","ModalManager","state","AlertManager","alerts","drawer","Drawer","route","mapRoutes","routes","scrollListener","ScrollListener","top","$app","$","offset","toggleClass","start","update","addClass","liveHumanTimes","preloadedApiDocument","apiDocument","results","screen","getComputedStyle","documentElement","getPropertyValue","setTitle","title","updateTitle","setTitleCount","count","titleCount","pageTitleWithSeparator","get","attribute","request","originalOptions","options","background","result","xhr","setRequestHeader","method","deserialize","responseText","errorHandler","original","extract","status","RequestError","getResponseHeader","app","JSON","parse","e","requestErrorAlert","then","response","content","errors","map","detail","reduce","a","b","concat","slice","trans","isDebug","formattedError","Array","isArray","decodeURI","alert","type","controls","Button","className","onclick","showDebug","bind","url","group","groupEnd","Promise","reject","RequestErrorModal","params","path","replace","hasOwnProperty","queryString","buildQueryString","prefix","Component","oninit","vnode","setAttrs","oncreate","element","dom","onbeforeupdate","selector","$element","find","component","componentAttrs","constructor","initAttrs","Model","freshness","Date","exists","id","attributes","pushData","innerKey","getIdentifier","pushAttributes","save","relationships","model","oldData","copyData","meta","apiEndpoint","body","remove","resolve","stringify","transform","value","hasOne","relationship","hasMany","transformDate","user","login","logout","models","included","pushObject","createRecord","query","join","getBy","all","filter","records","translations","addTranslations","parameters","translation","apply","transChoice","number","parseInt","pluralize","input","username","split","RegExp","hydrated","open","part","match","push","rawChildren","splice","fragment","shift","tag","unshift","sPluralRegex","cPluralRegex","iPluralRegex","standardRules","explicitRules","test","matches","rule","ns","n","leftNumber","convertNumber","rightNumber","pluralPosition","undefined","Number","NEGATIVE_INFINITY","POSITIVE_INFINITY","handlers","getHandlers","event","trigger","args","handler","on","one","wrapper","off","index","indexOf","Fragment","render","vdom","originalOnCreate","BasicEditorDriver","evented","Parent","Mixed","mixins","object","humanTime","computed","anchorScroll","abbreviateNumber","string","SubtreeRetainer","stringToColor","Stream","subclassOf","setRouteWithForcedRefresh","patchMithril","proxifyCompat","classList","extractText","formatNumber","withAttr","Page","Switch","Badge","LoadingIndicator","Placeholder","Separator","Dropdown","SplitDropdown","FieldSet","Select","Navigation","Link","LinkButton","Checkbox","SelectDropdown","GroupBadge","fullTime","avatar","icon","humanTimeHelper","punctuateSeries","highlight","userOnline","listItems","DefaultResolver","dismissible","ondismiss","dismissControl","entries","iconName","trust","label","tooltip","loading","disabled","getButtonContent","size","checked","onchange","getDisplay","buttonClassName","menuClassName","caretIcon","accessibleToggleLabel","showing","items","getButton","getMenu","onshow","$menu","isRight","hasClass","removeClass","height","scrollTop","left","width","scrollLeft","onhide","aria-haspopup","aria-label","data-toggle","style","backgroundColor","color","nameSingular","text","external","now","active","isActive","force","String","zIndex","css","lines","radius","Spinner","spin","animateShow","onready","onbeforeremove","animateHide","alertAttrs","isDismissible","hide","onsubmit","first","focus","select","loaded","onerror","source","pointer","readyCallback","backdrop","keyboard","history","pane","onmouseenter","onmouseleave","canGoBack","getBackButton","getPaneButton","getDrawerButton","previous","getPrevious","backUrl","shiftKey","ctrlKey","metaKey","which","preventDefault","back","pinned","togglePinned","newNotificationCount","stopPropagation","current","routeName","bodyClass","scrollTopOnCreate","useBrowserScrollRestoration","scrollRestoration","onremove","statusText","json","activeChild","defaultLabel","isListItem","firstChild","getFirstChild","buttonAttrs","callback","override","newMethod","hasTitle","displayName","avatarUrl","src","alt","charAt","toUpperCase","time","d","dayjs","datetime","format","full","pubdate","phrase","regexp","highlighted","Math","max","search","truncate","html","ago","humanTimeUtil","data-humantime","fontClass","isSeparator","item","prevItem","newItems","Boolean","i","withoutUnnecessarySeparators","itemClassName","itemName","second","list","third","lastSeenAt","isOnline","hasOnes","hasManys","PostTypes","add","postComponents","Routes","relativeTime","localizedFormat","slug","createdAt","firstPost","lastPostedAt","lastPostedUser","lastPost","lastPostNumber","commentCount","replyCount","mostRelevantPost","lastReadAt","lastReadPostNumber","isUnread","unreadCount","isRead","hiddenAt","hiddenUser","isHidden","canReply","canRename","canHide","canDelete","removePost","some","markedAllAsReadAt","min","badges","postIds","link","namePlural","ADMINISTRATOR_ID","GUEST_ID","MEMBER_ID","contentType","fromUser","subject","discussion","contentHtml","contentPlain","getPlainContent","editedAt","editedUser","isEdited","canEdit","email","isEmailConfirmed","password","preferences","joinTime","unreadNotificationCount","discussionCount","canEditCredentials","canEditGroups","avatarColor","calculateAvatarColor","subtract","isBefore","image","Image","onload","colorThief","ColorThief","getColor","crossOrigin","savePreferences","newPreferences","makeKey","param","makeAttrs","onmatch","requestedPath","every","set","el","createElement","build","classNames","placeholder","callInputListeners","inputListeners","listener","oninput","onkeyup","addEventListener","append","setValue","val","dispatchEvent","CustomEvent","bubbles","cancelable","moveCursorTo","position","setSelectionRange","getSelectionRange","selectionStart","selectionEnd","getLastNChars","insertAtCursor","insertAt","pos","insertBetween","end","before","after","replaceBeforeCursor","getCaretCoordinates","relCoords","destroy","click","isOpen","$drawer","$backdrop","appendTo","Item","priority","isEmpty","has","merge","sort","later","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","msRequestAnimationFrame","oRequestAnimationFrame","ticking","loop","pageYOffset","passive","stop","removeEventListener","callbacks","needsRebuild","check","invalidate","floor","toFixed","toString","$window","relativeScroll","clsx","dependentKeys","computedValue","compute","dependentValues","recompute","property","isAfter","diff","year","updateHumanTimes","each","$this","attr","setInterval","resolver","resolverClass","bidi","node","prop","multi","call","selectedOptions","x","option","selected","ctrl","global","defaultMithril","modifiedMithril","comp","compat","namespace","regex","Proxy","obj","newOptions","num","charCodeAt","rgb","h","s","v","r","g","f","p","q","t","hsvToRgb","A","B","cb","getAttribute"],"mappings":"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","file":"/common/common.js","sourcesContent":["import Modal from '../components/Modal';\n\nexport default class ModalManagerState {\n constructor() {\n this.modal = null;\n }\n\n /**\n * Show a modal dialog.\n *\n * @public\n */\n async show(componentClass, attrs) {\n // Breaking Change Compliance Warning, Remove in Beta 15.\n if (!(componentClass.prototype instanceof Modal)) {\n if (typeof componentClass === 'function') {\n const componentResolver = await componentClass();\n componentClass = componentResolver.default;\n } else {\n // This is duplicated so that if the error is caught, an error message still shows up in the debug console.\n console.error('The ModalManager can only show Modals');\n throw new Error('The ModalManager can only show Modals');\n }\n }\n if (componentClass.init) {\n // This is duplicated so that if the error is caught, an error message still shows up in the debug console.\n console.error(\n 'The componentClass parameter must be a modal class, not a modal instance. Whichever extension triggered this modal should be updated to comply with beta 14.'\n );\n throw new Error(\n 'The componentClass parameter must be a modal class, not a modal instance. Whichever extension triggered this modal should be updated to comply with beta 14.'\n );\n }\n // End Change Compliance Warning, Remove in Beta 15\n\n clearTimeout(this.closeTimeout);\n\n this.modal = { componentClass, attrs };\n\n m.redraw.sync();\n }\n\n /**\n * Close the modal dialog.\n *\n * @public\n */\n close() {\n if (!this.modal) return;\n\n // Don't hide the modal immediately, because if the consumer happens to call\n // the `show` method straight after to show another modal dialog, it will\n // cause Bootstrap's modal JS to misbehave. Instead we will wait for a tiny\n // bit to give the `show` method the opportunity to prevent this from going\n // ahead.\n this.closeTimeout = setTimeout(() => {\n this.modal = null;\n m.redraw();\n });\n }\n}\n","import Mithril from 'mithril';\nimport Alert, { AlertAttrs } from '../components/Alert';\n\n/**\n * Returned by `AlertManagerState.show`. Used to dismiss alerts.\n */\nexport type AlertIdentifier = number;\n\nexport interface AlertState {\n componentClass: typeof Alert;\n attrs: AlertAttrs;\n children: Mithril.Children;\n}\n\nexport default class AlertManagerState {\n protected activeAlerts: { [id: number]: AlertState } = {};\n protected alertId = 0;\n\n getActiveAlerts() {\n return this.activeAlerts;\n }\n\n /**\n * Show an Alert in the alerts area.\n *\n * @returns The alert's ID, which can be used to dismiss the alert.\n */\n show(children: Mithril.Children): AlertIdentifier;\n show(attrs: AlertAttrs, children: Mithril.Children): AlertIdentifier;\n show(componentClass: Alert, attrs: AlertAttrs, children: Mithril.Children): AlertIdentifier;\n\n show(arg1: any, arg2?: any, arg3?: any) {\n // Assigns variables as per the above signatures\n let componentClass = Alert;\n let attrs: AlertAttrs = {};\n let children: Mithril.Children;\n\n if (arguments.length == 1) {\n children = arg1 as Mithril.Children;\n } else if (arguments.length == 2) {\n attrs = arg1 as AlertAttrs;\n children = arg2 as Mithril.Children;\n } else if (arguments.length == 3) {\n componentClass = arg1 as typeof Alert;\n attrs = arg2 as AlertAttrs;\n children = arg3;\n }\n\n // Breaking Change Compliance Warning, Remove in Beta 15.\n // This is applied to the first argument (attrs) because previously, the alert was passed as the first argument.\n if (attrs === Alert || attrs instanceof Alert) {\n // This is duplicated so that if the error is caught, an error message still shows up in the debug console.\n console.error('The AlertManager can only show Alerts. Whichever extension triggered this alert should be updated to comply with beta 14.');\n throw new Error('The AlertManager can only show Alerts. Whichever extension triggered this alert should be updated to comply with beta 14.');\n }\n // End Change Compliance Warning, Remove in Beta 15\n this.activeAlerts[++this.alertId] = { children, attrs, componentClass };\n m.redraw();\n\n return this.alertId;\n }\n\n /**\n * Dismiss an alert.\n */\n dismiss(key: AlertIdentifier): void {\n if (!key || !(key in this.activeAlerts)) return;\n\n delete this.activeAlerts[key];\n m.redraw();\n }\n\n /**\n * Clear all alerts.\n */\n clear(): void {\n this.activeAlerts = {};\n m.redraw();\n }\n}\n","import ItemList from './utils/ItemList';\nimport Button from './components/Button';\nimport ModalManager from './components/ModalManager';\nimport AlertManager from './components/AlertManager';\nimport RequestErrorModal from './components/RequestErrorModal';\nimport Translator from './Translator';\nimport Store from './Store';\nimport Session from './Session';\nimport extract from './utils/extract';\nimport Drawer from './utils/Drawer';\nimport mapRoutes from './utils/mapRoutes';\nimport RequestError from './utils/RequestError';\nimport ScrollListener from './utils/ScrollListener';\nimport liveHumanTimes from './utils/liveHumanTimes';\nimport { extend } from './extend';\n\nimport Forum from './models/Forum';\nimport User from './models/User';\nimport Discussion from './models/Discussion';\nimport Post from './models/Post';\nimport Group from './models/Group';\nimport Notification from './models/Notification';\nimport { flattenDeep } from 'lodash-es';\nimport PageState from './states/PageState';\nimport ModalManagerState from './states/ModalManagerState';\nimport AlertManagerState from './states/AlertManagerState';\n\n/**\n * The `App` class provides a container for an application, as well as various\n * utilities for the rest of the app to use.\n */\nexport default class Application {\n /**\n * The forum model for this application.\n *\n * @type {Forum}\n * @public\n */\n forum = null;\n\n /**\n * A map of routes, keyed by a unique route name. Each route is an object\n * containing the following properties:\n *\n * - `path` The path that the route is accessed at.\n * - `component` The Mithril component to render when this route is active.\n *\n * @example\n * app.routes.discussion = {path: '/d/:id', component: DiscussionPage.component()};\n *\n * @type {Object}\n * @public\n */\n routes = {};\n\n /**\n * An ordered list of initializers to bootstrap the application.\n *\n * @type {ItemList}\n * @public\n */\n initializers = new ItemList();\n\n /**\n * The app's session.\n *\n * @type {Session}\n * @public\n */\n session = null;\n\n /**\n * The app's translator.\n *\n * @type {Translator}\n * @public\n */\n translator = new Translator();\n\n /**\n * The app's data store.\n *\n * @type {Store}\n * @public\n */\n store = new Store({\n forums: Forum,\n users: User,\n discussions: Discussion,\n posts: Post,\n groups: Group,\n notifications: Notification,\n });\n\n /**\n * A local cache that can be used to store data at the application level, so\n * that is persists between different routes.\n *\n * @type {Object}\n * @public\n */\n cache = {};\n\n /**\n * Whether or not the app has been booted.\n *\n * @type {Boolean}\n * @public\n */\n booted = false;\n\n /**\n * The key for an Alert that was shown as a result of an AJAX request error.\n * If present, it will be dismissed on the next successful request.\n *\n * @type {int}\n * @private\n */\n requestErrorAlert = null;\n\n /**\n * The page the app is currently on.\n *\n * This object holds information about the type of page we are currently\n * visiting, and sometimes additional arbitrary page state that may be\n * relevant to lower-level components.\n *\n * @type {PageState}\n */\n current = new PageState(null);\n\n /**\n * The page the app was on before the current page.\n *\n * Once the application navigates to another page, the object previously\n * assigned to this.current will be moved to this.previous, while this.current\n * is re-initialized.\n *\n * @type {PageState}\n */\n previous = new PageState(null);\n\n /*\n * An object that manages modal state.\n *\n * @type {ModalManagerState}\n */\n modal = new ModalManagerState();\n\n /**\n * An object that manages the state of active alerts.\n *\n * @type {AlertManagerState}\n */\n alerts = new AlertManagerState();\n\n data;\n\n title = '';\n titleCount = 0;\n\n initialRoute;\n\n load(payload) {\n this.data = payload;\n this.translator.locale = payload.locale;\n }\n\n boot() {\n this.initializers.toArray().forEach((initializer) => initializer(this));\n\n this.store.pushPayload({ data: this.data.resources });\n\n this.forum = this.store.getById('forums', 1);\n\n this.session = new Session(this.store.getById('users', this.data.session.userId), this.data.session.csrfToken);\n\n this.mount();\n\n this.initialRoute = window.location.href;\n }\n\n bootExtensions(extensions) {\n Object.keys(extensions).forEach((name) => {\n const extension = extensions[name];\n\n const extenders = flattenDeep(extension.extend);\n\n for (const extender of extenders) {\n extender.extend(this, { name, exports: extension });\n }\n });\n }\n\n mount(basePath = '') {\n // An object with a callable view property is used in order to pass arguments to the component; see https://mithril.js.org/mount.html\n m.mount(document.getElementById('modal'), { view: () => ModalManager.component({ state: this.modal }) });\n m.mount(document.getElementById('alerts'), { view: () => AlertManager.component({ state: this.alerts }) });\n\n this.drawer = new Drawer();\n\n m.route(document.getElementById('content'), basePath + '/', mapRoutes(this.routes, basePath));\n\n // Add a class to the body which indicates that the page has been scrolled\n // down. When this happens, we'll add classes to the header and app body\n // which will set the navbar's position to fixed. We don't want to always\n // have it fixed, as that could overlap with custom headers.\n const scrollListener = new ScrollListener((top) => {\n const $app = $('#app');\n const offset = $app.offset().top;\n\n $app.toggleClass('affix', top >= offset).toggleClass('scrolled', top > offset);\n $('.App-header').toggleClass('navbar-fixed-top', top >= offset);\n });\n\n scrollListener.start();\n scrollListener.update();\n\n $(() => {\n $('body').addClass('ontouchstart' in window ? 'touch' : 'no-touch');\n });\n\n liveHumanTimes();\n }\n\n /**\n * Get the API response document that has been preloaded into the application.\n *\n * @return {Object|null}\n * @public\n */\n preloadedApiDocument() {\n // If the URL has changed, the preloaded Api document is invalid.\n if (this.data.apiDocument && window.location.href === this.initialRoute) {\n const results = this.store.pushPayload(this.data.apiDocument);\n\n this.data.apiDocument = null;\n\n return results;\n }\n\n return null;\n }\n\n /**\n * Determine the current screen mode, based on our media queries.\n *\n * @returns {String} - one of \"phone\", \"tablet\", \"desktop\" or \"desktop-hd\"\n */\n screen() {\n const styles = getComputedStyle(document.documentElement);\n return styles.getPropertyValue('--flarum-screen');\n }\n\n /**\n * Set the of the page.\n *\n * @param {String} title\n * @public\n */\n setTitle(title) {\n this.title = title;\n this.updateTitle();\n }\n\n /**\n * Set a number to display in the <title> of the page.\n *\n * @param {Integer} count\n */\n setTitleCount(count) {\n this.titleCount = count;\n this.updateTitle();\n }\n\n updateTitle() {\n const count = this.titleCount ? `(${this.titleCount}) ` : '';\n const pageTitleWithSeparator = this.title && m.route.get() !== this.forum.attribute('basePath') + '/' ? this.title + ' - ' : '';\n const title = this.forum.attribute('title');\n document.title = count + pageTitleWithSeparator + title;\n }\n\n /**\n * Make an AJAX request, handling any low-level errors that may occur.\n *\n * @see https://mithril.js.org/request.html\n * @param {Object} options\n * @return {Promise}\n * @public\n */\n request(originalOptions) {\n const options = Object.assign({}, originalOptions);\n\n // Set some default options if they haven't been overridden. We want to\n // authenticate all requests with the session token. We also want all\n // requests to run asynchronously in the background, so that they don't\n // prevent redraws from occurring.\n options.background = options.background || true;\n\n extend(options, 'config', (result, xhr) => xhr.setRequestHeader('X-CSRF-Token', this.session.csrfToken));\n\n // If the method is something like PATCH or DELETE, which not all servers\n // and clients support, then we'll send it as a POST request with the\n // intended method specified in the X-HTTP-Method-Override header.\n if (options.method !== 'GET' && options.method !== 'POST') {\n const method = options.method;\n extend(options, 'config', (result, xhr) => xhr.setRequestHeader('X-HTTP-Method-Override', method));\n options.method = 'POST';\n }\n\n // When we deserialize JSON data, if for some reason the server has provided\n // a dud response, we don't want the application to crash. We'll show an\n // error message to the user instead.\n options.deserialize = options.deserialize || ((responseText) => responseText);\n\n options.errorHandler =\n options.errorHandler ||\n ((error) => {\n throw error;\n });\n\n // When extracting the data from the response, we can check the server\n // response code and show an error message to the user if something's gone\n // awry.\n const original = options.extract;\n options.extract = (xhr) => {\n let responseText;\n\n if (original) {\n responseText = original(xhr.responseText);\n } else {\n responseText = xhr.responseText || null;\n }\n\n const status = xhr.status;\n\n if (status < 200 || status > 299) {\n throw new RequestError(status, responseText, options, xhr);\n }\n\n if (xhr.getResponseHeader) {\n const csrfToken = xhr.getResponseHeader('X-CSRF-Token');\n if (csrfToken) app.session.csrfToken = csrfToken;\n }\n\n try {\n return JSON.parse(responseText);\n } catch (e) {\n throw new RequestError(500, responseText, options, xhr);\n }\n };\n\n if (this.requestErrorAlert) this.alerts.dismiss(this.requestErrorAlert);\n\n // Now make the request. If it's a failure, inspect the error that was\n // returned and show an alert containing its contents.\n return m.request(options).then(\n (response) => response,\n (error) => {\n let content;\n\n switch (error.status) {\n case 422:\n content = error.response.errors\n .map((error) => [error.detail, <br />])\n .reduce((a, b) => a.concat(b), [])\n .slice(0, -1);\n break;\n\n case 401:\n case 403:\n content = app.translator.trans('core.lib.error.permission_denied_message');\n break;\n\n case 404:\n case 410:\n content = app.translator.trans('core.lib.error.not_found_message');\n break;\n\n case 429:\n content = app.translator.trans('core.lib.error.rate_limit_exceeded_message');\n break;\n\n default:\n content = app.translator.trans('core.lib.error.generic_message');\n }\n\n const isDebug = app.forum.attribute('debug');\n // contains a formatted errors if possible, response must be an JSON API array of errors\n // the details property is decoded to transform escaped characters such as '\\n'\n const errors = error.response && error.response.errors;\n const formattedError = Array.isArray(errors) && errors[0] && errors[0].detail && errors.map((e) => decodeURI(e.detail));\n\n error.alert = {\n type: 'error',\n content,\n controls: isDebug && [\n <Button className=\"Button Button--link\" onclick={this.showDebug.bind(this, error, formattedError)}>\n Debug\n </Button>,\n ],\n };\n\n try {\n options.errorHandler(error);\n } catch (error) {\n if (isDebug && error.xhr) {\n const { method, url } = error.options;\n const { status = '' } = error.xhr;\n\n console.group(`${method} ${url} ${status}`);\n\n console.error(...(formattedError || [error]));\n\n console.groupEnd();\n }\n\n this.requestErrorAlert = this.alerts.show(error.alert, error.alert.content);\n }\n\n return Promise.reject(error);\n }\n );\n }\n\n /**\n * @param {RequestError} error\n * @param {string[]} [formattedError]\n * @private\n */\n showDebug(error, formattedError) {\n this.alerts.dismiss(this.requestErrorAlert);\n\n this.modal.show(RequestErrorModal, { error, formattedError });\n }\n\n /**\n * Construct a URL to the route with the given name.\n *\n * @param {String} name\n * @param {Object} params\n * @return {String}\n * @public\n */\n route(name, params = {}) {\n const route = this.routes[name];\n\n if (!route) throw new Error(`Route '${name}' does not exist`);\n\n const url = route.path.replace(/:([^\\/]+)/g, (m, key) => extract(params, key));\n\n // Remove falsy values in params to avoid having urls like '/?sort&q'\n for (const key in params) {\n if (params.hasOwnProperty(key) && !params[key]) delete params[key];\n }\n\n const queryString = m.buildQueryString(params);\n const prefix = m.route.prefix === '' ? this.forum.attribute('basePath') : '';\n\n return prefix + url + (queryString ? '?' + queryString : '');\n }\n}\n","import * as Mithril from 'mithril';\n\nexport interface ComponentAttrs extends Mithril.Attributes {}\n\n/**\n * The `Component` class defines a user interface 'building block'. A component\n * generates a virtual DOM to be rendered on each redraw.\n *\n * Essentially, this is a wrapper for Mithril's components that adds several useful features:\n *\n * - In the `oninit` and `onbeforeupdate` lifecycle hooks, we store vnode attrs in `this.attrs.\n * This allows us to use attrs across components without having to pass the vnode to every single\n * method.\n * - The static `initAttrs` method allows a convenient way to provide defaults (or to otherwise modify)\n * the attrs that have been passed into a component.\n * - When the component is created in the DOM, we store its DOM element under `this.element`; this lets\n * us use jQuery to modify child DOM state from internal methods via the `this.$()` method.\n * - A convenience `component` method, which serves as an alternative to hyperscript and JSX.\n *\n * As with other Mithril components, components extending Component can be initialized\n * and nested using JSX, hyperscript, or a combination of both. The `component` method can also\n * be used.\n *\n * @example\n * return m('div', <MyComponent foo=\"bar\"><p>Hello World</p></MyComponent>);\n *\n * @example\n * return m('div', MyComponent.component({foo: 'bar'), m('p', 'Hello World!'));\n *\n * @see https://mithril.js.org/components.html\n */\nexport default abstract class Component<T extends ComponentAttrs = ComponentAttrs> implements Mithril.ClassComponent<T> {\n /**\n * The root DOM element for the component.\n */\n protected element!: Element;\n\n /**\n * The attributes passed into the component.\n *\n * @see https://mithril.js.org/components.html#passing-data-to-components\n */\n protected attrs!: T;\n\n /**\n * @inheritdoc\n */\n abstract view(vnode: Mithril.Vnode<T, this>): Mithril.Children;\n\n /**\n * @inheritdoc\n */\n oninit(vnode: Mithril.Vnode<T, this>) {\n this.setAttrs(vnode.attrs);\n }\n\n /**\n * @inheritdoc\n */\n oncreate(vnode: Mithril.VnodeDOM<T, this>) {\n this.element = vnode.dom;\n }\n\n /**\n * @inheritdoc\n */\n onbeforeupdate(vnode: Mithril.VnodeDOM<T, this>) {\n this.setAttrs(vnode.attrs);\n }\n\n /**\n * Returns a jQuery object for this component's element. If you pass in a\n * selector string, this method will return a jQuery object, using the current\n * element as its buffer.\n *\n * For example, calling `component.$('li')` will return a jQuery object\n * containing all of the `li` elements inside the DOM element of this\n * component.\n *\n * @param [selector] a jQuery-compatible selector string\n * @returns the jQuery object for the DOM node\n * @final\n */\n protected $(selector: string): JQuery {\n const $element = $(this.element) as JQuery<HTMLElement>;\n\n return selector ? $element.find(selector) : $element;\n }\n\n /**\n * Convenience method to attach a component without JSX.\n * Has the same effect as calling `m(THIS_CLASS, attrs, children)`.\n *\n * @see https://mithril.js.org/hyperscript.html#mselector,-attributes,-children\n */\n static component(attrs = {}, children = null): Mithril.Vnode {\n const componentAttrs = Object.assign({}, attrs) as Record<string, unknown>;\n\n return m(this as any, componentAttrs, children);\n }\n\n /**\n * Saves a reference to the vnode attrs after running them through initAttrs,\n * and checking for common issues.\n */\n private setAttrs(attrs: T = {} as T): void {\n (this.constructor as typeof Component).initAttrs(attrs);\n\n if (attrs) {\n if ('children' in attrs) {\n throw new Error(\n `[${\n (this.constructor as any).name\n }] The \"children\" attribute of attrs should never be used. Either pass children in as the vnode children or rename the attribute`\n );\n }\n\n if ('tag' in attrs) {\n throw new Error(`[${(this.constructor as any).name}] You cannot use the \"tag\" attribute name with Mithril 2.`);\n }\n }\n\n this.attrs = attrs;\n }\n\n /**\n * Initialize the component's attrs.\n *\n * This can be used to assign default values for missing, optional attrs.\n */\n protected static initAttrs<T>(attrs: T): void {}\n}\n","/**\n * The `Model` class represents a local data resource. It provides methods to\n * persist changes via the API.\n *\n * @abstract\n */\nexport default class Model {\n /**\n * @param {Object} data A resource object from the API.\n * @param {Store} store The data store that this model should be persisted to.\n * @public\n */\n constructor(data = {}, store = null) {\n /**\n * The resource object from the API.\n *\n * @type {Object}\n * @public\n */\n this.data = data;\n\n /**\n * The time at which the model's data was last updated. Watching the value\n * of this property is a fast way to retain/cache a subtree if data hasn't\n * changed.\n *\n * @type {Date}\n * @public\n */\n this.freshness = new Date();\n\n /**\n * Whether or not the resource exists on the server.\n *\n * @type {Boolean}\n * @public\n */\n this.exists = false;\n\n /**\n * The data store that this resource should be persisted to.\n *\n * @type {Store}\n * @protected\n */\n this.store = store;\n }\n\n /**\n * Get the model's ID.\n *\n * @return {Integer}\n * @public\n * @final\n */\n id() {\n return this.data.id;\n }\n\n /**\n * Get one of the model's attributes.\n *\n * @param {String} attribute\n * @return {*}\n * @public\n * @final\n */\n attribute(attribute) {\n return this.data.attributes[attribute];\n }\n\n /**\n * Merge new data into this model locally.\n *\n * @param {Object} data A resource object to merge into this model\n * @public\n */\n pushData(data) {\n // Since most of the top-level items in a resource object are objects\n // (e.g. relationships, attributes), we'll need to check and perform the\n // merge at the second level if that's the case.\n for (const key in data) {\n if (typeof data[key] === 'object') {\n this.data[key] = this.data[key] || {};\n\n // For every item in a second-level object, we want to check if we've\n // been handed a Model instance. If so, we will convert it to a\n // relationship data object.\n for (const innerKey in data[key]) {\n if (data[key][innerKey] instanceof Model) {\n data[key][innerKey] = { data: Model.getIdentifier(data[key][innerKey]) };\n }\n this.data[key][innerKey] = data[key][innerKey];\n }\n } else {\n this.data[key] = data[key];\n }\n }\n\n // Now that we've updated the data, we can say that the model is fresh.\n // This is an easy way to invalidate retained subtrees etc.\n this.freshness = new Date();\n }\n\n /**\n * Merge new attributes into this model locally.\n *\n * @param {Object} attributes The attributes to merge.\n * @public\n */\n pushAttributes(attributes) {\n this.pushData({ attributes });\n }\n\n /**\n * Merge new attributes into this model, both locally and with persistence.\n *\n * @param {Object} attributes The attributes to save. If a 'relationships' key\n * exists, it will be extracted and relationships will also be saved.\n * @param {Object} [options]\n * @return {Promise}\n * @public\n */\n save(attributes, options = {}) {\n const data = {\n type: this.data.type,\n id: this.data.id,\n attributes,\n };\n\n // If a 'relationships' key exists, extract it from the attributes hash and\n // set it on the top-level data object instead. We will be sending this data\n // object to the API for persistence.\n if (attributes.relationships) {\n data.relationships = {};\n\n for (const key in attributes.relationships) {\n const model = attributes.relationships[key];\n\n data.relationships[key] = {\n data: model instanceof Array ? model.map(Model.getIdentifier) : Model.getIdentifier(model),\n };\n }\n\n delete attributes.relationships;\n }\n\n // Before we update the model's data, we should make a copy of the model's\n // old data so that we can revert back to it if something goes awry during\n // persistence.\n const oldData = this.copyData();\n\n this.pushData(data);\n\n const request = { data };\n if (options.meta) request.meta = options.meta;\n\n return app\n .request(\n Object.assign(\n {\n method: this.exists ? 'PATCH' : 'POST',\n url: app.forum.attribute('apiUrl') + this.apiEndpoint(),\n body: request,\n },\n options\n )\n )\n .then(\n // If everything went well, we'll make sure the store knows that this\n // model exists now (if it didn't already), and we'll push the data that\n // the API returned into the store.\n (payload) => {\n this.store.data[payload.data.type] = this.store.data[payload.data.type] || {};\n this.store.data[payload.data.type][payload.data.id] = this;\n return this.store.pushPayload(payload);\n },\n\n // If something went wrong, though... good thing we backed up our model's\n // old data! We'll revert to that and let others handle the error.\n (response) => {\n this.pushData(oldData);\n m.redraw();\n throw response;\n }\n );\n }\n\n /**\n * Send a request to delete the resource.\n *\n * @param {Object} body Data to send along with the DELETE request.\n * @param {Object} [options]\n * @return {Promise}\n * @public\n */\n delete(body, options = {}) {\n if (!this.exists) return Promise.resolve();\n\n return app\n .request(\n Object.assign(\n {\n method: 'DELETE',\n url: app.forum.attribute('apiUrl') + this.apiEndpoint(),\n body,\n },\n options\n )\n )\n .then(() => {\n this.exists = false;\n this.store.remove(this);\n });\n }\n\n /**\n * Construct a path to the API endpoint for this resource.\n *\n * @return {String}\n * @protected\n */\n apiEndpoint() {\n return '/' + this.data.type + (this.exists ? '/' + this.data.id : '');\n }\n\n copyData() {\n return JSON.parse(JSON.stringify(this.data));\n }\n\n /**\n * Generate a function which returns the value of the given attribute.\n *\n * @param {String} name\n * @param {function} [transform] A function to transform the attribute value\n * @return {*}\n * @public\n */\n static attribute(name, transform) {\n return function () {\n const value = this.data.attributes && this.data.attributes[name];\n\n return transform ? transform(value) : value;\n };\n }\n\n /**\n * Generate a function which returns the value of the given has-one\n * relationship.\n *\n * @param {String} name\n * @return {Model|Boolean|undefined} false if no information about the\n * relationship exists; undefined if the relationship exists but the model\n * has not been loaded; or the model if it has been loaded.\n * @public\n */\n static hasOne(name) {\n return function () {\n if (this.data.relationships) {\n const relationship = this.data.relationships[name];\n\n if (relationship) {\n return app.store.getById(relationship.data.type, relationship.data.id);\n }\n }\n\n return false;\n };\n }\n\n /**\n * Generate a function which returns the value of the given has-many\n * relationship.\n *\n * @param {String} name\n * @return {Array|Boolean} false if no information about the relationship\n * exists; an array if it does, containing models if they have been\n * loaded, and undefined for those that have not.\n * @public\n */\n static hasMany(name) {\n return function () {\n if (this.data.relationships) {\n const relationship = this.data.relationships[name];\n\n if (relationship) {\n return relationship.data.map((data) => app.store.getById(data.type, data.id));\n }\n }\n\n return false;\n };\n }\n\n /**\n * Transform the given value into a Date object.\n *\n * @param {String} value\n * @return {Date|null}\n * @public\n */\n static transformDate(value) {\n return value ? new Date(value) : null;\n }\n\n /**\n * Get a resource identifier object for the given model.\n *\n * @param {Model} model\n * @return {Object}\n * @protected\n */\n static getIdentifier(model) {\n return {\n type: model.data.type,\n id: model.data.id,\n };\n }\n}\n","/**\n * The `Session` class defines the current user session. It stores a reference\n * to the current authenticated user, and provides methods to log in/out.\n */\nexport default class Session {\n constructor(user, csrfToken) {\n /**\n * The current authenticated user.\n *\n * @type {User|null}\n * @public\n */\n this.user = user;\n\n /**\n * The CSRF token.\n *\n * @type {String|null}\n * @public\n */\n this.csrfToken = csrfToken;\n }\n\n /**\n * Attempt to log in a user.\n *\n * @param {String} identification The username/email.\n * @param {String} password\n * @param {Object} [options]\n * @return {Promise}\n * @public\n */\n login(body, options = {}) {\n return app.request(\n Object.assign(\n {\n method: 'POST',\n url: `${app.forum.attribute('baseUrl')}/login`,\n body,\n },\n options\n )\n );\n }\n\n /**\n * Log the user out.\n *\n * @public\n */\n logout() {\n window.location = `${app.forum.attribute('baseUrl')}/logout?token=${this.csrfToken}`;\n }\n}\n","/**\n * The `Store` class defines a local data store, and provides methods to\n * retrieve data from the API.\n */\nexport default class Store {\n constructor(models) {\n /**\n * The local data store. A tree of resource types to IDs, such that\n * accessing data[type][id] will return the model for that type/ID.\n *\n * @type {Object}\n * @protected\n */\n this.data = {};\n\n /**\n * The model registry. A map of resource types to the model class that\n * should be used to represent resources of that type.\n *\n * @type {Object}\n * @public\n */\n this.models = models;\n }\n\n /**\n * Push resources contained within an API payload into the store.\n *\n * @param {Object} payload\n * @return {Model|Model[]} The model(s) representing the resource(s) contained\n * within the 'data' key of the payload.\n * @public\n */\n pushPayload(payload) {\n if (payload.included) payload.included.map(this.pushObject.bind(this));\n\n const result = payload.data instanceof Array ? payload.data.map(this.pushObject.bind(this)) : this.pushObject(payload.data);\n\n // Attach the original payload to the model that we give back. This is\n // useful to consumers as it allows them to access meta information\n // associated with their request.\n result.payload = payload;\n\n return result;\n }\n\n /**\n * Create a model to represent a resource object (or update an existing one),\n * and push it into the store.\n *\n * @param {Object} data The resource object\n * @return {Model|null} The model, or null if no model class has been\n * registered for this resource type.\n * @public\n */\n pushObject(data) {\n if (!this.models[data.type]) return null;\n\n const type = (this.data[data.type] = this.data[data.type] || {});\n\n if (type[data.id]) {\n type[data.id].pushData(data);\n } else {\n type[data.id] = this.createRecord(data.type, data);\n }\n\n type[data.id].exists = true;\n\n return type[data.id];\n }\n\n /**\n * Make a request to the API to find record(s) of a specific type.\n *\n * @param {String} type The resource type.\n * @param {Integer|Integer[]|Object} [id] The ID(s) of the model(s) to retrieve.\n * Alternatively, if an object is passed, it will be handled as the\n * `query` parameter.\n * @param {Object} [query]\n * @param {Object} [options]\n * @return {Promise}\n * @public\n */\n find(type, id, query = {}, options = {}) {\n let params = query;\n let url = app.forum.attribute('apiUrl') + '/' + type;\n\n if (id instanceof Array) {\n url += '?filter[id]=' + id.join(',');\n } else if (typeof id === 'object') {\n params = id;\n } else if (id) {\n url += '/' + id;\n }\n\n return app\n .request(\n Object.assign(\n {\n method: 'GET',\n url,\n params,\n },\n options\n )\n )\n .then(this.pushPayload.bind(this));\n }\n\n /**\n * Get a record from the store by ID.\n *\n * @param {String} type The resource type.\n * @param {Integer} id The resource ID.\n * @return {Model}\n * @public\n */\n getById(type, id) {\n return this.data[type] && this.data[type][id];\n }\n\n /**\n * Get a record from the store by the value of a model attribute.\n *\n * @param {String} type The resource type.\n * @param {String} key The name of the method on the model.\n * @param {*} value The value of the model attribute.\n * @return {Model}\n * @public\n */\n getBy(type, key, value) {\n return this.all(type).filter((model) => model[key]() === value)[0];\n }\n\n /**\n * Get all loaded records of a specific type.\n *\n * @param {String} type\n * @return {Model[]}\n * @public\n */\n all(type) {\n const records = this.data[type];\n\n return records ? Object.keys(records).map((id) => records[id]) : [];\n }\n\n /**\n * Remove the given model from the store.\n *\n * @param {Model} model\n */\n remove(model) {\n delete this.data[model.data.type][model.id()];\n }\n\n /**\n * Create a new record of the given type.\n *\n * @param {String} type The resource type\n * @param {Object} [data] Any data to initialize the model with\n * @return {Model}\n * @public\n */\n createRecord(type, data = {}) {\n data.type = data.type || type;\n\n return new this.models[type](data, this);\n }\n}\n","import username from './helpers/username';\nimport extract from './utils/extract';\n\n/**\n * Translator with the same API as Symfony's.\n *\n * Derived from https://github.com/willdurand/BazingaJsTranslationBundle\n * which is available under the MIT License.\n * Copyright (c) William Durand <william.durand1@gmail.com>\n */\nexport default class Translator {\n constructor() {\n /**\n * A map of translation keys to their translated values.\n *\n * @type {Object}\n * @public\n */\n this.translations = {};\n\n this.locale = null;\n }\n\n addTranslations(translations) {\n Object.assign(this.translations, translations);\n }\n\n trans(id, parameters) {\n const translation = this.translations[id];\n\n if (translation) {\n return this.apply(translation, parameters || {});\n }\n\n return id;\n }\n\n transChoice(id, number, parameters) {\n let translation = this.translations[id];\n\n if (translation) {\n number = parseInt(number, 10);\n\n translation = this.pluralize(translation, number);\n\n return this.apply(translation, parameters || {});\n }\n\n return id;\n }\n\n apply(translation, input) {\n // If we've been given a user model as one of the input parameters, then\n // we'll extract the username and use that for the translation. In the\n // future there should be a hook here to inspect the user and change the\n // translation key. This will allow a gender property to determine which\n // translation key is used.\n if ('user' in input) {\n const user = extract(input, 'user');\n\n if (!input.username) input.username = username(user);\n }\n\n translation = translation.split(new RegExp('({[a-z0-9_]+}|</?[a-z0-9_]+>)', 'gi'));\n\n const hydrated = [];\n const open = [hydrated];\n\n translation.forEach((part) => {\n const match = part.match(new RegExp('{([a-z0-9_]+)}|<(/?)([a-z0-9_]+)>', 'i'));\n\n if (match) {\n // Either an opening or closing tag.\n if (match[1]) {\n open[0].push(input[match[1]]);\n } else if (match[3]) {\n if (match[2]) {\n // Closing tag. We start by removing all raw children (generally in the form of strings) from the temporary\n // holding array, then run them through m.fragment to convert them to vnodes. Usually this will just give us a\n // text vnode, but using m.fragment as opposed to an explicit conversion should be more flexible. This is necessary because\n // otherwise, our generated vnode will have raw strings as its children, and mithril expects vnodes.\n // Finally, we add the now-processed vnodes back onto the holding array (which is the same object in memory as the\n // children array of the vnode we are currently processing), and remove the reference to the holding array so that\n // further text will be added to the full set of returned elements.\n const rawChildren = open[0].splice(0, open[0].length);\n open[0].push(...m.fragment(rawChildren).children);\n open.shift();\n } else {\n // If a vnode with a matching tag was provided in the translator input, we use that. Otherwise, we create a new vnode\n // with this tag, and an empty children array (since we're expecting to insert children, as that's the point of having this in translator)\n let tag = input[match[3]] || { tag: match[3], children: [] };\n open[0].push(tag);\n // Insert the tag's children array as the first element of open, so that text in between the opening\n // and closing tags will be added to the tag's children, not to the full set of returned elements.\n open.unshift(tag.children || tag);\n }\n }\n } else {\n // Not an html tag, we add it to open[0], which is either the full set of returned elements (vnodes and text),\n // or if an html tag is currently being processed, the children attribute of that html tag's vnode.\n open[0].push(part);\n }\n });\n\n return hydrated.filter((part) => part);\n }\n\n pluralize(translation, number) {\n const sPluralRegex = new RegExp(/^\\w+\\: +(.+)$/),\n cPluralRegex = new RegExp(/^\\s*((\\{\\s*(\\-?\\d+[\\s*,\\s*\\-?\\d+]*)\\s*\\})|([\\[\\]])\\s*(-Inf|\\-?\\d+)\\s*,\\s*(\\+?Inf|\\-?\\d+)\\s*([\\[\\]]))\\s?(.+?)$/),\n iPluralRegex = new RegExp(/^\\s*(\\{\\s*(\\-?\\d+[\\s*,\\s*\\-?\\d+]*)\\s*\\})|([\\[\\]])\\s*(-Inf|\\-?\\d+)\\s*,\\s*(\\+?Inf|\\-?\\d+)\\s*([\\[\\]])/),\n standardRules = [],\n explicitRules = [];\n\n translation.split('|').forEach((part) => {\n if (cPluralRegex.test(part)) {\n const matches = part.match(cPluralRegex);\n explicitRules[matches[0]] = matches[matches.length - 1];\n } else if (sPluralRegex.test(part)) {\n const matches = part.match(sPluralRegex);\n standardRules.push(matches[1]);\n } else {\n standardRules.push(part);\n }\n });\n\n explicitRules.forEach((rule, e) => {\n if (iPluralRegex.test(e)) {\n const matches = e.match(iPluralRegex);\n\n if (matches[1]) {\n const ns = matches[2].split(',');\n\n for (let n in ns) {\n if (number == ns[n]) {\n return explicitRules[e];\n }\n }\n } else {\n var leftNumber = this.convertNumber(matches[4]);\n var rightNumber = this.convertNumber(matches[5]);\n\n if (\n ('[' === matches[3] ? number >= leftNumber : number > leftNumber) &&\n (']' === matches[6] ? number <= rightNumber : number < rightNumber)\n ) {\n return explicitRules[e];\n }\n }\n }\n });\n\n return standardRules[this.pluralPosition(number, this.locale)] || standardRules[0] || undefined;\n }\n\n convertNumber(number) {\n if ('-Inf' === number) {\n return Number.NEGATIVE_INFINITY;\n } else if ('+Inf' === number || 'Inf' === number) {\n return Number.POSITIVE_INFINITY;\n }\n\n return parseInt(number, 10);\n }\n\n pluralPosition(number, locale) {\n if ('pt_BR' === locale) {\n locale = 'xbr';\n }\n\n if (locale.length > 3) {\n locale = locale.split('_')[0];\n }\n\n switch (locale) {\n case 'bo':\n case 'dz':\n case 'id':\n case 'ja':\n case 'jv':\n case 'ka':\n case 'km':\n case 'kn':\n case 'ko':\n case 'ms':\n case 'th':\n case 'vi':\n case 'zh':\n return 0;\n\n case 'af':\n case 'az':\n case 'bn':\n case 'bg':\n case 'ca':\n case 'da':\n case 'de':\n case 'el':\n case 'en':\n case 'eo':\n case 'es':\n case 'et':\n case 'eu':\n case 'fa':\n case 'fi':\n case 'fo':\n case 'fur':\n case 'fy':\n case 'gl':\n case 'gu':\n case 'ha':\n case 'he':\n case 'hu':\n case 'is':\n case 'it':\n case 'ku':\n case 'lb':\n case 'ml':\n case 'mn':\n case 'mr':\n case 'nah':\n case 'nb':\n case 'ne':\n case 'nl':\n case 'nn':\n case 'no':\n case 'om':\n case 'or':\n case 'pa':\n case 'pap':\n case 'ps':\n case 'pt':\n case 'so':\n case 'sq':\n case 'sv':\n case 'sw':\n case 'ta':\n case 'te':\n case 'tk':\n case 'tr':\n case 'ur':\n case 'zu':\n return number == 1 ? 0 : 1;\n\n case 'am':\n case 'bh':\n case 'fil':\n case 'fr':\n case 'gun':\n case 'hi':\n case 'ln':\n case 'mg':\n case 'nso':\n case 'xbr':\n case 'ti':\n case 'wa':\n return number === 0 || number == 1 ? 0 : 1;\n\n case 'be':\n case 'bs':\n case 'hr':\n case 'ru':\n case 'sr':\n case 'uk':\n return number % 10 == 1 && number % 100 != 11 ? 0 : number % 10 >= 2 && number % 10 <= 4 && (number % 100 < 10 || number % 100 >= 20) ? 1 : 2;\n\n case 'cs':\n case 'sk':\n return number == 1 ? 0 : number >= 2 && number <= 4 ? 1 : 2;\n\n case 'ga':\n return number == 1 ? 0 : number == 2 ? 1 : 2;\n\n case 'lt':\n return number % 10 == 1 && number % 100 != 11 ? 0 : number % 10 >= 2 && (number % 100 < 10 || number % 100 >= 20) ? 1 : 2;\n\n case 'sl':\n return number % 100 == 1 ? 0 : number % 100 == 2 ? 1 : number % 100 == 3 || number % 100 == 4 ? 2 : 3;\n\n case 'mk':\n return number % 10 == 1 ? 0 : 1;\n\n case 'mt':\n return number == 1 ? 0 : number === 0 || (number % 100 > 1 && number % 100 < 11) ? 1 : number % 100 > 10 && number % 100 < 20 ? 2 : 3;\n\n case 'lv':\n return number === 0 ? 0 : number % 10 == 1 && number % 100 != 11 ? 1 : 2;\n\n case 'pl':\n return number == 1 ? 0 : number % 10 >= 2 && number % 10 <= 4 && (number % 100 < 12 || number % 100 > 14) ? 1 : 2;\n\n case 'cy':\n return number == 1 ? 0 : number == 2 ? 1 : number == 8 || number == 11 ? 2 : 3;\n\n case 'ro':\n return number == 1 ? 0 : number === 0 || (number % 100 > 0 && number % 100 < 20) ? 1 : 2;\n\n case 'ar':\n return number === 0 ? 0 : number == 1 ? 1 : number == 2 ? 2 : number >= 3 && number <= 10 ? 3 : number >= 11 && number <= 99 ? 4 : 5;\n\n default:\n return 0;\n }\n }\n}\n","/**\n * The `evented` mixin provides methods allowing an object to trigger events,\n * running externally registered event handlers.\n */\nexport default {\n /**\n * Arrays of registered event handlers, grouped by the event name.\n *\n * @type {Object}\n * @protected\n */\n handlers: null,\n\n /**\n * Get all of the registered handlers for an event.\n *\n * @param {String} event The name of the event.\n * @return {Array}\n * @protected\n */\n getHandlers(event) {\n this.handlers = this.handlers || {};\n\n this.handlers[event] = this.handlers[event] || [];\n\n return this.handlers[event];\n },\n\n /**\n * Trigger an event.\n *\n * @param {String} event The name of the event.\n * @param {...*} args Arguments to pass to event handlers.\n * @public\n */\n trigger(event, ...args) {\n this.getHandlers(event).forEach((handler) => handler.apply(this, args));\n },\n\n /**\n * Register an event handler.\n *\n * @param {String} event The name of the event.\n * @param {function} handler The function to handle the event.\n */\n on(event, handler) {\n this.getHandlers(event).push(handler);\n },\n\n /**\n * Register an event handler so that it will run only once, and then\n * unregister itself.\n *\n * @param {String} event The name of the event.\n * @param {function} handler The function to handle the event.\n */\n one(event, handler) {\n const wrapper = function () {\n handler.apply(this, arguments);\n\n this.off(event, wrapper);\n };\n\n this.getHandlers(event).push(wrapper);\n },\n\n /**\n * Unregister an event handler.\n *\n * @param {String} event The name of the event.\n * @param {function} handler The function that handles the event.\n */\n off(event, handler) {\n const handlers = this.getHandlers(event);\n const index = handlers.indexOf(handler);\n\n if (index !== -1) {\n handlers.splice(index, 1);\n }\n },\n};\n","import * as Mithril from 'mithril';\n\n/**\n * The `Fragment` class represents a chunk of DOM that is rendered once with Mithril and then takes\n * over control of its own DOM and lifecycle.\n *\n * This is very similar to the `Component` wrapper class, but is used for more fine-grained control over\n * the rendering and display of some significant chunks of the DOM. In contrast to components, fragments\n * do not offer Mithril's lifecycle hooks.\n *\n * Use this when you want to enjoy the benefits of JSX / VDOM for initial rendering, combined with\n * small helper methods that then make updates to that DOM directly, instead of fully redrawing\n * everything through Mithril.\n *\n * This should only be used when necessary, and only with `m.render`. If you are unsure whether you need\n * this or `Component, you probably need `Component`.\n */\nexport default abstract class Fragment {\n /**\n * The root DOM element for the fragment.\n */\n protected element!: Element;\n\n /**\n * Returns a jQuery object for this fragment's element. If you pass in a\n * selector string, this method will return a jQuery object, using the current\n * element as its buffer.\n *\n * For example, calling `fragment.$('li')` will return a jQuery object\n * containing all of the `li` elements inside the DOM element of this\n * fragment.\n *\n * @param {String} [selector] a jQuery-compatible selector string\n * @returns {jQuery} the jQuery object for the DOM node\n * @final\n */\n public $(selector) {\n const $element = $(this.element);\n\n return selector ? $element.find(selector) : $element;\n }\n\n /**\n * Get the renderable virtual DOM that represents the fragment's view.\n *\n * This should NOT be overridden by subclasses. Subclasses wishing to define\n * their virtual DOM should override Fragment#view instead.\n *\n * @example\n * const fragment = new MyFragment();\n * m.render(document.body, fragment.render());\n *\n * @final\n */\n public render(): Mithril.Vnode<Mithril.Attributes, this> {\n const vdom = this.view();\n\n vdom.attrs = vdom.attrs || {};\n\n const originalOnCreate = vdom.attrs.oncreate;\n\n vdom.attrs.oncreate = (vnode) => {\n this.element = vnode.dom;\n if (originalOnCreate) originalOnCreate.apply(this, [vnode]);\n };\n\n return vdom;\n }\n\n /**\n * Creates a view out of virtual elements.\n */\n abstract view(): Mithril.Vnode<Mithril.Attributes, this>;\n}\n","import * as extend from './extend';\nimport Session from './Session';\nimport Store from './Store';\nimport BasicEditorDriver from './utils/BasicEditorDriver';\nimport evented from './utils/evented';\nimport liveHumanTimes from './utils/liveHumanTimes';\nimport ItemList from './utils/ItemList';\nimport mixin from './utils/mixin';\nimport humanTime from './utils/humanTime';\nimport computed from './utils/computed';\nimport Drawer from './utils/Drawer';\nimport anchorScroll from './utils/anchorScroll';\nimport RequestError from './utils/RequestError';\nimport abbreviateNumber from './utils/abbreviateNumber';\nimport * as string from './utils/string';\nimport Stream from './utils/Stream';\nimport SubtreeRetainer from './utils/SubtreeRetainer';\nimport setRouteWithForcedRefresh from './utils/setRouteWithForcedRefresh';\nimport extract from './utils/extract';\nimport ScrollListener from './utils/ScrollListener';\nimport stringToColor from './utils/stringToColor';\nimport subclassOf from './utils/subclassOf';\nimport patchMithril from './utils/patchMithril';\nimport proxifyCompat from './utils/proxifyCompat';\nimport classList from './utils/classList';\nimport extractText from './utils/extractText';\nimport formatNumber from './utils/formatNumber';\nimport mapRoutes from './utils/mapRoutes';\nimport withAttr from './utils/withAttr';\nimport Notification from './models/Notification';\nimport User from './models/User';\nimport Post from './models/Post';\nimport Discussion from './models/Discussion';\nimport Group from './models/Group';\nimport Forum from './models/Forum';\nimport Component from './Component';\nimport Translator from './Translator';\nimport AlertManager from './components/AlertManager';\nimport Page from './components/Page';\nimport Switch from './components/Switch';\nimport Badge from './components/Badge';\nimport LoadingIndicator from './components/LoadingIndicator';\nimport Placeholder from './components/Placeholder';\nimport Separator from './components/Separator';\nimport Dropdown from './components/Dropdown';\nimport SplitDropdown from './components/SplitDropdown';\nimport RequestErrorModal from './components/RequestErrorModal';\nimport FieldSet from './components/FieldSet';\nimport Select from './components/Select';\nimport Navigation from './components/Navigation';\nimport Alert from './components/Alert';\nimport Link from './components/Link';\nimport LinkButton from './components/LinkButton';\nimport Checkbox from './components/Checkbox';\nimport SelectDropdown from './components/SelectDropdown';\nimport ModalManager from './components/ModalManager';\nimport Button from './components/Button';\nimport Modal from './components/Modal';\nimport GroupBadge from './components/GroupBadge';\n//import TextEditorButton from './components/TextEditorButton';\nimport Model from './Model';\nimport Application from './Application';\nimport fullTime from './helpers/fullTime';\nimport avatar from './helpers/avatar';\nimport icon from './helpers/icon';\nimport humanTimeHelper from './helpers/humanTime';\nimport punctuateSeries from './helpers/punctuateSeries';\nimport highlight from './helpers/highlight';\nimport username from './helpers/username';\nimport userOnline from './helpers/userOnline';\nimport listItems from './helpers/listItems';\nimport Fragment from './Fragment';\nimport DefaultResolver from './resolvers/DefaultResolver';\n\nexport default {\n extend: extend,\n Session: Session,\n Store: Store,\n 'utils/BasicEditorDriver': BasicEditorDriver,\n 'utils/evented': evented,\n 'utils/liveHumanTimes': liveHumanTimes,\n 'utils/ItemList': ItemList,\n 'utils/mixin': mixin,\n 'utils/humanTime': humanTime,\n 'utils/computed': computed,\n 'utils/Drawer': Drawer,\n 'utils/anchorScroll': anchorScroll,\n 'utils/RequestError': RequestError,\n 'utils/abbreviateNumber': abbreviateNumber,\n 'utils/string': string,\n 'utils/SubtreeRetainer': SubtreeRetainer,\n 'utils/extract': extract,\n 'utils/ScrollListener': ScrollListener,\n 'utils/stringToColor': stringToColor,\n 'utils/Stream': Stream,\n 'utils/subclassOf': subclassOf,\n 'utils/setRouteWithForcedRefresh': setRouteWithForcedRefresh,\n 'utils/patchMithril': patchMithril,\n 'utils/proxifyCompat': proxifyCompat,\n 'utils/classList': classList,\n 'utils/extractText': extractText,\n 'utils/formatNumber': formatNumber,\n 'utils/mapRoutes': mapRoutes,\n 'utils/withAttr': withAttr,\n 'models/Notification': Notification,\n 'models/User': User,\n 'models/Post': Post,\n 'models/Discussion': Discussion,\n 'models/Group': Group,\n 'models/Forum': Forum,\n Component: Component,\n Fragment: Fragment,\n Translator: Translator,\n 'components/AlertManager': AlertManager,\n 'components/Page': Page,\n 'components/Switch': Switch,\n 'components/Badge': Badge,\n 'components/LoadingIndicator': LoadingIndicator,\n 'components/Placeholder': Placeholder,\n 'components/Separator': Separator,\n 'components/Dropdown': Dropdown,\n 'components/SplitDropdown': SplitDropdown,\n 'components/RequestErrorModal': RequestErrorModal,\n 'components/FieldSet': FieldSet,\n 'components/Select': Select,\n 'components/Navigation': Navigation,\n 'components/Alert': Alert,\n 'components/Link': Link,\n 'components/LinkButton': LinkButton,\n 'components/Checkbox': Checkbox,\n 'components/SelectDropdown': SelectDropdown,\n 'components/ModalManager': ModalManager,\n 'components/Button': Button,\n 'components/Modal': Modal,\n 'components/GroupBadge': GroupBadge,\n //'components/TextEditor': TextEditor,\n //'components/TextEditorButton': TextEditorButton,\n Model: Model,\n Application: Application,\n 'helpers/fullTime': fullTime,\n 'helpers/avatar': avatar,\n 'helpers/icon': icon,\n 'helpers/humanTime': humanTimeHelper,\n 'helpers/punctuateSeries': punctuateSeries,\n 'helpers/highlight': highlight,\n 'helpers/username': username,\n 'helpers/userOnline': userOnline,\n 'helpers/listItems': listItems,\n 'resolvers/DefaultResolver': DefaultResolver,\n};\n","/**\n * The `mixin` utility assigns the properties of a set of 'mixin' objects to\n * the prototype of a parent object.\n *\n * @example\n * class MyClass extends mixin(ExistingClass, evented, etc) {}\n *\n * @param {Class} Parent The class to extend the new class from.\n * @param {...Object} mixins The objects to mix in.\n * @return {Class} A new class that extends Parent and contains the mixins.\n */\nexport default function mixin(Parent, ...mixins) {\n class Mixed extends Parent {}\n\n mixins.forEach((object) => {\n Object.assign(Mixed.prototype, object);\n });\n\n return Mixed;\n}\n","import Component, { ComponentAttrs } from '../Component';\nimport Button from './Button';\nimport listItems from '../helpers/listItems';\nimport extract from '../utils/extract';\nimport Mithril from 'mithril';\n\nexport interface AlertAttrs extends ComponentAttrs {\n /** The type of alert this is. Will be used to give the alert a class name of `Alert--{type}`. */\n type?: string;\n /** An array of controls to show in the alert. */\n controls?: Mithril.Children;\n /** Whether or not the alert can be dismissed. */\n dismissible?: boolean;\n /** A callback to run when the alert is dismissed */\n ondismiss?: Function;\n}\n\n/**\n * The `Alert` component represents an alert box, which contains a message,\n * some controls, and may be dismissible.\n */\nexport default class Alert<T extends AlertAttrs = AlertAttrs> extends Component<T> {\n view(vnode: Mithril.Vnode) {\n const attrs = Object.assign({}, this.attrs);\n\n const type = extract(attrs, 'type');\n attrs.className = 'Alert Alert--' + type + ' ' + (attrs.className || '');\n\n const content = extract(attrs, 'content') || vnode.children;\n const controls = (extract(attrs, 'controls') || []) as Mithril.ChildArray;\n\n // If the alert is meant to be dismissible (which is the case by default),\n // then we will create a dismiss button to append as the final control in\n // the alert.\n const dismissible = extract(attrs, 'dismissible');\n const ondismiss = extract(attrs, 'ondismiss');\n const dismissControl = [];\n\n if (dismissible || dismissible === undefined) {\n dismissControl.push(<Button icon=\"fas fa-times\" className=\"Button Button--link Button--icon Alert-dismiss\" onclick={ondismiss} />);\n }\n\n return (\n <div {...attrs}>\n <span className=\"Alert-body\">{content}</span>\n <ul className=\"Alert-controls\">{listItems(controls.concat(dismissControl))}</ul>\n </div>\n );\n }\n}\n","import Component from '../Component';\nimport Alert from './Alert';\n\n/**\n * The `AlertManager` component provides an area in which `Alert` components can\n * be shown and dismissed.\n */\nexport default class AlertManager extends Component {\n oninit(vnode) {\n super.oninit(vnode);\n\n this.state = this.attrs.state;\n }\n\n view() {\n return (\n <div className=\"AlertManager\">\n {Object.entries(this.state.getActiveAlerts()).map(([key, alert]) => (\n <div className=\"AlertManager-alert\">\n <alert.componentClass {...alert.attrs} ondismiss={this.state.dismiss.bind(this.state, key)}>\n {alert.children}\n </alert.componentClass>\n </div>\n ))}\n </div>\n );\n }\n}\n","import Component from '../Component';\nimport icon from '../helpers/icon';\nimport extract from '../utils/extract';\n\n/**\n * The `Badge` component represents a user/discussion badge, indicating some\n * status (e.g. a discussion is stickied, a user is an admin).\n *\n * A badge may have the following special attrs:\n *\n * - `type` The type of badge this is. This will be used to give the badge a\n * class name of `Badge--{type}`.\n * - `icon` The name of an icon to show inside the badge.\n * - `label`\n *\n * All other attrs will be assigned as attributes on the badge element.\n */\nexport default class Badge extends Component {\n view() {\n const attrs = Object.assign({}, this.attrs);\n const type = extract(attrs, 'type');\n const iconName = extract(attrs, 'icon');\n\n attrs.className = 'Badge ' + (type ? 'Badge--' + type : '') + ' ' + (attrs.className || '');\n attrs.title = extract(attrs, 'label') || '';\n\n return <span {...attrs}>{iconName ? icon(iconName, { className: 'Badge-icon' }) : m.trust(' ')}</span>;\n }\n\n oncreate(vnode) {\n super.oncreate(vnode);\n\n if (this.attrs.label) this.$().tooltip();\n }\n}\n","import Component from '../Component';\nimport icon from '../helpers/icon';\nimport classList from '../utils/classList';\nimport extract from '../utils/extract';\nimport extractText from '../utils/extractText';\nimport LoadingIndicator from './LoadingIndicator';\n\n/**\n * The `Button` component defines an element which, when clicked, performs an\n * action.\n *\n * ### Attrs\n *\n * - `icon` The name of the icon class. If specified, the button will be given a\n * 'has-icon' class name.\n * - `disabled` Whether or not the button is disabled. If truthy, the button\n * will be given a 'disabled' class name, and any `onclick` handler will be\n * removed.\n * - `loading` Whether or not the button should be in a disabled loading state.\n *\n * All other attrs will be assigned as attributes on the button element.\n *\n * Note that a Button has no default class names. This is because a Button can\n * be used to represent any generic clickable control, like a menu item.\n */\nexport default class Button extends Component {\n view(vnode) {\n const attrs = Object.assign({}, this.attrs);\n\n attrs.type = attrs.type || 'button';\n\n // If a tooltip was provided for buttons without additional content, we also\n // use this tooltip as text for screen readers\n if (attrs.title && !vnode.children) {\n attrs['aria-label'] = attrs.title;\n }\n\n // If given a translation object, extract the text.\n if (typeof attrs.title === 'object') {\n attrs.title = extractText(attrs.title);\n }\n\n // If nothing else is provided, we use the textual button content as tooltip\n if (!attrs.title && vnode.children) {\n attrs.title = extractText(vnode.children);\n }\n\n const iconName = extract(attrs, 'icon');\n\n const loading = extract(attrs, 'loading');\n if (attrs.disabled || loading) {\n delete attrs.onclick;\n }\n\n attrs.className = classList([attrs.className, iconName && 'hasIcon', (attrs.disabled || loading) && 'disabled', loading && 'loading']);\n\n return <button {...attrs}>{this.getButtonContent(vnode.children)}</button>;\n }\n\n /**\n * Get the template for the button's content.\n *\n * @return {*}\n * @protected\n */\n getButtonContent(children) {\n const iconName = this.attrs.icon;\n\n return [\n iconName && iconName !== true ? icon(iconName, { className: 'Button-icon' }) : '',\n children ? <span className=\"Button-label\">{children}</span> : '',\n this.attrs.loading ? <LoadingIndicator size=\"tiny\" className=\"LoadingIndicator--inline\" /> : '',\n ];\n }\n}\n","import Component from '../Component';\nimport LoadingIndicator from './LoadingIndicator';\nimport icon from '../helpers/icon';\nimport classList from '../utils/classList';\nimport withAttr from '../utils/withAttr';\n\n/**\n * The `Checkbox` component defines a checkbox input.\n *\n * ### Attrs\n *\n * - `state` Whether or not the checkbox is checked.\n * - `className` The class name for the root element.\n * - `disabled` Whether or not the checkbox is disabled.\n * - `loading` Whether or not the checkbox is loading.\n * - `onchange` A callback to run when the checkbox is checked/unchecked.\n * - `children` A text label to display next to the checkbox.\n */\nexport default class Checkbox extends Component {\n view(vnode) {\n // Sometimes, false is stored in the DB as '0'. This is a temporary\n // conversion layer until a more robust settings encoding is introduced\n if (this.attrs.state === '0') this.attrs.state = false;\n\n const className = classList([\n 'Checkbox',\n this.attrs.state ? 'on' : 'off',\n this.attrs.className,\n this.attrs.loading && 'loading',\n this.attrs.disabled && 'disabled',\n ]);\n\n return (\n <label className={className}>\n <input type=\"checkbox\" checked={this.attrs.state} disabled={this.attrs.disabled} onchange={withAttr('checked', this.onchange.bind(this))} />\n <div className=\"Checkbox-display\">{this.getDisplay()}</div>\n {vnode.children}\n </label>\n );\n }\n\n /**\n * Get the template for the checkbox's display (tick/cross icon).\n *\n * @return {*}\n * @protected\n */\n getDisplay() {\n return this.attrs.loading ? <LoadingIndicator size=\"tiny\" /> : icon(this.attrs.state ? 'fas fa-check' : 'fas fa-times');\n }\n\n /**\n * Run a callback when the state of the checkbox is changed.\n *\n * @param {Boolean} checked\n * @protected\n */\n onchange(checked) {\n if (this.attrs.onchange) this.attrs.onchange(checked, this);\n }\n}\n","import Component from '../Component';\nimport icon from '../helpers/icon';\nimport listItems from '../helpers/listItems';\n\n/**\n * The `Dropdown` component displays a button which, when clicked, shows a\n * dropdown menu beneath it.\n *\n * ### Attrs\n *\n * - `buttonClassName` A class name to apply to the dropdown toggle button.\n * - `menuClassName` A class name to apply to the dropdown menu.\n * - `icon` The name of an icon to show in the dropdown toggle button.\n * - `caretIcon` The name of an icon to show on the right of the button.\n * - `label` The label of the dropdown toggle button. Defaults to 'Controls'.\n * - `accessibleToggleLabel` The label used to describe the dropdown toggle button to assistive readers. Defaults to 'Toggle dropdown menu'.\n * - `onhide`\n * - `onshow`\n *\n * The children will be displayed as a list inside of the dropdown menu.\n */\nexport default class Dropdown extends Component {\n static initAttrs(attrs) {\n attrs.className = attrs.className || '';\n attrs.buttonClassName = attrs.buttonClassName || '';\n attrs.menuClassName = attrs.menuClassName || '';\n attrs.label = attrs.label || '';\n attrs.caretIcon = typeof attrs.caretIcon !== 'undefined' ? attrs.caretIcon : 'fas fa-caret-down';\n attrs.accessibleToggleLabel = attrs.accessibleToggleLabel || app.translator.trans('core.lib.dropdown.toggle_dropdown_accessible_label');\n }\n\n oninit(vnode) {\n super.oninit(vnode);\n\n this.showing = false;\n }\n\n view(vnode) {\n const items = vnode.children ? listItems(vnode.children) : [];\n\n return (\n <div className={'ButtonGroup Dropdown dropdown ' + this.attrs.className + ' itemCount' + items.length + (this.showing ? ' open' : '')}>\n {this.getButton(vnode.children)}\n {this.getMenu(items)}\n </div>\n );\n }\n\n oncreate(vnode) {\n super.oncreate(vnode);\n\n // When opening the dropdown menu, work out if the menu goes beyond the\n // bottom of the viewport. If it does, we will apply class to make it show\n // above the toggle button instead of below it.\n this.$().on('shown.bs.dropdown', () => {\n this.showing = true;\n\n if (this.attrs.onshow) {\n this.attrs.onshow();\n }\n\n m.redraw();\n\n const $menu = this.$('.Dropdown-menu');\n const isRight = $menu.hasClass('Dropdown-menu--right');\n\n $menu.removeClass('Dropdown-menu--top Dropdown-menu--right');\n\n $menu.toggleClass('Dropdown-menu--top', $menu.offset().top + $menu.height() > $(window).scrollTop() + $(window).height());\n\n if ($menu.offset().top < 0) {\n $menu.removeClass('Dropdown-menu--top');\n }\n\n $menu.toggleClass('Dropdown-menu--right', isRight || $menu.offset().left + $menu.width() > $(window).scrollLeft() + $(window).width());\n });\n\n this.$().on('hidden.bs.dropdown', () => {\n this.showing = false;\n\n if (this.attrs.onhide) {\n this.attrs.onhide();\n }\n\n m.redraw();\n });\n }\n\n /**\n * Get the template for the button.\n *\n * @return {*}\n * @protected\n */\n getButton(children) {\n return (\n <button\n className={'Dropdown-toggle ' + this.attrs.buttonClassName}\n aria-haspopup=\"menu\"\n aria-label={this.attrs.accessibleToggleLabel}\n data-toggle=\"dropdown\"\n onclick={this.attrs.onclick}\n >\n {this.getButtonContent(children)}\n </button>\n );\n }\n\n /**\n * Get the template for the button's content.\n *\n * @return {*}\n * @protected\n */\n getButtonContent(children) {\n return [\n this.attrs.icon ? icon(this.attrs.icon, { className: 'Button-icon' }) : '',\n <span className=\"Button-label\">{this.attrs.label}</span>,\n this.attrs.caretIcon ? icon(this.attrs.caretIcon, { className: 'Button-caret' }) : '',\n ];\n }\n\n getMenu(items) {\n return <ul className={'Dropdown-menu dropdown-menu ' + this.attrs.menuClassName}>{items}</ul>;\n }\n}\n","import Component from '../Component';\nimport listItems from '../helpers/listItems';\n\n/**\n * The `FieldSet` component defines a collection of fields, displayed in a list\n * underneath a title. Accepted properties are:\n *\n * - `className` The class name for the fieldset.\n * - `label` The title of this group of fields.\n *\n * The children should be an array of items to show in the fieldset.\n */\nexport default class FieldSet extends Component {\n view(vnode) {\n return (\n <fieldset className={this.attrs.className}>\n <legend>{this.attrs.label}</legend>\n <ul>{listItems(vnode.children)}</ul>\n </fieldset>\n );\n }\n}\n","import Badge from './Badge';\n\nexport default class GroupBadge extends Badge {\n static initAttrs(attrs) {\n super.initAttrs(attrs);\n\n if (attrs.group) {\n attrs.icon = attrs.group.icon();\n attrs.style = { backgroundColor: attrs.group.color() };\n attrs.label = typeof attrs.label === 'undefined' ? attrs.group.nameSingular() : attrs.label;\n attrs.type = 'group--' + attrs.group.id();\n\n delete attrs.group;\n }\n }\n}\n","import Component from '../Component';\nimport extract from '../utils/extract';\n\n/**\n * The link component enables both internal and external links.\n * It will return a regular HTML link for any links to external sites,\n * and it will use Mithril's m.route.Link for any internal links.\n *\n * Links will default to internal; the 'external' attr must be set to\n * `true` for the link to be external.\n */\nexport default class Link extends Component {\n view(vnode) {\n let { options = {}, ...attrs } = vnode.attrs;\n\n attrs.href = attrs.href || '';\n\n // For some reason, m.route.Link does not like vnode.text, so if present, we\n // need to convert it to text vnodes and store it in children.\n const children = vnode.children || { tag: '#', children: vnode.text };\n\n if (attrs.external) {\n return <a {...attrs}>{children}</a>;\n }\n\n // If the href URL of the link is the same as the current page path\n // we will not add a new entry to the browser history.\n // This allows us to still refresh the Page component\n // without adding endless history entries.\n if (attrs.href === m.route.get()) {\n if (!('replace' in options)) options.replace = true;\n }\n\n // Mithril 2 does not completely rerender the page if a route change leads to the same route\n // (or the same component handling a different route).\n // Here, the `force` parameter will use Mithril's key system to force a full rerender\n // see https://mithril.js.org/route.html#key-parameter\n if (extract(attrs, 'force')) {\n if (!('state' in options)) options.state = {};\n if (!('key' in options.state)) options.state.key = Date.now();\n }\n\n attrs.options = options;\n\n return <m.route.Link {...attrs}>{children}</m.route.Link>;\n }\n}\n","import Button from './Button';\nimport Link from './Link';\n\n/**\n * The `LinkButton` component defines a `Button` which links to a route.\n *\n * ### Attrs\n *\n * All of the attrs accepted by `Button`, plus:\n *\n * - `active` Whether or not the page that this button links to is currently\n * active.\n * - `href` The URL to link to. If the current URL `m.route()` matches this,\n * the `active` prop will automatically be set to true.\n * - `force` Whether the page should be fully rerendered. Defaults to `true`.\n */\nexport default class LinkButton extends Button {\n static initAttrs(attrs) {\n super.initAttrs(attrs);\n\n attrs.active = this.isActive(attrs);\n if (attrs.force === undefined) attrs.force = true;\n }\n\n view(vnode) {\n const vdom = super.view(vnode);\n\n vdom.tag = Link;\n vdom.attrs.active = String(vdom.attrs.active);\n\n return vdom;\n }\n\n /**\n * Determine whether a component with the given attrs is 'active'.\n *\n * @param {Object} attrs\n * @return {Boolean}\n */\n static isActive(attrs) {\n return typeof attrs.active !== 'undefined' ? attrs.active : m.route.get() === attrs.href;\n }\n}\n","import Component from '../Component';\nimport { Spinner } from 'spin.js';\n\n/**\n * The `LoadingIndicator` component displays a loading spinner with spin.js.\n *\n * ### Attrs\n *\n * - `size` The spin.js size preset to use. Defaults to 'small'.\n *\n * All other attrs will be assigned as attributes on the DOM element.\n */\nexport default class LoadingIndicator extends Component {\n view() {\n const attrs = Object.assign({}, this.attrs);\n\n attrs.className = 'LoadingIndicator ' + (attrs.className || '');\n delete attrs.size;\n\n return <div {...attrs}>{m.trust(' ')}</div>;\n }\n\n oncreate(vnode) {\n super.oncreate(vnode);\n\n const options = { zIndex: 'auto', color: this.$().css('color') };\n\n switch (this.attrs.size) {\n case 'large':\n Object.assign(options, { lines: 10, length: 8, width: 4, radius: 8 });\n break;\n\n case 'tiny':\n Object.assign(options, { lines: 8, length: 2, width: 2, radius: 3 });\n break;\n\n default:\n Object.assign(options, { lines: 8, length: 4, width: 3, radius: 5 });\n }\n\n new Spinner(options).spin(this.element);\n }\n}\n","import Component from '../Component';\nimport Alert from './Alert';\nimport Button from './Button';\n\n/**\n * The `Modal` component displays a modal dialog, wrapped in a form. Subclasses\n * should implement the `className`, `title`, and `content` methods.\n *\n * @abstract\n */\nexport default class Modal extends Component {\n /**\n * Determine whether or not the modal should be dismissible via an 'x' button.\n */\n static isDismissible = true;\n\n /**\n * Attributes for an alert component to show below the header.\n *\n * @type {object}\n */\n alertAttrs = null;\n\n oncreate(vnode) {\n super.oncreate(vnode);\n\n this.attrs.animateShow(() => this.onready());\n }\n\n onbeforeremove() {\n // If the global modal state currently contains a modal,\n // we've just opened up a new one, and accordingly,\n // we don't need to show a hide animation.\n if (!this.attrs.state.modal) {\n this.attrs.animateHide();\n // Here, we ensure that the animation has time to complete.\n // See https://mithril.js.org/lifecycle-methods.html#onbeforeremove\n // Bootstrap's Modal.TRANSITION_DURATION is 300 ms.\n return new Promise((resolve) => setTimeout(resolve, 300));\n }\n }\n\n view() {\n if (this.alertAttrs) {\n this.alertAttrs.dismissible = false;\n }\n\n return (\n <div className={'Modal modal-dialog ' + this.className()}>\n <div className=\"Modal-content\">\n {this.constructor.isDismissible ? (\n <div className=\"Modal-close App-backControl\">\n {Button.component({\n icon: 'fas fa-times',\n onclick: this.hide.bind(this),\n className: 'Button Button--icon Button--link',\n })}\n </div>\n ) : (\n ''\n )}\n\n <form onsubmit={this.onsubmit.bind(this)}>\n <div className=\"Modal-header\">\n <h3 className=\"App-titleControl App-titleControl--text\">{this.title()}</h3>\n </div>\n\n {this.alertAttrs ? <div className=\"Modal-alert\">{Alert.component(this.alertAttrs)}</div> : ''}\n\n {this.content()}\n </form>\n </div>\n </div>\n );\n }\n\n /**\n * Get the class name to apply to the modal.\n *\n * @return {String}\n * @abstract\n */\n className() {}\n\n /**\n * Get the title of the modal dialog.\n *\n * @return {String}\n * @abstract\n */\n title() {}\n\n /**\n * Get the content of the modal.\n *\n * @return {VirtualElement}\n * @abstract\n */\n content() {}\n\n /**\n * Handle the modal form's submit event.\n *\n * @param {Event} e\n */\n onsubmit() {}\n\n /**\n * Focus on the first input when the modal is ready to be used.\n */\n onready() {\n this.$('form').find('input, select, textarea').first().focus().select();\n }\n\n /**\n * Hide the modal.\n */\n hide() {\n this.attrs.state.close();\n }\n\n /**\n * Stop loading.\n */\n loaded() {\n this.loading = false;\n m.redraw();\n }\n\n /**\n * Show an alert describing an error returned from the API, and give focus to\n * the first relevant field.\n *\n * @param {RequestError} error\n */\n onerror(error) {\n this.alertAttrs = error.alert;\n\n m.redraw();\n\n if (error.status === 422 && error.response.errors) {\n this.$('form [name=' + error.response.errors[0].source.pointer.replace('/data/attributes/', '') + ']').select();\n } else {\n this.onready();\n }\n }\n}\n","import Component from '../Component';\n\n/**\n * The `ModalManager` component manages a modal dialog. Only one modal dialog\n * can be shown at once; loading a new component into the ModalManager will\n * overwrite the previous one.\n */\nexport default class ModalManager extends Component {\n view() {\n const modal = this.attrs.state.modal;\n\n return (\n <div className=\"ModalManager modal fade\">\n {modal\n ? modal.componentClass.component({\n ...modal.attrs,\n animateShow: this.animateShow.bind(this),\n animateHide: this.animateHide.bind(this),\n state: this.attrs.state,\n })\n : ''}\n </div>\n );\n }\n\n oncreate(vnode) {\n super.oncreate(vnode);\n\n // Ensure the modal state is notified about a closed modal, even when the\n // DOM-based Bootstrap JavaScript code triggered the closing of the modal,\n // e.g. via ESC key or a click on the modal backdrop.\n this.$().on('hidden.bs.modal', this.attrs.state.close.bind(this.attrs.state));\n }\n\n animateShow(readyCallback) {\n const dismissible = !!this.attrs.state.modal.componentClass.isDismissible;\n\n // If we are opening this modal while another modal is already open,\n // the shown event will not run, because the modal is already open.\n // So, we need to manually trigger the readyCallback.\n if (this.$().hasClass('in')) {\n readyCallback();\n return;\n }\n\n this.$()\n .one('shown.bs.modal', readyCallback)\n .modal({\n backdrop: dismissible || 'static',\n keyboard: dismissible,\n })\n .modal('show');\n }\n\n animateHide() {\n this.$().modal('hide');\n }\n}\n","import Component from '../Component';\nimport Button from './Button';\nimport LinkButton from './LinkButton';\n\n/**\n * The `Navigation` component displays a set of navigation buttons. Typically\n * this is just a back button which pops the app's History. If the user is on\n * the root page and there is no history to pop, then in some instances it may\n * show a button that toggles the app's drawer.\n *\n * If the app has a pane, it will also include a 'pin' button which toggles the\n * pinned state of the pane.\n *\n * Accepts the following attrs:\n *\n * - `className` The name of a class to set on the root element.\n * - `drawer` Whether or not to show a button to toggle the app's drawer if\n * there is no more history to pop.\n */\nexport default class Navigation extends Component {\n view() {\n const { history, pane } = app;\n\n return (\n <div\n className={'Navigation ButtonGroup ' + (this.attrs.className || '')}\n onmouseenter={pane && pane.show.bind(pane)}\n onmouseleave={pane && pane.onmouseleave.bind(pane)}\n >\n {history.canGoBack() ? [this.getBackButton(), this.getPaneButton()] : this.getDrawerButton()}\n </div>\n );\n }\n\n /**\n * Get the back button.\n *\n * @return {Object}\n * @protected\n */\n getBackButton() {\n const { history } = app;\n const previous = history.getPrevious() || {};\n\n return LinkButton.component({\n className: 'Button Navigation-back Button--icon',\n href: history.backUrl(),\n icon: 'fas fa-chevron-left',\n title: previous.title,\n onclick: (e) => {\n if (e.shiftKey || e.ctrlKey || e.metaKey || e.which === 2) return;\n e.preventDefault();\n history.back();\n },\n });\n }\n\n /**\n * Get the pane pinned toggle button.\n *\n * @return {Object|String}\n * @protected\n */\n getPaneButton() {\n const { pane } = app;\n\n if (!pane || !pane.active) return '';\n\n return Button.component({\n className: 'Button Button--icon Navigation-pin' + (pane.pinned ? ' active' : ''),\n onclick: pane.togglePinned.bind(pane),\n icon: 'fas fa-thumbtack',\n });\n }\n\n /**\n * Get the drawer toggle button.\n *\n * @return {Object|String}\n * @protected\n */\n getDrawerButton() {\n if (!this.attrs.drawer) return '';\n\n const { drawer } = app;\n const user = app.session.user;\n\n return Button.component({\n className: 'Button Button--icon Navigation-drawer' + (user && user.newNotificationCount() ? ' new' : ''),\n onclick: (e) => {\n e.stopPropagation();\n drawer.show();\n },\n icon: 'fas fa-bars',\n });\n }\n}\n","import Component from '../Component';\nimport PageState from '../states/PageState';\n\n/**\n * The `Page` component\n *\n * @abstract\n */\nexport default class Page extends Component {\n oninit(vnode) {\n super.oninit(vnode);\n\n app.previous = app.current;\n app.current = new PageState(this.constructor, { routeName: this.attrs.routeName });\n\n app.drawer.hide();\n app.modal.close();\n\n /**\n * A class name to apply to the body while the route is active.\n *\n * @type {String}\n */\n this.bodyClass = '';\n\n /**\n * Whether we should scroll to the top of the page when its rendered.\n *\n * @type {Boolean}\n */\n this.scrollTopOnCreate = true;\n\n /**\n * Whether the browser should restore scroll state on refreshes.\n *\n * @type {Boolean}\n */\n this.useBrowserScrollRestoration = true;\n }\n\n oncreate(vnode) {\n super.oncreate(vnode);\n\n if (this.bodyClass) {\n $('#app').addClass(this.bodyClass);\n }\n\n if (this.scrollTopOnCreate) {\n $(window).scrollTop(0);\n }\n\n if ('scrollRestoration' in history) {\n history.scrollRestoration = this.useBrowserScrollRestoration ? 'auto' : 'manual';\n }\n }\n\n onremove() {\n if (this.bodyClass) {\n $('#app').removeClass(this.bodyClass);\n }\n }\n}\n","import Component from '../Component';\n\n/**\n * The `Placeholder` component displays a muted text with some call to action,\n * usually used as an empty state.\n *\n * ### Attrs\n *\n * - `text`\n */\nexport default class Placeholder extends Component {\n view() {\n return (\n <div className=\"Placeholder\">\n <p>{this.attrs.text}</p>\n </div>\n );\n }\n}\n","import Modal from './Modal';\n\nexport default class RequestErrorModal extends Modal {\n className() {\n return 'RequestErrorModal Modal--large';\n }\n\n title() {\n return this.attrs.error.xhr ? `${this.attrs.error.xhr.status} ${this.attrs.error.xhr.statusText}` : '';\n }\n\n content() {\n const { error, formattedError } = this.attrs;\n\n let responseText;\n\n // If the error is already formatted, just add line endings;\n // else try to parse it as JSON and stringify it with indentation\n if (formattedError) {\n responseText = formattedError.join('\\n\\n');\n } else {\n try {\n const json = error.response || JSON.parse(error.responseText);\n\n responseText = JSON.stringify(json, null, 2);\n } catch (e) {\n responseText = error.responseText;\n }\n }\n\n return (\n <div className=\"Modal-body\">\n <pre>\n {this.attrs.error.options.method} {this.attrs.error.options.url}\n <br />\n <br />\n {responseText}\n </pre>\n </div>\n );\n }\n}\n","import Component from '../Component';\nimport icon from '../helpers/icon';\nimport withAttr from '../utils/withAttr';\n\n/**\n * The `Select` component displays a <select> input, surrounded with some extra\n * elements for styling. It accepts the following attrs:\n *\n * - `options` A map of option values to labels.\n * - `onchange` A callback to run when the selected value is changed.\n * - `value` The value of the selected option.\n * - `disabled` Disabled state for the input.\n */\nexport default class Select extends Component {\n view() {\n const { options, onchange, value, disabled } = this.attrs;\n\n return (\n <span className=\"Select\">\n <select\n className=\"Select-input FormControl\"\n onchange={onchange ? withAttr('value', onchange.bind(this)) : undefined}\n value={value}\n disabled={disabled}\n >\n {Object.keys(options).map((key) => (\n <option value={key}>{options[key]}</option>\n ))}\n </select>\n {icon('fas fa-sort', { className: 'Select-caret' })}\n </span>\n );\n }\n}\n","import Dropdown from './Dropdown';\nimport icon from '../helpers/icon';\n\n/**\n * Determines via a vnode is currently \"active\".\n * Due to changes in Mithril 2, attrs will not be instantiated until AFTER view()\n * is initially called on the parent component, so we can not always depend on the\n * active attr to determine which element should be displayed as the \"active child\".\n *\n * This is a temporary patch, and as so, is not exported / placed in utils.\n */\nfunction isActive(vnode) {\n const tag = vnode.tag;\n\n // Allow non-selectable dividers/headers to be added.\n if (typeof tag === 'string' && tag !== 'a' && tag !== 'button') return false;\n\n if ('initAttrs' in tag) {\n tag.initAttrs(vnode.attrs);\n }\n\n return 'isActive' in tag ? tag.isActive(vnode.attrs) : vnode.attrs.active;\n}\n\n/**\n * The `SelectDropdown` component is the same as a `Dropdown`, except the toggle\n * button's label is set as the label of the first child which has a truthy\n * `active` prop.\n *\n * ### Attrs\n *\n * - `caretIcon`\n * - `defaultLabel`\n */\nexport default class SelectDropdown extends Dropdown {\n static initAttrs(attrs) {\n attrs.caretIcon = typeof attrs.caretIcon !== 'undefined' ? attrs.caretIcon : 'fas fa-sort';\n\n super.initAttrs(attrs);\n\n attrs.className += ' Dropdown--select';\n }\n\n getButtonContent(children) {\n const activeChild = children.find(isActive);\n let label = (activeChild && activeChild.children) || this.attrs.defaultLabel;\n\n if (label instanceof Array) label = label[0];\n\n return [<span className=\"Button-label\">{label}</span>, icon(this.attrs.caretIcon, { className: 'Button-caret' })];\n }\n}\n","import Component from '../Component';\n\n/**\n * The `Separator` component defines a menu separator item.\n */\nclass Separator extends Component {\n view() {\n return <li className=\"Dropdown-separator\" />;\n }\n}\n\nSeparator.isListItem = true;\n\nexport default Separator;\n","import Dropdown from './Dropdown';\nimport Button from './Button';\nimport icon from '../helpers/icon';\n\n/**\n * The `SplitDropdown` component is similar to `Dropdown`, but the first child\n * is displayed as its own button prior to the toggle button.\n */\nexport default class SplitDropdown extends Dropdown {\n static initAttrs(attrs) {\n super.initAttrs(attrs);\n\n attrs.className += ' Dropdown--split';\n attrs.menuClassName += ' Dropdown-menu--right';\n }\n\n getButton(children) {\n // Make a copy of the attrs of the first child component. We will assign\n // these attrs to a new button, so that it has exactly the same behaviour as\n // the first child.\n const firstChild = this.getFirstChild(children);\n const buttonAttrs = Object.assign({}, firstChild.attrs);\n buttonAttrs.className = (buttonAttrs.className || '') + ' SplitDropdown-button Button ' + this.attrs.buttonClassName;\n\n return [\n Button.component(buttonAttrs, firstChild.children),\n <button\n className={'Dropdown-toggle Button Button--icon ' + this.attrs.buttonClassName}\n aria-haspopup=\"menu\"\n aria-label={this.attrs.accessibleToggleLabel}\n data-toggle=\"dropdown\"\n >\n {icon(this.attrs.icon, { className: 'Button-icon' })}\n {icon('fas fa-caret-down', { className: 'Button-caret' })}\n </button>,\n ];\n }\n\n /**\n * Get the first child. If the first child is an array, the first item in that\n * array will be returned.\n *\n * @return {*}\n * @protected\n */\n getFirstChild(children) {\n let firstChild = children;\n\n while (firstChild instanceof Array) firstChild = firstChild[0];\n\n return firstChild;\n }\n}\n","import Checkbox from './Checkbox';\n\n/**\n * The `Switch` component is a `Checkbox`, but with a switch display instead of\n * a tick/cross one.\n */\nexport default class Switch extends Checkbox {\n static initAttrs(attrs) {\n super.initAttrs(attrs);\n\n attrs.className = (attrs.className || '') + ' Checkbox--switch';\n }\n\n getDisplay() {\n return this.attrs.loading ? super.getDisplay() : '';\n }\n}\n","/**\n * Extend an object's method by running its output through a mutating callback\n * every time it is called.\n *\n * The callback accepts the method's return value and should perform any\n * mutations directly on this value. For this reason, this function will not be\n * effective on methods which return scalar values (numbers, strings, booleans).\n *\n * Care should be taken to extend the correct object – in most cases, a class'\n * prototype will be the desired target of extension, not the class itself.\n *\n * @example\n * extend(Discussion.prototype, 'badges', function(badges) {\n * // do something with `badges`\n * });\n *\n * @param {Object} object The object that owns the method\n * @param {String} method The name of the method to extend\n * @param {function} callback A callback which mutates the method's output\n */\nexport function extend(object, method, callback) {\n const original = object[method];\n\n object[method] = function (...args) {\n const value = original ? original.apply(this, args) : undefined;\n\n callback.apply(this, [value].concat(args));\n\n return value;\n };\n\n Object.assign(object[method], original);\n}\n\n/**\n * Override an object's method by replacing it with a new function, so that the\n * new function will be run every time the object's method is called.\n *\n * The replacement function accepts the original method as its first argument,\n * which is like a call to 'super'. Any arguments passed to the original method\n * are also passed to the replacement.\n *\n * Care should be taken to extend the correct object – in most cases, a class'\n * prototype will be the desired target of extension, not the class itself.\n *\n * @example\n * override(Discussion.prototype, 'badges', function(original) {\n * const badges = original();\n * // do something with badges\n * return badges;\n * });\n *\n * @param {Object} object The object that owns the method\n * @param {String} method The name of the method to override\n * @param {function} newMethod The method to replace it with\n */\nexport function override(object, method, newMethod) {\n const original = object[method];\n\n object[method] = function (...args) {\n return newMethod.apply(this, [original.bind(this)].concat(args));\n };\n\n Object.assign(object[method], original);\n}\n","import * as Mithril from 'mithril';\nimport User from '../models/User';\n\n/**\n * The `avatar` helper displays a user's avatar.\n *\n * @param user\n * @param attrs Attributes to apply to the avatar element\n */\nexport default function avatar(user: User, attrs: Object = {}): Mithril.Vnode {\n attrs.className = 'Avatar ' + (attrs.className || '');\n let content: string = '';\n\n // If the `title` attribute is set to null or false, we don't want to give the\n // avatar a title. On the other hand, if it hasn't been given at all, we can\n // safely default it to the user's username.\n const hasTitle: boolean | string = attrs.title === 'undefined' || attrs.title;\n if (!hasTitle) delete attrs.title;\n\n // If a user has been passed, then we will set up an avatar using their\n // uploaded image, or the first letter of their username if they haven't\n // uploaded one.\n if (user) {\n const username: string = user.displayName() || '?';\n const avatarUrl: string = user.avatarUrl();\n\n if (hasTitle) attrs.title = attrs.title || username;\n\n if (avatarUrl) {\n return <img {...attrs} src={avatarUrl} alt=\"\" />;\n }\n\n content = username.charAt(0).toUpperCase();\n attrs.style = { background: user.color() };\n }\n\n return <span {...attrs}>{content}</span>;\n}\n","import dayjs from 'dayjs';\nimport * as Mithril from 'mithril';\n\n/**\n * The `fullTime` helper displays a formatted time string wrapped in a <time>\n * tag.\n */\nexport default function fullTime(time: Date): Mithril.Vnode {\n const d = dayjs(time);\n\n const datetime = d.format();\n const full = d.format('LLLL');\n\n return (\n <time pubdate datetime={datetime}>\n {full}\n </time>\n );\n}\n","import * as Mithril from 'mithril';\nimport { truncate } from '../utils/string';\n\n/**\n * The `highlight` helper searches for a word phrase in a string, and wraps\n * matches with the <mark> tag.\n *\n * @param string The string to highlight.\n * @param phrase The word or words to highlight.\n * @param [length] The number of characters to truncate the string to.\n * The string will be truncated surrounding the first match.\n */\nexport default function highlight(string: string, phrase: string | RegExp, length?: number): Mithril.Vnode<any, any> | string {\n if (!phrase && !length) return string;\n\n // Convert the word phrase into a global regular expression (if it isn't\n // already) so we can search the string for matched.\n const regexp = phrase instanceof RegExp ? phrase : new RegExp(phrase, 'gi');\n\n let highlighted = string;\n let start = 0;\n\n // If a length was given, the truncate the string surrounding the first match.\n if (length) {\n if (phrase) start = Math.max(0, string.search(regexp) - length / 2);\n\n highlighted = truncate(highlighted, length, start);\n }\n\n // Convert the string into HTML entities, then highlight all matches with\n // <mark> tags. Then we will return the result as a trusted HTML string.\n highlighted = $('<div/>').text(highlighted).html();\n\n if (phrase) highlighted = highlighted.replace(regexp, '<mark>$&</mark>');\n\n return m.trust(highlighted);\n}\n","import dayjs from 'dayjs';\nimport * as Mithril from 'mithril';\nimport humanTimeUtil from '../utils/humanTime';\n\n/**\n * The `humanTime` helper displays a time in a human-friendly time-ago format\n * (e.g. '12 days ago'), wrapped in a <time> tag with other information about\n * the time.\n */\nexport default function humanTime(time: Date): Mithril.Vnode {\n const d = dayjs(time);\n\n const datetime = d.format();\n const full = d.format('LLLL');\n const ago = humanTimeUtil(time);\n\n return (\n <time pubdate datetime={datetime} title={full} data-humantime>\n {ago}\n </time>\n );\n}\n","import * as Mithril from 'mithril';\n\n/**\n * The `icon` helper displays an icon.\n *\n * @param fontClass The full icon class, prefix and the icon’s name.\n * @param attrs Any other attributes to apply.\n */\nexport default function icon(fontClass: string, attrs: Mithril.Attributes = {}): Mithril.Vnode {\n attrs.className = 'icon ' + fontClass + ' ' + (attrs.className || '');\n\n return <i {...attrs} />;\n}\n","import * as Mithril from 'mithril';\nimport Separator from '../components/Separator';\nimport classList from '../utils/classList';\n\nfunction isSeparator(item): boolean {\n return item.tag === Separator;\n}\n\nfunction withoutUnnecessarySeparators(items: Array<Mithril.Vnode>): Array<Mithril.Vnode> {\n const newItems = [];\n let prevItem;\n\n items.filter(Boolean).forEach((item: Mithril.Vnode, i: number) => {\n if (!isSeparator(item) || (prevItem && !isSeparator(prevItem) && i !== items.length - 1)) {\n prevItem = item;\n newItems.push(item);\n }\n });\n\n return newItems;\n}\n\n/**\n * The `listItems` helper wraps a collection of components in <li> tags,\n * stripping out any unnecessary `Separator` components.\n */\nexport default function listItems(items: Mithril.Vnode | Array<Mithril.Vnode>): Array<Mithril.Vnode> {\n if (!(items instanceof Array)) items = [items];\n\n return withoutUnnecessarySeparators(items).map((item: Mithril.Vnode) => {\n const isListItem = item.tag && item.tag.isListItem;\n const active = item.tag && item.tag.isActive && item.tag.isActive(item.attrs);\n const className = (item.attrs && item.attrs.itemClassName) || item.itemClassName;\n\n if (isListItem) {\n item.attrs = item.attrs || {};\n item.attrs.key = item.attrs.key || item.itemName;\n item.key = item.attrs.key;\n }\n\n const node: Mithril.Vnode = isListItem ? (\n item\n ) : (\n <li\n className={classList([className, item.itemName && `item-${item.itemName}`, active && 'active'])}\n key={(item.attrs && item.attrs.key) || item.itemName}\n >\n {item}\n </li>\n );\n\n return node;\n });\n}\n","/**\n * The `punctuateSeries` helper formats a list of strings (e.g. names) to read\n * fluently in the application's locale.\n *\n * ```js\n * punctuateSeries(['Toby', 'Franz', 'Dominion']) // Toby, Franz, and Dominion\n * ```\n *\n * @param {Array} items\n * @return {VirtualElement}\n */\nexport default function punctuateSeries(items) {\n if (items.length === 2) {\n return app.translator.trans('core.lib.series.two_text', {\n first: items[0],\n second: items[1],\n });\n } else if (items.length >= 3) {\n // If there are three or more items, we will join all but the first and\n // last items with the equivalent of a comma, and then we will feed that\n // into the translator along with the first and last item.\n const second = items\n .slice(1, items.length - 1)\n .reduce((list, item) => list.concat([item, app.translator.trans('core.lib.series.glue_text')]), [])\n .slice(0, -1);\n\n return app.translator.trans('core.lib.series.three_text', {\n first: items[0],\n second,\n third: items[items.length - 1],\n });\n }\n\n return items;\n}\n","import * as Mithril from 'mithril';\nimport User from '../models/User';\nimport icon from './icon';\n\n/**\n * The `useronline` helper displays a green circle if the user is online\n */\nexport default function userOnline(user: User): Mithril.Vnode {\n if (user.lastSeenAt() && user.isOnline()) {\n return <span className=\"UserOnline\">{icon('fas fa-circle')}</span>;\n }\n}\n","import * as Mithril from 'mithril';\nimport User from '../models/User';\n\n/**\n * The `username` helper displays a user's username in a <span class=\"username\">\n * tag. If the user doesn't exist, the username will be displayed as [deleted].\n */\nexport default function username(user: User): Mithril.Vnode {\n const name = (user && user.displayName()) || app.translator.trans('core.lib.username.deleted_text');\n\n return <span className=\"username\">{name}</span>;\n}\n","export default class Model {\n type;\n attributes = [];\n hasOnes = [];\n hasManys = [];\n\n constructor(type, model = null) {\n this.type = type;\n this.model = model;\n }\n\n attribute(name) {\n this.attributes.push(name);\n\n return this;\n }\n\n hasOne(type) {\n this.hasOnes.push(type);\n\n return this;\n }\n\n hasMany(type) {\n this.hasManys.push(type);\n\n return this;\n }\n\n extend(app, extension) {\n if (this.model) {\n app.store.models[this.type] = this.model;\n }\n\n const model = app.store.models[this.type];\n\n this.attributes.forEach((name) => (model.prototype[name] = model.attribute(name)));\n this.hasOnes.forEach((name) => (model.prototype[name] = model.hasOne(name)));\n this.hasManys.forEach((name) => (model.prototype[name] = model.hasMany(name)));\n }\n}\n","export default class PostTypes {\n postComponents = {};\n\n add(name, component) {\n this.postComponents[name] = component;\n\n return this;\n }\n\n extend(app, extension) {\n Object.assign(app.postComponents, this.postComponents);\n }\n}\n","export default class Routes {\n routes = {};\n\n add(name, path, component) {\n this.routes[name] = { path, component };\n\n return this;\n }\n\n extend(app, extension) {\n Object.assign(app.routes, this.routes);\n }\n}\n","// Expose jQuery, mithril and dayjs to the window browser object\nimport 'expose-loader?exposes[]=$&exposes[]=jQuery!jquery';\nimport 'expose-loader?exposes=m!mithril';\nimport 'expose-loader?exposes=dayjs!dayjs';\n\nimport 'bootstrap/js/affix';\nimport 'bootstrap/js/dropdown';\nimport 'bootstrap/js/modal';\nimport 'bootstrap/js/tooltip';\nimport 'bootstrap/js/transition';\nimport 'jquery.hotkeys/jquery.hotkeys';\n\nimport relativeTime from 'dayjs/plugin/relativeTime';\nimport localizedFormat from 'dayjs/plugin/localizedFormat';\n\ndayjs.extend(relativeTime);\ndayjs.extend(localizedFormat);\n\nimport patchMithril from './utils/patchMithril';\n\npatchMithril(window);\n\nimport * as Extend from './extend/index';\n\nexport { Extend };\n","import Model from '../Model';\nimport computed from '../utils/computed';\nimport ItemList from '../utils/ItemList';\nimport Badge from '../components/Badge';\n\nexport default class Discussion extends Model {}\n\nObject.assign(Discussion.prototype, {\n title: Model.attribute('title'),\n slug: Model.attribute('slug'),\n\n createdAt: Model.attribute('createdAt', Model.transformDate),\n user: Model.hasOne('user'),\n firstPost: Model.hasOne('firstPost'),\n\n lastPostedAt: Model.attribute('lastPostedAt', Model.transformDate),\n lastPostedUser: Model.hasOne('lastPostedUser'),\n lastPost: Model.hasOne('lastPost'),\n lastPostNumber: Model.attribute('lastPostNumber'),\n\n commentCount: Model.attribute('commentCount'),\n replyCount: computed('commentCount', (commentCount) => Math.max(0, commentCount - 1)),\n posts: Model.hasMany('posts'),\n mostRelevantPost: Model.hasOne('mostRelevantPost'),\n\n lastReadAt: Model.attribute('lastReadAt', Model.transformDate),\n lastReadPostNumber: Model.attribute('lastReadPostNumber'),\n isUnread: computed('unreadCount', (unreadCount) => !!unreadCount),\n isRead: computed('unreadCount', (unreadCount) => app.session.user && !unreadCount),\n\n hiddenAt: Model.attribute('hiddenAt', Model.transformDate),\n hiddenUser: Model.hasOne('hiddenUser'),\n isHidden: computed('hiddenAt', (hiddenAt) => !!hiddenAt),\n\n canReply: Model.attribute('canReply'),\n canRename: Model.attribute('canRename'),\n canHide: Model.attribute('canHide'),\n canDelete: Model.attribute('canDelete'),\n\n /**\n * Remove a post from the discussion's posts relationship.\n *\n * @param {Integer} id The ID of the post to remove.\n * @public\n */\n removePost(id) {\n const relationships = this.data.relationships;\n const posts = relationships && relationships.posts;\n\n if (posts) {\n posts.data.some((data, i) => {\n if (id === data.id) {\n posts.data.splice(i, 1);\n return true;\n }\n });\n }\n },\n\n /**\n * Get the estimated number of unread posts in this discussion for the current\n * user.\n *\n * @return {Integer}\n * @public\n */\n unreadCount() {\n const user = app.session.user;\n\n if (user && user.markedAllAsReadAt() < this.lastPostedAt()) {\n const unreadCount = Math.max(0, this.lastPostNumber() - (this.lastReadPostNumber() || 0));\n // If posts have been deleted, it's possible that the unread count could exceed the\n // actual post count. As such, we take the min of the two to ensure this isn't an issue.\n return Math.min(unreadCount, this.commentCount());\n }\n\n return 0;\n },\n\n /**\n * Get the Badge components that apply to this discussion.\n *\n * @return {ItemList}\n * @public\n */\n badges() {\n const items = new ItemList();\n\n if (this.isHidden()) {\n items.add('hidden', <Badge type=\"hidden\" icon=\"fas fa-trash\" label={app.translator.trans('core.lib.badge.hidden_tooltip')} />);\n }\n\n return items;\n },\n\n /**\n * Get a list of all of the post IDs in this discussion.\n *\n * @return {Array}\n * @public\n */\n postIds() {\n const posts = this.data.relationships.posts;\n\n return posts ? posts.data.map((link) => link.id) : [];\n },\n});\n","import Model from '../Model';\n\nexport default class Forum extends Model {\n apiEndpoint() {\n return '/';\n }\n}\n","import Model from '../Model';\n\nclass Group extends Model {}\n\nObject.assign(Group.prototype, {\n nameSingular: Model.attribute('nameSingular'),\n namePlural: Model.attribute('namePlural'),\n color: Model.attribute('color'),\n icon: Model.attribute('icon'),\n isHidden: Model.attribute('isHidden'),\n});\n\nGroup.ADMINISTRATOR_ID = '1';\nGroup.GUEST_ID = '2';\nGroup.MEMBER_ID = '3';\n\nexport default Group;\n","import Model from '../Model';\n\nexport default class Notification extends Model {}\n\nObject.assign(Notification.prototype, {\n contentType: Model.attribute('contentType'),\n content: Model.attribute('content'),\n createdAt: Model.attribute('createdAt', Model.transformDate),\n\n isRead: Model.attribute('isRead'),\n\n user: Model.hasOne('user'),\n fromUser: Model.hasOne('fromUser'),\n subject: Model.hasOne('subject'),\n});\n","import Model from '../Model';\nimport computed from '../utils/computed';\nimport { getPlainContent } from '../utils/string';\n\nexport default class Post extends Model {}\n\nObject.assign(Post.prototype, {\n number: Model.attribute('number'),\n discussion: Model.hasOne('discussion'),\n\n createdAt: Model.attribute('createdAt', Model.transformDate),\n user: Model.hasOne('user'),\n contentType: Model.attribute('contentType'),\n content: Model.attribute('content'),\n contentHtml: Model.attribute('contentHtml'),\n contentPlain: computed('contentHtml', getPlainContent),\n\n editedAt: Model.attribute('editedAt', Model.transformDate),\n editedUser: Model.hasOne('editedUser'),\n isEdited: computed('editedAt', (editedAt) => !!editedAt),\n\n hiddenAt: Model.attribute('hiddenAt', Model.transformDate),\n hiddenUser: Model.hasOne('hiddenUser'),\n isHidden: computed('hiddenAt', (hiddenAt) => !!hiddenAt),\n\n canEdit: Model.attribute('canEdit'),\n canHide: Model.attribute('canHide'),\n canDelete: Model.attribute('canDelete'),\n});\n","/*global ColorThief*/\n\nimport Model from '../Model';\nimport stringToColor from '../utils/stringToColor';\nimport ItemList from '../utils/ItemList';\nimport computed from '../utils/computed';\nimport GroupBadge from '../components/GroupBadge';\n\nexport default class User extends Model {}\n\nObject.assign(User.prototype, {\n username: Model.attribute('username'),\n slug: Model.attribute('slug'),\n displayName: Model.attribute('displayName'),\n email: Model.attribute('email'),\n isEmailConfirmed: Model.attribute('isEmailConfirmed'),\n password: Model.attribute('password'),\n\n avatarUrl: Model.attribute('avatarUrl'),\n preferences: Model.attribute('preferences'),\n groups: Model.hasMany('groups'),\n\n joinTime: Model.attribute('joinTime', Model.transformDate),\n lastSeenAt: Model.attribute('lastSeenAt', Model.transformDate),\n markedAllAsReadAt: Model.attribute('markedAllAsReadAt', Model.transformDate),\n unreadNotificationCount: Model.attribute('unreadNotificationCount'),\n newNotificationCount: Model.attribute('newNotificationCount'),\n\n discussionCount: Model.attribute('discussionCount'),\n commentCount: Model.attribute('commentCount'),\n\n canEdit: Model.attribute('canEdit'),\n canEditCredentials: Model.attribute('canEditCredentials'),\n canEditGroups: Model.attribute('canEditGroups'),\n canDelete: Model.attribute('canDelete'),\n\n avatarColor: null,\n color: computed('username', 'avatarUrl', 'avatarColor', function (username, avatarUrl, avatarColor) {\n // If we've already calculated and cached the dominant color of the user's\n // avatar, then we can return that in RGB format. If we haven't, we'll want\n // to calculate it. Unless the user doesn't have an avatar, in which case\n // we generate a color from their username.\n if (avatarColor) {\n return 'rgb(' + avatarColor.join(', ') + ')';\n } else if (avatarUrl) {\n this.calculateAvatarColor();\n return '';\n }\n\n return '#' + stringToColor(username);\n }),\n\n /**\n * Check whether or not the user has been seen in the last 5 minutes.\n *\n * @return {Boolean}\n * @public\n */\n isOnline() {\n return dayjs().subtract(5, 'minutes').isBefore(this.lastSeenAt());\n },\n\n /**\n * Get the Badge components that apply to this user.\n *\n * @return {ItemList}\n */\n badges() {\n const items = new ItemList();\n const groups = this.groups();\n\n if (groups) {\n groups.forEach((group) => {\n items.add('group' + group.id(), GroupBadge.component({ group }));\n });\n }\n\n return items;\n },\n\n /**\n * Calculate the dominant color of the user's avatar. The dominant color will\n * be set to the `avatarColor` property once it has been calculated.\n *\n * @protected\n */\n calculateAvatarColor() {\n const image = new Image();\n const user = this;\n\n image.onload = function () {\n const colorThief = new ColorThief();\n user.avatarColor = colorThief.getColor(this);\n user.freshness = new Date();\n m.redraw();\n };\n image.crossOrigin = 'anonymous';\n image.src = this.avatarUrl();\n },\n\n /**\n * Update the user's preferences.\n *\n * @param {Object} newPreferences\n * @return {Promise}\n */\n savePreferences(newPreferences) {\n const preferences = this.preferences();\n\n Object.assign(preferences, newPreferences);\n\n return this.save({ preferences });\n },\n});\n","import Component from '../Component';\n\n/**\n * Generates a route resolver for a given component.\n * In addition to regular route resolver functionality:\n * - It provide the current route name as an attr\n * - It sets a key on the component so a rerender will be triggered on route change.\n */\nexport default class DefaultResolver {\n component: Component | Function;\n routeName: string;\n\n constructor(component, routeName) {\n this.component = component;\n this.routeName = routeName;\n }\n\n /**\n * When a route change results in a changed key, a full page\n * rerender occurs. This method can be overriden in subclasses\n * to prevent rerenders on some route changes.\n */\n makeKey() {\n return this.routeName + JSON.stringify(m.route.param());\n }\n\n makeAttrs(vnode) {\n return {\n ...vnode.attrs,\n routeName: this.routeName,\n };\n }\n\n async onmatch(args, requestedPath, route) {\n if (typeof this.component.component === 'function') {\n return this.component;\n } else {\n const component = await this.component();\n return component.default;\n }\n }\n\n render(vnode) {\n return [{ ...vnode, attrs: this.makeAttrs(vnode), key: this.makeKey() }];\n }\n}\n","import subclassOf from '../../common/utils/subclassOf';\n\nexport default class PageState {\n constructor(type, data = {}) {\n this.type = type;\n this.data = data;\n }\n\n /**\n * Determine whether the page matches the given class and data.\n *\n * @param {object} type The page class to check against. Subclasses are\n * accepted as well.\n * @param {object} data\n * @return {boolean}\n */\n matches(type, data = {}) {\n // Fail early when the page is of a different type\n if (!subclassOf(this.type, type)) return false;\n\n // Now that the type is known to be correct, we loop through the provided\n // data to see whether it matches the data in our state.\n return Object.keys(data).every((key) => this.data[key] === data[key]);\n }\n\n get(key) {\n return this.data[key];\n }\n\n set(key, value) {\n this.data[key] = value;\n }\n}\n","import getCaretCoordinates from 'textarea-caret';\nimport EditorDriverInterface, { EditorDriverParams } from './EditorDriverInterface';\n\nexport default class BasicEditorDriver implements EditorDriverInterface {\n el: HTMLTextAreaElement;\n\n constructor(dom: HTMLElement, params: EditorDriverParams) {\n this.el = document.createElement('textarea');\n\n this.build(dom, params);\n }\n\n build(dom: HTMLElement, params: EditorDriverParams) {\n this.el.className = params.classNames.join(' ');\n this.el.disabled = params.disabled;\n this.el.placeholder = params.placeholder;\n this.el.value = params.value;\n\n const callInputListeners = (e) => {\n params.inputListeners.forEach((listener) => {\n listener();\n });\n\n e.redraw = false;\n };\n\n this.el.oninput = (e) => {\n params.oninput(this.el.value);\n callInputListeners(e);\n };\n\n this.el.onclick = callInputListeners;\n this.el.onkeyup = callInputListeners;\n\n this.el.addEventListener('keydown', function (e) {\n if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n params.onsubmit();\n }\n });\n\n dom.append(this.el);\n }\n\n protected setValue(value: string) {\n $(this.el).val(value).trigger('input');\n\n this.el.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }));\n }\n\n moveCursorTo(position: number) {\n this.setSelectionRange(position, position);\n }\n\n getSelectionRange(): Array<number> {\n return [this.el.selectionStart, this.el.selectionEnd];\n }\n\n getLastNChars(n: number): string {\n const value = this.el.value;\n\n return value.slice(Math.max(0, this.el.selectionStart - n), this.el.selectionStart);\n }\n\n insertAtCursor(text: string) {\n this.insertAt(this.el.selectionStart, text);\n }\n\n insertAt(pos: number, text: string) {\n this.insertBetween(pos, pos, text);\n }\n\n insertBetween(start: number, end: number, text: string) {\n const value = this.el.value;\n\n const before = value.slice(0, start);\n const after = value.slice(end);\n\n this.setValue(`${before}${text}${after}`);\n\n // Move the textarea cursor to the end of the content we just inserted.\n this.moveCursorTo(start + text.length);\n }\n\n replaceBeforeCursor(start: number, text: string) {\n this.insertBetween(start, this.el.selectionStart, text);\n }\n\n protected setSelectionRange(start: number, end: number) {\n this.el.setSelectionRange(start, end);\n this.focus();\n }\n\n getCaretCoordinates(position: number) {\n const relCoords = getCaretCoordinates(this.el, position);\n\n return {\n top: relCoords.top - this.el.scrollTop,\n left: relCoords.left,\n };\n }\n\n // DOM Interactions\n\n /**\n * Set the disabled status of the editor.\n */\n disabled(disabled: boolean) {\n this.el.disabled = disabled;\n }\n\n /**\n * Focus on the editor.\n */\n focus() {\n this.el.focus();\n }\n\n /**\n * Destroy the editor\n */\n destroy() {\n this.el.remove();\n }\n}\n","/**\n * The `Drawer` class controls the page's drawer. The drawer is the area the\n * slides out from the left on mobile devices; it contains the header and the\n * footer.\n */\nexport default class Drawer {\n constructor() {\n // Set up an event handler so that whenever the content area is tapped,\n // the drawer will close.\n $('#content').click((e) => {\n if (this.isOpen()) {\n e.preventDefault();\n this.hide();\n }\n });\n }\n\n /**\n * Check whether or not the drawer is currently open.\n *\n * @return {Boolean}\n * @public\n */\n isOpen() {\n return $('#app').hasClass('drawerOpen');\n }\n\n /**\n * Hide the drawer.\n *\n * @public\n */\n hide() {\n /**\n * As part of hiding the drawer, this function also ensures that the drawer\n * correctly animates out, while ensuring it is not part of the navigation\n * tree while off-screen.\n *\n * More info: https://github.com/flarum/core/pull/2666#discussion_r595381014\n */\n\n const $app = $('#app');\n\n if (!$app.hasClass('drawerOpen')) return;\n\n const $drawer = $('#drawer');\n\n // Used to prevent `visibility: hidden` from breaking the exit animation\n $drawer.css('visibility', 'visible').one('transitionend', () => $drawer.css('visibility', ''));\n\n $app.removeClass('drawerOpen');\n\n if (this.$backdrop) this.$backdrop.remove();\n }\n\n /**\n * Show the drawer.\n *\n * @public\n */\n show() {\n $('#app').addClass('drawerOpen');\n\n this.$backdrop = $('<div/>')\n .addClass('drawer-backdrop fade')\n .appendTo('body')\n .click(() => this.hide());\n\n setTimeout(() => this.$backdrop.addClass('in'));\n }\n}\n","class Item {\n content: any;\n priority: number;\n key?: number;\n\n constructor(content: any, priority?: number) {\n this.content = content;\n this.priority = priority;\n }\n}\n\n/**\n * The `ItemList` class collects items and then arranges them into an array\n * by priority.\n */\nexport default class ItemList {\n /**\n * The items in the list\n */\n items: { [key: string]: Item } = {};\n\n /**\n * Check whether the list is empty.\n */\n isEmpty(): boolean {\n for (const i in this.items) {\n if (this.items.hasOwnProperty(i)) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Check whether an item is present in the list.\n */\n has(key: string): boolean {\n return !!this.items[key];\n }\n\n /**\n * Get the content of an item.\n */\n get(key: string): any {\n return this.items[key].content;\n }\n\n /**\n * Add an item to the list.\n *\n * @param key A unique key for the item.\n * @param content The item's content.\n * @param [priority] The priority of the item. Items with a higher\n * priority will be positioned before items with a lower priority.\n */\n add(key: string, content: any, priority: number = 0): this {\n this.items[key] = new Item(content, priority);\n\n return this;\n }\n\n /**\n * Replace an item in the list, only if it is already present.\n */\n replace(key: string, content: any = null, priority: number = null): this {\n if (this.items[key]) {\n if (content !== null) {\n this.items[key].content = content;\n }\n\n if (priority !== null) {\n this.items[key].priority = priority;\n }\n }\n\n return this;\n }\n\n /**\n * Remove an item from the list.\n */\n remove(key: string): this {\n delete this.items[key];\n\n return this;\n }\n\n /**\n * Merge another list's items into this one.\n */\n merge(items: this): this {\n for (const i in items.items) {\n if (items.items.hasOwnProperty(i) && items.items[i] instanceof Item) {\n this.items[i] = items.items[i];\n }\n }\n\n return this;\n }\n\n /**\n * Convert the list into an array of item content arranged by priority. Each\n * item's content will be assigned an `itemName` property equal to the item's\n * unique key.\n */\n toArray(): any[] {\n const items: Item[] = [];\n\n for (const i in this.items) {\n if (this.items.hasOwnProperty(i) && this.items[i] instanceof Item) {\n this.items[i].content = Object(this.items[i].content);\n\n this.items[i].content.itemName = i;\n items.push(this.items[i]);\n this.items[i].key = items.length;\n }\n }\n\n return items\n .sort((a, b) => {\n if (a.priority === b.priority) {\n return a.key - b.key;\n } else if (a.priority > b.priority) {\n return -1;\n }\n return 1;\n })\n .map((item) => item.content);\n }\n}\n","export default class RequestError {\n status: string;\n options: object;\n xhr: XMLHttpRequest;\n\n responseText: string | null;\n response: object | null;\n\n alert: any;\n\n constructor(status: string, responseText: string | null, options: object, xhr: XMLHttpRequest) {\n this.status = status;\n this.responseText = responseText;\n this.options = options;\n this.xhr = xhr;\n\n try {\n this.response = JSON.parse(responseText);\n } catch (e) {\n this.response = null;\n }\n\n this.alert = null;\n }\n}\n","const later =\n window.requestAnimationFrame ||\n window.webkitRequestAnimationFrame ||\n window.mozRequestAnimationFrame ||\n window.msRequestAnimationFrame ||\n window.oRequestAnimationFrame ||\n ((callback) => window.setTimeout(callback, 1000 / 60));\n\n/**\n * The `ScrollListener` class sets up a listener that handles window scroll\n * events.\n */\nexport default class ScrollListener {\n /**\n * @param {Function} callback The callback to run when the scroll position\n * changes.\n * @public\n */\n constructor(callback) {\n this.callback = callback;\n this.ticking = false;\n }\n\n /**\n * On each animation frame, as long as the listener is active, run the\n * `update` method.\n *\n * @protected\n */\n loop() {\n // THROTTLE: If the callback is still running (or hasn't yet run), we ignore\n // further scroll events.\n if (this.ticking) return;\n\n // Schedule the callback to be executed soon (TM), and stop throttling once\n // the callback is done.\n later(() => {\n this.update();\n this.ticking = false;\n });\n\n this.ticking = true;\n }\n\n /**\n * Run the callback, whether there was a scroll event or not.\n *\n * @public\n */\n update() {\n this.callback(window.pageYOffset);\n }\n\n /**\n * Start listening to and handling the window's scroll position.\n *\n * @public\n */\n start() {\n if (!this.active) {\n window.addEventListener('scroll', (this.active = this.loop.bind(this)), { passive: true });\n }\n }\n\n /**\n * Stop listening to and handling the window's scroll position.\n *\n * @public\n */\n stop() {\n window.removeEventListener('scroll', this.active);\n\n this.active = null;\n }\n}\n","import Stream from 'mithril/stream';\n\nexport default Stream;\n","/**\n * The `SubtreeRetainer` class keeps track of a number of pieces of data,\n * comparing the values of these pieces at every iteration.\n *\n * This is useful for preventing redraws to relatively static (or huge)\n * components whose VDOM only depends on very few values, when none of them\n * have changed.\n *\n * @example\n * // Check two callbacks for changes on each update\n * this.subtree = new SubtreeRetainer(\n * () => this.attrs.post.freshness,\n * () => this.showing\n * );\n *\n * // Add more callbacks to be checked for updates\n * this.subtree.check(() => this.attrs.user.freshness);\n *\n * // In a component's onbeforeupdate() method:\n * return this.subtree.needsRebuild()\n *\n * @see https://mithril.js.org/lifecycle-methods.html#onbeforeupdate\n */\nexport default class SubtreeRetainer {\n /**\n * @param {...callbacks} callbacks Functions returning data to keep track of.\n */\n constructor(...callbacks) {\n this.callbacks = callbacks;\n this.data = {};\n // Build the initial data, so it is available when calling\n // needsRebuild from the onbeforeupdate hook.\n this.needsRebuild();\n }\n\n /**\n * Return whether any data has changed since the last check.\n * If so, Mithril needs to re-diff the vnode and its children.\n *\n * @return {boolean}\n * @public\n */\n needsRebuild() {\n let needsRebuild = false;\n\n this.callbacks.forEach((callback, i) => {\n const result = callback();\n\n if (result !== this.data[i]) {\n this.data[i] = result;\n needsRebuild = true;\n }\n });\n\n return needsRebuild;\n }\n\n /**\n * Add another callback to be checked.\n *\n * @param {...Function} callbacks\n * @public\n */\n check(...callbacks) {\n this.callbacks = this.callbacks.concat(callbacks);\n // Update the data cache when new checks are added.\n this.needsRebuild();\n }\n\n /**\n * Invalidate the subtree, forcing it to be rerendered.\n *\n * @public\n */\n invalidate() {\n this.data = {};\n }\n}\n","/**\n * The `abbreviateNumber` utility converts a number to a shorter localized form.\n *\n * @example\n * abbreviateNumber(1234);\n * // \"1.2K\"\n */\nexport default function abbreviateNumber(number: number): string {\n // TODO: translation\n if (number >= 1000000) {\n return Math.floor(number / 1000000) + app.translator.trans('core.lib.number_suffix.mega_text');\n } else if (number >= 1000) {\n return (number / 1000).toFixed(1) + app.translator.trans('core.lib.number_suffix.kilo_text');\n } else {\n return number.toString();\n }\n}\n","/**\n * The `anchorScroll` utility saves the scroll position relative to an element,\n * and then restores it after a callback has been run.\n *\n * This is useful if a redraw will change the page's content above the viewport.\n * Normally doing this will result in the content in the viewport being pushed\n * down or pulled up. By wrapping the redraw with this utility, the scroll\n * position can be anchor to an element that is in or below the viewport, so\n * the content in the viewport will stay the same.\n *\n * @param {DOMElement} element The element to anchor the scroll position to.\n * @param {Function} callback The callback to run that will change page content.\n */\nexport default function anchorScroll(element, callback) {\n const $window = $(window);\n const relativeScroll = $(element).offset().top - $window.scrollTop();\n\n callback();\n\n $window.scrollTop($(element).offset().top - relativeScroll);\n}\n","import clsx from 'clsx';\n\n/**\n * This util exposes `clsx` to core and extensions as a re-usable utility.\n *\n * For full documentation, see `clsx` on GitHub.\n *\n * @see https://github.com/lukeed/clsx\n */\nconst classList = clsx;\n\nexport default classList;\n","/**\n * The `computed` utility creates a function that will cache its output until\n * any of the dependent values are dirty.\n *\n * @param {...String} dependentKeys The keys of the dependent values.\n * @param {function} compute The function which computes the value using the\n * dependent values.\n * @return {Function}\n */\nexport default function computed(...dependentKeys) {\n const keys = dependentKeys.slice(0, -1);\n const compute = dependentKeys.slice(-1)[0];\n\n const dependentValues = {};\n let computedValue;\n\n return function () {\n let recompute = false;\n\n // Read all of the dependent values. If any of them have changed since last\n // time, then we'll want to recompute our output.\n keys.forEach((key) => {\n const value = typeof this[key] === 'function' ? this[key]() : this[key];\n\n if (dependentValues[key] !== value) {\n recompute = true;\n dependentValues[key] = value;\n }\n });\n\n if (recompute) {\n computedValue = compute.apply(\n this,\n keys.map((key) => dependentValues[key])\n );\n }\n\n return computedValue;\n };\n}\n","/**\n * The `extract` utility deletes a property from an object and returns its\n * value.\n *\n * @param object The object that owns the property\n * @param property The name of the property to extract\n * @return The value of the property\n */\nexport default function extract<T, K extends keyof T>(object: T, property: K): T[K] {\n const value = object[property];\n\n delete object[property];\n\n return value;\n}\n","/**\n * Extract the text nodes from a virtual element.\n *\n * @param {VirtualElement} vdom\n * @return {String}\n */\nexport default function extractText(vdom) {\n if (vdom instanceof Array) {\n return vdom.map((element) => extractText(element)).join('');\n } else if (typeof vdom === 'object' && vdom !== null) {\n return vdom.children ? extractText(vdom.children) : vdom.text;\n } else {\n return vdom;\n }\n}\n","/**\n * The `formatNumber` utility localizes a number into a string with the\n * appropriate punctuation.\n *\n * @example\n * formatNumber(1234);\n * // 1,234\n */\nexport default function formatNumber(number: number): string {\n return number.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',');\n}\n","import dayjs from 'dayjs';\nimport 'dayjs/plugin/relativeTime';\n\n/**\n * The `humanTime` utility converts a date to a localized, human-readable time-\n * ago string.\n */\nexport default function humanTime(time: Date): string {\n let d = dayjs(time);\n const now = dayjs();\n\n // To prevent showing things like \"in a few seconds\" due to small offsets\n // between client and server time, we always reset future dates to the\n // current time. This will result in \"just now\" being shown instead.\n if (d.isAfter(now)) {\n d = now;\n }\n\n const day = 864e5;\n const diff = d.diff(dayjs());\n let ago: string;\n\n // If this date was more than a month ago, we'll show the name of the month\n // in the string. If it wasn't this year, we'll show the year as well.\n if (diff < -30 * day) {\n if (d.year() === dayjs().year()) {\n ago = d.format('D MMM');\n } else {\n ago = d.format('ll');\n }\n } else {\n ago = '5 days';\n }\n\n return ago;\n}\n","import humanTime from './humanTime';\n\nfunction updateHumanTimes() {\n $('[data-humantime]').each(function () {\n const $this = $(this);\n const ago = humanTime($this.attr('datetime'));\n\n $this.html(ago);\n });\n}\n\n/**\n * The `liveHumanTimes` initializer sets up a loop every 1 second to update\n * timestamps rendered with the `humanTime` helper.\n */\nexport default function liveHumanTimes() {\n setInterval(updateHumanTimes, 10000);\n}\n","import DefaultResolver from '../resolvers/DefaultResolver';\n\n/**\n * The `mapRoutes` utility converts a map of named application routes into a\n * format that can be understood by Mithril, and wraps them in route resolvers\n * to provide each route with the current route name.\n *\n * @see https://mithril.js.org/route.html#signature\n * @param {Object} routes\n * @param {String} [basePath]\n * @return {Object}\n */\nexport default function mapRoutes(routes, basePath = '') {\n const map = {};\n\n for (const routeName in routes) {\n const route = routes[routeName];\n\n if ('resolver' in route) {\n map[basePath + route.path] = route.resolver;\n } else if ('component' in route) {\n const resolverClass = 'resolverClass' in route ? route.resolverClass : DefaultResolver;\n map[basePath + route.path] = new resolverClass(route.component, routeName);\n } else {\n throw new Error(`Either a resolver or a component must be provided for the route [${routeName}]`);\n }\n }\n\n return map;\n}\n","function bidi(node, prop) {\n var type = node.tag === 'select' ? (node.attrs.multi ? 'multi' : 'select') : node.attrs.type;\n\n // Setup: bind listeners\n if (type === 'multi') {\n node.attrs.onchange = function () {\n prop(\n [].slice.call(this.selectedOptions, function (x) {\n return x.value;\n })\n );\n };\n } else if (type === 'select') {\n node.attrs.onchange = function (e) {\n prop(this.selectedOptions[0].value);\n };\n } else if (type === 'checkbox') {\n node.attrs.onchange = function (e) {\n prop(this.checked);\n };\n } else {\n node.attrs.onchange = node.attrs.oninput = function (e) {\n prop(this.value);\n };\n }\n\n if (node.tag === 'select') {\n node.children.forEach(function (option) {\n if (option.attrs.value === prop() || option.children[0] === prop()) {\n option.attrs.selected = true;\n }\n });\n } else if (type === 'checkbox') {\n node.attrs.checked = prop();\n } else if (type === 'radio') {\n node.attrs.checked = prop() === node.attrs.value;\n } else {\n node.attrs.value = prop();\n }\n\n node.attrs.bidi = null;\n\n return node;\n}\n\nbidi.view = function (ctrl, node, prop) {\n return bidi(node, node.attrs.bidi);\n};\n\nexport default bidi;\n","import bidi from './bidi';\n\nexport default function patchMithril(global) {\n const defaultMithril = global.m;\n\n const modifiedMithril = function (comp, ...args) {\n const node = defaultMithril.apply(this, arguments);\n\n if (!node.attrs) node.attrs = {};\n\n // Allows the use of the bidi attr.\n if (node.attrs.bidi) {\n bidi(node, node.attrs.bidi);\n }\n\n return node;\n };\n\n Object.keys(defaultMithril).forEach((key) => (modifiedMithril[key] = defaultMithril[key]));\n\n global.m = modifiedMithril;\n}\n","export default (compat: { [key: string]: any }, namespace: string) => {\n // regex to replace common/ and NAMESPACE/ for core & core extensions\n // e.g. admin/utils/extract --> utils/extract\n // e.g. tags/common/utils/sortTags --> tags/utils/sortTags\n const regex = new RegExp(`(\\\\w+\\\\/)?(${namespace}|common)\\\\/`);\n\n return new Proxy(compat, {\n get: (obj, prop: string) => obj[prop] || obj[prop.replace(regex, '$1')],\n });\n};\n","import Mithril from 'mithril';\n\n/**\n * Mithril 2 does not completely rerender the page if a route change leads to the same route\n * (or the same component handling a different route). This util calls m.route.set, forcing a reonit.\n *\n * @see https://mithril.js.org/route.html#key-parameter\n */\nexport default function setRouteWithForcedRefresh(route: string, params = null, options: Mithril.RouteOptions = {}) {\n const newOptions = { ...options };\n newOptions.state = newOptions.state || {};\n newOptions.state.key = Date.now();\n\n m.route.set(route, params, newOptions);\n}\n","type RGB = { r: number; g: number; b: number };\n\nfunction hsvToRgb(h: number, s: number, v: number): RGB {\n let r;\n let g;\n let b;\n\n const i = Math.floor(h * 6);\n const f = h * 6 - i;\n const p = v * (1 - s);\n const q = v * (1 - f * s);\n const t = v * (1 - (1 - f) * s);\n\n switch (i % 6) {\n case 0:\n r = v;\n g = t;\n b = p;\n break;\n case 1:\n r = q;\n g = v;\n b = p;\n break;\n case 2:\n r = p;\n g = v;\n b = t;\n break;\n case 3:\n r = p;\n g = q;\n b = v;\n break;\n case 4:\n r = t;\n g = p;\n b = v;\n break;\n case 5:\n r = v;\n g = p;\n b = q;\n break;\n }\n\n return {\n r: Math.floor(r * 255),\n g: Math.floor(g * 255),\n b: Math.floor(b * 255),\n };\n}\n\n/**\n * Convert the given string to a unique color.\n */\nexport default function stringToColor(string: string): string {\n let num = 0;\n\n // Convert the username into a number based on the ASCII value of each\n // character.\n for (let i = 0; i < string.length; i++) {\n num += string.charCodeAt(i);\n }\n\n // Construct a color using the remainder of that number divided by 360, and\n // some predefined saturation and value values.\n const hue = num % 360;\n const rgb = hsvToRgb(hue / 360, 0.3, 0.9);\n\n return '' + rgb.r.toString(16) + rgb.g.toString(16) + rgb.b.toString(16);\n}\n","/**\n * Check if class A is the same as or a subclass of class B.\n */\nexport default function subclassOf(A, B) {\n return A && (A === B || A.prototype instanceof B);\n}\n","/**\n * An event handler factory that makes it simpler to implement data binding\n * for component event listeners.\n *\n * The handler created by this factory passes the DOM element's attribute\n * identified by the first argument to the callback (usually a bidirectional\n * Mithril stream: https://mithril.js.org/stream.html#bidirectional-bindings).\n *\n * Replaces m.withAttr for Mithril 2.0.\n * @see https://mithril.js.org/archive/v0.2.5/mithril.withAttr.html\n */\nexport default (key: string, cb: Function) =>\n function (this: Element) {\n cb(this.getAttribute(key) || this[key]);\n };\n"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack://@flarum/core/./src/common/states/ModalManagerState.js","webpack://@flarum/core/./src/common/states/AlertManagerState.ts","webpack://@flarum/core/./src/common/Application.js","webpack://@flarum/core/./src/common/Component.ts","webpack://@flarum/core/./src/common/Model.js","webpack://@flarum/core/./src/common/Session.js","webpack://@flarum/core/./src/common/Store.js","webpack://@flarum/core/./src/common/Translator.js","webpack://@flarum/core/./src/common/utils/evented.js","webpack://@flarum/core/./src/common/Fragment.ts","webpack://@flarum/core/./src/common/compat.js","webpack://@flarum/core/./src/common/utils/mixin.js","webpack://@flarum/core/./src/common/components/Alert.tsx","webpack://@flarum/core/./src/common/components/AlertManager.js","webpack://@flarum/core/./src/common/components/Badge.js","webpack://@flarum/core/./src/common/components/Button.js","webpack://@flarum/core/./src/common/components/Checkbox.js","webpack://@flarum/core/./src/common/components/Dropdown.js","webpack://@flarum/core/./src/common/components/FieldSet.js","webpack://@flarum/core/./src/common/components/GroupBadge.js","webpack://@flarum/core/./src/common/components/Link.js","webpack://@flarum/core/./src/common/components/LinkButton.js","webpack://@flarum/core/./src/common/components/LoadingIndicator.js","webpack://@flarum/core/./src/common/components/Modal.js","webpack://@flarum/core/./src/common/components/ModalManager.js","webpack://@flarum/core/./src/common/components/Navigation.js","webpack://@flarum/core/./src/common/components/Page.js","webpack://@flarum/core/./src/common/components/Placeholder.js","webpack://@flarum/core/./src/common/components/RequestErrorModal.js","webpack://@flarum/core/./src/common/components/Select.js","webpack://@flarum/core/./src/common/components/SelectDropdown.js","webpack://@flarum/core/./src/common/components/Separator.js","webpack://@flarum/core/./src/common/components/SplitDropdown.js","webpack://@flarum/core/./src/common/components/Switch.js","webpack://@flarum/core/./src/common/extend.js","webpack://@flarum/core/./src/common/helpers/avatar.tsx","webpack://@flarum/core/./src/common/helpers/fullTime.tsx","webpack://@flarum/core/./src/common/helpers/highlight.tsx","webpack://@flarum/core/./src/common/helpers/humanTime.tsx","webpack://@flarum/core/./src/common/helpers/icon.tsx","webpack://@flarum/core/./src/common/helpers/listItems.tsx","webpack://@flarum/core/./src/common/helpers/punctuateSeries.js","webpack://@flarum/core/./src/common/helpers/userOnline.tsx","webpack://@flarum/core/./src/common/helpers/username.tsx","webpack://@flarum/core/./src/common/extend/Model.js","webpack://@flarum/core/./src/common/extend/PostTypes.js","webpack://@flarum/core/./src/common/extend/Routes.js","webpack://@flarum/core/./src/common/index.js","webpack://@flarum/core/./src/common/models/Discussion.js","webpack://@flarum/core/./src/common/models/Forum.js","webpack://@flarum/core/./src/common/models/Group.js","webpack://@flarum/core/./src/common/models/Notification.js","webpack://@flarum/core/./src/common/models/Post.js","webpack://@flarum/core/./src/common/models/User.js","webpack://@flarum/core/./src/common/resolvers/DefaultResolver.ts","webpack://@flarum/core/./src/common/states/PageState.js","webpack://@flarum/core/./src/common/utils/BasicEditorDriver.ts","webpack://@flarum/core/./src/common/utils/Drawer.js","webpack://@flarum/core/./src/common/utils/ItemList.ts","webpack://@flarum/core/./src/common/utils/RequestError.ts","webpack://@flarum/core/./src/common/utils/ScrollListener.js","webpack://@flarum/core/./src/common/utils/Stream.js","webpack://@flarum/core/./src/common/utils/SubtreeRetainer.js","webpack://@flarum/core/./src/common/utils/abbreviateNumber.ts","webpack://@flarum/core/./src/common/utils/anchorScroll.js","webpack://@flarum/core/./src/common/utils/classList.ts","webpack://@flarum/core/./src/common/utils/computed.js","webpack://@flarum/core/./src/common/utils/extract.ts","webpack://@flarum/core/./src/common/utils/extractText.js","webpack://@flarum/core/./src/common/utils/formatNumber.ts","webpack://@flarum/core/./src/common/utils/humanTime.ts","webpack://@flarum/core/./src/common/utils/liveHumanTimes.ts","webpack://@flarum/core/./src/common/utils/mapRoutes.js","webpack://@flarum/core/./src/common/utils/bidi.js","webpack://@flarum/core/./src/common/utils/patchMithril.js","webpack://@flarum/core/./src/common/utils/proxifyCompat.ts","webpack://@flarum/core/./src/common/utils/setRouteWithForcedRefresh.ts","webpack://@flarum/core/./src/common/utils/stringToColor.ts","webpack://@flarum/core/./src/common/utils/subclassOf.js","webpack://@flarum/core/./src/common/utils/withAttr.ts"],"names":["ModalManagerState","this","modal","show","componentClass","attrs","prototype","Modal","componentResolver","console","error","Error","init","clearTimeout","closeTimeout","m","redraw","sync","close","setTimeout","AlertManagerState","getActiveAlerts","activeAlerts","arg1","arg2","arg3","children","Alert","arguments","length","alertId","dismiss","key","clear","Application","ItemList","Translator","Store","forums","Forum","users","User","discussions","Discussion","posts","Post","groups","Group","notifications","Notification","PageState","load","payload","data","translator","locale","boot","initializers","toArray","forEach","initializer","store","pushPayload","resources","forum","getById","session","Session","userId","csrfToken","mount","initialRoute","window","location","href","bootExtensions","extensions","Object","keys","name","extension","flattenDeep","extend","exports","basePath","document","getElementById","view","ModalManager","state","AlertManager","alerts","drawer","Drawer","route","mapRoutes","routes","scrollListener","ScrollListener","top","$app","$","offset","toggleClass","start","update","addClass","liveHumanTimes","preloadedApiDocument","apiDocument","results","screen","getComputedStyle","documentElement","getPropertyValue","setTitle","title","updateTitle","setTitleCount","count","titleCount","pageTitleWithSeparator","get","attribute","request","originalOptions","options","background","result","xhr","setRequestHeader","method","deserialize","responseText","errorHandler","original","extract","status","RequestError","getResponseHeader","app","JSON","parse","e","requestErrorAlert","then","response","content","errors","map","detail","reduce","a","b","concat","slice","trans","isDebug","formattedError","Array","isArray","decodeURI","alert","type","controls","Button","className","onclick","showDebug","bind","url","group","groupEnd","Promise","reject","RequestErrorModal","params","path","replace","hasOwnProperty","queryString","buildQueryString","prefix","Component","oninit","vnode","setAttrs","oncreate","element","dom","onbeforeupdate","selector","$element","find","component","componentAttrs","constructor","initAttrs","Model","freshness","Date","exists","id","attributes","pushData","innerKey","getIdentifier","pushAttributes","save","relationships","model","oldData","copyData","meta","apiEndpoint","body","remove","resolve","stringify","transform","value","hasOne","relationship","hasMany","transformDate","user","login","logout","models","included","pushObject","createRecord","query","join","getBy","all","filter","records","translations","addTranslations","parameters","translation","apply","transChoice","number","parseInt","pluralize","input","username","split","RegExp","hydrated","open","part","match","push","rawChildren","splice","fragment","shift","tag","unshift","sPluralRegex","cPluralRegex","iPluralRegex","standardRules","explicitRules","test","matches","rule","ns","n","leftNumber","convertNumber","rightNumber","pluralPosition","undefined","Number","NEGATIVE_INFINITY","POSITIVE_INFINITY","handlers","getHandlers","event","trigger","args","handler","on","one","wrapper","off","index","indexOf","Fragment","render","vdom","originalOnCreate","BasicEditorDriver","evented","Parent","Mixed","mixins","object","humanTime","computed","anchorScroll","abbreviateNumber","string","SubtreeRetainer","stringToColor","Stream","subclassOf","setRouteWithForcedRefresh","patchMithril","proxifyCompat","classList","extractText","formatNumber","withAttr","Page","Switch","Badge","LoadingIndicator","Placeholder","Separator","Dropdown","SplitDropdown","FieldSet","Select","Navigation","Link","LinkButton","Checkbox","SelectDropdown","GroupBadge","fullTime","avatar","icon","humanTimeHelper","punctuateSeries","highlight","userOnline","listItems","DefaultResolver","dismissible","ondismiss","dismissControl","entries","iconName","trust","label","tooltip","loading","disabled","getButtonContent","size","checked","onchange","getDisplay","buttonClassName","menuClassName","caretIcon","accessibleToggleLabel","showing","items","getButton","getMenu","onshow","$menu","isRight","hasClass","removeClass","height","scrollTop","left","width","scrollLeft","onhide","aria-haspopup","aria-label","data-toggle","style","backgroundColor","color","nameSingular","text","external","now","active","isActive","force","String","zIndex","css","lines","radius","Spinner","spin","animateShow","onready","onbeforeremove","animateHide","alertAttrs","isDismissible","hide","onsubmit","first","focus","select","loaded","onerror","source","pointer","readyCallback","backdrop","keyboard","history","pane","onmouseenter","onmouseleave","canGoBack","getBackButton","getPaneButton","getDrawerButton","previous","getPrevious","backUrl","shiftKey","ctrlKey","metaKey","which","preventDefault","back","pinned","togglePinned","newNotificationCount","stopPropagation","current","routeName","bodyClass","scrollTopOnCreate","useBrowserScrollRestoration","scrollRestoration","onremove","statusText","json","activeChild","defaultLabel","isListItem","firstChild","getFirstChild","buttonAttrs","callback","override","newMethod","hasTitle","displayName","avatarUrl","src","alt","charAt","toUpperCase","time","d","dayjs","datetime","format","full","pubdate","phrase","regexp","highlighted","Math","max","search","truncate","html","ago","humanTimeUtil","data-humantime","fontClass","isSeparator","item","prevItem","newItems","Boolean","i","withoutUnnecessarySeparators","itemClassName","itemName","second","list","third","lastSeenAt","isOnline","hasOnes","hasManys","PostTypes","add","postComponents","Routes","relativeTime","localizedFormat","slug","createdAt","firstPost","lastPostedAt","lastPostedUser","lastPost","lastPostNumber","commentCount","replyCount","mostRelevantPost","lastReadAt","lastReadPostNumber","isUnread","unreadCount","isRead","hiddenAt","hiddenUser","isHidden","canReply","canRename","canHide","canDelete","removePost","some","markedAllAsReadAt","min","badges","postIds","link","namePlural","ADMINISTRATOR_ID","GUEST_ID","MEMBER_ID","contentType","fromUser","subject","discussion","contentHtml","contentPlain","getPlainContent","editedAt","editedUser","isEdited","canEdit","email","isEmailConfirmed","password","preferences","joinTime","unreadNotificationCount","discussionCount","canEditCredentials","canEditGroups","avatarColor","calculateAvatarColor","subtract","isBefore","image","Image","onload","colorThief","ColorThief","getColor","crossOrigin","savePreferences","newPreferences","makeKey","param","makeAttrs","onmatch","requestedPath","every","set","el","createElement","build","classNames","placeholder","callInputListeners","inputListeners","listener","oninput","onkeyup","addEventListener","append","setValue","val","dispatchEvent","CustomEvent","bubbles","cancelable","moveCursorTo","position","setSelectionRange","getSelectionRange","selectionStart","selectionEnd","getLastNChars","insertAtCursor","insertAt","pos","insertBetween","end","before","after","replaceBeforeCursor","getCaretCoordinates","relCoords","destroy","click","isOpen","$drawer","$backdrop","appendTo","Item","priority","isEmpty","has","merge","sort","later","requestAnimationFrame","webkitRequestAnimationFrame","mozRequestAnimationFrame","msRequestAnimationFrame","oRequestAnimationFrame","ticking","loop","pageYOffset","passive","stop","removeEventListener","callbacks","needsRebuild","check","invalidate","floor","toFixed","toString","$window","relativeScroll","clsx","dependentKeys","computedValue","compute","dependentValues","recompute","property","isAfter","diff","year","fromNow","updateHumanTimes","each","$this","attr","setInterval","resolver","resolverClass","bidi","node","prop","multi","call","selectedOptions","x","option","selected","ctrl","global","defaultMithril","modifiedMithril","comp","compat","namespace","regex","Proxy","obj","newOptions","num","charCodeAt","rgb","h","s","v","r","g","f","p","q","t","hsvToRgb","A","B","cb","getAttribute"],"mappings":"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","file":"/common/common.js","sourcesContent":["import Modal from '../components/Modal';\n\nexport default class ModalManagerState {\n constructor() {\n this.modal = null;\n }\n\n /**\n * Show a modal dialog.\n *\n * @public\n */\n async show(componentClass, attrs) {\n // Breaking Change Compliance Warning, Remove in Beta 15.\n if (!(componentClass.prototype instanceof Modal)) {\n if (typeof componentClass === 'function') {\n const componentResolver = await componentClass();\n componentClass = componentResolver.default;\n } else {\n // This is duplicated so that if the error is caught, an error message still shows up in the debug console.\n console.error('The ModalManager can only show Modals');\n throw new Error('The ModalManager can only show Modals');\n }\n }\n if (componentClass.init) {\n // This is duplicated so that if the error is caught, an error message still shows up in the debug console.\n console.error(\n 'The componentClass parameter must be a modal class, not a modal instance. Whichever extension triggered this modal should be updated to comply with beta 14.'\n );\n throw new Error(\n 'The componentClass parameter must be a modal class, not a modal instance. Whichever extension triggered this modal should be updated to comply with beta 14.'\n );\n }\n // End Change Compliance Warning, Remove in Beta 15\n\n clearTimeout(this.closeTimeout);\n\n this.modal = { componentClass, attrs };\n\n m.redraw.sync();\n }\n\n /**\n * Close the modal dialog.\n *\n * @public\n */\n close() {\n if (!this.modal) return;\n\n // Don't hide the modal immediately, because if the consumer happens to call\n // the `show` method straight after to show another modal dialog, it will\n // cause Bootstrap's modal JS to misbehave. Instead we will wait for a tiny\n // bit to give the `show` method the opportunity to prevent this from going\n // ahead.\n this.closeTimeout = setTimeout(() => {\n this.modal = null;\n m.redraw();\n });\n }\n}\n","import Mithril from 'mithril';\nimport Alert, { AlertAttrs } from '../components/Alert';\n\n/**\n * Returned by `AlertManagerState.show`. Used to dismiss alerts.\n */\nexport type AlertIdentifier = number;\n\nexport interface AlertState {\n componentClass: typeof Alert;\n attrs: AlertAttrs;\n children: Mithril.Children;\n}\n\nexport default class AlertManagerState {\n protected activeAlerts: { [id: number]: AlertState } = {};\n protected alertId = 0;\n\n getActiveAlerts() {\n return this.activeAlerts;\n }\n\n /**\n * Show an Alert in the alerts area.\n *\n * @returns The alert's ID, which can be used to dismiss the alert.\n */\n show(children: Mithril.Children): AlertIdentifier;\n show(attrs: AlertAttrs, children: Mithril.Children): AlertIdentifier;\n show(componentClass: Alert, attrs: AlertAttrs, children: Mithril.Children): AlertIdentifier;\n\n show(arg1: any, arg2?: any, arg3?: any) {\n // Assigns variables as per the above signatures\n let componentClass = Alert;\n let attrs: AlertAttrs = {};\n let children: Mithril.Children;\n\n if (arguments.length == 1) {\n children = arg1 as Mithril.Children;\n } else if (arguments.length == 2) {\n attrs = arg1 as AlertAttrs;\n children = arg2 as Mithril.Children;\n } else if (arguments.length == 3) {\n componentClass = arg1 as typeof Alert;\n attrs = arg2 as AlertAttrs;\n children = arg3;\n }\n\n // Breaking Change Compliance Warning, Remove in Beta 15.\n // This is applied to the first argument (attrs) because previously, the alert was passed as the first argument.\n if (attrs === Alert || attrs instanceof Alert) {\n // This is duplicated so that if the error is caught, an error message still shows up in the debug console.\n console.error('The AlertManager can only show Alerts. Whichever extension triggered this alert should be updated to comply with beta 14.');\n throw new Error('The AlertManager can only show Alerts. Whichever extension triggered this alert should be updated to comply with beta 14.');\n }\n // End Change Compliance Warning, Remove in Beta 15\n this.activeAlerts[++this.alertId] = { children, attrs, componentClass };\n m.redraw();\n\n return this.alertId;\n }\n\n /**\n * Dismiss an alert.\n */\n dismiss(key: AlertIdentifier): void {\n if (!key || !(key in this.activeAlerts)) return;\n\n delete this.activeAlerts[key];\n m.redraw();\n }\n\n /**\n * Clear all alerts.\n */\n clear(): void {\n this.activeAlerts = {};\n m.redraw();\n }\n}\n","import ItemList from './utils/ItemList';\nimport Button from './components/Button';\nimport ModalManager from './components/ModalManager';\nimport AlertManager from './components/AlertManager';\nimport RequestErrorModal from './components/RequestErrorModal';\nimport Translator from './Translator';\nimport Store from './Store';\nimport Session from './Session';\nimport extract from './utils/extract';\nimport Drawer from './utils/Drawer';\nimport mapRoutes from './utils/mapRoutes';\nimport RequestError from './utils/RequestError';\nimport ScrollListener from './utils/ScrollListener';\nimport liveHumanTimes from './utils/liveHumanTimes';\nimport { extend } from './extend';\n\nimport Forum from './models/Forum';\nimport User from './models/User';\nimport Discussion from './models/Discussion';\nimport Post from './models/Post';\nimport Group from './models/Group';\nimport Notification from './models/Notification';\nimport { flattenDeep } from 'lodash-es';\nimport PageState from './states/PageState';\nimport ModalManagerState from './states/ModalManagerState';\nimport AlertManagerState from './states/AlertManagerState';\n\n/**\n * The `App` class provides a container for an application, as well as various\n * utilities for the rest of the app to use.\n */\nexport default class Application {\n /**\n * The forum model for this application.\n *\n * @type {Forum}\n * @public\n */\n forum = null;\n\n /**\n * A map of routes, keyed by a unique route name. Each route is an object\n * containing the following properties:\n *\n * - `path` The path that the route is accessed at.\n * - `component` The Mithril component to render when this route is active.\n *\n * @example\n * app.routes.discussion = {path: '/d/:id', component: DiscussionPage.component()};\n *\n * @type {Object}\n * @public\n */\n routes = {};\n\n /**\n * An ordered list of initializers to bootstrap the application.\n *\n * @type {ItemList}\n * @public\n */\n initializers = new ItemList();\n\n /**\n * The app's session.\n *\n * @type {Session}\n * @public\n */\n session = null;\n\n /**\n * The app's translator.\n *\n * @type {Translator}\n * @public\n */\n translator = new Translator();\n\n /**\n * The app's data store.\n *\n * @type {Store}\n * @public\n */\n store = new Store({\n forums: Forum,\n users: User,\n discussions: Discussion,\n posts: Post,\n groups: Group,\n notifications: Notification,\n });\n\n /**\n * A local cache that can be used to store data at the application level, so\n * that is persists between different routes.\n *\n * @type {Object}\n * @public\n */\n cache = {};\n\n /**\n * Whether or not the app has been booted.\n *\n * @type {Boolean}\n * @public\n */\n booted = false;\n\n /**\n * The key for an Alert that was shown as a result of an AJAX request error.\n * If present, it will be dismissed on the next successful request.\n *\n * @type {int}\n * @private\n */\n requestErrorAlert = null;\n\n /**\n * The page the app is currently on.\n *\n * This object holds information about the type of page we are currently\n * visiting, and sometimes additional arbitrary page state that may be\n * relevant to lower-level components.\n *\n * @type {PageState}\n */\n current = new PageState(null);\n\n /**\n * The page the app was on before the current page.\n *\n * Once the application navigates to another page, the object previously\n * assigned to this.current will be moved to this.previous, while this.current\n * is re-initialized.\n *\n * @type {PageState}\n */\n previous = new PageState(null);\n\n /*\n * An object that manages modal state.\n *\n * @type {ModalManagerState}\n */\n modal = new ModalManagerState();\n\n /**\n * An object that manages the state of active alerts.\n *\n * @type {AlertManagerState}\n */\n alerts = new AlertManagerState();\n\n data;\n\n title = '';\n titleCount = 0;\n\n initialRoute;\n\n load(payload) {\n this.data = payload;\n this.translator.locale = payload.locale;\n }\n\n boot() {\n this.initializers.toArray().forEach((initializer) => initializer(this));\n\n this.store.pushPayload({ data: this.data.resources });\n\n this.forum = this.store.getById('forums', 1);\n\n this.session = new Session(this.store.getById('users', this.data.session.userId), this.data.session.csrfToken);\n\n this.mount();\n\n this.initialRoute = window.location.href;\n }\n\n bootExtensions(extensions) {\n Object.keys(extensions).forEach((name) => {\n const extension = extensions[name];\n\n const extenders = flattenDeep(extension.extend);\n\n for (const extender of extenders) {\n extender.extend(this, { name, exports: extension });\n }\n });\n }\n\n mount(basePath = '') {\n // An object with a callable view property is used in order to pass arguments to the component; see https://mithril.js.org/mount.html\n m.mount(document.getElementById('modal'), { view: () => ModalManager.component({ state: this.modal }) });\n m.mount(document.getElementById('alerts'), { view: () => AlertManager.component({ state: this.alerts }) });\n\n this.drawer = new Drawer();\n\n m.route(document.getElementById('content'), basePath + '/', mapRoutes(this.routes, basePath));\n\n // Add a class to the body which indicates that the page has been scrolled\n // down. When this happens, we'll add classes to the header and app body\n // which will set the navbar's position to fixed. We don't want to always\n // have it fixed, as that could overlap with custom headers.\n const scrollListener = new ScrollListener((top) => {\n const $app = $('#app');\n const offset = $app.offset().top;\n\n $app.toggleClass('affix', top >= offset).toggleClass('scrolled', top > offset);\n $('.App-header').toggleClass('navbar-fixed-top', top >= offset);\n });\n\n scrollListener.start();\n scrollListener.update();\n\n $(() => {\n $('body').addClass('ontouchstart' in window ? 'touch' : 'no-touch');\n });\n\n liveHumanTimes();\n }\n\n /**\n * Get the API response document that has been preloaded into the application.\n *\n * @return {Object|null}\n * @public\n */\n preloadedApiDocument() {\n // If the URL has changed, the preloaded Api document is invalid.\n if (this.data.apiDocument && window.location.href === this.initialRoute) {\n const results = this.store.pushPayload(this.data.apiDocument);\n\n this.data.apiDocument = null;\n\n return results;\n }\n\n return null;\n }\n\n /**\n * Determine the current screen mode, based on our media queries.\n *\n * @returns {String} - one of \"phone\", \"tablet\", \"desktop\" or \"desktop-hd\"\n */\n screen() {\n const styles = getComputedStyle(document.documentElement);\n return styles.getPropertyValue('--flarum-screen');\n }\n\n /**\n * Set the <title> of the page.\n *\n * @param {String} title\n * @public\n */\n setTitle(title) {\n this.title = title;\n this.updateTitle();\n }\n\n /**\n * Set a number to display in the <title> of the page.\n *\n * @param {Integer} count\n */\n setTitleCount(count) {\n this.titleCount = count;\n this.updateTitle();\n }\n\n updateTitle() {\n const count = this.titleCount ? `(${this.titleCount}) ` : '';\n const pageTitleWithSeparator = this.title && m.route.get() !== this.forum.attribute('basePath') + '/' ? this.title + ' - ' : '';\n const title = this.forum.attribute('title');\n document.title = count + pageTitleWithSeparator + title;\n }\n\n /**\n * Make an AJAX request, handling any low-level errors that may occur.\n *\n * @see https://mithril.js.org/request.html\n * @param {Object} options\n * @return {Promise}\n * @public\n */\n request(originalOptions) {\n const options = Object.assign({}, originalOptions);\n\n // Set some default options if they haven't been overridden. We want to\n // authenticate all requests with the session token. We also want all\n // requests to run asynchronously in the background, so that they don't\n // prevent redraws from occurring.\n options.background = options.background || true;\n\n extend(options, 'config', (result, xhr) => xhr.setRequestHeader('X-CSRF-Token', this.session.csrfToken));\n\n // If the method is something like PATCH or DELETE, which not all servers\n // and clients support, then we'll send it as a POST request with the\n // intended method specified in the X-HTTP-Method-Override header.\n if (options.method !== 'GET' && options.method !== 'POST') {\n const method = options.method;\n extend(options, 'config', (result, xhr) => xhr.setRequestHeader('X-HTTP-Method-Override', method));\n options.method = 'POST';\n }\n\n // When we deserialize JSON data, if for some reason the server has provided\n // a dud response, we don't want the application to crash. We'll show an\n // error message to the user instead.\n options.deserialize = options.deserialize || ((responseText) => responseText);\n\n options.errorHandler =\n options.errorHandler ||\n ((error) => {\n throw error;\n });\n\n // When extracting the data from the response, we can check the server\n // response code and show an error message to the user if something's gone\n // awry.\n const original = options.extract;\n options.extract = (xhr) => {\n let responseText;\n\n if (original) {\n responseText = original(xhr.responseText);\n } else {\n responseText = xhr.responseText || null;\n }\n\n const status = xhr.status;\n\n if (status < 200 || status > 299) {\n throw new RequestError(status, responseText, options, xhr);\n }\n\n if (xhr.getResponseHeader) {\n const csrfToken = xhr.getResponseHeader('X-CSRF-Token');\n if (csrfToken) app.session.csrfToken = csrfToken;\n }\n\n try {\n return JSON.parse(responseText);\n } catch (e) {\n throw new RequestError(500, responseText, options, xhr);\n }\n };\n\n if (this.requestErrorAlert) this.alerts.dismiss(this.requestErrorAlert);\n\n // Now make the request. If it's a failure, inspect the error that was\n // returned and show an alert containing its contents.\n return m.request(options).then(\n (response) => response,\n (error) => {\n let content;\n\n switch (error.status) {\n case 422:\n content = error.response.errors\n .map((error) => [error.detail, <br />])\n .reduce((a, b) => a.concat(b), [])\n .slice(0, -1);\n break;\n\n case 401:\n case 403:\n content = app.translator.trans('core.lib.error.permission_denied_message');\n break;\n\n case 404:\n case 410:\n content = app.translator.trans('core.lib.error.not_found_message');\n break;\n\n case 429:\n content = app.translator.trans('core.lib.error.rate_limit_exceeded_message');\n break;\n\n default:\n content = app.translator.trans('core.lib.error.generic_message');\n }\n\n const isDebug = app.forum.attribute('debug');\n // contains a formatted errors if possible, response must be an JSON API array of errors\n // the details property is decoded to transform escaped characters such as '\\n'\n const errors = error.response && error.response.errors;\n const formattedError = Array.isArray(errors) && errors[0] && errors[0].detail && errors.map((e) => decodeURI(e.detail));\n\n error.alert = {\n type: 'error',\n content,\n controls: isDebug && [\n <Button className=\"Button Button--link\" onclick={this.showDebug.bind(this, error, formattedError)}>\n Debug\n </Button>,\n ],\n };\n\n try {\n options.errorHandler(error);\n } catch (error) {\n if (isDebug && error.xhr) {\n const { method, url } = error.options;\n const { status = '' } = error.xhr;\n\n console.group(`${method} ${url} ${status}`);\n\n console.error(...(formattedError || [error]));\n\n console.groupEnd();\n }\n\n this.requestErrorAlert = this.alerts.show(error.alert, error.alert.content);\n }\n\n return Promise.reject(error);\n }\n );\n }\n\n /**\n * @param {RequestError} error\n * @param {string[]} [formattedError]\n * @private\n */\n showDebug(error, formattedError) {\n this.alerts.dismiss(this.requestErrorAlert);\n\n this.modal.show(RequestErrorModal, { error, formattedError });\n }\n\n /**\n * Construct a URL to the route with the given name.\n *\n * @param {String} name\n * @param {Object} params\n * @return {String}\n * @public\n */\n route(name, params = {}) {\n const route = this.routes[name];\n\n if (!route) throw new Error(`Route '${name}' does not exist`);\n\n const url = route.path.replace(/:([^\\/]+)/g, (m, key) => extract(params, key));\n\n // Remove falsy values in params to avoid having urls like '/?sort&q'\n for (const key in params) {\n if (params.hasOwnProperty(key) && !params[key]) delete params[key];\n }\n\n const queryString = m.buildQueryString(params);\n const prefix = m.route.prefix === '' ? this.forum.attribute('basePath') : '';\n\n return prefix + url + (queryString ? '?' + queryString : '');\n }\n}\n","import * as Mithril from 'mithril';\n\nexport interface ComponentAttrs extends Mithril.Attributes {}\n\n/**\n * The `Component` class defines a user interface 'building block'. A component\n * generates a virtual DOM to be rendered on each redraw.\n *\n * Essentially, this is a wrapper for Mithril's components that adds several useful features:\n *\n * - In the `oninit` and `onbeforeupdate` lifecycle hooks, we store vnode attrs in `this.attrs.\n * This allows us to use attrs across components without having to pass the vnode to every single\n * method.\n * - The static `initAttrs` method allows a convenient way to provide defaults (or to otherwise modify)\n * the attrs that have been passed into a component.\n * - When the component is created in the DOM, we store its DOM element under `this.element`; this lets\n * us use jQuery to modify child DOM state from internal methods via the `this.$()` method.\n * - A convenience `component` method, which serves as an alternative to hyperscript and JSX.\n *\n * As with other Mithril components, components extending Component can be initialized\n * and nested using JSX, hyperscript, or a combination of both. The `component` method can also\n * be used.\n *\n * @example\n * return m('div', <MyComponent foo=\"bar\"><p>Hello World</p></MyComponent>);\n *\n * @example\n * return m('div', MyComponent.component({foo: 'bar'), m('p', 'Hello World!'));\n *\n * @see https://mithril.js.org/components.html\n */\nexport default abstract class Component<T extends ComponentAttrs = ComponentAttrs> implements Mithril.ClassComponent<T> {\n /**\n * The root DOM element for the component.\n */\n protected element!: Element;\n\n /**\n * The attributes passed into the component.\n *\n * @see https://mithril.js.org/components.html#passing-data-to-components\n */\n protected attrs!: T;\n\n /**\n * @inheritdoc\n */\n abstract view(vnode: Mithril.Vnode<T, this>): Mithril.Children;\n\n /**\n * @inheritdoc\n */\n oninit(vnode: Mithril.Vnode<T, this>) {\n this.setAttrs(vnode.attrs);\n }\n\n /**\n * @inheritdoc\n */\n oncreate(vnode: Mithril.VnodeDOM<T, this>) {\n this.element = vnode.dom;\n }\n\n /**\n * @inheritdoc\n */\n onbeforeupdate(vnode: Mithril.VnodeDOM<T, this>) {\n this.setAttrs(vnode.attrs);\n }\n\n /**\n * Returns a jQuery object for this component's element. If you pass in a\n * selector string, this method will return a jQuery object, using the current\n * element as its buffer.\n *\n * For example, calling `component.$('li')` will return a jQuery object\n * containing all of the `li` elements inside the DOM element of this\n * component.\n *\n * @param [selector] a jQuery-compatible selector string\n * @returns the jQuery object for the DOM node\n * @final\n */\n protected $(selector: string): JQuery {\n const $element = $(this.element) as JQuery<HTMLElement>;\n\n return selector ? $element.find(selector) : $element;\n }\n\n /**\n * Convenience method to attach a component without JSX.\n * Has the same effect as calling `m(THIS_CLASS, attrs, children)`.\n *\n * @see https://mithril.js.org/hyperscript.html#mselector,-attributes,-children\n */\n static component(attrs = {}, children = null): Mithril.Vnode {\n const componentAttrs = Object.assign({}, attrs) as Record<string, unknown>;\n\n return m(this as any, componentAttrs, children);\n }\n\n /**\n * Saves a reference to the vnode attrs after running them through initAttrs,\n * and checking for common issues.\n */\n private setAttrs(attrs: T = {} as T): void {\n (this.constructor as typeof Component).initAttrs(attrs);\n\n if (attrs) {\n if ('children' in attrs) {\n throw new Error(\n `[${\n (this.constructor as any).name\n }] The \"children\" attribute of attrs should never be used. Either pass children in as the vnode children or rename the attribute`\n );\n }\n\n if ('tag' in attrs) {\n throw new Error(`[${(this.constructor as any).name}] You cannot use the \"tag\" attribute name with Mithril 2.`);\n }\n }\n\n this.attrs = attrs;\n }\n\n /**\n * Initialize the component's attrs.\n *\n * This can be used to assign default values for missing, optional attrs.\n */\n protected static initAttrs<T>(attrs: T): void {}\n}\n","/**\n * The `Model` class represents a local data resource. It provides methods to\n * persist changes via the API.\n *\n * @abstract\n */\nexport default class Model {\n /**\n * @param {Object} data A resource object from the API.\n * @param {Store} store The data store that this model should be persisted to.\n * @public\n */\n constructor(data = {}, store = null) {\n /**\n * The resource object from the API.\n *\n * @type {Object}\n * @public\n */\n this.data = data;\n\n /**\n * The time at which the model's data was last updated. Watching the value\n * of this property is a fast way to retain/cache a subtree if data hasn't\n * changed.\n *\n * @type {Date}\n * @public\n */\n this.freshness = new Date();\n\n /**\n * Whether or not the resource exists on the server.\n *\n * @type {Boolean}\n * @public\n */\n this.exists = false;\n\n /**\n * The data store that this resource should be persisted to.\n *\n * @type {Store}\n * @protected\n */\n this.store = store;\n }\n\n /**\n * Get the model's ID.\n *\n * @return {Integer}\n * @public\n * @final\n */\n id() {\n return this.data.id;\n }\n\n /**\n * Get one of the model's attributes.\n *\n * @param {String} attribute\n * @return {*}\n * @public\n * @final\n */\n attribute(attribute) {\n return this.data.attributes[attribute];\n }\n\n /**\n * Merge new data into this model locally.\n *\n * @param {Object} data A resource object to merge into this model\n * @public\n */\n pushData(data) {\n // Since most of the top-level items in a resource object are objects\n // (e.g. relationships, attributes), we'll need to check and perform the\n // merge at the second level if that's the case.\n for (const key in data) {\n if (typeof data[key] === 'object') {\n this.data[key] = this.data[key] || {};\n\n // For every item in a second-level object, we want to check if we've\n // been handed a Model instance. If so, we will convert it to a\n // relationship data object.\n for (const innerKey in data[key]) {\n if (data[key][innerKey] instanceof Model) {\n data[key][innerKey] = { data: Model.getIdentifier(data[key][innerKey]) };\n }\n this.data[key][innerKey] = data[key][innerKey];\n }\n } else {\n this.data[key] = data[key];\n }\n }\n\n // Now that we've updated the data, we can say that the model is fresh.\n // This is an easy way to invalidate retained subtrees etc.\n this.freshness = new Date();\n }\n\n /**\n * Merge new attributes into this model locally.\n *\n * @param {Object} attributes The attributes to merge.\n * @public\n */\n pushAttributes(attributes) {\n this.pushData({ attributes });\n }\n\n /**\n * Merge new attributes into this model, both locally and with persistence.\n *\n * @param {Object} attributes The attributes to save. If a 'relationships' key\n * exists, it will be extracted and relationships will also be saved.\n * @param {Object} [options]\n * @return {Promise}\n * @public\n */\n save(attributes, options = {}) {\n const data = {\n type: this.data.type,\n id: this.data.id,\n attributes,\n };\n\n // If a 'relationships' key exists, extract it from the attributes hash and\n // set it on the top-level data object instead. We will be sending this data\n // object to the API for persistence.\n if (attributes.relationships) {\n data.relationships = {};\n\n for (const key in attributes.relationships) {\n const model = attributes.relationships[key];\n\n data.relationships[key] = {\n data: model instanceof Array ? model.map(Model.getIdentifier) : Model.getIdentifier(model),\n };\n }\n\n delete attributes.relationships;\n }\n\n // Before we update the model's data, we should make a copy of the model's\n // old data so that we can revert back to it if something goes awry during\n // persistence.\n const oldData = this.copyData();\n\n this.pushData(data);\n\n const request = { data };\n if (options.meta) request.meta = options.meta;\n\n return app\n .request(\n Object.assign(\n {\n method: this.exists ? 'PATCH' : 'POST',\n url: app.forum.attribute('apiUrl') + this.apiEndpoint(),\n body: request,\n },\n options\n )\n )\n .then(\n // If everything went well, we'll make sure the store knows that this\n // model exists now (if it didn't already), and we'll push the data that\n // the API returned into the store.\n (payload) => {\n this.store.data[payload.data.type] = this.store.data[payload.data.type] || {};\n this.store.data[payload.data.type][payload.data.id] = this;\n return this.store.pushPayload(payload);\n },\n\n // If something went wrong, though... good thing we backed up our model's\n // old data! We'll revert to that and let others handle the error.\n (response) => {\n this.pushData(oldData);\n m.redraw();\n throw response;\n }\n );\n }\n\n /**\n * Send a request to delete the resource.\n *\n * @param {Object} body Data to send along with the DELETE request.\n * @param {Object} [options]\n * @return {Promise}\n * @public\n */\n delete(body, options = {}) {\n if (!this.exists) return Promise.resolve();\n\n return app\n .request(\n Object.assign(\n {\n method: 'DELETE',\n url: app.forum.attribute('apiUrl') + this.apiEndpoint(),\n body,\n },\n options\n )\n )\n .then(() => {\n this.exists = false;\n this.store.remove(this);\n });\n }\n\n /**\n * Construct a path to the API endpoint for this resource.\n *\n * @return {String}\n * @protected\n */\n apiEndpoint() {\n return '/' + this.data.type + (this.exists ? '/' + this.data.id : '');\n }\n\n copyData() {\n return JSON.parse(JSON.stringify(this.data));\n }\n\n /**\n * Generate a function which returns the value of the given attribute.\n *\n * @param {String} name\n * @param {function} [transform] A function to transform the attribute value\n * @return {*}\n * @public\n */\n static attribute(name, transform) {\n return function () {\n const value = this.data.attributes && this.data.attributes[name];\n\n return transform ? transform(value) : value;\n };\n }\n\n /**\n * Generate a function which returns the value of the given has-one\n * relationship.\n *\n * @param {String} name\n * @return {Model|Boolean|undefined} false if no information about the\n * relationship exists; undefined if the relationship exists but the model\n * has not been loaded; or the model if it has been loaded.\n * @public\n */\n static hasOne(name) {\n return function () {\n if (this.data.relationships) {\n const relationship = this.data.relationships[name];\n\n if (relationship) {\n return app.store.getById(relationship.data.type, relationship.data.id);\n }\n }\n\n return false;\n };\n }\n\n /**\n * Generate a function which returns the value of the given has-many\n * relationship.\n *\n * @param {String} name\n * @return {Array|Boolean} false if no information about the relationship\n * exists; an array if it does, containing models if they have been\n * loaded, and undefined for those that have not.\n * @public\n */\n static hasMany(name) {\n return function () {\n if (this.data.relationships) {\n const relationship = this.data.relationships[name];\n\n if (relationship) {\n return relationship.data.map((data) => app.store.getById(data.type, data.id));\n }\n }\n\n return false;\n };\n }\n\n /**\n * Transform the given value into a Date object.\n *\n * @param {String} value\n * @return {Date|null}\n * @public\n */\n static transformDate(value) {\n return value ? new Date(value) : null;\n }\n\n /**\n * Get a resource identifier object for the given model.\n *\n * @param {Model} model\n * @return {Object}\n * @protected\n */\n static getIdentifier(model) {\n return {\n type: model.data.type,\n id: model.data.id,\n };\n }\n}\n","/**\n * The `Session` class defines the current user session. It stores a reference\n * to the current authenticated user, and provides methods to log in/out.\n */\nexport default class Session {\n constructor(user, csrfToken) {\n /**\n * The current authenticated user.\n *\n * @type {User|null}\n * @public\n */\n this.user = user;\n\n /**\n * The CSRF token.\n *\n * @type {String|null}\n * @public\n */\n this.csrfToken = csrfToken;\n }\n\n /**\n * Attempt to log in a user.\n *\n * @param {String} identification The username/email.\n * @param {String} password\n * @param {Object} [options]\n * @return {Promise}\n * @public\n */\n login(body, options = {}) {\n return app.request(\n Object.assign(\n {\n method: 'POST',\n url: `${app.forum.attribute('baseUrl')}/login`,\n body,\n },\n options\n )\n );\n }\n\n /**\n * Log the user out.\n *\n * @public\n */\n logout() {\n window.location = `${app.forum.attribute('baseUrl')}/logout?token=${this.csrfToken}`;\n }\n}\n","/**\n * The `Store` class defines a local data store, and provides methods to\n * retrieve data from the API.\n */\nexport default class Store {\n constructor(models) {\n /**\n * The local data store. A tree of resource types to IDs, such that\n * accessing data[type][id] will return the model for that type/ID.\n *\n * @type {Object}\n * @protected\n */\n this.data = {};\n\n /**\n * The model registry. A map of resource types to the model class that\n * should be used to represent resources of that type.\n *\n * @type {Object}\n * @public\n */\n this.models = models;\n }\n\n /**\n * Push resources contained within an API payload into the store.\n *\n * @param {Object} payload\n * @return {Model|Model[]} The model(s) representing the resource(s) contained\n * within the 'data' key of the payload.\n * @public\n */\n pushPayload(payload) {\n if (payload.included) payload.included.map(this.pushObject.bind(this));\n\n const result = payload.data instanceof Array ? payload.data.map(this.pushObject.bind(this)) : this.pushObject(payload.data);\n\n // Attach the original payload to the model that we give back. This is\n // useful to consumers as it allows them to access meta information\n // associated with their request.\n result.payload = payload;\n\n return result;\n }\n\n /**\n * Create a model to represent a resource object (or update an existing one),\n * and push it into the store.\n *\n * @param {Object} data The resource object\n * @return {Model|null} The model, or null if no model class has been\n * registered for this resource type.\n * @public\n */\n pushObject(data) {\n if (!this.models[data.type]) return null;\n\n const type = (this.data[data.type] = this.data[data.type] || {});\n\n if (type[data.id]) {\n type[data.id].pushData(data);\n } else {\n type[data.id] = this.createRecord(data.type, data);\n }\n\n type[data.id].exists = true;\n\n return type[data.id];\n }\n\n /**\n * Make a request to the API to find record(s) of a specific type.\n *\n * @param {String} type The resource type.\n * @param {Integer|Integer[]|Object} [id] The ID(s) of the model(s) to retrieve.\n * Alternatively, if an object is passed, it will be handled as the\n * `query` parameter.\n * @param {Object} [query]\n * @param {Object} [options]\n * @return {Promise}\n * @public\n */\n find(type, id, query = {}, options = {}) {\n let params = query;\n let url = app.forum.attribute('apiUrl') + '/' + type;\n\n if (id instanceof Array) {\n url += '?filter[id]=' + id.join(',');\n } else if (typeof id === 'object') {\n params = id;\n } else if (id) {\n url += '/' + id;\n }\n\n return app\n .request(\n Object.assign(\n {\n method: 'GET',\n url,\n params,\n },\n options\n )\n )\n .then(this.pushPayload.bind(this));\n }\n\n /**\n * Get a record from the store by ID.\n *\n * @param {String} type The resource type.\n * @param {Integer} id The resource ID.\n * @return {Model}\n * @public\n */\n getById(type, id) {\n return this.data[type] && this.data[type][id];\n }\n\n /**\n * Get a record from the store by the value of a model attribute.\n *\n * @param {String} type The resource type.\n * @param {String} key The name of the method on the model.\n * @param {*} value The value of the model attribute.\n * @return {Model}\n * @public\n */\n getBy(type, key, value) {\n return this.all(type).filter((model) => model[key]() === value)[0];\n }\n\n /**\n * Get all loaded records of a specific type.\n *\n * @param {String} type\n * @return {Model[]}\n * @public\n */\n all(type) {\n const records = this.data[type];\n\n return records ? Object.keys(records).map((id) => records[id]) : [];\n }\n\n /**\n * Remove the given model from the store.\n *\n * @param {Model} model\n */\n remove(model) {\n delete this.data[model.data.type][model.id()];\n }\n\n /**\n * Create a new record of the given type.\n *\n * @param {String} type The resource type\n * @param {Object} [data] Any data to initialize the model with\n * @return {Model}\n * @public\n */\n createRecord(type, data = {}) {\n data.type = data.type || type;\n\n return new this.models[type](data, this);\n }\n}\n","import username from './helpers/username';\nimport extract from './utils/extract';\n\n/**\n * Translator with the same API as Symfony's.\n *\n * Derived from https://github.com/willdurand/BazingaJsTranslationBundle\n * which is available under the MIT License.\n * Copyright (c) William Durand <william.durand1@gmail.com>\n */\nexport default class Translator {\n constructor() {\n /**\n * A map of translation keys to their translated values.\n *\n * @type {Object}\n * @public\n */\n this.translations = {};\n\n this.locale = null;\n }\n\n addTranslations(translations) {\n Object.assign(this.translations, translations);\n }\n\n trans(id, parameters) {\n const translation = this.translations[id];\n\n if (translation) {\n return this.apply(translation, parameters || {});\n }\n\n return id;\n }\n\n transChoice(id, number, parameters) {\n let translation = this.translations[id];\n\n if (translation) {\n number = parseInt(number, 10);\n\n translation = this.pluralize(translation, number);\n\n return this.apply(translation, parameters || {});\n }\n\n return id;\n }\n\n apply(translation, input) {\n // If we've been given a user model as one of the input parameters, then\n // we'll extract the username and use that for the translation. In the\n // future there should be a hook here to inspect the user and change the\n // translation key. This will allow a gender property to determine which\n // translation key is used.\n if ('user' in input) {\n const user = extract(input, 'user');\n\n if (!input.username) input.username = username(user);\n }\n\n translation = translation.split(new RegExp('({[a-z0-9_]+}|</?[a-z0-9_]+>)', 'gi'));\n\n const hydrated = [];\n const open = [hydrated];\n\n translation.forEach((part) => {\n const match = part.match(new RegExp('{([a-z0-9_]+)}|<(/?)([a-z0-9_]+)>', 'i'));\n\n if (match) {\n // Either an opening or closing tag.\n if (match[1]) {\n open[0].push(input[match[1]]);\n } else if (match[3]) {\n if (match[2]) {\n // Closing tag. We start by removing all raw children (generally in the form of strings) from the temporary\n // holding array, then run them through m.fragment to convert them to vnodes. Usually this will just give us a\n // text vnode, but using m.fragment as opposed to an explicit conversion should be more flexible. This is necessary because\n // otherwise, our generated vnode will have raw strings as its children, and mithril expects vnodes.\n // Finally, we add the now-processed vnodes back onto the holding array (which is the same object in memory as the\n // children array of the vnode we are currently processing), and remove the reference to the holding array so that\n // further text will be added to the full set of returned elements.\n const rawChildren = open[0].splice(0, open[0].length);\n open[0].push(...m.fragment(rawChildren).children);\n open.shift();\n } else {\n // If a vnode with a matching tag was provided in the translator input, we use that. Otherwise, we create a new vnode\n // with this tag, and an empty children array (since we're expecting to insert children, as that's the point of having this in translator)\n let tag = input[match[3]] || { tag: match[3], children: [] };\n open[0].push(tag);\n // Insert the tag's children array as the first element of open, so that text in between the opening\n // and closing tags will be added to the tag's children, not to the full set of returned elements.\n open.unshift(tag.children || tag);\n }\n }\n } else {\n // Not an html tag, we add it to open[0], which is either the full set of returned elements (vnodes and text),\n // or if an html tag is currently being processed, the children attribute of that html tag's vnode.\n open[0].push(part);\n }\n });\n\n return hydrated.filter((part) => part);\n }\n\n pluralize(translation, number) {\n const sPluralRegex = new RegExp(/^\\w+\\: +(.+)$/),\n cPluralRegex = new RegExp(/^\\s*((\\{\\s*(\\-?\\d+[\\s*,\\s*\\-?\\d+]*)\\s*\\})|([\\[\\]])\\s*(-Inf|\\-?\\d+)\\s*,\\s*(\\+?Inf|\\-?\\d+)\\s*([\\[\\]]))\\s?(.+?)$/),\n iPluralRegex = new RegExp(/^\\s*(\\{\\s*(\\-?\\d+[\\s*,\\s*\\-?\\d+]*)\\s*\\})|([\\[\\]])\\s*(-Inf|\\-?\\d+)\\s*,\\s*(\\+?Inf|\\-?\\d+)\\s*([\\[\\]])/),\n standardRules = [],\n explicitRules = [];\n\n translation.split('|').forEach((part) => {\n if (cPluralRegex.test(part)) {\n const matches = part.match(cPluralRegex);\n explicitRules[matches[0]] = matches[matches.length - 1];\n } else if (sPluralRegex.test(part)) {\n const matches = part.match(sPluralRegex);\n standardRules.push(matches[1]);\n } else {\n standardRules.push(part);\n }\n });\n\n explicitRules.forEach((rule, e) => {\n if (iPluralRegex.test(e)) {\n const matches = e.match(iPluralRegex);\n\n if (matches[1]) {\n const ns = matches[2].split(',');\n\n for (let n in ns) {\n if (number == ns[n]) {\n return explicitRules[e];\n }\n }\n } else {\n var leftNumber = this.convertNumber(matches[4]);\n var rightNumber = this.convertNumber(matches[5]);\n\n if (\n ('[' === matches[3] ? number >= leftNumber : number > leftNumber) &&\n (']' === matches[6] ? number <= rightNumber : number < rightNumber)\n ) {\n return explicitRules[e];\n }\n }\n }\n });\n\n return standardRules[this.pluralPosition(number, this.locale)] || standardRules[0] || undefined;\n }\n\n convertNumber(number) {\n if ('-Inf' === number) {\n return Number.NEGATIVE_INFINITY;\n } else if ('+Inf' === number || 'Inf' === number) {\n return Number.POSITIVE_INFINITY;\n }\n\n return parseInt(number, 10);\n }\n\n pluralPosition(number, locale) {\n if ('pt_BR' === locale) {\n locale = 'xbr';\n }\n\n if (locale.length > 3) {\n locale = locale.split('_')[0];\n }\n\n switch (locale) {\n case 'bo':\n case 'dz':\n case 'id':\n case 'ja':\n case 'jv':\n case 'ka':\n case 'km':\n case 'kn':\n case 'ko':\n case 'ms':\n case 'th':\n case 'vi':\n case 'zh':\n return 0;\n\n case 'af':\n case 'az':\n case 'bn':\n case 'bg':\n case 'ca':\n case 'da':\n case 'de':\n case 'el':\n case 'en':\n case 'eo':\n case 'es':\n case 'et':\n case 'eu':\n case 'fa':\n case 'fi':\n case 'fo':\n case 'fur':\n case 'fy':\n case 'gl':\n case 'gu':\n case 'ha':\n case 'he':\n case 'hu':\n case 'is':\n case 'it':\n case 'ku':\n case 'lb':\n case 'ml':\n case 'mn':\n case 'mr':\n case 'nah':\n case 'nb':\n case 'ne':\n case 'nl':\n case 'nn':\n case 'no':\n case 'om':\n case 'or':\n case 'pa':\n case 'pap':\n case 'ps':\n case 'pt':\n case 'so':\n case 'sq':\n case 'sv':\n case 'sw':\n case 'ta':\n case 'te':\n case 'tk':\n case 'tr':\n case 'ur':\n case 'zu':\n return number == 1 ? 0 : 1;\n\n case 'am':\n case 'bh':\n case 'fil':\n case 'fr':\n case 'gun':\n case 'hi':\n case 'ln':\n case 'mg':\n case 'nso':\n case 'xbr':\n case 'ti':\n case 'wa':\n return number === 0 || number == 1 ? 0 : 1;\n\n case 'be':\n case 'bs':\n case 'hr':\n case 'ru':\n case 'sr':\n case 'uk':\n return number % 10 == 1 && number % 100 != 11 ? 0 : number % 10 >= 2 && number % 10 <= 4 && (number % 100 < 10 || number % 100 >= 20) ? 1 : 2;\n\n case 'cs':\n case 'sk':\n return number == 1 ? 0 : number >= 2 && number <= 4 ? 1 : 2;\n\n case 'ga':\n return number == 1 ? 0 : number == 2 ? 1 : 2;\n\n case 'lt':\n return number % 10 == 1 && number % 100 != 11 ? 0 : number % 10 >= 2 && (number % 100 < 10 || number % 100 >= 20) ? 1 : 2;\n\n case 'sl':\n return number % 100 == 1 ? 0 : number % 100 == 2 ? 1 : number % 100 == 3 || number % 100 == 4 ? 2 : 3;\n\n case 'mk':\n return number % 10 == 1 ? 0 : 1;\n\n case 'mt':\n return number == 1 ? 0 : number === 0 || (number % 100 > 1 && number % 100 < 11) ? 1 : number % 100 > 10 && number % 100 < 20 ? 2 : 3;\n\n case 'lv':\n return number === 0 ? 0 : number % 10 == 1 && number % 100 != 11 ? 1 : 2;\n\n case 'pl':\n return number == 1 ? 0 : number % 10 >= 2 && number % 10 <= 4 && (number % 100 < 12 || number % 100 > 14) ? 1 : 2;\n\n case 'cy':\n return number == 1 ? 0 : number == 2 ? 1 : number == 8 || number == 11 ? 2 : 3;\n\n case 'ro':\n return number == 1 ? 0 : number === 0 || (number % 100 > 0 && number % 100 < 20) ? 1 : 2;\n\n case 'ar':\n return number === 0 ? 0 : number == 1 ? 1 : number == 2 ? 2 : number >= 3 && number <= 10 ? 3 : number >= 11 && number <= 99 ? 4 : 5;\n\n default:\n return 0;\n }\n }\n}\n","/**\n * The `evented` mixin provides methods allowing an object to trigger events,\n * running externally registered event handlers.\n */\nexport default {\n /**\n * Arrays of registered event handlers, grouped by the event name.\n *\n * @type {Object}\n * @protected\n */\n handlers: null,\n\n /**\n * Get all of the registered handlers for an event.\n *\n * @param {String} event The name of the event.\n * @return {Array}\n * @protected\n */\n getHandlers(event) {\n this.handlers = this.handlers || {};\n\n this.handlers[event] = this.handlers[event] || [];\n\n return this.handlers[event];\n },\n\n /**\n * Trigger an event.\n *\n * @param {String} event The name of the event.\n * @param {...*} args Arguments to pass to event handlers.\n * @public\n */\n trigger(event, ...args) {\n this.getHandlers(event).forEach((handler) => handler.apply(this, args));\n },\n\n /**\n * Register an event handler.\n *\n * @param {String} event The name of the event.\n * @param {function} handler The function to handle the event.\n */\n on(event, handler) {\n this.getHandlers(event).push(handler);\n },\n\n /**\n * Register an event handler so that it will run only once, and then\n * unregister itself.\n *\n * @param {String} event The name of the event.\n * @param {function} handler The function to handle the event.\n */\n one(event, handler) {\n const wrapper = function () {\n handler.apply(this, arguments);\n\n this.off(event, wrapper);\n };\n\n this.getHandlers(event).push(wrapper);\n },\n\n /**\n * Unregister an event handler.\n *\n * @param {String} event The name of the event.\n * @param {function} handler The function that handles the event.\n */\n off(event, handler) {\n const handlers = this.getHandlers(event);\n const index = handlers.indexOf(handler);\n\n if (index !== -1) {\n handlers.splice(index, 1);\n }\n },\n};\n","import * as Mithril from 'mithril';\n\n/**\n * The `Fragment` class represents a chunk of DOM that is rendered once with Mithril and then takes\n * over control of its own DOM and lifecycle.\n *\n * This is very similar to the `Component` wrapper class, but is used for more fine-grained control over\n * the rendering and display of some significant chunks of the DOM. In contrast to components, fragments\n * do not offer Mithril's lifecycle hooks.\n *\n * Use this when you want to enjoy the benefits of JSX / VDOM for initial rendering, combined with\n * small helper methods that then make updates to that DOM directly, instead of fully redrawing\n * everything through Mithril.\n *\n * This should only be used when necessary, and only with `m.render`. If you are unsure whether you need\n * this or `Component, you probably need `Component`.\n */\nexport default abstract class Fragment {\n /**\n * The root DOM element for the fragment.\n */\n protected element!: Element;\n\n /**\n * Returns a jQuery object for this fragment's element. If you pass in a\n * selector string, this method will return a jQuery object, using the current\n * element as its buffer.\n *\n * For example, calling `fragment.$('li')` will return a jQuery object\n * containing all of the `li` elements inside the DOM element of this\n * fragment.\n *\n * @param {String} [selector] a jQuery-compatible selector string\n * @returns {jQuery} the jQuery object for the DOM node\n * @final\n */\n public $(selector) {\n const $element = $(this.element);\n\n return selector ? $element.find(selector) : $element;\n }\n\n /**\n * Get the renderable virtual DOM that represents the fragment's view.\n *\n * This should NOT be overridden by subclasses. Subclasses wishing to define\n * their virtual DOM should override Fragment#view instead.\n *\n * @example\n * const fragment = new MyFragment();\n * m.render(document.body, fragment.render());\n *\n * @final\n */\n public render(): Mithril.Vnode<Mithril.Attributes, this> {\n const vdom = this.view();\n\n vdom.attrs = vdom.attrs || {};\n\n const originalOnCreate = vdom.attrs.oncreate;\n\n vdom.attrs.oncreate = (vnode) => {\n this.element = vnode.dom;\n if (originalOnCreate) originalOnCreate.apply(this, [vnode]);\n };\n\n return vdom;\n }\n\n /**\n * Creates a view out of virtual elements.\n */\n abstract view(): Mithril.Vnode<Mithril.Attributes, this>;\n}\n","import * as extend from './extend';\nimport Session from './Session';\nimport Store from './Store';\nimport BasicEditorDriver from './utils/BasicEditorDriver';\nimport evented from './utils/evented';\nimport liveHumanTimes from './utils/liveHumanTimes';\nimport ItemList from './utils/ItemList';\nimport mixin from './utils/mixin';\nimport humanTime from './utils/humanTime';\nimport computed from './utils/computed';\nimport Drawer from './utils/Drawer';\nimport anchorScroll from './utils/anchorScroll';\nimport RequestError from './utils/RequestError';\nimport abbreviateNumber from './utils/abbreviateNumber';\nimport * as string from './utils/string';\nimport Stream from './utils/Stream';\nimport SubtreeRetainer from './utils/SubtreeRetainer';\nimport setRouteWithForcedRefresh from './utils/setRouteWithForcedRefresh';\nimport extract from './utils/extract';\nimport ScrollListener from './utils/ScrollListener';\nimport stringToColor from './utils/stringToColor';\nimport subclassOf from './utils/subclassOf';\nimport patchMithril from './utils/patchMithril';\nimport proxifyCompat from './utils/proxifyCompat';\nimport classList from './utils/classList';\nimport extractText from './utils/extractText';\nimport formatNumber from './utils/formatNumber';\nimport mapRoutes from './utils/mapRoutes';\nimport withAttr from './utils/withAttr';\nimport Notification from './models/Notification';\nimport User from './models/User';\nimport Post from './models/Post';\nimport Discussion from './models/Discussion';\nimport Group from './models/Group';\nimport Forum from './models/Forum';\nimport Component from './Component';\nimport Translator from './Translator';\nimport AlertManager from './components/AlertManager';\nimport Page from './components/Page';\nimport Switch from './components/Switch';\nimport Badge from './components/Badge';\nimport LoadingIndicator from './components/LoadingIndicator';\nimport Placeholder from './components/Placeholder';\nimport Separator from './components/Separator';\nimport Dropdown from './components/Dropdown';\nimport SplitDropdown from './components/SplitDropdown';\nimport RequestErrorModal from './components/RequestErrorModal';\nimport FieldSet from './components/FieldSet';\nimport Select from './components/Select';\nimport Navigation from './components/Navigation';\nimport Alert from './components/Alert';\nimport Link from './components/Link';\nimport LinkButton from './components/LinkButton';\nimport Checkbox from './components/Checkbox';\nimport SelectDropdown from './components/SelectDropdown';\nimport ModalManager from './components/ModalManager';\nimport Button from './components/Button';\nimport Modal from './components/Modal';\nimport GroupBadge from './components/GroupBadge';\n//import TextEditorButton from './components/TextEditorButton';\nimport Model from './Model';\nimport Application from './Application';\nimport fullTime from './helpers/fullTime';\nimport avatar from './helpers/avatar';\nimport icon from './helpers/icon';\nimport humanTimeHelper from './helpers/humanTime';\nimport punctuateSeries from './helpers/punctuateSeries';\nimport highlight from './helpers/highlight';\nimport username from './helpers/username';\nimport userOnline from './helpers/userOnline';\nimport listItems from './helpers/listItems';\nimport Fragment from './Fragment';\nimport DefaultResolver from './resolvers/DefaultResolver';\n\nexport default {\n extend: extend,\n Session: Session,\n Store: Store,\n 'utils/BasicEditorDriver': BasicEditorDriver,\n 'utils/evented': evented,\n 'utils/liveHumanTimes': liveHumanTimes,\n 'utils/ItemList': ItemList,\n 'utils/mixin': mixin,\n 'utils/humanTime': humanTime,\n 'utils/computed': computed,\n 'utils/Drawer': Drawer,\n 'utils/anchorScroll': anchorScroll,\n 'utils/RequestError': RequestError,\n 'utils/abbreviateNumber': abbreviateNumber,\n 'utils/string': string,\n 'utils/SubtreeRetainer': SubtreeRetainer,\n 'utils/extract': extract,\n 'utils/ScrollListener': ScrollListener,\n 'utils/stringToColor': stringToColor,\n 'utils/Stream': Stream,\n 'utils/subclassOf': subclassOf,\n 'utils/setRouteWithForcedRefresh': setRouteWithForcedRefresh,\n 'utils/patchMithril': patchMithril,\n 'utils/proxifyCompat': proxifyCompat,\n 'utils/classList': classList,\n 'utils/extractText': extractText,\n 'utils/formatNumber': formatNumber,\n 'utils/mapRoutes': mapRoutes,\n 'utils/withAttr': withAttr,\n 'models/Notification': Notification,\n 'models/User': User,\n 'models/Post': Post,\n 'models/Discussion': Discussion,\n 'models/Group': Group,\n 'models/Forum': Forum,\n Component: Component,\n Fragment: Fragment,\n Translator: Translator,\n 'components/AlertManager': AlertManager,\n 'components/Page': Page,\n 'components/Switch': Switch,\n 'components/Badge': Badge,\n 'components/LoadingIndicator': LoadingIndicator,\n 'components/Placeholder': Placeholder,\n 'components/Separator': Separator,\n 'components/Dropdown': Dropdown,\n 'components/SplitDropdown': SplitDropdown,\n 'components/RequestErrorModal': RequestErrorModal,\n 'components/FieldSet': FieldSet,\n 'components/Select': Select,\n 'components/Navigation': Navigation,\n 'components/Alert': Alert,\n 'components/Link': Link,\n 'components/LinkButton': LinkButton,\n 'components/Checkbox': Checkbox,\n 'components/SelectDropdown': SelectDropdown,\n 'components/ModalManager': ModalManager,\n 'components/Button': Button,\n 'components/Modal': Modal,\n 'components/GroupBadge': GroupBadge,\n //'components/TextEditor': TextEditor,\n //'components/TextEditorButton': TextEditorButton,\n Model: Model,\n Application: Application,\n 'helpers/fullTime': fullTime,\n 'helpers/avatar': avatar,\n 'helpers/icon': icon,\n 'helpers/humanTime': humanTimeHelper,\n 'helpers/punctuateSeries': punctuateSeries,\n 'helpers/highlight': highlight,\n 'helpers/username': username,\n 'helpers/userOnline': userOnline,\n 'helpers/listItems': listItems,\n 'resolvers/DefaultResolver': DefaultResolver,\n};\n","/**\n * The `mixin` utility assigns the properties of a set of 'mixin' objects to\n * the prototype of a parent object.\n *\n * @example\n * class MyClass extends mixin(ExistingClass, evented, etc) {}\n *\n * @param {Class} Parent The class to extend the new class from.\n * @param {...Object} mixins The objects to mix in.\n * @return {Class} A new class that extends Parent and contains the mixins.\n */\nexport default function mixin(Parent, ...mixins) {\n class Mixed extends Parent {}\n\n mixins.forEach((object) => {\n Object.assign(Mixed.prototype, object);\n });\n\n return Mixed;\n}\n","import Component, { ComponentAttrs } from '../Component';\nimport Button from './Button';\nimport listItems from '../helpers/listItems';\nimport extract from '../utils/extract';\nimport Mithril from 'mithril';\n\nexport interface AlertAttrs extends ComponentAttrs {\n /** The type of alert this is. Will be used to give the alert a class name of `Alert--{type}`. */\n type?: string;\n /** An array of controls to show in the alert. */\n controls?: Mithril.Children;\n /** Whether or not the alert can be dismissed. */\n dismissible?: boolean;\n /** A callback to run when the alert is dismissed */\n ondismiss?: Function;\n}\n\n/**\n * The `Alert` component represents an alert box, which contains a message,\n * some controls, and may be dismissible.\n */\nexport default class Alert<T extends AlertAttrs = AlertAttrs> extends Component<T> {\n view(vnode: Mithril.Vnode) {\n const attrs = Object.assign({}, this.attrs);\n\n const type = extract(attrs, 'type');\n attrs.className = 'Alert Alert--' + type + ' ' + (attrs.className || '');\n\n const content = extract(attrs, 'content') || vnode.children;\n const controls = (extract(attrs, 'controls') || []) as Mithril.ChildArray;\n\n // If the alert is meant to be dismissible (which is the case by default),\n // then we will create a dismiss button to append as the final control in\n // the alert.\n const dismissible = extract(attrs, 'dismissible');\n const ondismiss = extract(attrs, 'ondismiss');\n const dismissControl = [];\n\n if (dismissible || dismissible === undefined) {\n dismissControl.push(<Button icon=\"fas fa-times\" className=\"Button Button--link Button--icon Alert-dismiss\" onclick={ondismiss} />);\n }\n\n return (\n <div {...attrs}>\n <span className=\"Alert-body\">{content}</span>\n <ul className=\"Alert-controls\">{listItems(controls.concat(dismissControl))}</ul>\n </div>\n );\n }\n}\n","import Component from '../Component';\nimport Alert from './Alert';\n\n/**\n * The `AlertManager` component provides an area in which `Alert` components can\n * be shown and dismissed.\n */\nexport default class AlertManager extends Component {\n oninit(vnode) {\n super.oninit(vnode);\n\n this.state = this.attrs.state;\n }\n\n view() {\n return (\n <div className=\"AlertManager\">\n {Object.entries(this.state.getActiveAlerts()).map(([key, alert]) => (\n <div className=\"AlertManager-alert\">\n <alert.componentClass {...alert.attrs} ondismiss={this.state.dismiss.bind(this.state, key)}>\n {alert.children}\n </alert.componentClass>\n </div>\n ))}\n </div>\n );\n }\n}\n","import Component from '../Component';\nimport icon from '../helpers/icon';\nimport extract from '../utils/extract';\n\n/**\n * The `Badge` component represents a user/discussion badge, indicating some\n * status (e.g. a discussion is stickied, a user is an admin).\n *\n * A badge may have the following special attrs:\n *\n * - `type` The type of badge this is. This will be used to give the badge a\n * class name of `Badge--{type}`.\n * - `icon` The name of an icon to show inside the badge.\n * - `label`\n *\n * All other attrs will be assigned as attributes on the badge element.\n */\nexport default class Badge extends Component {\n view() {\n const attrs = Object.assign({}, this.attrs);\n const type = extract(attrs, 'type');\n const iconName = extract(attrs, 'icon');\n\n attrs.className = 'Badge ' + (type ? 'Badge--' + type : '') + ' ' + (attrs.className || '');\n attrs.title = extract(attrs, 'label') || '';\n\n return <span {...attrs}>{iconName ? icon(iconName, { className: 'Badge-icon' }) : m.trust(' ')}</span>;\n }\n\n oncreate(vnode) {\n super.oncreate(vnode);\n\n if (this.attrs.label) this.$().tooltip();\n }\n}\n","import Component from '../Component';\nimport icon from '../helpers/icon';\nimport classList from '../utils/classList';\nimport extract from '../utils/extract';\nimport extractText from '../utils/extractText';\nimport LoadingIndicator from './LoadingIndicator';\n\n/**\n * The `Button` component defines an element which, when clicked, performs an\n * action.\n *\n * ### Attrs\n *\n * - `icon` The name of the icon class. If specified, the button will be given a\n * 'has-icon' class name.\n * - `disabled` Whether or not the button is disabled. If truthy, the button\n * will be given a 'disabled' class name, and any `onclick` handler will be\n * removed.\n * - `loading` Whether or not the button should be in a disabled loading state.\n *\n * All other attrs will be assigned as attributes on the button element.\n *\n * Note that a Button has no default class names. This is because a Button can\n * be used to represent any generic clickable control, like a menu item.\n */\nexport default class Button extends Component {\n view(vnode) {\n const attrs = Object.assign({}, this.attrs);\n\n attrs.type = attrs.type || 'button';\n\n // If a tooltip was provided for buttons without additional content, we also\n // use this tooltip as text for screen readers\n if (attrs.title && !vnode.children) {\n attrs['aria-label'] = attrs.title;\n }\n\n // If given a translation object, extract the text.\n if (typeof attrs.title === 'object') {\n attrs.title = extractText(attrs.title);\n }\n\n // If nothing else is provided, we use the textual button content as tooltip\n if (!attrs.title && vnode.children) {\n attrs.title = extractText(vnode.children);\n }\n\n const iconName = extract(attrs, 'icon');\n\n const loading = extract(attrs, 'loading');\n if (attrs.disabled || loading) {\n delete attrs.onclick;\n }\n\n attrs.className = classList([attrs.className, iconName && 'hasIcon', (attrs.disabled || loading) && 'disabled', loading && 'loading']);\n\n return <button {...attrs}>{this.getButtonContent(vnode.children)}</button>;\n }\n\n /**\n * Get the template for the button's content.\n *\n * @return {*}\n * @protected\n */\n getButtonContent(children) {\n const iconName = this.attrs.icon;\n\n return [\n iconName && iconName !== true ? icon(iconName, { className: 'Button-icon' }) : '',\n children ? <span className=\"Button-label\">{children}</span> : '',\n this.attrs.loading ? <LoadingIndicator size=\"tiny\" className=\"LoadingIndicator--inline\" /> : '',\n ];\n }\n}\n","import Component from '../Component';\nimport LoadingIndicator from './LoadingIndicator';\nimport icon from '../helpers/icon';\nimport classList from '../utils/classList';\nimport withAttr from '../utils/withAttr';\n\n/**\n * The `Checkbox` component defines a checkbox input.\n *\n * ### Attrs\n *\n * - `state` Whether or not the checkbox is checked.\n * - `className` The class name for the root element.\n * - `disabled` Whether or not the checkbox is disabled.\n * - `loading` Whether or not the checkbox is loading.\n * - `onchange` A callback to run when the checkbox is checked/unchecked.\n * - `children` A text label to display next to the checkbox.\n */\nexport default class Checkbox extends Component {\n view(vnode) {\n // Sometimes, false is stored in the DB as '0'. This is a temporary\n // conversion layer until a more robust settings encoding is introduced\n if (this.attrs.state === '0') this.attrs.state = false;\n\n const className = classList([\n 'Checkbox',\n this.attrs.state ? 'on' : 'off',\n this.attrs.className,\n this.attrs.loading && 'loading',\n this.attrs.disabled && 'disabled',\n ]);\n\n return (\n <label className={className}>\n <input type=\"checkbox\" checked={this.attrs.state} disabled={this.attrs.disabled} onchange={withAttr('checked', this.onchange.bind(this))} />\n <div className=\"Checkbox-display\">{this.getDisplay()}</div>\n {vnode.children}\n </label>\n );\n }\n\n /**\n * Get the template for the checkbox's display (tick/cross icon).\n *\n * @return {*}\n * @protected\n */\n getDisplay() {\n return this.attrs.loading ? <LoadingIndicator size=\"tiny\" /> : icon(this.attrs.state ? 'fas fa-check' : 'fas fa-times');\n }\n\n /**\n * Run a callback when the state of the checkbox is changed.\n *\n * @param {Boolean} checked\n * @protected\n */\n onchange(checked) {\n if (this.attrs.onchange) this.attrs.onchange(checked, this);\n }\n}\n","import Component from '../Component';\nimport icon from '../helpers/icon';\nimport listItems from '../helpers/listItems';\n\n/**\n * The `Dropdown` component displays a button which, when clicked, shows a\n * dropdown menu beneath it.\n *\n * ### Attrs\n *\n * - `buttonClassName` A class name to apply to the dropdown toggle button.\n * - `menuClassName` A class name to apply to the dropdown menu.\n * - `icon` The name of an icon to show in the dropdown toggle button.\n * - `caretIcon` The name of an icon to show on the right of the button.\n * - `label` The label of the dropdown toggle button. Defaults to 'Controls'.\n * - `accessibleToggleLabel` The label used to describe the dropdown toggle button to assistive readers. Defaults to 'Toggle dropdown menu'.\n * - `onhide`\n * - `onshow`\n *\n * The children will be displayed as a list inside of the dropdown menu.\n */\nexport default class Dropdown extends Component {\n static initAttrs(attrs) {\n attrs.className = attrs.className || '';\n attrs.buttonClassName = attrs.buttonClassName || '';\n attrs.menuClassName = attrs.menuClassName || '';\n attrs.label = attrs.label || '';\n attrs.caretIcon = typeof attrs.caretIcon !== 'undefined' ? attrs.caretIcon : 'fas fa-caret-down';\n attrs.accessibleToggleLabel = attrs.accessibleToggleLabel || app.translator.trans('core.lib.dropdown.toggle_dropdown_accessible_label');\n }\n\n oninit(vnode) {\n super.oninit(vnode);\n\n this.showing = false;\n }\n\n view(vnode) {\n const items = vnode.children ? listItems(vnode.children) : [];\n\n return (\n <div className={'ButtonGroup Dropdown dropdown ' + this.attrs.className + ' itemCount' + items.length + (this.showing ? ' open' : '')}>\n {this.getButton(vnode.children)}\n {this.getMenu(items)}\n </div>\n );\n }\n\n oncreate(vnode) {\n super.oncreate(vnode);\n\n // When opening the dropdown menu, work out if the menu goes beyond the\n // bottom of the viewport. If it does, we will apply class to make it show\n // above the toggle button instead of below it.\n this.$().on('shown.bs.dropdown', () => {\n this.showing = true;\n\n if (this.attrs.onshow) {\n this.attrs.onshow();\n }\n\n m.redraw();\n\n const $menu = this.$('.Dropdown-menu');\n const isRight = $menu.hasClass('Dropdown-menu--right');\n\n $menu.removeClass('Dropdown-menu--top Dropdown-menu--right');\n\n $menu.toggleClass('Dropdown-menu--top', $menu.offset().top + $menu.height() > $(window).scrollTop() + $(window).height());\n\n if ($menu.offset().top < 0) {\n $menu.removeClass('Dropdown-menu--top');\n }\n\n $menu.toggleClass('Dropdown-menu--right', isRight || $menu.offset().left + $menu.width() > $(window).scrollLeft() + $(window).width());\n });\n\n this.$().on('hidden.bs.dropdown', () => {\n this.showing = false;\n\n if (this.attrs.onhide) {\n this.attrs.onhide();\n }\n\n m.redraw();\n });\n }\n\n /**\n * Get the template for the button.\n *\n * @return {*}\n * @protected\n */\n getButton(children) {\n return (\n <button\n className={'Dropdown-toggle ' + this.attrs.buttonClassName}\n aria-haspopup=\"menu\"\n aria-label={this.attrs.accessibleToggleLabel}\n data-toggle=\"dropdown\"\n onclick={this.attrs.onclick}\n >\n {this.getButtonContent(children)}\n </button>\n );\n }\n\n /**\n * Get the template for the button's content.\n *\n * @return {*}\n * @protected\n */\n getButtonContent(children) {\n return [\n this.attrs.icon ? icon(this.attrs.icon, { className: 'Button-icon' }) : '',\n <span className=\"Button-label\">{this.attrs.label}</span>,\n this.attrs.caretIcon ? icon(this.attrs.caretIcon, { className: 'Button-caret' }) : '',\n ];\n }\n\n getMenu(items) {\n return <ul className={'Dropdown-menu dropdown-menu ' + this.attrs.menuClassName}>{items}</ul>;\n }\n}\n","import Component from '../Component';\nimport listItems from '../helpers/listItems';\n\n/**\n * The `FieldSet` component defines a collection of fields, displayed in a list\n * underneath a title. Accepted properties are:\n *\n * - `className` The class name for the fieldset.\n * - `label` The title of this group of fields.\n *\n * The children should be an array of items to show in the fieldset.\n */\nexport default class FieldSet extends Component {\n view(vnode) {\n return (\n <fieldset className={this.attrs.className}>\n <legend>{this.attrs.label}</legend>\n <ul>{listItems(vnode.children)}</ul>\n </fieldset>\n );\n }\n}\n","import Badge from './Badge';\n\nexport default class GroupBadge extends Badge {\n static initAttrs(attrs) {\n super.initAttrs(attrs);\n\n if (attrs.group) {\n attrs.icon = attrs.group.icon();\n attrs.style = { backgroundColor: attrs.group.color() };\n attrs.label = typeof attrs.label === 'undefined' ? attrs.group.nameSingular() : attrs.label;\n attrs.type = 'group--' + attrs.group.id();\n\n delete attrs.group;\n }\n }\n}\n","import Component from '../Component';\nimport extract from '../utils/extract';\n\n/**\n * The link component enables both internal and external links.\n * It will return a regular HTML link for any links to external sites,\n * and it will use Mithril's m.route.Link for any internal links.\n *\n * Links will default to internal; the 'external' attr must be set to\n * `true` for the link to be external.\n */\nexport default class Link extends Component {\n view(vnode) {\n let { options = {}, ...attrs } = vnode.attrs;\n\n attrs.href = attrs.href || '';\n\n // For some reason, m.route.Link does not like vnode.text, so if present, we\n // need to convert it to text vnodes and store it in children.\n const children = vnode.children || { tag: '#', children: vnode.text };\n\n if (attrs.external) {\n return <a {...attrs}>{children}</a>;\n }\n\n // If the href URL of the link is the same as the current page path\n // we will not add a new entry to the browser history.\n // This allows us to still refresh the Page component\n // without adding endless history entries.\n if (attrs.href === m.route.get()) {\n if (!('replace' in options)) options.replace = true;\n }\n\n // Mithril 2 does not completely rerender the page if a route change leads to the same route\n // (or the same component handling a different route).\n // Here, the `force` parameter will use Mithril's key system to force a full rerender\n // see https://mithril.js.org/route.html#key-parameter\n if (extract(attrs, 'force')) {\n if (!('state' in options)) options.state = {};\n if (!('key' in options.state)) options.state.key = Date.now();\n }\n\n attrs.options = options;\n\n return <m.route.Link {...attrs}>{children}</m.route.Link>;\n }\n}\n","import Button from './Button';\nimport Link from './Link';\n\n/**\n * The `LinkButton` component defines a `Button` which links to a route.\n *\n * ### Attrs\n *\n * All of the attrs accepted by `Button`, plus:\n *\n * - `active` Whether or not the page that this button links to is currently\n * active.\n * - `href` The URL to link to. If the current URL `m.route()` matches this,\n * the `active` prop will automatically be set to true.\n * - `force` Whether the page should be fully rerendered. Defaults to `true`.\n */\nexport default class LinkButton extends Button {\n static initAttrs(attrs) {\n super.initAttrs(attrs);\n\n attrs.active = this.isActive(attrs);\n if (attrs.force === undefined) attrs.force = true;\n }\n\n view(vnode) {\n const vdom = super.view(vnode);\n\n vdom.tag = Link;\n vdom.attrs.active = String(vdom.attrs.active);\n\n return vdom;\n }\n\n /**\n * Determine whether a component with the given attrs is 'active'.\n *\n * @param {Object} attrs\n * @return {Boolean}\n */\n static isActive(attrs) {\n return typeof attrs.active !== 'undefined' ? attrs.active : m.route.get() === attrs.href;\n }\n}\n","import Component from '../Component';\nimport { Spinner } from 'spin.js';\n\n/**\n * The `LoadingIndicator` component displays a loading spinner with spin.js.\n *\n * ### Attrs\n *\n * - `size` The spin.js size preset to use. Defaults to 'small'.\n *\n * All other attrs will be assigned as attributes on the DOM element.\n */\nexport default class LoadingIndicator extends Component {\n view() {\n const attrs = Object.assign({}, this.attrs);\n\n attrs.className = 'LoadingIndicator ' + (attrs.className || '');\n delete attrs.size;\n\n return <div {...attrs}>{m.trust(' ')}</div>;\n }\n\n oncreate(vnode) {\n super.oncreate(vnode);\n\n const options = { zIndex: 'auto', color: this.$().css('color') };\n\n switch (this.attrs.size) {\n case 'large':\n Object.assign(options, { lines: 10, length: 8, width: 4, radius: 8 });\n break;\n\n case 'tiny':\n Object.assign(options, { lines: 8, length: 2, width: 2, radius: 3 });\n break;\n\n default:\n Object.assign(options, { lines: 8, length: 4, width: 3, radius: 5 });\n }\n\n new Spinner(options).spin(this.element);\n }\n}\n","import Component from '../Component';\nimport Alert from './Alert';\nimport Button from './Button';\n\n/**\n * The `Modal` component displays a modal dialog, wrapped in a form. Subclasses\n * should implement the `className`, `title`, and `content` methods.\n *\n * @abstract\n */\nexport default class Modal extends Component {\n /**\n * Determine whether or not the modal should be dismissible via an 'x' button.\n */\n static isDismissible = true;\n\n /**\n * Attributes for an alert component to show below the header.\n *\n * @type {object}\n */\n alertAttrs = null;\n\n oncreate(vnode) {\n super.oncreate(vnode);\n\n this.attrs.animateShow(() => this.onready());\n }\n\n onbeforeremove() {\n // If the global modal state currently contains a modal,\n // we've just opened up a new one, and accordingly,\n // we don't need to show a hide animation.\n if (!this.attrs.state.modal) {\n this.attrs.animateHide();\n // Here, we ensure that the animation has time to complete.\n // See https://mithril.js.org/lifecycle-methods.html#onbeforeremove\n // Bootstrap's Modal.TRANSITION_DURATION is 300 ms.\n return new Promise((resolve) => setTimeout(resolve, 300));\n }\n }\n\n view() {\n if (this.alertAttrs) {\n this.alertAttrs.dismissible = false;\n }\n\n return (\n <div className={'Modal modal-dialog ' + this.className()}>\n <div className=\"Modal-content\">\n {this.constructor.isDismissible ? (\n <div className=\"Modal-close App-backControl\">\n {Button.component({\n icon: 'fas fa-times',\n onclick: this.hide.bind(this),\n className: 'Button Button--icon Button--link',\n })}\n </div>\n ) : (\n ''\n )}\n\n <form onsubmit={this.onsubmit.bind(this)}>\n <div className=\"Modal-header\">\n <h3 className=\"App-titleControl App-titleControl--text\">{this.title()}</h3>\n </div>\n\n {this.alertAttrs ? <div className=\"Modal-alert\">{Alert.component(this.alertAttrs)}</div> : ''}\n\n {this.content()}\n </form>\n </div>\n </div>\n );\n }\n\n /**\n * Get the class name to apply to the modal.\n *\n * @return {String}\n * @abstract\n */\n className() {}\n\n /**\n * Get the title of the modal dialog.\n *\n * @return {String}\n * @abstract\n */\n title() {}\n\n /**\n * Get the content of the modal.\n *\n * @return {VirtualElement}\n * @abstract\n */\n content() {}\n\n /**\n * Handle the modal form's submit event.\n *\n * @param {Event} e\n */\n onsubmit() {}\n\n /**\n * Focus on the first input when the modal is ready to be used.\n */\n onready() {\n this.$('form').find('input, select, textarea').first().focus().select();\n }\n\n /**\n * Hide the modal.\n */\n hide() {\n this.attrs.state.close();\n }\n\n /**\n * Stop loading.\n */\n loaded() {\n this.loading = false;\n m.redraw();\n }\n\n /**\n * Show an alert describing an error returned from the API, and give focus to\n * the first relevant field.\n *\n * @param {RequestError} error\n */\n onerror(error) {\n this.alertAttrs = error.alert;\n\n m.redraw();\n\n if (error.status === 422 && error.response.errors) {\n this.$('form [name=' + error.response.errors[0].source.pointer.replace('/data/attributes/', '') + ']').select();\n } else {\n this.onready();\n }\n }\n}\n","import Component from '../Component';\n\n/**\n * The `ModalManager` component manages a modal dialog. Only one modal dialog\n * can be shown at once; loading a new component into the ModalManager will\n * overwrite the previous one.\n */\nexport default class ModalManager extends Component {\n view() {\n const modal = this.attrs.state.modal;\n\n return (\n <div className=\"ModalManager modal fade\">\n {modal\n ? modal.componentClass.component({\n ...modal.attrs,\n animateShow: this.animateShow.bind(this),\n animateHide: this.animateHide.bind(this),\n state: this.attrs.state,\n })\n : ''}\n </div>\n );\n }\n\n oncreate(vnode) {\n super.oncreate(vnode);\n\n // Ensure the modal state is notified about a closed modal, even when the\n // DOM-based Bootstrap JavaScript code triggered the closing of the modal,\n // e.g. via ESC key or a click on the modal backdrop.\n this.$().on('hidden.bs.modal', this.attrs.state.close.bind(this.attrs.state));\n }\n\n animateShow(readyCallback) {\n const dismissible = !!this.attrs.state.modal.componentClass.isDismissible;\n\n // If we are opening this modal while another modal is already open,\n // the shown event will not run, because the modal is already open.\n // So, we need to manually trigger the readyCallback.\n if (this.$().hasClass('in')) {\n readyCallback();\n return;\n }\n\n this.$()\n .one('shown.bs.modal', readyCallback)\n .modal({\n backdrop: dismissible || 'static',\n keyboard: dismissible,\n })\n .modal('show');\n }\n\n animateHide() {\n this.$().modal('hide');\n }\n}\n","import Component from '../Component';\nimport Button from './Button';\nimport LinkButton from './LinkButton';\n\n/**\n * The `Navigation` component displays a set of navigation buttons. Typically\n * this is just a back button which pops the app's History. If the user is on\n * the root page and there is no history to pop, then in some instances it may\n * show a button that toggles the app's drawer.\n *\n * If the app has a pane, it will also include a 'pin' button which toggles the\n * pinned state of the pane.\n *\n * Accepts the following attrs:\n *\n * - `className` The name of a class to set on the root element.\n * - `drawer` Whether or not to show a button to toggle the app's drawer if\n * there is no more history to pop.\n */\nexport default class Navigation extends Component {\n view() {\n const { history, pane } = app;\n\n return (\n <div\n className={'Navigation ButtonGroup ' + (this.attrs.className || '')}\n onmouseenter={pane && pane.show.bind(pane)}\n onmouseleave={pane && pane.onmouseleave.bind(pane)}\n >\n {history.canGoBack() ? [this.getBackButton(), this.getPaneButton()] : this.getDrawerButton()}\n </div>\n );\n }\n\n /**\n * Get the back button.\n *\n * @return {Object}\n * @protected\n */\n getBackButton() {\n const { history } = app;\n const previous = history.getPrevious() || {};\n\n return LinkButton.component({\n className: 'Button Navigation-back Button--icon',\n href: history.backUrl(),\n icon: 'fas fa-chevron-left',\n title: previous.title,\n onclick: (e) => {\n if (e.shiftKey || e.ctrlKey || e.metaKey || e.which === 2) return;\n e.preventDefault();\n history.back();\n },\n });\n }\n\n /**\n * Get the pane pinned toggle button.\n *\n * @return {Object|String}\n * @protected\n */\n getPaneButton() {\n const { pane } = app;\n\n if (!pane || !pane.active) return '';\n\n return Button.component({\n className: 'Button Button--icon Navigation-pin' + (pane.pinned ? ' active' : ''),\n onclick: pane.togglePinned.bind(pane),\n icon: 'fas fa-thumbtack',\n });\n }\n\n /**\n * Get the drawer toggle button.\n *\n * @return {Object|String}\n * @protected\n */\n getDrawerButton() {\n if (!this.attrs.drawer) return '';\n\n const { drawer } = app;\n const user = app.session.user;\n\n return Button.component({\n className: 'Button Button--icon Navigation-drawer' + (user && user.newNotificationCount() ? ' new' : ''),\n onclick: (e) => {\n e.stopPropagation();\n drawer.show();\n },\n icon: 'fas fa-bars',\n });\n }\n}\n","import Component from '../Component';\nimport PageState from '../states/PageState';\n\n/**\n * The `Page` component\n *\n * @abstract\n */\nexport default class Page extends Component {\n oninit(vnode) {\n super.oninit(vnode);\n\n app.previous = app.current;\n app.current = new PageState(this.constructor, { routeName: this.attrs.routeName });\n\n app.drawer.hide();\n app.modal.close();\n\n /**\n * A class name to apply to the body while the route is active.\n *\n * @type {String}\n */\n this.bodyClass = '';\n\n /**\n * Whether we should scroll to the top of the page when its rendered.\n *\n * @type {Boolean}\n */\n this.scrollTopOnCreate = true;\n\n /**\n * Whether the browser should restore scroll state on refreshes.\n *\n * @type {Boolean}\n */\n this.useBrowserScrollRestoration = true;\n }\n\n oncreate(vnode) {\n super.oncreate(vnode);\n\n if (this.bodyClass) {\n $('#app').addClass(this.bodyClass);\n }\n\n if (this.scrollTopOnCreate) {\n $(window).scrollTop(0);\n }\n\n if ('scrollRestoration' in history) {\n history.scrollRestoration = this.useBrowserScrollRestoration ? 'auto' : 'manual';\n }\n }\n\n onremove() {\n if (this.bodyClass) {\n $('#app').removeClass(this.bodyClass);\n }\n }\n}\n","import Component from '../Component';\n\n/**\n * The `Placeholder` component displays a muted text with some call to action,\n * usually used as an empty state.\n *\n * ### Attrs\n *\n * - `text`\n */\nexport default class Placeholder extends Component {\n view() {\n return (\n <div className=\"Placeholder\">\n <p>{this.attrs.text}</p>\n </div>\n );\n }\n}\n","import Modal from './Modal';\n\nexport default class RequestErrorModal extends Modal {\n className() {\n return 'RequestErrorModal Modal--large';\n }\n\n title() {\n return this.attrs.error.xhr ? `${this.attrs.error.xhr.status} ${this.attrs.error.xhr.statusText}` : '';\n }\n\n content() {\n const { error, formattedError } = this.attrs;\n\n let responseText;\n\n // If the error is already formatted, just add line endings;\n // else try to parse it as JSON and stringify it with indentation\n if (formattedError) {\n responseText = formattedError.join('\\n\\n');\n } else {\n try {\n const json = error.response || JSON.parse(error.responseText);\n\n responseText = JSON.stringify(json, null, 2);\n } catch (e) {\n responseText = error.responseText;\n }\n }\n\n return (\n <div className=\"Modal-body\">\n <pre>\n {this.attrs.error.options.method} {this.attrs.error.options.url}\n <br />\n <br />\n {responseText}\n </pre>\n </div>\n );\n }\n}\n","import Component from '../Component';\nimport icon from '../helpers/icon';\nimport withAttr from '../utils/withAttr';\n\n/**\n * The `Select` component displays a <select> input, surrounded with some extra\n * elements for styling. It accepts the following attrs:\n *\n * - `options` A map of option values to labels.\n * - `onchange` A callback to run when the selected value is changed.\n * - `value` The value of the selected option.\n * - `disabled` Disabled state for the input.\n */\nexport default class Select extends Component {\n view() {\n const { options, onchange, value, disabled } = this.attrs;\n\n return (\n <span className=\"Select\">\n <select\n className=\"Select-input FormControl\"\n onchange={onchange ? withAttr('value', onchange.bind(this)) : undefined}\n value={value}\n disabled={disabled}\n >\n {Object.keys(options).map((key) => (\n <option value={key}>{options[key]}</option>\n ))}\n </select>\n {icon('fas fa-sort', { className: 'Select-caret' })}\n </span>\n );\n }\n}\n","import Dropdown from './Dropdown';\nimport icon from '../helpers/icon';\n\n/**\n * Determines via a vnode is currently \"active\".\n * Due to changes in Mithril 2, attrs will not be instantiated until AFTER view()\n * is initially called on the parent component, so we can not always depend on the\n * active attr to determine which element should be displayed as the \"active child\".\n *\n * This is a temporary patch, and as so, is not exported / placed in utils.\n */\nfunction isActive(vnode) {\n const tag = vnode.tag;\n\n // Allow non-selectable dividers/headers to be added.\n if (typeof tag === 'string' && tag !== 'a' && tag !== 'button') return false;\n\n if ('initAttrs' in tag) {\n tag.initAttrs(vnode.attrs);\n }\n\n return 'isActive' in tag ? tag.isActive(vnode.attrs) : vnode.attrs.active;\n}\n\n/**\n * The `SelectDropdown` component is the same as a `Dropdown`, except the toggle\n * button's label is set as the label of the first child which has a truthy\n * `active` prop.\n *\n * ### Attrs\n *\n * - `caretIcon`\n * - `defaultLabel`\n */\nexport default class SelectDropdown extends Dropdown {\n static initAttrs(attrs) {\n attrs.caretIcon = typeof attrs.caretIcon !== 'undefined' ? attrs.caretIcon : 'fas fa-sort';\n\n super.initAttrs(attrs);\n\n attrs.className += ' Dropdown--select';\n }\n\n getButtonContent(children) {\n const activeChild = children.find(isActive);\n let label = (activeChild && activeChild.children) || this.attrs.defaultLabel;\n\n if (label instanceof Array) label = label[0];\n\n return [<span className=\"Button-label\">{label}</span>, icon(this.attrs.caretIcon, { className: 'Button-caret' })];\n }\n}\n","import Component from '../Component';\n\n/**\n * The `Separator` component defines a menu separator item.\n */\nclass Separator extends Component {\n view() {\n return <li className=\"Dropdown-separator\" />;\n }\n}\n\nSeparator.isListItem = true;\n\nexport default Separator;\n","import Dropdown from './Dropdown';\nimport Button from './Button';\nimport icon from '../helpers/icon';\n\n/**\n * The `SplitDropdown` component is similar to `Dropdown`, but the first child\n * is displayed as its own button prior to the toggle button.\n */\nexport default class SplitDropdown extends Dropdown {\n static initAttrs(attrs) {\n super.initAttrs(attrs);\n\n attrs.className += ' Dropdown--split';\n attrs.menuClassName += ' Dropdown-menu--right';\n }\n\n getButton(children) {\n // Make a copy of the attrs of the first child component. We will assign\n // these attrs to a new button, so that it has exactly the same behaviour as\n // the first child.\n const firstChild = this.getFirstChild(children);\n const buttonAttrs = Object.assign({}, firstChild.attrs);\n buttonAttrs.className = (buttonAttrs.className || '') + ' SplitDropdown-button Button ' + this.attrs.buttonClassName;\n\n return [\n Button.component(buttonAttrs, firstChild.children),\n <button\n className={'Dropdown-toggle Button Button--icon ' + this.attrs.buttonClassName}\n aria-haspopup=\"menu\"\n aria-label={this.attrs.accessibleToggleLabel}\n data-toggle=\"dropdown\"\n >\n {icon(this.attrs.icon, { className: 'Button-icon' })}\n {icon('fas fa-caret-down', { className: 'Button-caret' })}\n </button>,\n ];\n }\n\n /**\n * Get the first child. If the first child is an array, the first item in that\n * array will be returned.\n *\n * @return {*}\n * @protected\n */\n getFirstChild(children) {\n let firstChild = children;\n\n while (firstChild instanceof Array) firstChild = firstChild[0];\n\n return firstChild;\n }\n}\n","import Checkbox from './Checkbox';\n\n/**\n * The `Switch` component is a `Checkbox`, but with a switch display instead of\n * a tick/cross one.\n */\nexport default class Switch extends Checkbox {\n static initAttrs(attrs) {\n super.initAttrs(attrs);\n\n attrs.className = (attrs.className || '') + ' Checkbox--switch';\n }\n\n getDisplay() {\n return this.attrs.loading ? super.getDisplay() : '';\n }\n}\n","/**\n * Extend an object's method by running its output through a mutating callback\n * every time it is called.\n *\n * The callback accepts the method's return value and should perform any\n * mutations directly on this value. For this reason, this function will not be\n * effective on methods which return scalar values (numbers, strings, booleans).\n *\n * Care should be taken to extend the correct object – in most cases, a class'\n * prototype will be the desired target of extension, not the class itself.\n *\n * @example\n * extend(Discussion.prototype, 'badges', function(badges) {\n * // do something with `badges`\n * });\n *\n * @param {Object} object The object that owns the method\n * @param {String} method The name of the method to extend\n * @param {function} callback A callback which mutates the method's output\n */\nexport function extend(object, method, callback) {\n const original = object[method];\n\n object[method] = function (...args) {\n const value = original ? original.apply(this, args) : undefined;\n\n callback.apply(this, [value].concat(args));\n\n return value;\n };\n\n Object.assign(object[method], original);\n}\n\n/**\n * Override an object's method by replacing it with a new function, so that the\n * new function will be run every time the object's method is called.\n *\n * The replacement function accepts the original method as its first argument,\n * which is like a call to 'super'. Any arguments passed to the original method\n * are also passed to the replacement.\n *\n * Care should be taken to extend the correct object – in most cases, a class'\n * prototype will be the desired target of extension, not the class itself.\n *\n * @example\n * override(Discussion.prototype, 'badges', function(original) {\n * const badges = original();\n * // do something with badges\n * return badges;\n * });\n *\n * @param {Object} object The object that owns the method\n * @param {String} method The name of the method to override\n * @param {function} newMethod The method to replace it with\n */\nexport function override(object, method, newMethod) {\n const original = object[method];\n\n object[method] = function (...args) {\n return newMethod.apply(this, [original.bind(this)].concat(args));\n };\n\n Object.assign(object[method], original);\n}\n","import * as Mithril from 'mithril';\nimport User from '../models/User';\n\n/**\n * The `avatar` helper displays a user's avatar.\n *\n * @param user\n * @param attrs Attributes to apply to the avatar element\n */\nexport default function avatar(user: User, attrs: Object = {}): Mithril.Vnode {\n attrs.className = 'Avatar ' + (attrs.className || '');\n let content: string = '';\n\n // If the `title` attribute is set to null or false, we don't want to give the\n // avatar a title. On the other hand, if it hasn't been given at all, we can\n // safely default it to the user's username.\n const hasTitle: boolean | string = attrs.title === 'undefined' || attrs.title;\n if (!hasTitle) delete attrs.title;\n\n // If a user has been passed, then we will set up an avatar using their\n // uploaded image, or the first letter of their username if they haven't\n // uploaded one.\n if (user) {\n const username: string = user.displayName() || '?';\n const avatarUrl: string = user.avatarUrl();\n\n if (hasTitle) attrs.title = attrs.title || username;\n\n if (avatarUrl) {\n return <img {...attrs} src={avatarUrl} alt=\"\" />;\n }\n\n content = username.charAt(0).toUpperCase();\n attrs.style = { background: user.color() };\n }\n\n return <span {...attrs}>{content}</span>;\n}\n","import dayjs from 'dayjs';\nimport * as Mithril from 'mithril';\n\n/**\n * The `fullTime` helper displays a formatted time string wrapped in a <time>\n * tag.\n */\nexport default function fullTime(time: Date): Mithril.Vnode {\n const d = dayjs(time);\n\n const datetime = d.format();\n const full = d.format('LLLL');\n\n return (\n <time pubdate datetime={datetime}>\n {full}\n </time>\n );\n}\n","import * as Mithril from 'mithril';\nimport { truncate } from '../utils/string';\n\n/**\n * The `highlight` helper searches for a word phrase in a string, and wraps\n * matches with the <mark> tag.\n *\n * @param string The string to highlight.\n * @param phrase The word or words to highlight.\n * @param [length] The number of characters to truncate the string to.\n * The string will be truncated surrounding the first match.\n */\nexport default function highlight(string: string, phrase: string | RegExp, length?: number): Mithril.Vnode<any, any> | string {\n if (!phrase && !length) return string;\n\n // Convert the word phrase into a global regular expression (if it isn't\n // already) so we can search the string for matched.\n const regexp = phrase instanceof RegExp ? phrase : new RegExp(phrase, 'gi');\n\n let highlighted = string;\n let start = 0;\n\n // If a length was given, the truncate the string surrounding the first match.\n if (length) {\n if (phrase) start = Math.max(0, string.search(regexp) - length / 2);\n\n highlighted = truncate(highlighted, length, start);\n }\n\n // Convert the string into HTML entities, then highlight all matches with\n // <mark> tags. Then we will return the result as a trusted HTML string.\n highlighted = $('<div/>').text(highlighted).html();\n\n if (phrase) highlighted = highlighted.replace(regexp, '<mark>$&</mark>');\n\n return m.trust(highlighted);\n}\n","import dayjs from 'dayjs';\nimport * as Mithril from 'mithril';\nimport humanTimeUtil from '../utils/humanTime';\n\n/**\n * The `humanTime` helper displays a time in a human-friendly time-ago format\n * (e.g. '12 days ago'), wrapped in a <time> tag with other information about\n * the time.\n */\nexport default function humanTime(time: Date): Mithril.Vnode {\n const d = dayjs(time);\n\n const datetime = d.format();\n const full = d.format('LLLL');\n const ago = humanTimeUtil(time);\n\n return (\n <time pubdate datetime={datetime} title={full} data-humantime>\n {ago}\n </time>\n );\n}\n","import * as Mithril from 'mithril';\n\n/**\n * The `icon` helper displays an icon.\n *\n * @param fontClass The full icon class, prefix and the icon’s name.\n * @param attrs Any other attributes to apply.\n */\nexport default function icon(fontClass: string, attrs: Mithril.Attributes = {}): Mithril.Vnode {\n attrs.className = 'icon ' + fontClass + ' ' + (attrs.className || '');\n\n return <i {...attrs} />;\n}\n","import * as Mithril from 'mithril';\nimport Separator from '../components/Separator';\nimport classList from '../utils/classList';\n\nfunction isSeparator(item): boolean {\n return item.tag === Separator;\n}\n\nfunction withoutUnnecessarySeparators(items: Array<Mithril.Vnode>): Array<Mithril.Vnode> {\n const newItems = [];\n let prevItem;\n\n items.filter(Boolean).forEach((item: Mithril.Vnode, i: number) => {\n if (!isSeparator(item) || (prevItem && !isSeparator(prevItem) && i !== items.length - 1)) {\n prevItem = item;\n newItems.push(item);\n }\n });\n\n return newItems;\n}\n\n/**\n * The `listItems` helper wraps a collection of components in <li> tags,\n * stripping out any unnecessary `Separator` components.\n */\nexport default function listItems(items: Mithril.Vnode | Array<Mithril.Vnode>): Array<Mithril.Vnode> {\n if (!(items instanceof Array)) items = [items];\n\n return withoutUnnecessarySeparators(items).map((item: Mithril.Vnode) => {\n const isListItem = item.tag && item.tag.isListItem;\n const active = item.tag && item.tag.isActive && item.tag.isActive(item.attrs);\n const className = (item.attrs && item.attrs.itemClassName) || item.itemClassName;\n\n if (isListItem) {\n item.attrs = item.attrs || {};\n item.attrs.key = item.attrs.key || item.itemName;\n item.key = item.attrs.key;\n }\n\n const node: Mithril.Vnode = isListItem ? (\n item\n ) : (\n <li\n className={classList([className, item.itemName && `item-${item.itemName}`, active && 'active'])}\n key={(item.attrs && item.attrs.key) || item.itemName}\n >\n {item}\n </li>\n );\n\n return node;\n });\n}\n","/**\n * The `punctuateSeries` helper formats a list of strings (e.g. names) to read\n * fluently in the application's locale.\n *\n * ```js\n * punctuateSeries(['Toby', 'Franz', 'Dominion']) // Toby, Franz, and Dominion\n * ```\n *\n * @param {Array} items\n * @return {VirtualElement}\n */\nexport default function punctuateSeries(items) {\n if (items.length === 2) {\n return app.translator.trans('core.lib.series.two_text', {\n first: items[0],\n second: items[1],\n });\n } else if (items.length >= 3) {\n // If there are three or more items, we will join all but the first and\n // last items with the equivalent of a comma, and then we will feed that\n // into the translator along with the first and last item.\n const second = items\n .slice(1, items.length - 1)\n .reduce((list, item) => list.concat([item, app.translator.trans('core.lib.series.glue_text')]), [])\n .slice(0, -1);\n\n return app.translator.trans('core.lib.series.three_text', {\n first: items[0],\n second,\n third: items[items.length - 1],\n });\n }\n\n return items;\n}\n","import * as Mithril from 'mithril';\nimport User from '../models/User';\nimport icon from './icon';\n\n/**\n * The `useronline` helper displays a green circle if the user is online\n */\nexport default function userOnline(user: User): Mithril.Vnode {\n if (user.lastSeenAt() && user.isOnline()) {\n return <span className=\"UserOnline\">{icon('fas fa-circle')}</span>;\n }\n}\n","import * as Mithril from 'mithril';\nimport User from '../models/User';\n\n/**\n * The `username` helper displays a user's username in a <span class=\"username\">\n * tag. If the user doesn't exist, the username will be displayed as [deleted].\n */\nexport default function username(user: User): Mithril.Vnode {\n const name = (user && user.displayName()) || app.translator.trans('core.lib.username.deleted_text');\n\n return <span className=\"username\">{name}</span>;\n}\n","export default class Model {\n type;\n attributes = [];\n hasOnes = [];\n hasManys = [];\n\n constructor(type, model = null) {\n this.type = type;\n this.model = model;\n }\n\n attribute(name) {\n this.attributes.push(name);\n\n return this;\n }\n\n hasOne(type) {\n this.hasOnes.push(type);\n\n return this;\n }\n\n hasMany(type) {\n this.hasManys.push(type);\n\n return this;\n }\n\n extend(app, extension) {\n if (this.model) {\n app.store.models[this.type] = this.model;\n }\n\n const model = app.store.models[this.type];\n\n this.attributes.forEach((name) => (model.prototype[name] = model.attribute(name)));\n this.hasOnes.forEach((name) => (model.prototype[name] = model.hasOne(name)));\n this.hasManys.forEach((name) => (model.prototype[name] = model.hasMany(name)));\n }\n}\n","export default class PostTypes {\n postComponents = {};\n\n add(name, component) {\n this.postComponents[name] = component;\n\n return this;\n }\n\n extend(app, extension) {\n Object.assign(app.postComponents, this.postComponents);\n }\n}\n","export default class Routes {\n routes = {};\n\n add(name, path, component) {\n this.routes[name] = { path, component };\n\n return this;\n }\n\n extend(app, extension) {\n Object.assign(app.routes, this.routes);\n }\n}\n","// Expose jQuery, mithril and dayjs to the window browser object\nimport 'expose-loader?exposes[]=$&exposes[]=jQuery!jquery';\nimport 'expose-loader?exposes=m!mithril';\nimport 'expose-loader?exposes=dayjs!dayjs';\n\nimport 'bootstrap/js/affix';\nimport 'bootstrap/js/dropdown';\nimport 'bootstrap/js/modal';\nimport 'bootstrap/js/tooltip';\nimport 'bootstrap/js/transition';\nimport 'jquery.hotkeys/jquery.hotkeys';\n\nimport relativeTime from 'dayjs/plugin/relativeTime';\nimport localizedFormat from 'dayjs/plugin/localizedFormat';\n\ndayjs.extend(relativeTime);\ndayjs.extend(localizedFormat);\n\nimport patchMithril from './utils/patchMithril';\n\npatchMithril(window);\n\nimport * as Extend from './extend/index';\n\nexport { Extend };\n","import Model from '../Model';\nimport computed from '../utils/computed';\nimport ItemList from '../utils/ItemList';\nimport Badge from '../components/Badge';\n\nexport default class Discussion extends Model {}\n\nObject.assign(Discussion.prototype, {\n title: Model.attribute('title'),\n slug: Model.attribute('slug'),\n\n createdAt: Model.attribute('createdAt', Model.transformDate),\n user: Model.hasOne('user'),\n firstPost: Model.hasOne('firstPost'),\n\n lastPostedAt: Model.attribute('lastPostedAt', Model.transformDate),\n lastPostedUser: Model.hasOne('lastPostedUser'),\n lastPost: Model.hasOne('lastPost'),\n lastPostNumber: Model.attribute('lastPostNumber'),\n\n commentCount: Model.attribute('commentCount'),\n replyCount: computed('commentCount', (commentCount) => Math.max(0, commentCount - 1)),\n posts: Model.hasMany('posts'),\n mostRelevantPost: Model.hasOne('mostRelevantPost'),\n\n lastReadAt: Model.attribute('lastReadAt', Model.transformDate),\n lastReadPostNumber: Model.attribute('lastReadPostNumber'),\n isUnread: computed('unreadCount', (unreadCount) => !!unreadCount),\n isRead: computed('unreadCount', (unreadCount) => app.session.user && !unreadCount),\n\n hiddenAt: Model.attribute('hiddenAt', Model.transformDate),\n hiddenUser: Model.hasOne('hiddenUser'),\n isHidden: computed('hiddenAt', (hiddenAt) => !!hiddenAt),\n\n canReply: Model.attribute('canReply'),\n canRename: Model.attribute('canRename'),\n canHide: Model.attribute('canHide'),\n canDelete: Model.attribute('canDelete'),\n\n /**\n * Remove a post from the discussion's posts relationship.\n *\n * @param {Integer} id The ID of the post to remove.\n * @public\n */\n removePost(id) {\n const relationships = this.data.relationships;\n const posts = relationships && relationships.posts;\n\n if (posts) {\n posts.data.some((data, i) => {\n if (id === data.id) {\n posts.data.splice(i, 1);\n return true;\n }\n });\n }\n },\n\n /**\n * Get the estimated number of unread posts in this discussion for the current\n * user.\n *\n * @return {Integer}\n * @public\n */\n unreadCount() {\n const user = app.session.user;\n\n if (user && user.markedAllAsReadAt() < this.lastPostedAt()) {\n const unreadCount = Math.max(0, this.lastPostNumber() - (this.lastReadPostNumber() || 0));\n // If posts have been deleted, it's possible that the unread count could exceed the\n // actual post count. As such, we take the min of the two to ensure this isn't an issue.\n return Math.min(unreadCount, this.commentCount());\n }\n\n return 0;\n },\n\n /**\n * Get the Badge components that apply to this discussion.\n *\n * @return {ItemList}\n * @public\n */\n badges() {\n const items = new ItemList();\n\n if (this.isHidden()) {\n items.add('hidden', <Badge type=\"hidden\" icon=\"fas fa-trash\" label={app.translator.trans('core.lib.badge.hidden_tooltip')} />);\n }\n\n return items;\n },\n\n /**\n * Get a list of all of the post IDs in this discussion.\n *\n * @return {Array}\n * @public\n */\n postIds() {\n const posts = this.data.relationships.posts;\n\n return posts ? posts.data.map((link) => link.id) : [];\n },\n});\n","import Model from '../Model';\n\nexport default class Forum extends Model {\n apiEndpoint() {\n return '/';\n }\n}\n","import Model from '../Model';\n\nclass Group extends Model {}\n\nObject.assign(Group.prototype, {\n nameSingular: Model.attribute('nameSingular'),\n namePlural: Model.attribute('namePlural'),\n color: Model.attribute('color'),\n icon: Model.attribute('icon'),\n isHidden: Model.attribute('isHidden'),\n});\n\nGroup.ADMINISTRATOR_ID = '1';\nGroup.GUEST_ID = '2';\nGroup.MEMBER_ID = '3';\n\nexport default Group;\n","import Model from '../Model';\n\nexport default class Notification extends Model {}\n\nObject.assign(Notification.prototype, {\n contentType: Model.attribute('contentType'),\n content: Model.attribute('content'),\n createdAt: Model.attribute('createdAt', Model.transformDate),\n\n isRead: Model.attribute('isRead'),\n\n user: Model.hasOne('user'),\n fromUser: Model.hasOne('fromUser'),\n subject: Model.hasOne('subject'),\n});\n","import Model from '../Model';\nimport computed from '../utils/computed';\nimport { getPlainContent } from '../utils/string';\n\nexport default class Post extends Model {}\n\nObject.assign(Post.prototype, {\n number: Model.attribute('number'),\n discussion: Model.hasOne('discussion'),\n\n createdAt: Model.attribute('createdAt', Model.transformDate),\n user: Model.hasOne('user'),\n contentType: Model.attribute('contentType'),\n content: Model.attribute('content'),\n contentHtml: Model.attribute('contentHtml'),\n contentPlain: computed('contentHtml', getPlainContent),\n\n editedAt: Model.attribute('editedAt', Model.transformDate),\n editedUser: Model.hasOne('editedUser'),\n isEdited: computed('editedAt', (editedAt) => !!editedAt),\n\n hiddenAt: Model.attribute('hiddenAt', Model.transformDate),\n hiddenUser: Model.hasOne('hiddenUser'),\n isHidden: computed('hiddenAt', (hiddenAt) => !!hiddenAt),\n\n canEdit: Model.attribute('canEdit'),\n canHide: Model.attribute('canHide'),\n canDelete: Model.attribute('canDelete'),\n});\n","/*global ColorThief*/\n\nimport Model from '../Model';\nimport stringToColor from '../utils/stringToColor';\nimport ItemList from '../utils/ItemList';\nimport computed from '../utils/computed';\nimport GroupBadge from '../components/GroupBadge';\n\nexport default class User extends Model {}\n\nObject.assign(User.prototype, {\n username: Model.attribute('username'),\n slug: Model.attribute('slug'),\n displayName: Model.attribute('displayName'),\n email: Model.attribute('email'),\n isEmailConfirmed: Model.attribute('isEmailConfirmed'),\n password: Model.attribute('password'),\n\n avatarUrl: Model.attribute('avatarUrl'),\n preferences: Model.attribute('preferences'),\n groups: Model.hasMany('groups'),\n\n joinTime: Model.attribute('joinTime', Model.transformDate),\n lastSeenAt: Model.attribute('lastSeenAt', Model.transformDate),\n markedAllAsReadAt: Model.attribute('markedAllAsReadAt', Model.transformDate),\n unreadNotificationCount: Model.attribute('unreadNotificationCount'),\n newNotificationCount: Model.attribute('newNotificationCount'),\n\n discussionCount: Model.attribute('discussionCount'),\n commentCount: Model.attribute('commentCount'),\n\n canEdit: Model.attribute('canEdit'),\n canEditCredentials: Model.attribute('canEditCredentials'),\n canEditGroups: Model.attribute('canEditGroups'),\n canDelete: Model.attribute('canDelete'),\n\n avatarColor: null,\n color: computed('username', 'avatarUrl', 'avatarColor', function (username, avatarUrl, avatarColor) {\n // If we've already calculated and cached the dominant color of the user's\n // avatar, then we can return that in RGB format. If we haven't, we'll want\n // to calculate it. Unless the user doesn't have an avatar, in which case\n // we generate a color from their username.\n if (avatarColor) {\n return 'rgb(' + avatarColor.join(', ') + ')';\n } else if (avatarUrl) {\n this.calculateAvatarColor();\n return '';\n }\n\n return '#' + stringToColor(username);\n }),\n\n /**\n * Check whether or not the user has been seen in the last 5 minutes.\n *\n * @return {Boolean}\n * @public\n */\n isOnline() {\n return dayjs().subtract(5, 'minutes').isBefore(this.lastSeenAt());\n },\n\n /**\n * Get the Badge components that apply to this user.\n *\n * @return {ItemList}\n */\n badges() {\n const items = new ItemList();\n const groups = this.groups();\n\n if (groups) {\n groups.forEach((group) => {\n items.add('group' + group.id(), GroupBadge.component({ group }));\n });\n }\n\n return items;\n },\n\n /**\n * Calculate the dominant color of the user's avatar. The dominant color will\n * be set to the `avatarColor` property once it has been calculated.\n *\n * @protected\n */\n calculateAvatarColor() {\n const image = new Image();\n const user = this;\n\n image.onload = function () {\n const colorThief = new ColorThief();\n user.avatarColor = colorThief.getColor(this);\n user.freshness = new Date();\n m.redraw();\n };\n image.crossOrigin = 'anonymous';\n image.src = this.avatarUrl();\n },\n\n /**\n * Update the user's preferences.\n *\n * @param {Object} newPreferences\n * @return {Promise}\n */\n savePreferences(newPreferences) {\n const preferences = this.preferences();\n\n Object.assign(preferences, newPreferences);\n\n return this.save({ preferences });\n },\n});\n","import Component from '../Component';\n\n/**\n * Generates a route resolver for a given component.\n * In addition to regular route resolver functionality:\n * - It provide the current route name as an attr\n * - It sets a key on the component so a rerender will be triggered on route change.\n */\nexport default class DefaultResolver {\n component: Component | Function;\n routeName: string;\n\n constructor(component, routeName) {\n this.component = component;\n this.routeName = routeName;\n }\n\n /**\n * When a route change results in a changed key, a full page\n * rerender occurs. This method can be overriden in subclasses\n * to prevent rerenders on some route changes.\n */\n makeKey() {\n return this.routeName + JSON.stringify(m.route.param());\n }\n\n makeAttrs(vnode) {\n return {\n ...vnode.attrs,\n routeName: this.routeName,\n };\n }\n\n async onmatch(args, requestedPath, route) {\n if (typeof this.component.component === 'function') {\n return this.component;\n } else {\n const component = await this.component();\n return component.default;\n }\n }\n\n render(vnode) {\n return [{ ...vnode, attrs: this.makeAttrs(vnode), key: this.makeKey() }];\n }\n}\n","import subclassOf from '../../common/utils/subclassOf';\n\nexport default class PageState {\n constructor(type, data = {}) {\n this.type = type;\n this.data = data;\n }\n\n /**\n * Determine whether the page matches the given class and data.\n *\n * @param {object} type The page class to check against. Subclasses are\n * accepted as well.\n * @param {object} data\n * @return {boolean}\n */\n matches(type, data = {}) {\n // Fail early when the page is of a different type\n if (!subclassOf(this.type, type)) return false;\n\n // Now that the type is known to be correct, we loop through the provided\n // data to see whether it matches the data in our state.\n return Object.keys(data).every((key) => this.data[key] === data[key]);\n }\n\n get(key) {\n return this.data[key];\n }\n\n set(key, value) {\n this.data[key] = value;\n }\n}\n","import getCaretCoordinates from 'textarea-caret';\nimport EditorDriverInterface, { EditorDriverParams } from './EditorDriverInterface';\n\nexport default class BasicEditorDriver implements EditorDriverInterface {\n el: HTMLTextAreaElement;\n\n constructor(dom: HTMLElement, params: EditorDriverParams) {\n this.el = document.createElement('textarea');\n\n this.build(dom, params);\n }\n\n build(dom: HTMLElement, params: EditorDriverParams) {\n this.el.className = params.classNames.join(' ');\n this.el.disabled = params.disabled;\n this.el.placeholder = params.placeholder;\n this.el.value = params.value;\n\n const callInputListeners = (e) => {\n params.inputListeners.forEach((listener) => {\n listener();\n });\n\n e.redraw = false;\n };\n\n this.el.oninput = (e) => {\n params.oninput(this.el.value);\n callInputListeners(e);\n };\n\n this.el.onclick = callInputListeners;\n this.el.onkeyup = callInputListeners;\n\n this.el.addEventListener('keydown', function (e) {\n if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') {\n params.onsubmit();\n }\n });\n\n dom.append(this.el);\n }\n\n protected setValue(value: string) {\n $(this.el).val(value).trigger('input');\n\n this.el.dispatchEvent(new CustomEvent('input', { bubbles: true, cancelable: true }));\n }\n\n moveCursorTo(position: number) {\n this.setSelectionRange(position, position);\n }\n\n getSelectionRange(): Array<number> {\n return [this.el.selectionStart, this.el.selectionEnd];\n }\n\n getLastNChars(n: number): string {\n const value = this.el.value;\n\n return value.slice(Math.max(0, this.el.selectionStart - n), this.el.selectionStart);\n }\n\n insertAtCursor(text: string) {\n this.insertAt(this.el.selectionStart, text);\n }\n\n insertAt(pos: number, text: string) {\n this.insertBetween(pos, pos, text);\n }\n\n insertBetween(start: number, end: number, text: string) {\n const value = this.el.value;\n\n const before = value.slice(0, start);\n const after = value.slice(end);\n\n this.setValue(`${before}${text}${after}`);\n\n // Move the textarea cursor to the end of the content we just inserted.\n this.moveCursorTo(start + text.length);\n }\n\n replaceBeforeCursor(start: number, text: string) {\n this.insertBetween(start, this.el.selectionStart, text);\n }\n\n protected setSelectionRange(start: number, end: number) {\n this.el.setSelectionRange(start, end);\n this.focus();\n }\n\n getCaretCoordinates(position: number) {\n const relCoords = getCaretCoordinates(this.el, position);\n\n return {\n top: relCoords.top - this.el.scrollTop,\n left: relCoords.left,\n };\n }\n\n // DOM Interactions\n\n /**\n * Set the disabled status of the editor.\n */\n disabled(disabled: boolean) {\n this.el.disabled = disabled;\n }\n\n /**\n * Focus on the editor.\n */\n focus() {\n this.el.focus();\n }\n\n /**\n * Destroy the editor\n */\n destroy() {\n this.el.remove();\n }\n}\n","/**\n * The `Drawer` class controls the page's drawer. The drawer is the area the\n * slides out from the left on mobile devices; it contains the header and the\n * footer.\n */\nexport default class Drawer {\n constructor() {\n // Set up an event handler so that whenever the content area is tapped,\n // the drawer will close.\n $('#content').click((e) => {\n if (this.isOpen()) {\n e.preventDefault();\n this.hide();\n }\n });\n }\n\n /**\n * Check whether or not the drawer is currently open.\n *\n * @return {Boolean}\n * @public\n */\n isOpen() {\n return $('#app').hasClass('drawerOpen');\n }\n\n /**\n * Hide the drawer.\n *\n * @public\n */\n hide() {\n /**\n * As part of hiding the drawer, this function also ensures that the drawer\n * correctly animates out, while ensuring it is not part of the navigation\n * tree while off-screen.\n *\n * More info: https://github.com/flarum/core/pull/2666#discussion_r595381014\n */\n\n const $app = $('#app');\n\n if (!$app.hasClass('drawerOpen')) return;\n\n const $drawer = $('#drawer');\n\n // Used to prevent `visibility: hidden` from breaking the exit animation\n $drawer.css('visibility', 'visible').one('transitionend', () => $drawer.css('visibility', ''));\n\n $app.removeClass('drawerOpen');\n\n if (this.$backdrop) this.$backdrop.remove();\n }\n\n /**\n * Show the drawer.\n *\n * @public\n */\n show() {\n $('#app').addClass('drawerOpen');\n\n this.$backdrop = $('<div/>')\n .addClass('drawer-backdrop fade')\n .appendTo('body')\n .click(() => this.hide());\n\n setTimeout(() => this.$backdrop.addClass('in'));\n }\n}\n","class Item {\n content: any;\n priority: number;\n key?: number;\n\n constructor(content: any, priority?: number) {\n this.content = content;\n this.priority = priority;\n }\n}\n\n/**\n * The `ItemList` class collects items and then arranges them into an array\n * by priority.\n */\nexport default class ItemList {\n /**\n * The items in the list\n */\n items: { [key: string]: Item } = {};\n\n /**\n * Check whether the list is empty.\n */\n isEmpty(): boolean {\n for (const i in this.items) {\n if (this.items.hasOwnProperty(i)) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Check whether an item is present in the list.\n */\n has(key: string): boolean {\n return !!this.items[key];\n }\n\n /**\n * Get the content of an item.\n */\n get(key: string): any {\n return this.items[key].content;\n }\n\n /**\n * Add an item to the list.\n *\n * @param key A unique key for the item.\n * @param content The item's content.\n * @param [priority] The priority of the item. Items with a higher\n * priority will be positioned before items with a lower priority.\n */\n add(key: string, content: any, priority: number = 0): this {\n this.items[key] = new Item(content, priority);\n\n return this;\n }\n\n /**\n * Replace an item in the list, only if it is already present.\n */\n replace(key: string, content: any = null, priority: number = null): this {\n if (this.items[key]) {\n if (content !== null) {\n this.items[key].content = content;\n }\n\n if (priority !== null) {\n this.items[key].priority = priority;\n }\n }\n\n return this;\n }\n\n /**\n * Remove an item from the list.\n */\n remove(key: string): this {\n delete this.items[key];\n\n return this;\n }\n\n /**\n * Merge another list's items into this one.\n */\n merge(items: this): this {\n for (const i in items.items) {\n if (items.items.hasOwnProperty(i) && items.items[i] instanceof Item) {\n this.items[i] = items.items[i];\n }\n }\n\n return this;\n }\n\n /**\n * Convert the list into an array of item content arranged by priority. Each\n * item's content will be assigned an `itemName` property equal to the item's\n * unique key.\n */\n toArray(): any[] {\n const items: Item[] = [];\n\n for (const i in this.items) {\n if (this.items.hasOwnProperty(i) && this.items[i] instanceof Item) {\n this.items[i].content = Object(this.items[i].content);\n\n this.items[i].content.itemName = i;\n items.push(this.items[i]);\n this.items[i].key = items.length;\n }\n }\n\n return items\n .sort((a, b) => {\n if (a.priority === b.priority) {\n return a.key - b.key;\n } else if (a.priority > b.priority) {\n return -1;\n }\n return 1;\n })\n .map((item) => item.content);\n }\n}\n","export default class RequestError {\n status: string;\n options: object;\n xhr: XMLHttpRequest;\n\n responseText: string | null;\n response: object | null;\n\n alert: any;\n\n constructor(status: string, responseText: string | null, options: object, xhr: XMLHttpRequest) {\n this.status = status;\n this.responseText = responseText;\n this.options = options;\n this.xhr = xhr;\n\n try {\n this.response = JSON.parse(responseText);\n } catch (e) {\n this.response = null;\n }\n\n this.alert = null;\n }\n}\n","const later =\n window.requestAnimationFrame ||\n window.webkitRequestAnimationFrame ||\n window.mozRequestAnimationFrame ||\n window.msRequestAnimationFrame ||\n window.oRequestAnimationFrame ||\n ((callback) => window.setTimeout(callback, 1000 / 60));\n\n/**\n * The `ScrollListener` class sets up a listener that handles window scroll\n * events.\n */\nexport default class ScrollListener {\n /**\n * @param {Function} callback The callback to run when the scroll position\n * changes.\n * @public\n */\n constructor(callback) {\n this.callback = callback;\n this.ticking = false;\n }\n\n /**\n * On each animation frame, as long as the listener is active, run the\n * `update` method.\n *\n * @protected\n */\n loop() {\n // THROTTLE: If the callback is still running (or hasn't yet run), we ignore\n // further scroll events.\n if (this.ticking) return;\n\n // Schedule the callback to be executed soon (TM), and stop throttling once\n // the callback is done.\n later(() => {\n this.update();\n this.ticking = false;\n });\n\n this.ticking = true;\n }\n\n /**\n * Run the callback, whether there was a scroll event or not.\n *\n * @public\n */\n update() {\n this.callback(window.pageYOffset);\n }\n\n /**\n * Start listening to and handling the window's scroll position.\n *\n * @public\n */\n start() {\n if (!this.active) {\n window.addEventListener('scroll', (this.active = this.loop.bind(this)), { passive: true });\n }\n }\n\n /**\n * Stop listening to and handling the window's scroll position.\n *\n * @public\n */\n stop() {\n window.removeEventListener('scroll', this.active);\n\n this.active = null;\n }\n}\n","import Stream from 'mithril/stream';\n\nexport default Stream;\n","/**\n * The `SubtreeRetainer` class keeps track of a number of pieces of data,\n * comparing the values of these pieces at every iteration.\n *\n * This is useful for preventing redraws to relatively static (or huge)\n * components whose VDOM only depends on very few values, when none of them\n * have changed.\n *\n * @example\n * // Check two callbacks for changes on each update\n * this.subtree = new SubtreeRetainer(\n * () => this.attrs.post.freshness,\n * () => this.showing\n * );\n *\n * // Add more callbacks to be checked for updates\n * this.subtree.check(() => this.attrs.user.freshness);\n *\n * // In a component's onbeforeupdate() method:\n * return this.subtree.needsRebuild()\n *\n * @see https://mithril.js.org/lifecycle-methods.html#onbeforeupdate\n */\nexport default class SubtreeRetainer {\n /**\n * @param {...callbacks} callbacks Functions returning data to keep track of.\n */\n constructor(...callbacks) {\n this.callbacks = callbacks;\n this.data = {};\n // Build the initial data, so it is available when calling\n // needsRebuild from the onbeforeupdate hook.\n this.needsRebuild();\n }\n\n /**\n * Return whether any data has changed since the last check.\n * If so, Mithril needs to re-diff the vnode and its children.\n *\n * @return {boolean}\n * @public\n */\n needsRebuild() {\n let needsRebuild = false;\n\n this.callbacks.forEach((callback, i) => {\n const result = callback();\n\n if (result !== this.data[i]) {\n this.data[i] = result;\n needsRebuild = true;\n }\n });\n\n return needsRebuild;\n }\n\n /**\n * Add another callback to be checked.\n *\n * @param {...Function} callbacks\n * @public\n */\n check(...callbacks) {\n this.callbacks = this.callbacks.concat(callbacks);\n // Update the data cache when new checks are added.\n this.needsRebuild();\n }\n\n /**\n * Invalidate the subtree, forcing it to be rerendered.\n *\n * @public\n */\n invalidate() {\n this.data = {};\n }\n}\n","/**\n * The `abbreviateNumber` utility converts a number to a shorter localized form.\n *\n * @example\n * abbreviateNumber(1234);\n * // \"1.2K\"\n */\nexport default function abbreviateNumber(number: number): string {\n // TODO: translation\n if (number >= 1000000) {\n return Math.floor(number / 1000000) + app.translator.trans('core.lib.number_suffix.mega_text');\n } else if (number >= 1000) {\n return (number / 1000).toFixed(1) + app.translator.trans('core.lib.number_suffix.kilo_text');\n } else {\n return number.toString();\n }\n}\n","/**\n * The `anchorScroll` utility saves the scroll position relative to an element,\n * and then restores it after a callback has been run.\n *\n * This is useful if a redraw will change the page's content above the viewport.\n * Normally doing this will result in the content in the viewport being pushed\n * down or pulled up. By wrapping the redraw with this utility, the scroll\n * position can be anchor to an element that is in or below the viewport, so\n * the content in the viewport will stay the same.\n *\n * @param {DOMElement} element The element to anchor the scroll position to.\n * @param {Function} callback The callback to run that will change page content.\n */\nexport default function anchorScroll(element, callback) {\n const $window = $(window);\n const relativeScroll = $(element).offset().top - $window.scrollTop();\n\n callback();\n\n $window.scrollTop($(element).offset().top - relativeScroll);\n}\n","import clsx from 'clsx';\n\n/**\n * This util exposes `clsx` to core and extensions as a re-usable utility.\n *\n * For full documentation, see `clsx` on GitHub.\n *\n * @see https://github.com/lukeed/clsx\n */\nconst classList = clsx;\n\nexport default classList;\n","/**\n * The `computed` utility creates a function that will cache its output until\n * any of the dependent values are dirty.\n *\n * @param {...String} dependentKeys The keys of the dependent values.\n * @param {function} compute The function which computes the value using the\n * dependent values.\n * @return {Function}\n */\nexport default function computed(...dependentKeys) {\n const keys = dependentKeys.slice(0, -1);\n const compute = dependentKeys.slice(-1)[0];\n\n const dependentValues = {};\n let computedValue;\n\n return function () {\n let recompute = false;\n\n // Read all of the dependent values. If any of them have changed since last\n // time, then we'll want to recompute our output.\n keys.forEach((key) => {\n const value = typeof this[key] === 'function' ? this[key]() : this[key];\n\n if (dependentValues[key] !== value) {\n recompute = true;\n dependentValues[key] = value;\n }\n });\n\n if (recompute) {\n computedValue = compute.apply(\n this,\n keys.map((key) => dependentValues[key])\n );\n }\n\n return computedValue;\n };\n}\n","/**\n * The `extract` utility deletes a property from an object and returns its\n * value.\n *\n * @param object The object that owns the property\n * @param property The name of the property to extract\n * @return The value of the property\n */\nexport default function extract<T, K extends keyof T>(object: T, property: K): T[K] {\n const value = object[property];\n\n delete object[property];\n\n return value;\n}\n","/**\n * Extract the text nodes from a virtual element.\n *\n * @param {VirtualElement} vdom\n * @return {String}\n */\nexport default function extractText(vdom) {\n if (vdom instanceof Array) {\n return vdom.map((element) => extractText(element)).join('');\n } else if (typeof vdom === 'object' && vdom !== null) {\n return vdom.children ? extractText(vdom.children) : vdom.text;\n } else {\n return vdom;\n }\n}\n","/**\n * The `formatNumber` utility localizes a number into a string with the\n * appropriate punctuation.\n *\n * @example\n * formatNumber(1234);\n * // 1,234\n */\nexport default function formatNumber(number: number): string {\n return number.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',');\n}\n","import dayjs from 'dayjs';\nimport 'dayjs/plugin/relativeTime';\n\n/**\n * The `humanTime` utility converts a date to a localized, human-readable time-\n * ago string.\n */\nexport default function humanTime(time: Date): string {\n let d = dayjs(time);\n const now = dayjs();\n\n // To prevent showing things like \"in a few seconds\" due to small offsets\n // between client and server time, we always reset future dates to the\n // current time. This will result in \"just now\" being shown instead.\n if (d.isAfter(now)) {\n d = now;\n }\n\n const day = 864e5;\n const diff = d.diff(dayjs());\n let ago: string;\n\n // If this date was more than a month ago, we'll show the name of the month\n // in the string. If it wasn't this year, we'll show the year as well.\n if (diff < -30 * day) {\n if (d.year() === dayjs().year()) {\n ago = d.format('D MMM');\n } else {\n ago = d.format('ll');\n }\n } else {\n ago = d.fromNow();\n }\n\n return ago;\n}\n","import humanTime from './humanTime';\n\nfunction updateHumanTimes() {\n $('[data-humantime]').each(function () {\n const $this = $(this);\n const ago = humanTime($this.attr('datetime'));\n\n $this.html(ago);\n });\n}\n\n/**\n * The `liveHumanTimes` initializer sets up a loop every 1 second to update\n * timestamps rendered with the `humanTime` helper.\n */\nexport default function liveHumanTimes() {\n setInterval(updateHumanTimes, 10000);\n}\n","import DefaultResolver from '../resolvers/DefaultResolver';\n\n/**\n * The `mapRoutes` utility converts a map of named application routes into a\n * format that can be understood by Mithril, and wraps them in route resolvers\n * to provide each route with the current route name.\n *\n * @see https://mithril.js.org/route.html#signature\n * @param {Object} routes\n * @param {String} [basePath]\n * @return {Object}\n */\nexport default function mapRoutes(routes, basePath = '') {\n const map = {};\n\n for (const routeName in routes) {\n const route = routes[routeName];\n\n if ('resolver' in route) {\n map[basePath + route.path] = route.resolver;\n } else if ('component' in route) {\n const resolverClass = 'resolverClass' in route ? route.resolverClass : DefaultResolver;\n map[basePath + route.path] = new resolverClass(route.component, routeName);\n } else {\n throw new Error(`Either a resolver or a component must be provided for the route [${routeName}]`);\n }\n }\n\n return map;\n}\n","function bidi(node, prop) {\n var type = node.tag === 'select' ? (node.attrs.multi ? 'multi' : 'select') : node.attrs.type;\n\n // Setup: bind listeners\n if (type === 'multi') {\n node.attrs.onchange = function () {\n prop(\n [].slice.call(this.selectedOptions, function (x) {\n return x.value;\n })\n );\n };\n } else if (type === 'select') {\n node.attrs.onchange = function (e) {\n prop(this.selectedOptions[0].value);\n };\n } else if (type === 'checkbox') {\n node.attrs.onchange = function (e) {\n prop(this.checked);\n };\n } else {\n node.attrs.onchange = node.attrs.oninput = function (e) {\n prop(this.value);\n };\n }\n\n if (node.tag === 'select') {\n node.children.forEach(function (option) {\n if (option.attrs.value === prop() || option.children[0] === prop()) {\n option.attrs.selected = true;\n }\n });\n } else if (type === 'checkbox') {\n node.attrs.checked = prop();\n } else if (type === 'radio') {\n node.attrs.checked = prop() === node.attrs.value;\n } else {\n node.attrs.value = prop();\n }\n\n node.attrs.bidi = null;\n\n return node;\n}\n\nbidi.view = function (ctrl, node, prop) {\n return bidi(node, node.attrs.bidi);\n};\n\nexport default bidi;\n","import bidi from './bidi';\n\nexport default function patchMithril(global) {\n const defaultMithril = global.m;\n\n const modifiedMithril = function (comp, ...args) {\n const node = defaultMithril.apply(this, arguments);\n\n if (!node.attrs) node.attrs = {};\n\n // Allows the use of the bidi attr.\n if (node.attrs.bidi) {\n bidi(node, node.attrs.bidi);\n }\n\n return node;\n };\n\n Object.keys(defaultMithril).forEach((key) => (modifiedMithril[key] = defaultMithril[key]));\n\n global.m = modifiedMithril;\n}\n","export default (compat: { [key: string]: any }, namespace: string) => {\n // regex to replace common/ and NAMESPACE/ for core & core extensions\n // e.g. admin/utils/extract --> utils/extract\n // e.g. tags/common/utils/sortTags --> tags/utils/sortTags\n const regex = new RegExp(`(\\\\w+\\\\/)?(${namespace}|common)\\\\/`);\n\n return new Proxy(compat, {\n get: (obj, prop: string) => obj[prop] || obj[prop.replace(regex, '$1')],\n });\n};\n","import Mithril from 'mithril';\n\n/**\n * Mithril 2 does not completely rerender the page if a route change leads to the same route\n * (or the same component handling a different route). This util calls m.route.set, forcing a reonit.\n *\n * @see https://mithril.js.org/route.html#key-parameter\n */\nexport default function setRouteWithForcedRefresh(route: string, params = null, options: Mithril.RouteOptions = {}) {\n const newOptions = { ...options };\n newOptions.state = newOptions.state || {};\n newOptions.state.key = Date.now();\n\n m.route.set(route, params, newOptions);\n}\n","type RGB = { r: number; g: number; b: number };\n\nfunction hsvToRgb(h: number, s: number, v: number): RGB {\n let r;\n let g;\n let b;\n\n const i = Math.floor(h * 6);\n const f = h * 6 - i;\n const p = v * (1 - s);\n const q = v * (1 - f * s);\n const t = v * (1 - (1 - f) * s);\n\n switch (i % 6) {\n case 0:\n r = v;\n g = t;\n b = p;\n break;\n case 1:\n r = q;\n g = v;\n b = p;\n break;\n case 2:\n r = p;\n g = v;\n b = t;\n break;\n case 3:\n r = p;\n g = q;\n b = v;\n break;\n case 4:\n r = t;\n g = p;\n b = v;\n break;\n case 5:\n r = v;\n g = p;\n b = q;\n break;\n }\n\n return {\n r: Math.floor(r * 255),\n g: Math.floor(g * 255),\n b: Math.floor(b * 255),\n };\n}\n\n/**\n * Convert the given string to a unique color.\n */\nexport default function stringToColor(string: string): string {\n let num = 0;\n\n // Convert the username into a number based on the ASCII value of each\n // character.\n for (let i = 0; i < string.length; i++) {\n num += string.charCodeAt(i);\n }\n\n // Construct a color using the remainder of that number divided by 360, and\n // some predefined saturation and value values.\n const hue = num % 360;\n const rgb = hsvToRgb(hue / 360, 0.3, 0.9);\n\n return '' + rgb.r.toString(16) + rgb.g.toString(16) + rgb.b.toString(16);\n}\n","/**\n * Check if class A is the same as or a subclass of class B.\n */\nexport default function subclassOf(A, B) {\n return A && (A === B || A.prototype instanceof B);\n}\n","/**\n * An event handler factory that makes it simpler to implement data binding\n * for component event listeners.\n *\n * The handler created by this factory passes the DOM element's attribute\n * identified by the first argument to the callback (usually a bidirectional\n * Mithril stream: https://mithril.js.org/stream.html#bidirectional-bindings).\n *\n * Replaces m.withAttr for Mithril 2.0.\n * @see https://mithril.js.org/archive/v0.2.5/mithril.withAttr.html\n */\nexport default (key: string, cb: Function) =>\n function (this: Element) {\n cb(this.getAttribute(key) || this[key]);\n };\n"],"sourceRoot":""} \ No newline at end of file diff --git a/js/src/common/utils/humanTime.ts b/js/src/common/utils/humanTime.ts index f97248842..6586658ba 100644 --- a/js/src/common/utils/humanTime.ts +++ b/js/src/common/utils/humanTime.ts @@ -29,7 +29,7 @@ export default function humanTime(time: Date): string { ago = d.format('ll'); } } else { - ago = '5 days'; + ago = d.fromNow(); } return ago;