Browse Source

updated js bulid

Rafał Pitoń 9 years ago
parent
commit
6e8325e61e

+ 0 - 45
docs/developers/user_sites.rst

@@ -1,45 +0,0 @@
-====================
-Extending User Sites
-====================
-
-There are three sites associated with user accounts:
-
-* User Control Panel
-* User Profiles List
-* User Profile
-
-Each of those sites consists of its own layout and list of pages. For example, User Profile layout displays user name, information about user status, and pages (tabs) with lists of user threads, posts, followers and likes.
-
-Each site is associated to instance of special object, :py:class:`misago.users.sites.Site`, which contains list of all pages belonging to it. Those instances are :py:object:`misago.users.sites.usercp`, :py:object:`misago.users.sites.users_list` and :py:object:`misago.users.sites.user_profile`.
-
-:py:class:`misago.users.sites.Site` instances expose following API:
-
-
-.. function:: add_page(link, name, icon=None, after=None, before=None,
-                 	   visible_if=None, badge=None)
-
-Adds page to site. ``after`` and ``before`` arguments should be value of other page ``link``. ``visible_if`` argument accepts callable that will be called with args passed to ``get_pages`` function on page render to resolve if link to page should be displayed. ``badge`` argument should be none or callable that will be called to get button badge, like number of posts on tab.
-
-
-.. function:: get_pages(link, request, profile=None)
-
-Returns list of pages assigned to this site. Each page is a dict of kwargs passed to ``add_page`` with additional ``is_active`` argument that controls if selected page is displayed one.
-
-
-.. function:: get_default_link()
-
-Returns default link name that should be used as argument for ``{% url %}`` template tag.
-
-Default links for Misago sites are available in templates trough following variables:
-
-* **USERCP_URL** - Default link to user control panel site.
-* **USERS_LIST_URL** - Default link to users lists site.
-* **USER_PROFILE_URL** - Default link to user profile site.
-
-
-Adding pages to User Control Panel
-==================================
-
-To add custom page to UserCP, register it on :py:object:`misago.users.sites.usercp` object using ``add_page`` method described above.
-
-After this, write your view(s), making sure they are using :py:object:`misago.users.views.usercp.render` function instead of :py:object:`django.shortcuts.render` to render response, and that your templates are extending ``misago/usercp/base.html`` template, defining custom html in ``page`` block instead of usual ``content``.

+ 2 - 3
misago/static/misago/js/misago.js

@@ -1,4 +1,3 @@
-!function(){"use strict";window.Misago=function(){var t=Object.getPrototypeOf(this),e=this;this._initServices=function(n){var o=new t.OrderedList(n).order(!1);o.forEach(function(t){var n=null;n=void 0!==t.item.factory?t.item.factory:t.item;var o=n(e);o&&(e[t.key]=o)})},this._destroyServices=function(n){var o=new t.OrderedList(n).order();o.reverse(),o.forEach(function(t){void 0!==t.destroy&&t.destroy(e)})},this.context={SETTINGS:{}},this.setup=!1,this.init=function(e,n){this.setup={fixture:t.get(e,"fixture",null),test:t.get(e,"test",!1),api:t.get(e,"api","/api/")},n&&(this.context=n),this._initServices(t._services)},this.destroy=function(){this._destroyServices(t._services)}};var t=window.Misago.prototype;t._services=[],t.addService=function(e,n,o){t._services.push({key:e,item:n,after:t.get(o,"after"),before:t.get(o,"before")})},t.PermissionDenied=function(t){this.detail=t,this.status=403,this.toString=function(){return this.detail||"Permission denied"}}}(),function(t){"use strict";t.has=function(t,e){return t?t.hasOwnProperty(e):!1},t.get=function(e,n,o){return t.has(e,n)?e[n]:void 0!==o?o:void 0},t.pop=function(e,n,o){var r=t.get(e,n,o);return t.has(e,n)&&(e[n]=null),r}}(Misago.prototype),function(t){"use strict";function e(t,e,n){n.retain=!0}t.input=function(t){var n={disabled:t.disabled||!1,config:t.config||e};t.placeholder&&(n.placeholder=t.placeholder),t.autocomplete===!1&&(n.autocomplete="off");var o="input";return t.id&&(o+="#"+t.id,n.key="field-"+t.id),o+=".form-control"+(t["class"]||""),o+='[type="'+(t.type||"text")+'"]',t.value&&(n.value=t.value(),n.oninput=m.withAttr("value",t.value)),m(o,n)}}(Misago.prototype),function(t){"use strict";var e=function(){};t.stateHooks=function(t,n,o){if(t._hasLifecycleHooks)return t;t._hasLifecycleHooks=!0,t.isActive=!0;var r=o.bind(t),i=t.controller||e;if(t.controller=function(){try{t.isActive=!0;var n=i.apply(t,arguments)||{},o=n.onunload||e;return n.onunload=function(){o.apply(t,arguments),t.isActive=!1},n}catch(s){r(s)}},t.vm&&t.vm.init){if(!t.loading){var s=n.bind(t);t.loading=s}var a=t.view;t.view=function(){return t.vm.isReady?a.apply(t,arguments):t.loading.apply(t,arguments)};var u=t.vm.init;t.vm.init=function(){var e=arguments,n=u.apply(t.vm,e);n&&n.then(function(){if(t.isActive&&t.vm.ondata){for(var n=[],o=0;o<arguments.length;o++)n.push(arguments[o]);for(var r=0;r<e.length;r++)n.push(e[r]);t.vm.ondata.apply(t.vm,n)}},function(e){t.isActive&&r(e)})}}return t}}(Misago.prototype),function(t){"use strict";t.OrderedList=function(e){this.isOrdered=!1,this._items=e||[],this.add=function(e,n,o){this._items.push({key:e,item:n,after:t.get(o,"after"),before:t.get(o,"before")})},this.get=function(t,e){for(var n=0;n<this._items.length;n++)if(this._items[n].key===t)return this._items[n].item;return e},this.has=function(t){return void 0!==this.get(t)},this.values=function(){for(var t=[],e=0;e<this._items.length;e++)t.push(this._items[e].item);return t},this.order=function(t){return this.isOrdered||(this._items=this._order(this._items),this.isOrdered=!0),t||"undefined"==typeof t?this.values():this._items},this._order=function(t){function e(t){var e=-1;-1===r.indexOf(t.key)&&(t.after?(e=r.indexOf(t.after),-1!==e&&(e+=1)):t.before&&(e=r.indexOf(t.before)),-1!==e&&(o.splice(e,0,t),r.splice(e,0,t.key)))}var n=[];t.forEach(function(t){n.push(t.key)});var o=[],r=[];t.forEach(function(t){t.after||t.before||(o.push(t),r.push(t.key))}),t.forEach(function(t){"_end"===t.before&&(o.push(t),r.push(t.key))});for(var i=200;i>0&&n.length!==r.length;)i-=1,t.forEach(e);return o}}}(Misago.prototype),function(t){t.serializeDatetime=function(t){return t?t.format():null},t.deserializeDatetime=function(t){return t?moment(t):null}}(Misago.prototype),function(t){"use strict";t.Site=function(t,e){this.name=t,this.isFinalized=!1,this._pages=[];this.addPage=function(t){if(this.isFinalized)throw this.name+" site was initialized already and no longer accepts new pages";this._pages.push(t)},this.getPages=function(){return this.finalize(),this._pages},this.getDefaultLink=function(){return this.finalize(),this._pages[0].link}}}(Misago.prototype),function(t){"use strict";t.startsWith=function(t,e){return 0===t.indexOf(e)},t.endsWith=function(t,e){return-1!==t.indexOf(e,t.length-e.length)}}(Misago.prototype),function(t){"use strict";t.UrlConf=function(){var e=this;this._patterns=[],this.patterns=function(){return this._patterns};var n=function(t,e){return(t+e).replace("//","/")},o=function(t,o){for(var r=0;r<o.length;r++)e.url(n(t,o[r].pattern),o[r].component,o[r].name)};this.url=function(e,n,r){""===e&&(e="/"),n instanceof t.UrlConf?o(e,n.patterns()):this._patterns.push({pattern:e,component:n.replace(/_/g,"-"),name:r||n})}}}(Misago.prototype),function(t){"use strict";t.loadingPage=function(t){return m(".page.page-loading",t.component("loader"))}}(Misago.prototype),function(t){"use strict";var e=function(e){if(-1!==document.cookie.indexOf(e)){var n=new RegExp(e+"=([^;]*)"),o=t.get(document.cookie.match(n),0);return o.split("=")[1]}return null},n=function(n){this.refreshCsrfToken=function(){this.csrfToken=e(n.context.CSRF_COOKIE_NAME)},this.refreshCsrfToken();var o={};this.ajax=function(e,n,r,i){var s=m.deferred(),a={url:n,method:e,headers:{"X-CSRFToken":this.csrfToken},data:r||{},dataType:"json",success:function(r){"GET"===e&&t.pop(o,n),s.resolve(r)},error:function(r){"GET"===e&&t.pop(o,n);var i=r.responseJSON||{};i.status=r.status,i.statusText=r.statusText,s.reject(i)}};return i?void 0:($.ajax(a),s.promise)},this.get=function(e){var r=t.pop(n.context,e);if(r){var i=m.deferred();return i.resolve(r),i.promise}return void 0!==o[e]?o[e]:(o[e]=this.ajax("GET",e),o[e])},this.post=function(t,e){return this.ajax("POST",t,e)},this.patch=function(t,e){return this.ajax("PATCH",t,e)},this.put=function(t,e){return this.ajax("PUT",t,e)},this["delete"]=function(t){return this.ajax("DELETE",t)}};t.addService("ajax",function(t){return new n(t)})}(Misago.prototype),function(t){"use strict";var e=5e3,n=70,o=9e3,r=300,i=function(t){var i=this;this.type="",this.message=null,this.isVisible=!1;var s=function(r,s){i.type=r,i.message=s,i.isVisible=!0;var a=e;a+=s.length*n,a>o&&(a=o),t.runloop.runOnce(function(){m.startComputation(),i.isVisible=!1,m.endComputation()},"flash-message-hide",a)},a=function(e,n){t.runloop.stop("flash-message-hide"),t.runloop.stop("flash-message-show"),i.isVisible?(i.isVisible=!1,t.runloop.runOnce(function(){m.startComputation(),s(e,n),m.endComputation()},"flash-message-show",r)):s(e,n)};this.info=function(t){a("info",t)},this.success=function(t){a("success",t)},this.warning=function(t){a("warning",t)},this.error=function(t){a("error",t)}};t.addService("alert",{factory:function(t){return new i(t)}})}(Misago.prototype),function(t){"use strict";var e=function(t){if("object"==typeof t){var e=[];for(var n in t)if(t.hasOwnProperty(n)){var o=encodeURIComponent(n),r=encodeURIComponent(t[n]);e.push(o+"="+r)}return"?"+e.join("&")}return t+"/"},n=function(t,o){this.url=o.url||t.setup.api,this.url+=o.path?o.path+"/":o.related?o.related+"/":o.model+"s/",o.filters&&(this.url+=e(o.filters)),o.model&&(this.related=function(e,r){return new n(t,{url:this.url,relation:o.model,related:e,filters:r})}),this.endpoint=function(e,o){return new n(t,{url:this.url,path:e,filters:o})},this.get=function(){var e=null;return o.related?e=o.relation+":"+o.related:o.model&&(e=o.model),t.ajax.get(this.url).then(function(n){return e?n.results?(n.results.map(function(n){return t.models["new"](e,n)}),n):t.models["new"](e,n):n})},this.post=function(e){return t.ajax.post(this.url,e)},this.patch=function(e){return t.ajax.patch(this.url,e)},this.put=function(e){return t.ajax.put(this.url,e)},this["delete"]=function(){return t.ajax["delete"](this.url)},this.then=function(t,e){return this.get().then(t,e)}},o=function(t){this.model=function(e,o){return new n(t,{model:e,filters:o})},this.endpoint=function(e,o){return new n(t,{path:e,filters:o})},this.alert=function(e){var n=gettext("Unknown error has occured.");0===e.status&&(n=gettext("Lost connection with application.")),403===e.status&&(n=e.detail,"Permission denied"===n&&(n=gettext("You don't have permission to perform this action."))),404===e.status&&(n=gettext("Action link is invalid.")),t.alert.error(n)}};t.addService("api",function(t){return new o(t)})}(Misago.prototype),function(t){"use strict";var e=function(e){var n=this;e.user=e.models.deserialize("user",e.context.user),this.isDesynced=!1,this.newUser=null;var o=function(t){n.isDesynced||(m.startComputation(),n.isDesynced=!0,t&&(n.newUser=e.localstore.get("auth-user")),m.endComputation())},r=function(t){n.isDesynced||(m.startComputation(),e.user.id!==t.id?(n.isDesynced=!0,n.newUser=t):t&&(e.user=$.extend(e.user,t)),m.endComputation())},i=function(){e.localstore.set("auth-user",e.user),e.localstore.set("auth-is-authenticated",e.user.isAuthenticated),e.localstore.watch("auth-is-authenticated",o),e.localstore.watch("auth-user",r)};i(),this.denyAuthenticated=function(n){if(e.user.isAuthenticated)throw new t.PermissionDenied(n||gettext("This page is not available to signed in users."))},this.denyAnonymous=function(n){if(e.user.isAnonymous)throw new t.PermissionDenied(n||gettext("This page is not available to guests."))}};t.addService("auth",function(t){return new e(t)},{after:"model:user"})}(Misago.prototype),function(t){"use strict";var e=function(){var t=m.deferred();t.resolve(),this.load=function(){return t.promise},this.value=function(){return null}},n=function(t){var e=this;this.loading=!1,this.question=null,this.value=m.prop("");var n=m.deferred();this.load=function(){return this.value(""),this.question||this.loading||(this.loading=!0,t.api.endpoint("captcha-question").get().then(function(t){e.question=t,n.resolve()},function(){t.api.alert(gettext("Failed to load CAPTCHA.")),n.reject()}).then(function(){e.loading=!0})),n.promise},this.component=function(e){return t.component("form-group",{label:this.question.question,labelClass:e.labelClass||null,controlClass:e.controlClass||null,control:t.input({value:t.validate(e.form,"captcha"),id:"id_captcha",disabled:e.form.isBusy}),validation:e.form.errors,validationKey:"captcha",helpText:this.question.help_text})},this.validator=function(){return[]}},o=function(t){this.included=!1,this.question=null;var e=m.deferred(),n=function(e){"undefined"!=typeof grecaptcha?e.resolve():t.runloop.runOnce(function(){n(e)},"loading-grecaptcha",150)};this.load=function(){return"undefined"!=typeof grecaptcha&&grecaptcha.reset(),this.included||(t.include("https://www.google.com/recaptcha/api.js",!0),this.included=!0),n(e),e.promise};var o=function(e,n,o){o.retain=!0,n||grecaptcha.render("recaptcha",{sitekey:t.settings.recaptcha_site_key})};this.component=function(e){var n=m("#recaptcha",{config:o});return t.component("form-group",{label:gettext("Security test"),labelClass:e.labelClass||null,controlClass:e.controlClass||null,control:n,validation:e.form.errors,validationKey:"captcha"})},this.value=function(){return"undefined"!=typeof grecaptcha?grecaptcha.getResponse():""},this.clean=function(t){t.errors.captcha=this.value()?!0:[gettext("This field is required.")]},this.validator=function(){return[]}},r=function(t){var r={no:e,qa:n,re:o},i=new r[t.settings.captcha_type](t);this.value=i.value,this.load=function(){return i.load()},this.component=function(t){return i.component?i.component(t):null},this.validator=function(){return i.validator?i.validator():null},this.clean=function(t){i.clean?i.clean(t):t.errors.captcha=!0}};t.addService("captcha",function(t){return new r(t)},{after:"include"})}(Misago.prototype),function(t){"use strict";var e=function(t,e){if(this._components[t]){if(arguments.length>1){for(var n=[this._components[t]],o=1;o<arguments.length;o+=1)n.push(arguments[o]);return n.push(this),m.component.apply(void 0,n)}return m.component(this._components[t],this)}if(!e)throw'"'+t+"\" component is not registered and can't be created";this._components[t]=e};t.addService("components",function(t){t._components={},t.component=e})}(Misago.prototype),function(t){"use strict";t.addService("conf",function(e){e.settings=t.get(e.context,"SETTINGS",{})})}(Misago.prototype),function(t){"use strict";var e=function(t,e,n){e||(n.retain=!0,$(t).on("click",function(){$(t).removeClass("open")}),n.onunload=function(){$(t).removeClass("open"),$(t).off()})},n=function(t){var n={};this.slot=function(t){return m("#dropdown-"+t+".dropdown.mobile-dropdown",{config:e})},this.toggle=function(e,o){var r=document.getElementById("dropdown-"+e);r.hasChildNodes()&&n[e]===o?(n[e]=null,m.mount(r,null),$(r).removeClass("open")):(n[e]=o,m.mount(r,t.component(o)),$(r).addClass("open"))}};t.addService("dropdown",{factory:function(t){return new n(t)}},{before:"components"})}(Misago.prototype),function(t){"use strict";var e=function(t){var e=t.submit,n=t.success,o=t.error;return t.isBusy=!1,t.errors=null,t.submit=function(){return t.isBusy?!1:(t.clean?t.clean()&&(t.isBusy=!0,e.apply(t)):t.isBusy=!0,!1)},t.success=function(){m.startComputation(),n.apply(t,arguments),t.isBusy=!1,m.endComputation()},t.error=function(){m.startComputation(),o.apply(t,arguments),t.isBusy=!1,m.endComputation()},t.hasErrors=function(){if(null===t.errors)return!1;for(var e in t.validation)if(t.validation.hasOwnProperty(e)&&t.errors[e]!==!0)return!0;return!1},t},n=function(t,n){return this._forms[t]?e(n?new this._forms[t](n,this):new this._forms[t](this)):void(this._forms[t]=n)};t.addService("forms",function(t){t._forms={},t.form=n})}(Misago.prototype),function(t){"use strict";t.addService("forum-layout",{factory:function(t){t.setup.fixture&&m.mount(document.getElementById(t.setup.fixture),t.component("forum-layout"))},destroy:function(t){t.setup.fixture&&m.mount(document.getElementById(t.setup.fixture),null)}},{before:"start-routing"})}(Misago.prototype),function(t){"use strict";var e=function(t,e){e||(t=this.context.STATIC_URL+t),$.ajax({url:t,cache:!0,dataType:"script"})};t.addService("include",function(t){t.include=e},{after:"conf"})}(Misago.prototype),function(t){"use strict";var e=function(){var t=window.localStorage,e="_misago_",n=[],o=function(t){var e=JSON.parse(t.newValue);$.each(n,function(n,o){o.keyName===t.key&&t.oldValue!==t.newValue&&o.callback(e)})};window.addEventListener("storage",o);var r=function(t){return e+t};this.set=function(e,n){t.setItem(r(e),JSON.stringify(n))},this.get=function(e){var n=t.getItem(r(e));return n?JSON.parse(n):null},this.watch=function(t,e){n.push({keyName:r(t),callback:e})},this.destroy=function(){this.watchers=[]}};t.addService("localstore",{factory:function(){return new e},destroy:function(t){t.localstore.destroy()}})}(Misago.prototype),function(t){"use strict";var e=function(){var t=this,e=document.getElementById("misago-modal"),n="click.misago-modal";$(e).on(n,"a",function(){t.hide()}),this.destroy=function(){$(e).off(),$("body").removeClass("modal-open"),$(".modal-backdrop").remove()};var o=$(e).modal({show:!1});this.open=!1,o.on("hidden.bs.modal",function(){t.open&&(m.mount(e,null),this.open=!1)}),this.show=function(t){this.open=!0,m.mount(e,t),o.modal("show")},this.hide=function(){o.modal("hide")}};t.addService("_modal",{factory:function(){return new e},destroy:function(t){t._modal.destroy()}},{after:"start-routing"})}(Misago.prototype),function(t){"use strict";var e=function(t,e){if(this._modals[t]){for(var n=[this._modals[t]],o=1;o<arguments.length;o+=1)n.push(arguments[o]);n.push(this),this._modal.show(m.component.apply(m,n))}else t?this._modals[t]=e:this._modal.hide()};t.addService("modals",function(t){t._modals={},t.modal=e},{after:"_modal"})}(Misago.prototype),function(t){"use strict";var e=function(){this.classes={},this.deserializers={},this.add=function(t,e){e["class"]&&(this.classes[t]=e["class"]),e.deserialize&&(this.deserializers[t]=e.deserialize)},this["new"]=function(t,e){return this.classes[t]?(e.id=e.id?String(e.id):null,new this.classes[t](e)):e},this.deserialize=function(t,e){return this.deserializers[t]?this["new"](t,this.deserializers[t](e,this)):this["new"](t,e)}};t.addService("models",function(){return new e})}(Misago.prototype),function(t){"use strict";t.addService("set-momentjs-locale",function(){moment.locale($("html").attr("lang"))})}(Misago.prototype),function(t){"use strict";var e=function(e){var n=this;this.baseUrl=$("base").attr("href");var o=t.get(e.context,"STATIC_URL","/"),r=t.get(e.context,"MEDIA_URL","/");this.urls={},this.reverses={};var i=function(t){t.patterns().forEach(function(t){var o=n.baseUrl+t.pattern;o=o.replace("//","/"),n.urls[o]=e.route(t.component),n.reverses[t.name]=o})};this.startRouting=function(t,n){i(t),this.fixture=n,m.route.mode=e.setup.test?"search":"pathname",m.route(n,"/",this.urls)},this.url=function(t){return this.reverses[t]},this.route=function(t){m.route(t)},this.redirect=function(t){this.route(this.url(t))},this.delegateElement=null,this.cleanUrl=function(t){if(t){var e="/"===t.substr(0,1)&&"//"!==t.substr(0,2);if(!e){var n=window.location;if("//"!==t.substr(0,2)){var i=t.substr(0,n.protocol.length+2);if(i!==n.protocol+"//")return;t=t.substr(n.protocol.length+2)}else t=t.substr(2);if(t.substr(0,n.host.length)!==n.host)return;t=t.substr(n.host.length)}if(t.substr(0,this.baseUrl.length)===this.baseUrl&&t.substr(0,o.length)!==o&&t.substr(0,r.length)!==r){var s="/user-avatar/";if(t.substr(0,s.length)!==s)return t}}};var s="click.misago-router",a='a:not([data-misago-routed="false"])';this.delegateClicks=function(t){this.delegateElement=t,$(this.delegateElement).on(s,a,function(t){var e=n.cleanUrl(t.currentTarget.href);e&&(e!=m.route()&&n.route(e),t.preventDefault())})},this.destroy=function(){$(this.delegateElement).off(s)};var u=function(t){return function(e){return t+e}};this.staticUrl=u(o),this.mediaUrl=u(r),this.error403=function(t){var n=null;n=t.ban?e.route("error:banned",t.detail,e.models.deserialize("ban",t.ban)):e.route("error:403",t.detail),m.mount(this.fixture,n)},this.error404=function(){m.mount(this.fixture,e.route("error:404"))},this.error500=function(){m.mount(this.fixture,e.route("error:500"))},this.error0=function(){m.mount(this.fixture,e.route("error:0"))},this.errorPage=function(t){0===t.status&&this.error0(),500===t.status&&this.error500(),404===t.status&&this.error404(),403===t.status&&this.error403(t)}};t.addService("router",function(t){return new e(t)}),t.addService("start-routing",function(e){var n=function(){var o=document.getElementById("router-fixture");o?(e.router.startRouting(t.urls,document.getElementById("router-fixture")),e.router.delegateClicks(document.getElementById(e.setup.fixture))):window.setTimeout(function(){n()},10)};n()},{before:"_end"})}(Misago.prototype),function(t){"use strict";var e=function(e){if(e._hasRouteBoilerplate)return e;e._hasRouteBoilerplate=!0;var n=function(){var t=this.container;return m(".page.page-loading",t.component("loader"))},o=function(t){if(!this.isActive||"undefined"==typeof t.status)throw t;this.vm&&this.vm.onerror?this.vm.onerror(t,this.container):this.container.router.errorPage(t)};return t.stateHooks(e,n,o)};t.addService("routes",function(t){t._routes={},t.route=function(n,o){if(this._routes[n]){if(arguments.length>1){for(var r=[this._routes[n]],i=1;i<arguments.length;i+=1)r.push(arguments[i]);return r.push(this),m.component.apply(void 0,r)}return m.component(this._routes[n],this)}if(!o)throw'"'+n+"\" route is not registered and can't be created";o.container=t,this._routes[n]=e(o)}})}(Misago.prototype),function(t){"use strict";var e=function(t){var e=this;this._intervals={};var n=function(t){e._intervals[t]&&(window.clearTimeout(e._intervals[t]),e._intervals[t]=null)};this.run=function(o,r,i){this._intervals[r]=window.setTimeout(function(){n(r);var s=o(t);s!==!1&&e.run(o,r,i)},i)},this.runOnce=function(e,o,r){this._intervals[o]=window.setTimeout(function(){n(o),e(t)},r)},this.stop=function(t){for(var e in this._intervals)t&&t!==e||n(e)}};t.addService("runloop",{factory:function(t){return new e(t)},destroy:function(t){t.runloop.stop()}})}(Misago.prototype),function(t){"use strict";t.addService("start-tick",function(t){var e=m.prop();t.runloop.run(function(){m.startComputation(),e(e()+1),m.endComputation()},"tick",6e4)})}(Misago.prototype),function(t){"use strict";var e=function(t){this.set=function(e){e?this._set_complex(e):document.title=t},this._set_complex=function(e){"string"==typeof e&&(e={title:e});var n=e.title;if("undefined"!=typeof e.page&&e.page>1){var o=interpolate(gettext("page %(page)s"),{page:e.page},!0);n+=" ("+o+")"}"undefined"!=typeof e.parent&&(n+=" | "+e.parent),document.title=n+" | "+t}};t.addService("page-title",function(t){t.title=new e(t.settings.forum_name)})}(Misago.prototype),function(t){"use strict";var e=/^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i,n=new RegExp("^[0-9a-z]+$","i");t.validators={required:function(){return function(t){return 0===$.trim(t).length?gettext("This field is required."):void 0}},email:function(t){return function(n){return e.test(n)?void 0:t||gettext("Enter a valid email address.")}},minLength:function(t,e){return function(n){var o="",r=$.trim(n).length;return t>r?(o=e?e(t,r):ngettext("Ensure this value has at least %(limit_value)s character (it has %(show_value)s).","Ensure this value has at least %(limit_value)s characters (it has %(show_value)s).",t),interpolate(o,{limit_value:t,show_value:r},!0)):void 0}},maxLength:function(t,e){return function(n){var o="",r=$.trim(n).length;return r>t?(o=e?e(t,r):ngettext("Ensure this value has at most %(limit_value)s character (it has %(show_value)s).","Ensure this value has at most %(limit_value)s characters (it has %(show_value)s).",t),interpolate(o,{limit_value:t,show_value:r},!0)):void 0}},usernameMinLength:function(t){var e=function(t){return ngettext("Username must be at least %(limit_value)s character long.","Username must be at least %(limit_value)s characters long.",t)};return this.minLength(t.username_length_min,e)},usernameMaxLength:function(t){var e=function(t){return ngettext("Username cannot be longer than %(limit_value)s character.","Username cannot be longer than %(limit_value)s characters.",t)};return this.maxLength(t.username_length_max,e)},usernameContent:function(){return function(t){return n.test($.trim(t))?void 0:gettext("Username can only contain latin alphabet letters and digits.")}},passwordMinLength:function(t){var e=function(t){return ngettext("Valid password must be at least %(limit_value)s character long.","Valid password must be at least %(limit_value)s characters long.",t)};return this.minLength(t.password_length_min,e)}};var o=function(e,n){var o=t.validators.required()(e),r=[];if(o)return[o];for(var i in n)o=n[i](e),o&&r.push(o);return r.length?r:!0},r=function(t){var e={},n=null,r=!0;for(var i in t.validation)t.validation.hasOwnProperty(i)&&(n=t[i](),e[i]=o(t[i](),t.validation[i]),e[i]!==!0&&(r=!1));return t.errors=e,r},i=function(t,e){return e?function(n){var r=null;return"undefined"!=typeof n?(r=o(n,t.validation[e]),r&&(t.errors||(t.errors={}),t.errors[e]=r),t[e](n),t[e](n)):t[e]()}:r(t)};t.addService("validate",{factory:function(){return i}})}(Misago.prototype),function(t){"use strict";var e=function(t){this.included=!1,this.scorePassword=function(t,e){return zxcvbn(t,e).score},this.include=function(){t.include("misago/js/zxcvbn.js"),this.included=!0};var e=function(n){"undefined"!=typeof zxcvbn?n.resolve():t.runloop.runOnce(function(){e(n)},"loading-zxcvbn",150)},n=m.deferred();this.load=function(){return this.included||this.include(),e(n),n.promise}};t.addService("zxcvbn",function(t){return new e(t)},{after:"include"})}(Misago.prototype),function(t){"use strict";var e=function(t){this.message={html:t.message.html,plain:t.message.plain},this.expires_on=t.expires_on},n=function(e){return e.expires_on=t.deserializeDatetime(e.expires_on),e};t.addService("model:ban",function(t){t.models.add("ban",{"class":e,deserialize:n})},{after:"models"})}(Misago.prototype),function(t){"use strict";var e=function(t){this.title=t.title,this.body=t.body,this.link=t.link};t.addService("model:legal-page",function(t){t.models.add("legal-page",{"class":e})},{after:"models"})}(Misago.prototype),function(t){"use strict";var e=function(t){this.id=t.id,this.name=t.name,this.slug=t.slug,this.description=t.description,this.title=t.title,this.css_class=t.css_class,this.is_tab=t.is_tab};t.addService("model:rank",function(t){t.models.add("rank",{"class":e})},{after:"models"})}(Misago.prototype),function(t){"use strict";var e=function(t){this.id=t.id,this.isAuthenticated=!!this.id,this.isAnonymous=!this.isAuthenticated,this.username=t.username,this.slug=t.slug,this.email=t.email,this.full_title=t.full_title,this.rank=t.rank,this.avatar_hash=t.avatar_hash,this.acl=t.acl},n=function(e,n){return e.joined_on&&(e.joined_on=t.deserializeDatetime(e.joined_on)),e.rank&&(e.rank=n.deserialize("rank",e.rank)),e};t.addService("model:user",function(t){t.models.add("user",{"class":e,deserialize:n})},{after:"model:rank"})}(Misago.prototype),function(t){"use strict";var e={error:null,username:null,isReady:!1,init:function(t){this.error=null,this.user=null,this.isReady=!1;var e=t.api.endpoint("auth").endpoint("activate-account");return e=e.endpoint(m.route.param("user_id")),e=e.endpoint(m.route.param("token")),e.post()},ondata:function(t,e){m.startComputation(),e.title.set(gettext("Account activated")),this.username=t.username,this.isReady=!0,m.endComputation()},onerror:function(t,e){400===t.status?(m.startComputation(),this.error=t,this.isReady=!0,m.endComputation()):e.router.errorPage(t)}},n={controller:function(t){t.auth.denyAuthenticated(gettext("You have to be signed out to activate account.")),t.title.set(gettext("Account activation")),this.vm.init(t)},vm:e,view:function(t,e){return this.vm.error?this.rejected(this.vm.error,e):this.success(this.vm.username,e)},success:function(t){var e=gettext("%(username)s, your account has been successfully activated!");return m(".page.page-message.page-message-success",m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon","check")),m(".message-body",[m("p.lead",interpolate(e,{username:t},!0)),m("p",gettext("You can now sign in to finish setting up your account and to participate in or start new discussions."))])])))},rejected:function(t){return m(".page.page-message.page-message-info",m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon","info_outline")),m(".message-body",[m("p.lead",gettext("Your account can't be activated at this time.")),m("p",t.detail)])])))},loading:function(t,e){return m(".page.page-loading",[e.component("loader"),m("p.lead",gettext("Activating account..."))])}};t.addService("route:activate-by-token",function(t){t.route("activate-by-token",n)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e={error:null,isReady:!1,form:null,init:function(t){this.error=null,this.user=null,this.isReady=!1;var e=t.api.endpoint("auth").endpoint("change-password");return e=e.endpoint(m.route.param("user_id")),e=e.endpoint(m.route.param("token")),e.get()},ondata:function(t,e){m.startComputation(),e.title.set(gettext("Change forgotten password")),this.form=e.form("change-password"),this.isReady=!0,m.endComputation()},onerror:function(t,e){400===t.status?(m.startComputation(),this.error=t,this.isReady=!0,m.endComputation()):e.router.errorPage(t)}},n={controller:function(t){return this.vm.init(t),{signin:function(){t.modal("sign-in")}}},vm:e,view:function(t,e){return this.vm.error?this.rejected(this.vm.error,e):this.vm.form.username?this.complete(t,this.vm.form.username,e):this.form(this.vm.form,e)},form:function(e,n){return m(".page.page-change-password",[n.component("header",{title:gettext("Change forgotten password")}),m(".container",m(".row",m(".col-md-4.col-md-offset-4",m(".well.well-form",m("form",{onsubmit:e.submit},[m(".form-group",m(".control-input",t.input({disabled:e.isBusy,value:e.password,type:"password",placeholder:gettext("Enter new password")}))),n.component("button",{"class":".btn-primary.btn-block",submit:!0,loading:e.isBusy,label:gettext("Change password")})])))))])},complete:function(t,e,n){var o=gettext("%(username)s, your password has been changed successfully.");return m(".page.page-message.page-message-success",m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon","check")),m(".message-body",[m("p.lead",interpolate(o,{username:e},!0)),m("p",gettext("You can now sign in to your account using your new password.")),m("p",n.component("button",{"class":".btn-default",submit:!1,label:gettext("Sign in"),onclick:t.signin}))])])))},rejected:function(t){return m(".page.page-message.page-message-info",m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon","info_outline")),m(".message-body",[m("p.lead",gettext("Your account can't be activated at this time.")),m("p",t.detail)])])))}};t.addService("route:change-password",function(t){t.route("change-password",n)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e=function(t){var e=[m("p.lead",t.message)];return t.help&&e.push(m("p.help",t.help)),m(".page.page-error.page-error-"+t.code,m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon",t.icon)),m(".message-body",e)])))},n={controller:function(){this.container.title.set(gettext("You are banned"))},view:function(t,e,n){var o=[];o.push(n.message.html?m(".lead",m.trust(n.message.html)):e?m("p.lead",e):m("p.lead",gettext("You are banned.")));var r=null;return r=n.expires_on?n.expires_on.isAfter(moment())?interpolate(gettext("This ban expires %(expires_on)s."),{expires_on:n.expires_on.fromNow()},!0):gettext("This ban has expired."):gettext("This ban is permanent."),o.push(m("p",r)),m(".page.page-error.page-error-banned",m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon","highlight_off")),m(".message-body",o)])))}},o={controller:function(){this.container.title.set(gettext("Page not available"))},view:function(t,n){return"Permission denied"===n&&(n=gettext("You don't have permission to access this page.")),e({code:403,icon:"remove_circle_outline",message:gettext("This page is not available."),help:n})}},r={controller:function(){this.container.title.set(gettext("Page not found"))},view:function(){return e({code:404,icon:"info_outline",message:gettext("Requested page could not be found."),help:gettext("The link you followed was incorrect or the page has been moved or deleted.")})}},i={controller:function(){this.container.title.set(gettext("Application error occured"))},view:function(){return e({code:500,icon:"error_outline",message:gettext("Requested page could not be displayed due to an error."),help:gettext("Please try again later or contact site staff if error persists.")})}},s={controller:function(){this.container.title.set(gettext("Lost connection with application"))},view:function(){return e({code:0,icon:"sync_problem",message:gettext("Could not connect to application."),help:gettext("This may be caused by problems with your connection or application server. Please check your internet connection and refresh page if problem persists.")})}};t.addService("route:error-pages",function(t){t.route("error:banned",n),t.route("error:403",o),t.route("error:404",r),t.route("error:500",i),t.route("error:0",s)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e={controller:function(t){return document.title=t.settings.forum_index_title||t.settings.forum_name,{activation:function(){t.router.url("request_activation")}}},view:function(t,e){return m(".container",[m("h1","Activation"),m("p","Test auth blocks"),m("p",m("a",{href:e.router.url("request_activation")},"Request activation."))])}};t.addService("route:index",function(t){t.route("index",e)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e=function(e,n){var o=e.replace(/_/g,"-");return{controller:function(n){t.get(n.settings,e+"_link")?window.location=t.get(n.settings,e+"_link"):this.vm.init(this,n);
-
-},vm:{page:null,isReady:!1,init:function(t,e){return this.isReady?void e.title.set(this.title):(e.title.set(),e.api.model("legal-page",o))},ondata:function(t,e,o){m.startComputation(),t.link?window.location=t.link:(t.title=t.title||n,this.page=t,this.isReady=!0,m.endComputation(),e.isActive&&o.title.set(this.page.title))}},view:function(t,e){return m(".page.page-legal.page-legal-"+o,[e.component("header",{title:this.vm.page.title}),m(".container",e.component("markup",this.vm.page.body))])}}};t.addService("route:legal-pages",function(t){t.route("terms-of-service",e("terms_of_service",gettext("Terms of service"))),t.route("privacy-policy",e("privacy_policy",gettext("Privacy policy")))},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e=function(){this.endpoint="send-activation",this.user=null,this.success=function(t){this.user=t},this.error=function(t,e){"already_active"===t.code?(e.alert.info(t.detail),e.modal("sign-in")):"inactive_admin"===t.code?e.alert.info(t.detail):e.alert.error(t.detail)},this.reset=function(){this.user=null}},n={controller:function(t){t.auth.denyAuthenticated(gettext("You have to be signed out to activate account.")),t.title.set(gettext("Activate your account"));var n=new e;return{vm:n,form:t.form("request-link",n)}},view:function(t,e){return t.vm.user?this.completed(t.form,t.vm,e):this.form(t.form,e)},completed:function(t,e,n){var o=gettext("%(username)s, we have sent your activation link to %(email)s.");return m(".page.page-message.page-message-success",m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon","check")),m(".message-body",[m("p.lead",gettext("Activation link has been sent.")),m("p",interpolate(o,{username:e.user.username,email:e.user.email},!0)),m("p",n.component("button",{"class":".btn-default",submit:!1,label:gettext("Request another link"),onclick:t.reset.bind(t)}))])])))},form:function(t,e){return m(".page.page-request-activation",[e.component("header",{title:gettext("Request activation link")}),m(".container",m(".row",[m(".col-md-8",[m("p",gettext("Site administrator may impose requirement on newly regitered accounts to be activated before users will be able to sign in.")),m("p",gettext("Depending on time of registration, you will be able activate your account by clicking special activation link. This link will be valid only for your browser, for seven days or until your account is activated.")),m("p",gettext('To receive this link, enter your account\'s e-mail addres in form and press "Send link" button.'))]),m(".col-md-4",e.component("request-link-form",t))]))])}};t.addService("route:request-activation",function(t){t.route("request-activation",n)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e=function(){this.endpoint="send-password-form",this.user=null,this.activation=null,this.activationMessage=null,this.success=function(t){this.user=t},this.error=function(t,e){["inactive_user","inactive_admin"].indexOf(t.code)>-1?(this.activation=t.code,this.activationMessage=t.detail):e.alert.error(t.detail)},this.reset=function(){this.user=null,this.activation=null,this.activationMessage=null}},n={controller:function(t){t.title.set(gettext("Change forgotten password"));var n=new e;return{vm:n,form:t.form("request-link",n)}},view:function(t,e){return t.vm.user?this.completed(t.form,t.vm,e):t.vm.activation?this.inactive(t.form,t.vm,e):this.form(t.form,e)},completed:function(t,e,n){var o=gettext("%(username)s, we have sent link to your password change form to %(email)s.");return m(".page.page-message.page-message-success",m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon","check")),m(".message-body",[m("p.lead",gettext("Change password form link sent.")),m("p",interpolate(o,{username:e.user.username,email:e.user.email},!0)),m("p",n.component("button",{"class":".btn-default",submit:!1,label:gettext("Request another link"),onclick:t.reset.bind(t)}))])])))},inactive:function(t,e,n){var o=null;return"inactive_user"===e.activation&&(o=m("a.btn.btn-primary",{href:n.router.url("request_activation")},gettext("Activate account"))),m(".page.page-message.page-message-info",m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon","info_outline")),m(".message-body",[m("p.lead",gettext("Your account is inactive.")),m("p",e.activationMessage),m("p",[o,n.component("button",{"class":".btn-default",submit:!1,label:gettext("Request another link"),onclick:t.reset.bind(t)})])])])))},form:function(t,e){return m(".page.page-request-activation",[e.component("header",{title:gettext("Change forgotten password")}),m(".container",m(".row",[m(".col-md-8",[m("p",gettext("Because user passwords are processed in an irreversible way before being saved to database, it is not possible for us to simply send you your password.")),m("p",gettext("Instead, you can change your password using special secure form that will be available by special link valid only for your browser, for seven days or until your password is changed.")),m("p",gettext('To receive this link, enter your account\'s e-mail addres in form and press "Send link" button.'))]),m(".col-md-4",e.component("request-link-form",t))]))])}};t.addService("route:request-password-change",function(t){t.route("request-password-change",n)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e={view:function(t,e){return m("",[e.component("header",{title:gettext("Options")}),m(".container",m("p","Lorem ipsum dolor met."))])}};t.addService("component:options:nav:dropdown",function(t){t.component("options:nav:dropdown",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={controller:function(t){t.auth.denyAnonymous(gettext("You have to be signed in to change your options.")),this.container.title.set({title:gettext("E-mail"),parent:gettext("Options")})},view:function(t,e){return m(".page.page-options.page-forum-options",[e.component("header",{title:gettext("Change options")}),m(".container",m("p","Lorem ipsum dolor met."))])}};t.addService("route:options:email",function(t){t.route("options-email",e)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e={controller:function(t){t.auth.denyAnonymous(gettext("You have to be signed in to change your options.")),this.container.title.set({title:gettext("Forum options"),parent:gettext("Options")})},view:function(t,e){return m(".page.page-options.page-forum-options",[e.component("header",{title:gettext("Options")}),m(".container",m("p","Lorem ipsum dolor met."))])}};t.addService("route:options:forum",function(t){t.route("options-forum",e)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e={controller:function(t){t.auth.denyAnonymous(gettext("You have to be signed in to change your options.")),t.router.redirect("options_forum")}};t.addService("route:options",function(t){t.route("options",e)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e={controller:function(t){t.auth.denyAnonymous(gettext("You have to be signed in to change your options.")),this.container.title.set({title:gettext("Password"),parent:gettext("Options")})},view:function(t,e){return m(".page.page-options.page-forum-options",[e.component("header",{title:gettext("Change options")}),m(".container",m("p","Lorem ipsum dolor met."))])}};t.addService("route:options:password",function(t){t.route("options-password",e)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e={view:function(t,e){return m(".list-group.nav-side",[])}};t.addService("component:options:nav:side",function(t){t.component("options:nav:side",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";function e(t,e,n){n.retain=!0}var n={classes:{info:"alert-info",success:"alert-success",warning:"alert-warning",error:"alert-danger"},view:function(t,n){return m(".alerts",{config:e,"class":n.alert.isVisible?"in":"out"},m("p.alert",{"class":this.classes[n.alert.type]},n.alert.message))}};t.addService("component:alert",function(t){t.component("alert",n)},{after:"components"})}(Misago.prototype),function(t){"use strict";function e(t,e,n){n.retain=!0}var n={refresh:function(){window.location.reload()},view:function(t,n){var o="",r={config:e,"class":n.auth.isDesynced?"show":null};return n.auth.isDesynced&&(n.auth.newUser&&n.auth.newUser.isAuthenticated?(o=gettext("You have signed in as %(username)s. Please refresh this page before continuing."),o=interpolate(o,{username:n.auth.newUser.username},!0)):(o=gettext("%(username)s, you have been signed out. Please refresh this page before continuing."),o=interpolate(o,{username:n.user.username},!0))),m(".auth-changed-message",r,m("",m(".container",[m("p",o),m("p",[m('button.btn.btn-default[type="button"]',{onclick:this.refresh},gettext("Reload page")),m("span.hidden-xs.hidden-sm.text-muted",gettext("or press F5 key."))])])))}};t.addService("component:auth-changed-message",function(t){t.component("auth-changed-message",n)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(t,e){var n={disabled:e.disabled||e.loading||!1,config:e.config||null,loading:e.loading||!1,type:e.submit?"submit":"button",onclick:e.onclick||null},o='button[type="'+n.type+'"].btn';n.loading&&(o+=".btn-loading"),e.id&&(o+="#"+e.id),o+=e["class"]||"";var r=e.label;return n.loading&&(r=[r,m(".loader-compact",[m(".bounce1"),m(".bounce2"),m(".bounce3")])]),m(o,n,r)}};t.addService("component:button",function(t){t.component("button",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e=["text","password","email"],n={view:function(t,n){var o=".form-group",r=null,i=null,s=n.control.attrs.type,a=n.control.attrs.id,u=a+"_feedback",c=null,l=null,d=n.validationKey&&null!==n.validation;return n.control.attrs["aria-describedby"]="",d&&n.validation[n.validationKey]&&(l=e.indexOf(s)>=0,n.control.attrs["aria-describedby"]=u,n.validation[n.validationKey]===!0?(o+=".has-success",c=[m("span.material-icon.form-control-feedback",{"aria-hidden":"true"},"check"),m("span.sr-only#"+u,gettext("(success)"))]):(o+=".has-error",r=n.validation[n.validationKey],c=[m("span.material-icon.form-control-feedback",{"aria-hidden":"true"},"clear"),m("span.sr-only#"+u,gettext("(error)"))])),n.helpText&&(i="string"==typeof n.helpText||n.helpText instanceof String?m("p.help-block",n.helpText):n.helpText),m(o,[m("label.control-label"+(n.labelClass||""),{"for":n.labelFor||a},n.label+":"),m(n.controlClass||"",[n.control,l?c:null,r?m(".help-block.errors",r.map(function(t){return m("p",t)})):null,i])])}};t.addService("component:form-group",function(t){t.component("form-group",n)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e=function(t,e,n){n.retain=!0},n={view:function(t,n){return[n.component("auth-changed-message"),n.component("alert"),n.component("navbar"),m(".navbar-dropdown",n.dropdown.slot("navbar-dropdown")),m("#router-fixture",{config:e}),n.component("footer"),n.component("modal")]}};t.addService("component:layout",function(t){t.component("forum-layout",n)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(){return m(".loader.sk-folding-cube",[m(".sk-cube1.sk-cube"),m(".sk-cube2.sk-cube"),m(".sk-cube4.sk-cube"),m(".sk-cube3.sk-cube")])}};t.addService("component:loader",function(t){t.component("loader",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e=function(t,e,n){n.retain=!0},n={view:function(t,n){return m("article.misago-markup",{config:e},m.trust(n))}};t.addService("component:markup",function(t){t.component("markup",n)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e=function(t,e,n){n.retain=!0},n={view:function(){return m('#misago-modal.modal.fade[role="dialog"]',{config:e,tabindex:"-1","aria-labelledby":"misago-modal-label"})}};t.addService("component:modal",function(t){t.component("modal",n)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(t,e){return m(".page-header",m(".container",[m("h1",e.title)]))}};t.addService("component:header",function(t){t.component("header",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e=function(t,e,n){n.retain=!0},n=["progress-bar-danger","progress-bar-warning","progress-bar-warning","progress-bar-primary","progress-bar-success"],o=[gettext("Entered password is very weak."),gettext("Entered password is weak."),gettext("Entered password is average."),gettext("Entered password is strong."),gettext("Entered password is very strong.")],r={view:function(t,r,i){var s=i.zxcvbn.scorePassword(r.password,r.inputs),a={config:e,"class":n[s],style:"width: "+(20+20*s)+"%",role:"progressbar","aria-valuenow":s,"aria-valuemin":"0","aria-valuemax":"4"};return m(".help-block.password-strength",{key:"password-strength"},[m(".progress",m(".progress-bar",a,m("span.sr-only",o[s]))),m("p.text-small",o[s])])}};t.addService("component:password-strength",function(t){t.component("password-strength",r)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={defaultSize:100,src:function(t,e,n){var o=n.router.baseUrl+"user-avatar/";return o+=t&&t.id?t.avatar_hash+"/"+e+"/"+t.id+".png":e+".png"},view:function(t,e,n,o){var r=n||this.defaultSize;return m("img",{alt:e&&e.username?e.username:gettext("Unregistered"),width:r,height:r,src:this.src(e,r,o)})}};t.addService("component:user-avatar",function(t){t.component("user-avatar",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(t,e){return m(".modal-header",[m('button.close[type="button"]',{"data-dismiss":"modal","aria-label":gettext("Close")},m("span",{"aria-hidden":"true"},m.trust("&times;"))),m("h4#misago-modal-label.modal-title",e)])}};t.addService("component:modal:header",function(t){t.component("modal:header",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e=function(t,e,n){n.retain=!0},n=function(){document.location.reload()},o={controller:function(t,e){"active"===t.activation&&e.runloop.runOnce(n,"refresh-after-registration",1e4)},view:function(t,n,o){var r=null;return r="active"===n.activation?this.active(n):this.inactive(n),m('.modal-dialog.modal-message.modal-register[role="document"]',{config:e},m(".modal-content",[o.component("modal:header",gettext("Registration complete")),m(".modal-body",r)]))},active:function(t){var e=gettext("%(username)s, your account has been created and you were signed in.");return[m(".message-icon",m("span.material-icon","check")),m(".message-body",[m("p.lead",interpolate(e,{username:t.username},!0)),m("p",gettext("The page will refresh automatically in 10 seconds.")),m("p",m('button[type="button"].btn.btn-default',{onclick:n},gettext("Refresh page")))])]},inactive:function(t){var e=null,n=null;return"user"===t.activation?(e=gettext("%(username)s, your account has been created but you need to activate it before you will be able to sign in."),n=gettext("We have sent an e-mail to %(email)s with link that you have to click to activate your account.")):"admin"===t.activation&&(e=gettext("%(username)s, your account has been created but board administrator will have to activate it before you will be able to sign in."),n=gettext("We will send an e-mail to %(email)s when this takes place.")),[m(".message-icon",m("span.material-icon","info_outline")),m(".message-body",[m("p.lead",interpolate(e,{username:t.username},!0)),m("p",interpolate(n,{email:t.email},!0))])]}};t.addService("modal:register-complete",function(t){t.modal("register-complete",o)},{after:"modals"})}(Misago.prototype),function(t){"use strict";var e=function(t,e,n){n.retain=!0},n={controller:function(t){return{form:t.form("register")}},view:function(t,n){var o=n.captcha.component({form:t.form,labelClass:".col-md-4",controlClass:".col-md-8"}),r=null,i=n.settings.terms_of_service_link;return!i&&n.settings.terms_of_service&&(i=n.router.url("terms_of_service")),i&&(r=m("a",{href:i},m.trust(interpolate(gettext("By registering you agree to site's %(terms)s."),{terms:"<strong>"+gettext("terms and conditions")+"</strong>"},!0)))),m('.modal-dialog.modal-form.modal-register[role="document"]',{config:e},m(".modal-content",[n.component("modal:header",gettext("Register")),m("form.form-horizontal",{onsubmit:t.form.submit},[m('input[type="text"]',{name:"_username",style:"display: none"}),m('input[type="password"]',{name:"_password",style:"display: none"}),m(".modal-body",[n.component("form-group",{label:gettext("Username"),labelClass:".col-md-4",controlClass:".col-md-8",control:n.input({value:n.validate(t.form,"username"),id:"id_username",disabled:t.form.isBusy}),validation:t.form.errors,validationKey:"username"}),n.component("form-group",{label:gettext("E-mail"),labelClass:".col-md-4",controlClass:".col-md-8",control:n.input({value:n.validate(t.form,"email"),id:"id_email",disabled:t.form.isBusy}),validation:t.form.errors,validationKey:"email"}),n.component("form-group",{label:gettext("Password"),labelClass:".col-md-4",controlClass:".col-md-8",control:n.input({value:n.validate(t.form,"password"),type:"password",id:"id_password",disabled:t.form.isBusy}),validation:t.form.errors,validationKey:"password",helpText:n.component("password-strength",{inputs:[t.form.username(),t.form.email()],password:t.form.password()})}),o]),m(".modal-footer",[r,n.component("button",{"class":".btn-primary",submit:!0,loading:t.form.isBusy,label:gettext("Register account")})])])]))}};t.addService("modal:register",function(t){t.modal("register",n)},{after:"modals"})}(Misago.prototype),function(t){"use strict";function e(t,e,n){n.retain=!0}var n={controller:function(t){return{form:t.form("sign-in")}},view:function(n,o){var r=null;return n.form.showActivation&&(r=m("a.btn.btn-block.btn-success",{href:o.router.url("request_activation")},gettext("Activate account"))),m('.modal-dialog.modal-sm.modal-signin[role="document"]',{config:e},m(".modal-content",[o.component("modal:header",gettext("Sign in")),m("form",{onsubmit:n.form.submit},[m(".modal-body",[m(".form-group",m(".control-input",t.input({disabled:n.form.isBusy,value:n.form.username,placeholder:gettext("Username or e-mail")}))),m(".form-group",m(".control-input",t.input({type:"password",disabled:n.form.isBusy,value:n.form.password,placeholder:gettext("Password")})))]),m(".modal-footer",[r,o.component("button",{"class":".btn-primary.btn-block",submit:!0,loading:n.form.isBusy,label:gettext("Sign in")}),m("a.btn.btn-block.btn-default",{href:o.router.url("request_password_change")},gettext("Forgot password?"))])])]))}};t.addService("modal:sign-in",function(t){t.modal("sign-in",n)},{after:"modals"})}(Misago.prototype),function(t){"use strict";var e={style:".navbar.navbar-misago.navbar-default.navbar-static-top",mainNav:function(t){var e=[{label:gettext("Threads"),icon:"chat",url:t.router.url("index")},{label:gettext("Forums"),icon:"forum",url:"/not-yet/forums/"},{label:gettext("Users"),icon:"group",url:"/not-yet/users/"}];return e},view:function(t,e){var n=this.mainNav(e);return m("nav"+this.style+'[role="navigation"]',[e.component("navbar:desktop",n),e.component("navbar:mobile",n)])}};t.addService("component:navbar",function(t){t.component("navbar",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={controller:function(t){return{showSignIn:function(){t.modal("sign-in")}}},view:function(t,e){return m('ul.dropdown-menu.user-dropdown.dropdown-menu-right[role="menu"]',m("li.guest-preview",[m("h4",gettext("You are browsing as guest.")),m("p",gettext("Sign in or register to start and participate in discussions.")),m(".row",[m(".col-xs-6",e.component("button",{"class":".btn.btn-default.btn-block",onclick:t.showSignIn,disabled:t.isBusy,label:gettext("Sign in")})),m(".col-xs-6",e.component("navbar:register-button",".btn.btn-primary.btn-block"))])]))}};t.addService("component:navbar:dropdown:guest",function(t){t.component("navbar:dropdown:guest",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={style:".nav.navbar-nav.navbar-compact-nav.hidden-md.hidden-lg",controller:function(t,e){return{openUserMenu:function(){return e.user.isAuthenticated?e.dropdown.toggle("navbar-dropdown","navbar:dropdown:user"):e.dropdown.toggle("navbar-dropdown","navbar:dropdown:guest"),!1}}},userMenu:function(t,e){return e.user.isAuthenticated?{element:e.component("user-avatar",e.user,64),config:{onclick:t.openUserMenu,url:"/not-yet/","data-misago-routed":"false"}}:{element:e.component("user-avatar",null,64),config:{onclick:t.openUserMenu,href:"#","data-misago-routed":"false"}}},mobileNav:function(t,e,n){var o=[{element:m("img",{src:n.router.staticUrl("misago/img/site-icon.png"),alt:n.settings.forum_name}),url:n.router.url("index")}];return e.forEach(function(t){t.url!==o[0].url&&o.push(t)}),o.push(this.userMenu(t,n)),o},view:function(t,e,n){var o=this.mobileNav(t,e,n);return m("ul"+this.style+".with-"+o.length+"-items",o.map(function(t){return m("li",m("a",t.config||{href:t.url},t.element||m("span.material-icon",{title:t.label},t.icon)))}))}};t.addService("component:navbar:mobile",function(t){t.component("navbar:mobile",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={controller:function(t,e){return{isBusy:!1,showRegister:function(){if("closed"===e.settings.account_activation)e.alert.info(gettext("New registrations are currently disabled."));else{m.startComputation(),this.isBusy=!0,m.endComputation();var t=this;m.sync([e.zxcvbn.load(),e.captcha.load()]).then(function(){e.modal("register")},function(){e.alert.error(gettext("Registation is not available now due to an error."))}).then(function(){m.startComputation(),t.isBusy=!1,m.endComputation()})}}}},view:function(t,e,n){return n.component("button",{"class":e,onclick:t.showRegister.bind(t),loading:t.isBusy,label:gettext("Register")})}};t.addService("component:navbar:register-button",function(t){t.component("navbar:register-button",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={"class":".dropdown-menu.user-dropdown.dropdown-menu-right",controller:function(){return{logout:function(){var t=confirm(gettext("Are you sure you want to sign out?"));t&&$("#hidden-logout-form").submit()}}},view:function(t,e){return m("ul"+this["class"]+'[role="menu"]',[m("li.dropdown-header",m("strong",e.user.username)),m("li.divider"),m("li",m("a",{href:"/not-yet/"},[m("span.material-icon","account_circle"),gettext("See your profile")])),m("li",m("a",{href:e.router.url("options")},[m("span.material-icon","done_all"),gettext("Change options")])),m("li",m('button.btn-link[type="button"]',[m("span.material-icon","face"),gettext("Change avatar")])),m("li.divider"),m("li.dropdown-footer",m("button.btn.btn-default.btn-block",{onclick:t.logout},gettext("Logout")))])}};t.addService("component:navbar:dropdown:user",function(t){t.component("navbar:dropdown:user",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={hasNav:function(t){return-1!==[!!t.settings.forum_footnote,!!t.settings.terms_of_service,!!t.settings.terms_of_service_link,!!t.settings.privacy_policy,!!t.settings.privacy_policy_link].indexOf(!0)},view:function(t,e){var n=null;return this.hasNav(e)&&(n=e.component("footer:nav")),m("footer.forum-footer",[m(".container",m(".footer-content",[n,e.component("footer:branding")]))])}};t.addService("component:footer",function(t){t.component("footer",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(){return m("a.misago-branding[href=http://misago-project.org]",["powered by ",m("strong","misago")])}};t.addService("component:footer:branding",function(t){t.component("footer:branding",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e=function(e,n,o){var r=t.get(e.settings,n+"_link");return!r&&t.get(e.settings,n)&&(r=e.router.url(n)),r?m("li",m("a",{href:r},t.get(e.settings,n+"_title",o))):null},n={isVisible:function(t){return-1!==[!!t.forum_footnote,!!t.terms_of_service,!!t.terms_of_service_link,!!t.privacy_policy,!!t.privacy_policy_link].indexOf(!0)},view:function(t,n){var o=[];return n.settings.forum_footnote&&o.push(m("li.forum-footnote",m.trust(n.settings.forum_footnote))),o.push(e(n,"terms_of_service",gettext("Terms of service"))),o.push(e(n,"privacy_policy",gettext("Privacy policy"))),m("ul.list-inline.footer-nav",o)}};t.addService("component:footer:nav",function(t){t.component("footer:nav",n)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(e,n,o){return m(".well.well-form",m("form",{onsubmit:n.submit},[m(".form-group",m(".control-input",t.input({disabled:n.isBusy,value:n.email,placeholder:gettext("Your e-mail address")}))),o.component("button",{"class":".btn-primary.btn-block",submit:!0,loading:n.isBusy,label:gettext("Send link")})]))}};t.addService("component:request-link-form",function(t){t.component("request-link-form",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(t,e,n){var o=[m("img",{src:n.router.staticUrl("misago/img/site-logo.png"),alt:n.settings.forum_name})];return e&&o.push(e),m("a.navbar-brand",{href:n.router.url("index")},o)}};t.addService("component:navbar:desktop:brand",function(t){t.component("navbar:desktop:brand",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={controller:function(t){return{showSignIn:function(){t.modal("sign-in")}}},view:function(t,e){return m("div.nav.nav-guest",[e.component("button",{"class":".navbar-btn.btn-default",onclick:t.showSignIn,disabled:t.isBusy,label:gettext("Sign in")}),e.component("navbar:register-button",".navbar-btn.btn-primary")])}};t.addService("component:navbar:desktop:guest-nav",function(t){t.component("navbar:desktop:guest-nav",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(t,e){return m("ul.nav.navbar-nav",[e.map(function(t){return m("li",m("a",t.config||{href:t.url},t.label))})])}};t.addService("component:navbar:desktop:main-nav",function(t){t.component("navbar:desktop:main-nav",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(t,e,n){var o=null,r=null;return n.settings.forum_branding_display&&(o=n.component("navbar:desktop:brand",n.settings.forum_branding_text)),r=n.component(n.user.isAuthenticated?"navbar:desktop:user-nav":"navbar:desktop:guest-nav"),m(".container.navbar-full.hidden-xs.hidden-sm",[o,n.component("navbar:desktop:main-nav",e),r])}};t.addService("component:navbar:desktop",function(t){t.component("navbar:desktop",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={controller:function(){return{dropdownToggle:{href:"/not-yet/","data-toggle":"dropdown","data-misago-routed":"false","aria-haspopup":"true","aria-expanded":"false"}}},view:function(t,e){return m("ul.nav.navbar-nav.nav-user",[m("li.dropdown",[m('a.dropdown-toggle[role="button"]',t.dropdownToggle,e.component("user-avatar",e.user,64)),e.component("navbar:dropdown:user")])])}};t.addService("component:navbar:desktop:user-nav",function(t){t.component("navbar:desktop:user-nav",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e=function(e){var n=this;this.username=null,this.password=m.prop(""),this.validation={password:[t.validators.passwordMinLength(e.settings)]},this.clean=function(){return e.validate(this)?!0:(e.alert.error($.trim(this.password()).length?this.errors.password:gettext("Enter new password.")),!1)},this.submit=function(){var t=e.api.endpoint("auth").endpoint("change-password");t=t.endpoint(m.route.param("user_id")),t=t.endpoint(m.route.param("token")),t.post({password:n.password()}).then(function(t){n.success(t)},function(t){n.error(t)})},this.success=function(t){this.username=t.username},this.error=function(t){403===t.status&&t.ban?e.router.error403({message:"",ban:t.ban}):400===t.status?e.alert.error(t.detail):e.api.alert(t)}};t.addService("form:change-password",function(t){t.form("change-password",e)},{after:"forms"})}(Misago.prototype),function(t){"use strict";var e=function(e){var n=this;this.showActivation=!1,this.username=m.prop(""),this.email=m.prop(""),this.password=m.prop(""),this.captcha=e.captcha.value,this.errors=null,this.validation={username:[t.validators.usernameContent(),t.validators.usernameMinLength(e.settings),t.validators.usernameMaxLength(e.settings)],email:[t.validators.email()],password:[t.validators.passwordMinLength(e.settings)],captcha:e.captcha.validator()},this.clean=function(){return null===this.errors&&e.validate(this),e.captcha.clean(this),this.hasErrors()?(e.alert.error(gettext("Form contains errors.")),!1):!0},this.submit=function(){e.api.model("user").post({username:this.username(),email:this.email(),password:this.password(),captcha:this.captcha()}).then(this.success,this.error)},this.success=function(t){e.modal("register-complete",t)},this.error=function(t){400===t.status?(e.alert.error(gettext("Form contains errors.")),$.extend(n.errors,t)):e.api.alert(t)}};t.addService("form:register",function(t){t.form("register",e)},{after:"forms"})}(Misago.prototype),function(t){"use strict";var e=function(e,n){var o=this;this.email=m.prop(""),this.validation={email:[t.validators.email()]},this.clean=function(){return n.validate(this)?!0:(n.alert.error(gettext("Enter a valid email address.")),!1)},this.submit=function(){n.api.endpoint("auth").endpoint(e.endpoint).post({email:o.email()}).then(function(t){o.success(t)},function(t){o.error(t)})},this.success=function(t){e.success(t)},this.error=function(t){400===t.status?e.error(t,n):403===t.status&&t.ban?n.router.error403({message:"",ban:t.ban}):n.api.alert(t)},this.reset=function(){this.email(""),e.reset()}};t.addService("form:request-link",function(t){t.form("request-link",e)},{after:"forms"})}(Misago.prototype),function(t){"use strict";var e=function(t){var e=this;this.showActivation=!1,this.username=m.prop(""),this.password=m.prop(""),this.validation={username:[],password:[]},this.clean=function(){return t.validate(this)?!0:(t.alert.error(gettext("Fill out both fields.")),!1)},this.submit=function(){t.api.endpoint("auth").post({username:e.username(),password:e.password()}).then(function(){e.success()},function(t){e.error(t)})},this.success=function(){t.modal();var e=$("#hidden-login-form");t.ajax.refreshCsrfToken(),e.find('input[type="hidden"]').val(t.ajax.csrfToken),e.find('input[name="redirect_to"]').val(m.route()),e.find('input[name="username"]').val(this.username()),e.find('input[name="password"]').val(this.password()),e.submit()},this.error=function(n){400===n.status?"inactive_admin"===n.code?t.alert.info(n.detail):"inactive_user"===n.code?(t.alert.info(n.detail),e.showActivation=!0):"banned"===n.code?(t.modal(),t.router.error403({message:"",ban:n.detail})):t.alert.error(n.detail):t.api.alert(n)}};t.addService("form:sign-in",function(t){t.form("sign-in",e)},{after:"forms"})}(Misago.prototype),function(t,e){"use strict";var n=new e;n.url("/","index"),n.url("/activation/","request_activation"),n.url("/activation/:user_id/:token/","activate_by_token"),n.url("/forgotten-password/","request_password_change"),n.url("/forgotten-password/:user_id/:token/","change_password"),n.url("/options/","options"),n.url("/options/forum/","options_forum"),n.url("/options/email/","options_email"),n.url("/options/password/","options_password"),n.url("/terms-of-service/","terms_of_service"),n.url("/privacy-policy/","privacy_policy"),n.url("/:rest...","error:404","not_found"),t.urls=n}(Misago.prototype,Misago.prototype.UrlConf);
+!function(){"use strict";window.Misago=function(){var t=Object.getPrototypeOf(this),e=this;this._initServices=function(n){var o=new t.OrderedList(n).order(!1);o.forEach(function(t){var n=null;n=void 0!==t.item.factory?t.item.factory:t.item;var o=n(e);o&&(e[t.key]=o)})},this._destroyServices=function(n){var o=new t.OrderedList(n).order();o.reverse(),o.forEach(function(t){void 0!==t.destroy&&t.destroy(e)})},this.context={SETTINGS:{}},this.setup=!1,this.init=function(e,n){this.setup={fixture:t.get(e,"fixture",null),test:t.get(e,"test",!1),api:t.get(e,"api","/api/")},n&&(this.context=n),this._initServices(t._services)},this.destroy=function(){this._destroyServices(t._services)}};var t=window.Misago.prototype;t._services=[],t.addService=function(e,n,o){t._services.push({key:e,item:n,after:t.get(o,"after"),before:t.get(o,"before")})},t.PermissionDenied=function(t){this.detail=t,this.status=403,this.toString=function(){return this.detail||"Permission denied"}}}(),function(t){"use strict";t.has=function(t,e){return t?t.hasOwnProperty(e):!1},t.get=function(e,n,o){return t.has(e,n)?e[n]:void 0!==o?o:void 0},t.pop=function(e,n,o){var r=t.get(e,n,o);return t.has(e,n)&&(e[n]=null),r}}(Misago.prototype),function(t){"use strict";function e(t,e,n){n.retain=!0}t.input=function(t){var n={disabled:t.disabled||!1,config:t.config||e};t.placeholder&&(n.placeholder=t.placeholder),t.autocomplete===!1&&(n.autocomplete="off");var o="input";return t.id&&(o+="#"+t.id,n.key="field-"+t.id),o+=".form-control"+(t["class"]||""),o+='[type="'+(t.type||"text")+'"]',t.value&&(n.value=t.value(),n.oninput=m.withAttr("value",t.value)),m(o,n)}}(Misago.prototype),function(t){"use strict";var e=function(){};t.stateHooks=function(t,n,o){if(t._hasLifecycleHooks)return t;t._hasLifecycleHooks=!0,t.isActive=!0;var r=o.bind(t),i=t.controller||e;if(t.controller=function(){try{t.isActive=!0;var n=i.apply(t,arguments)||{},o=n.onunload||e;return n.onunload=function(){o.apply(t,arguments),t.isActive=!1},n}catch(s){r(s)}},t.vm&&t.vm.init){if(!t.loading){var s=n.bind(t);t.loading=s}var a=t.view;t.view=function(){return t.vm.isReady?a.apply(t,arguments):t.loading.apply(t,arguments)};var u=t.vm.init;t.vm.init=function(){var e=arguments,n=u.apply(t.vm,e);n&&n.then(function(){if(t.isActive&&t.vm.ondata){for(var n=[],o=0;o<arguments.length;o++)n.push(arguments[o]);for(var r=0;r<e.length;r++)n.push(e[r]);t.vm.ondata.apply(t.vm,n)}},function(e){t.isActive&&r(e)})}}return t}}(Misago.prototype),function(t){"use strict";t.OrderedList=function(e){this.isOrdered=!1,this._items=e||[],this.add=function(e,n,o){this._items.push({key:e,item:n,after:t.get(o,"after"),before:t.get(o,"before")})},this.get=function(t,e){for(var n=0;n<this._items.length;n++)if(this._items[n].key===t)return this._items[n].item;return e},this.has=function(t){return void 0!==this.get(t)},this.values=function(){for(var t=[],e=0;e<this._items.length;e++)t.push(this._items[e].item);return t},this.order=function(t){return this.isOrdered||(this._items=this._order(this._items),this.isOrdered=!0),t||"undefined"==typeof t?this.values():this._items},this._order=function(t){function e(t){var e=-1;-1===r.indexOf(t.key)&&(t.after?(e=r.indexOf(t.after),-1!==e&&(e+=1)):t.before&&(e=r.indexOf(t.before)),-1!==e&&(o.splice(e,0,t),r.splice(e,0,t.key)))}var n=[];t.forEach(function(t){n.push(t.key)});var o=[],r=[];t.forEach(function(t){t.after||t.before||(o.push(t),r.push(t.key))}),t.forEach(function(t){"_end"===t.before&&(o.push(t),r.push(t.key))});for(var i=200;i>0&&n.length!==r.length;)i-=1,t.forEach(e);return o}}}(Misago.prototype),function(t){"use strict";t.Page=function(e,n){var o=this;this.name=e,this.isFinalized=!1,this._sections=[];var r=function(){if(!o.isFinalized){o.isFinalized=!0;var e=[];o._sections.forEach(function(t){(!t.visibleIf||t.visibleIf(n))&&e.push(t)}),o._sections=new t.OrderedList(e).order(!0)}};this.addSection=function(t){if(this.isFinalized)throw this.name+" page was initialized already and no longer accepts new sections";this._sections.push({key:t.link,item:t,after:t.after,before:t.before})},this.getSections=function(){return r(),this._sections},this.getDefaultLink=function(){return r(),this._sections[0].link}}}(Misago.prototype),function(t){t.serializeDatetime=function(t){return t?t.format():null},t.deserializeDatetime=function(t){return t?moment(t):null}}(Misago.prototype),function(t){"use strict";t.startsWith=function(t,e){return 0===t.indexOf(e)},t.endsWith=function(t,e){return-1!==t.indexOf(e,t.length-e.length)}}(Misago.prototype),function(t){"use strict";t.UrlConf=function(){var e=this;this._patterns=[],this.patterns=function(){return this._patterns};var n=function(t,e){return(t+e).replace("//","/")},o=function(t,o){for(var r=0;r<o.length;r++)e.url(n(t,o[r].pattern),o[r].component,o[r].name)};this.url=function(e,n,r){""===e&&(e="/"),n instanceof t.UrlConf?o(e,n.patterns()):this._patterns.push({pattern:e,component:n.replace(/_/g,"-"),name:r||n})}}}(Misago.prototype),function(t){"use strict";t.loadingPage=function(t){return m(".page.page-loading",t.component("loader"))}}(Misago.prototype),function(t){"use strict";var e=function(e){if(-1!==document.cookie.indexOf(e)){var n=new RegExp(e+"=([^;]*)"),o=t.get(document.cookie.match(n),0);return o.split("=")[1]}return null},n=function(n){this.refreshCsrfToken=function(){this.csrfToken=e(n.context.CSRF_COOKIE_NAME)},this.refreshCsrfToken();var o={};this.ajax=function(e,n,r,i){var s=m.deferred(),a={url:n,method:e,headers:{"X-CSRFToken":this.csrfToken},data:r||{},dataType:"json",success:function(r){"GET"===e&&t.pop(o,n),s.resolve(r)},error:function(r){"GET"===e&&t.pop(o,n);var i=r.responseJSON||{};i.status=r.status,i.statusText=r.statusText,s.reject(i)}};return i?void 0:($.ajax(a),s.promise)},this.get=function(e){var r=t.pop(n.context,e);if(r){var i=m.deferred();return i.resolve(r),i.promise}return void 0!==o[e]?o[e]:(o[e]=this.ajax("GET",e),o[e])},this.post=function(t,e){return this.ajax("POST",t,e)},this.patch=function(t,e){return this.ajax("PATCH",t,e)},this.put=function(t,e){return this.ajax("PUT",t,e)},this["delete"]=function(t){return this.ajax("DELETE",t)}};t.addService("ajax",function(t){return new n(t)})}(Misago.prototype),function(t){"use strict";var e=5e3,n=70,o=9e3,r=300,i=function(t){var i=this;this.type="",this.message=null,this.isVisible=!1;var s=function(r,s){i.type=r,i.message=s,i.isVisible=!0;var a=e;a+=s.length*n,a>o&&(a=o),t.runloop.runOnce(function(){m.startComputation(),i.isVisible=!1,m.endComputation()},"flash-message-hide",a)},a=function(e,n){t.runloop.stop("flash-message-hide"),t.runloop.stop("flash-message-show"),i.isVisible?(i.isVisible=!1,t.runloop.runOnce(function(){m.startComputation(),s(e,n),m.endComputation()},"flash-message-show",r)):s(e,n)};this.info=function(t){a("info",t)},this.success=function(t){a("success",t)},this.warning=function(t){a("warning",t)},this.error=function(t){a("error",t)}};t.addService("alert",{factory:function(t){return new i(t)}})}(Misago.prototype),function(t){"use strict";var e=function(t){if("object"==typeof t){var e=[];for(var n in t)if(t.hasOwnProperty(n)){var o=encodeURIComponent(n),r=encodeURIComponent(t[n]);e.push(o+"="+r)}return"?"+e.join("&")}return t+"/"},n=function(t,o){this.url=o.url||t.setup.api,this.url+=o.path?o.path+"/":o.related?o.related+"/":o.model+"s/",o.filters&&(this.url+=e(o.filters)),o.model&&(this.related=function(e,r){return new n(t,{url:this.url,relation:o.model,related:e,filters:r})}),this.endpoint=function(e,o){return new n(t,{url:this.url,path:e,filters:o})},this.get=function(){var e=null;return o.related?e=o.relation+":"+o.related:o.model&&(e=o.model),t.ajax.get(this.url).then(function(n){return e?n.results?(n.results.map(function(n){return t.models["new"](e,n)}),n):t.models["new"](e,n):n})},this.post=function(e){return t.ajax.post(this.url,e)},this.patch=function(e){return t.ajax.patch(this.url,e)},this.put=function(e){return t.ajax.put(this.url,e)},this["delete"]=function(){return t.ajax["delete"](this.url)},this.then=function(t,e){return this.get().then(t,e)}},o=function(t){this.model=function(e,o){return new n(t,{model:e,filters:o})},this.endpoint=function(e,o){return new n(t,{path:e,filters:o})},this.alert=function(e){var n=gettext("Unknown error has occured.");0===e.status&&(n=gettext("Lost connection with application.")),403===e.status&&(n=e.detail,"Permission denied"===n&&(n=gettext("You don't have permission to perform this action."))),404===e.status&&(n=gettext("Action link is invalid.")),t.alert.error(n)}};t.addService("api",function(t){return new o(t)})}(Misago.prototype),function(t){"use strict";var e=function(e){var n=this;e.user=e.models.deserialize("user",e.context.user),this.isDesynced=!1,this.newUser=null;var o=function(t){n.isDesynced||(m.startComputation(),n.isDesynced=!0,t&&(n.newUser=e.localstore.get("auth-user")),m.endComputation())},r=function(t){n.isDesynced||(m.startComputation(),e.user.id!==t.id?(n.isDesynced=!0,n.newUser=t):t&&(e.user=$.extend(e.user,t)),m.endComputation())},i=function(){e.localstore.set("auth-user",e.user),e.localstore.set("auth-is-authenticated",e.user.isAuthenticated),e.localstore.watch("auth-is-authenticated",o),e.localstore.watch("auth-user",r)};i(),this.denyAuthenticated=function(n){if(e.user.isAuthenticated)throw new t.PermissionDenied(n||gettext("This page is not available to signed in users."))},this.denyAnonymous=function(n){if(e.user.isAnonymous)throw new t.PermissionDenied(n||gettext("This page is not available to guests."))}};t.addService("auth",function(t){return new e(t)},{after:"model:user"})}(Misago.prototype),function(t){"use strict";var e=function(){var t=m.deferred();t.resolve(),this.load=function(){return t.promise},this.value=function(){return null}},n=function(t){var e=this;this.loading=!1,this.question=null,this.value=m.prop("");var n=m.deferred();this.load=function(){return this.value(""),this.question||this.loading||(this.loading=!0,t.api.endpoint("captcha-question").get().then(function(t){e.question=t,n.resolve()},function(){t.api.alert(gettext("Failed to load CAPTCHA.")),n.reject()}).then(function(){e.loading=!0})),n.promise},this.component=function(e){return t.component("form-group",{label:this.question.question,labelClass:e.labelClass||null,controlClass:e.controlClass||null,control:t.input({value:t.validate(e.form,"captcha"),id:"id_captcha",disabled:e.form.isBusy}),validation:e.form.errors,validationKey:"captcha",helpText:this.question.help_text})},this.validator=function(){return[]}},o=function(t){this.included=!1,this.question=null;var e=m.deferred(),n=function(e){"undefined"!=typeof grecaptcha?e.resolve():t.runloop.runOnce(function(){n(e)},"loading-grecaptcha",150)};this.load=function(){return"undefined"!=typeof grecaptcha&&grecaptcha.reset(),this.included||(t.include("https://www.google.com/recaptcha/api.js",!0),this.included=!0),n(e),e.promise};var o=function(e,n,o){o.retain=!0,n||grecaptcha.render("recaptcha",{sitekey:t.settings.recaptcha_site_key})};this.component=function(e){var n=m("#recaptcha",{config:o});return t.component("form-group",{label:gettext("Security test"),labelClass:e.labelClass||null,controlClass:e.controlClass||null,control:n,validation:e.form.errors,validationKey:"captcha"})},this.value=function(){return"undefined"!=typeof grecaptcha?grecaptcha.getResponse():""},this.clean=function(t){t.errors.captcha=this.value()?!0:[gettext("This field is required.")]},this.validator=function(){return[]}},r=function(t){var r={no:e,qa:n,re:o},i=new r[t.settings.captcha_type](t);this.value=i.value,this.load=function(){return i.load()},this.component=function(t){return i.component?i.component(t):null},this.validator=function(){return i.validator?i.validator():null},this.clean=function(t){i.clean?i.clean(t):t.errors.captcha=!0}};t.addService("captcha",function(t){return new r(t)},{after:"include"})}(Misago.prototype),function(t){"use strict";var e=function(t,e){if(this._components[t]){if(arguments.length>1){for(var n=[this._components[t]],o=1;o<arguments.length;o+=1)n.push(arguments[o]);return n.push(this),m.component.apply(void 0,n)}return m.component(this._components[t],this)}if(!e)throw'"'+t+"\" component is not registered and can't be created";this._components[t]=e};t.addService("components",function(t){t._components={},t.component=e})}(Misago.prototype),function(t){"use strict";t.addService("conf",function(e){e.settings=t.get(e.context,"SETTINGS",{})})}(Misago.prototype),function(t){"use strict";var e=function(t,e,n){e||(n.retain=!0,$(t).on("click",function(){$(t).removeClass("open")}),n.onunload=function(){$(t).removeClass("open"),$(t).off()})},n=function(t){var n={};this.slot=function(t){return m("#dropdown-"+t+".dropdown.mobile-dropdown",{config:e})},this.toggle=function(e,o){var r=document.getElementById("dropdown-"+e);r.hasChildNodes()&&n[e]===o?(n[e]=null,m.mount(r,null),$(r).removeClass("open")):(n[e]=o,m.mount(r,t.component(o)),$(r).addClass("open"))}};t.addService("dropdown",{factory:function(t){return new n(t)}},{before:"components"})}(Misago.prototype),function(t){"use strict";var e=function(t){var e=t.submit,n=t.success,o=t.error;return t.isBusy=!1,t.errors=null,t.submit=function(){return t.isBusy?!1:(t.clean?t.clean()&&(t.isBusy=!0,e.apply(t)):t.isBusy=!0,!1)},t.success=function(){m.startComputation(),n.apply(t,arguments),t.isBusy=!1,m.endComputation()},t.error=function(){m.startComputation(),o.apply(t,arguments),t.isBusy=!1,m.endComputation()},t.hasErrors=function(){if(null===t.errors)return!1;for(var e in t.validation)if(t.validation.hasOwnProperty(e)&&t.errors[e]!==!0)return!0;return!1},t},n=function(t,n){return this._forms[t]?e(n?new this._forms[t](n,this):new this._forms[t](this)):void(this._forms[t]=n)};t.addService("forms",function(t){t._forms={},t.form=n})}(Misago.prototype),function(t){"use strict";t.addService("forum-layout",{factory:function(t){t.setup.fixture&&m.mount(document.getElementById(t.setup.fixture),t.component("forum-layout"))},destroy:function(t){t.setup.fixture&&m.mount(document.getElementById(t.setup.fixture),null)}},{before:"start-routing"})}(Misago.prototype),function(t){"use strict";var e=function(t,e){e||(t=this.context.STATIC_URL+t),$.ajax({url:t,cache:!0,dataType:"script"})};t.addService("include",function(t){t.include=e},{after:"conf"})}(Misago.prototype),function(t){"use strict";var e=function(){var t=window.localStorage,e="_misago_",n=[],o=function(t){var e=JSON.parse(t.newValue);$.each(n,function(n,o){o.keyName===t.key&&t.oldValue!==t.newValue&&o.callback(e)})};window.addEventListener("storage",o);var r=function(t){return e+t};this.set=function(e,n){t.setItem(r(e),JSON.stringify(n))},this.get=function(e){var n=t.getItem(r(e));return n?JSON.parse(n):null},this.watch=function(t,e){n.push({keyName:r(t),callback:e})},this.destroy=function(){this.watchers=[]}};t.addService("localstore",{factory:function(){return new e},destroy:function(t){t.localstore.destroy()}})}(Misago.prototype),function(t){"use strict";var e=function(){var t=this,e=document.getElementById("misago-modal"),n="click.misago-modal";$(e).on(n,"a",function(){t.hide()}),this.destroy=function(){$(e).off(),$("body").removeClass("modal-open"),$(".modal-backdrop").remove()};var o=$(e).modal({show:!1});this.open=!1,o.on("hidden.bs.modal",function(){t.open&&(m.mount(e,null),this.open=!1)}),this.show=function(t){this.open=!0,m.mount(e,t),o.modal("show")},this.hide=function(){o.modal("hide")}};t.addService("_modal",{factory:function(){return new e},destroy:function(t){t._modal.destroy()}},{after:"start-routing"})}(Misago.prototype),function(t){"use strict";var e=function(t,e){if(this._modals[t]){for(var n=[this._modals[t]],o=1;o<arguments.length;o+=1)n.push(arguments[o]);n.push(this),this._modal.show(m.component.apply(m,n))}else t?this._modals[t]=e:this._modal.hide()};t.addService("modals",function(t){t._modals={},t.modal=e},{after:"_modal"})}(Misago.prototype),function(t){"use strict";var e=function(){this.classes={},this.deserializers={},this.add=function(t,e){e["class"]&&(this.classes[t]=e["class"]),e.deserialize&&(this.deserializers[t]=e.deserialize)},this["new"]=function(t,e){return this.classes[t]?(e.id=e.id?String(e.id):null,new this.classes[t](e)):e},this.deserialize=function(t,e){return this.deserializers[t]?this["new"](t,this.deserializers[t](e,this)):this["new"](t,e)}};t.addService("models",function(){return new e})}(Misago.prototype),function(t){"use strict";t.addService("set-momentjs-locale",function(){moment.locale($("html").attr("lang"))})}(Misago.prototype),function(t){"use strict";var e=function(e){var n=this;this.baseUrl=$("base").attr("href");var o=t.get(e.context,"STATIC_URL","/"),r=t.get(e.context,"MEDIA_URL","/");this.urls={},this.reverses={};var i=function(t){t.patterns().forEach(function(t){var o=n.baseUrl+t.pattern;o=o.replace("//","/"),n.urls[o]=e.route(t.component),n.reverses[t.name]=o})};this.startRouting=function(t,n){i(t),this.fixture=n,m.route.mode=e.setup.test?"search":"pathname",m.route(n,"/",this.urls)},this.url=function(t){return this.reverses[t]},this.route=function(t){m.route(t)},this.redirect=function(t){this.route(this.url(t))},this.delegateElement=null,this.cleanUrl=function(t){if(t){var e="/"===t.substr(0,1)&&"//"!==t.substr(0,2);if(!e){var n=window.location;if("//"!==t.substr(0,2)){var i=t.substr(0,n.protocol.length+2);if(i!==n.protocol+"//")return;t=t.substr(n.protocol.length+2)}else t=t.substr(2);if(t.substr(0,n.host.length)!==n.host)return;t=t.substr(n.host.length)}if(t.substr(0,this.baseUrl.length)===this.baseUrl&&t.substr(0,o.length)!==o&&t.substr(0,r.length)!==r){var s="/user-avatar/";if(t.substr(0,s.length)!==s)return t}}};var s="click.misago-router",a='a:not([data-misago-routed="false"])';this.delegateClicks=function(t){this.delegateElement=t,$(this.delegateElement).on(s,a,function(t){var e=n.cleanUrl(t.currentTarget.href);e&&(e!=m.route()&&n.route(e),t.preventDefault())})},this.destroy=function(){$(this.delegateElement).off(s)};var u=function(t){return function(e){return t+e}};this.staticUrl=u(o),this.mediaUrl=u(r),this.error403=function(t){var n=null;n=t.ban?e.route("error:banned",t.detail,e.models.deserialize("ban",t.ban)):e.route("error:403",t.detail),m.mount(this.fixture,n)},this.error404=function(){m.mount(this.fixture,e.route("error:404"))},this.error500=function(){m.mount(this.fixture,e.route("error:500"))},this.error0=function(){m.mount(this.fixture,e.route("error:0"))},this.errorPage=function(t){0===t.status&&this.error0(),500===t.status&&this.error500(),404===t.status&&this.error404(),403===t.status&&this.error403(t)}};t.addService("router",function(t){return new e(t)}),t.addService("start-routing",function(e){var n=function(){var o=document.getElementById("router-fixture");o?(e.router.startRouting(t.urls,document.getElementById("router-fixture")),e.router.delegateClicks(document.getElementById(e.setup.fixture))):window.setTimeout(function(){n()},10)};n()},{before:"_end"})}(Misago.prototype),function(t){"use strict";var e=function(e){if(e._hasRouteBoilerplate)return e;e._hasRouteBoilerplate=!0;var n=function(){var t=this.container;return m(".page.page-loading",t.component("loader"))},o=function(t){if(!this.isActive||"undefined"==typeof t.status)throw t;this.vm&&this.vm.onerror?this.vm.onerror(t,this.container):this.container.router.errorPage(t)};return t.stateHooks(e,n,o)};t.addService("routes",function(t){t._routes={},t.route=function(n,o){if(this._routes[n]){if(arguments.length>1){for(var r=[this._routes[n]],i=1;i<arguments.length;i+=1)r.push(arguments[i]);return r.push(this),m.component.apply(void 0,r)}return m.component(this._routes[n],this)}if(!o)throw'"'+n+"\" route is not registered and can't be created";o.container=t,this._routes[n]=e(o)}})}(Misago.prototype),function(t){"use strict";var e=function(t){var e=this;this._intervals={};var n=function(t){e._intervals[t]&&(window.clearTimeout(e._intervals[t]),e._intervals[t]=null)};this.run=function(o,r,i){this._intervals[r]=window.setTimeout(function(){n(r);var s=o(t);s!==!1&&e.run(o,r,i)},i)},this.runOnce=function(e,o,r){this._intervals[o]=window.setTimeout(function(){n(o),e(t)},r)},this.stop=function(t){for(var e in this._intervals)t&&t!==e||n(e)}};t.addService("runloop",{factory:function(t){return new e(t)},destroy:function(t){t.runloop.stop()}})}(Misago.prototype),function(t){"use strict";t.addService("start-tick",function(t){var e=m.prop();t.runloop.run(function(){m.startComputation(),e(e()+1),m.endComputation()},"tick",6e4)})}(Misago.prototype),function(t){"use strict";var e=function(t){this.set=function(e){e?this._set_complex(e):document.title=t},this._set_complex=function(e){"string"==typeof e&&(e={title:e});var n=e.title;if("undefined"!=typeof e.page&&e.page>1){var o=interpolate(gettext("page %(page)s"),{page:e.page},!0);n+=" ("+o+")"}"undefined"!=typeof e.parent&&(n+=" | "+e.parent),document.title=n+" | "+t}};t.addService("page-title",function(t){t.title=new e(t.settings.forum_name)})}(Misago.prototype),function(t){"use strict";var e=/^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i,n=new RegExp("^[0-9a-z]+$","i");t.validators={required:function(){return function(t){return 0===$.trim(t).length?gettext("This field is required."):void 0}},email:function(t){return function(n){return e.test(n)?void 0:t||gettext("Enter a valid email address.")}},minLength:function(t,e){return function(n){var o="",r=$.trim(n).length;return t>r?(o=e?e(t,r):ngettext("Ensure this value has at least %(limit_value)s character (it has %(show_value)s).","Ensure this value has at least %(limit_value)s characters (it has %(show_value)s).",t),interpolate(o,{limit_value:t,show_value:r},!0)):void 0}},maxLength:function(t,e){return function(n){var o="",r=$.trim(n).length;return r>t?(o=e?e(t,r):ngettext("Ensure this value has at most %(limit_value)s character (it has %(show_value)s).","Ensure this value has at most %(limit_value)s characters (it has %(show_value)s).",t),interpolate(o,{limit_value:t,show_value:r},!0)):void 0}},usernameMinLength:function(t){var e=function(t){return ngettext("Username must be at least %(limit_value)s character long.","Username must be at least %(limit_value)s characters long.",t)};return this.minLength(t.username_length_min,e)},usernameMaxLength:function(t){var e=function(t){return ngettext("Username cannot be longer than %(limit_value)s character.","Username cannot be longer than %(limit_value)s characters.",t)};return this.maxLength(t.username_length_max,e)},usernameContent:function(){return function(t){return n.test($.trim(t))?void 0:gettext("Username can only contain latin alphabet letters and digits.")}},passwordMinLength:function(t){var e=function(t){return ngettext("Valid password must be at least %(limit_value)s character long.","Valid password must be at least %(limit_value)s characters long.",t)};return this.minLength(t.password_length_min,e)}};var o=function(e,n){var o=t.validators.required()(e),r=[];if(o)return[o];for(var i in n)o=n[i](e),o&&r.push(o);return r.length?r:!0},r=function(t){var e={},n=null,r=!0;for(var i in t.validation)t.validation.hasOwnProperty(i)&&(n=t[i](),e[i]=o(t[i](),t.validation[i]),e[i]!==!0&&(r=!1));return t.errors=e,r},i=function(t,e){return e?function(n){var r=null;return"undefined"!=typeof n?(r=o(n,t.validation[e]),r&&(t.errors||(t.errors={}),t.errors[e]=r),t[e](n),t[e](n)):t[e]()}:r(t)};t.addService("validate",{factory:function(){return i}})}(Misago.prototype),function(t){"use strict";var e=function(t){this.included=!1,this.scorePassword=function(t,e){return zxcvbn(t,e).score},this.include=function(){t.include("misago/js/zxcvbn.js"),this.included=!0};var e=function(n){"undefined"!=typeof zxcvbn?n.resolve():t.runloop.runOnce(function(){e(n)},"loading-zxcvbn",150)},n=m.deferred();this.load=function(){return this.included||this.include(),e(n),n.promise}};t.addService("zxcvbn",function(t){return new e(t)},{after:"include"})}(Misago.prototype),function(t){"use strict";var e=function(t){this.message={html:t.message.html,plain:t.message.plain},this.expires_on=t.expires_on},n=function(e){return e.expires_on=t.deserializeDatetime(e.expires_on),e};t.addService("model:ban",function(t){t.models.add("ban",{"class":e,deserialize:n})},{after:"models"})}(Misago.prototype),function(t){"use strict";var e=function(t){this.title=t.title,this.body=t.body,this.link=t.link};t.addService("model:legal-page",function(t){t.models.add("legal-page",{"class":e})},{after:"models"})}(Misago.prototype),function(t){"use strict";var e=function(t){this.id=t.id,this.name=t.name,this.slug=t.slug,this.description=t.description,this.title=t.title,this.css_class=t.css_class,this.is_tab=t.is_tab};t.addService("model:rank",function(t){t.models.add("rank",{"class":e})},{after:"models"})}(Misago.prototype),function(t){"use strict";var e=function(t){this.id=t.id,this.isAuthenticated=!!this.id,this.isAnonymous=!this.isAuthenticated,this.username=t.username,this.slug=t.slug,this.email=t.email,this.full_title=t.full_title,this.rank=t.rank,this.avatar_hash=t.avatar_hash,this.acl=t.acl},n=function(e,n){return e.joined_on&&(e.joined_on=t.deserializeDatetime(e.joined_on)),e.rank&&(e.rank=n.deserialize("rank",e.rank)),e};t.addService("model:user",function(t){t.models.add("user",{"class":e,deserialize:n})},{after:"model:rank"})}(Misago.prototype),function(t){"use strict";var e={view:function(t,e){return m("",[e.component("header",{title:gettext("Options")}),m(".container",m("p","Lorem ipsum dolor met."))])}};t.addService("component:options:nav:dropdown",function(t){t.component("options:nav:dropdown",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={controller:function(t){t.auth.denyAnonymous(gettext("You have to be signed in to change your options.")),this.container.title.set({title:gettext("E-mail"),parent:gettext("Options")})},view:function(t,e){return m(".page.page-options.page-forum-options",[e.component("header",{title:gettext("Change options")}),m(".container",m("p","Lorem ipsum dolor met."))])}};t.addService("route:options:email",function(t){t.route("options-email",e)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e={controller:function(t){t.auth.denyAnonymous(gettext("You have to be signed in to change your options.")),this.container.title.set({title:gettext("Forum options"),parent:gettext("Options")})},view:function(t,e){return m(".page.page-options.page-forum-options",[e.component("header",{title:gettext("Options")}),m(".container",m("p","Lorem ipsum dolor met."))])}};t.addService("route:options:forum",function(t){t.route("options-forum",e)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e={controller:function(t){t.auth.denyAnonymous(gettext("You have to be signed in to change your options.")),t.router.redirect("options_forum")}};t.addService("route:options",function(t){t.route("options",e)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e={controller:function(t){t.auth.denyAnonymous(gettext("You have to be signed in to change your options.")),this.container.title.set({title:gettext("Password"),parent:gettext("Options")})},view:function(t,e){return m(".page.page-options.page-forum-options",[e.component("header",{title:gettext("Change options")}),m(".container",m("p","Lorem ipsum dolor met."))])}};t.addService("route:options:password",function(t){t.route("options-password",e)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e={view:function(t,e){return m(".list-group.nav-side",[])}};t.addService("component:options:nav:side",function(t){t.component("options:nav:side",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={error:null,username:null,isReady:!1,init:function(t){this.error=null,this.user=null,this.isReady=!1;var e=t.api.endpoint("auth").endpoint("activate-account");return e=e.endpoint(m.route.param("user_id")),e=e.endpoint(m.route.param("token")),e.post()},ondata:function(t,e){m.startComputation(),e.title.set(gettext("Account activated")),this.username=t.username,this.isReady=!0,m.endComputation()},onerror:function(t,e){400===t.status?(m.startComputation(),this.error=t,this.isReady=!0,m.endComputation()):e.router.errorPage(t)}},n={controller:function(t){t.auth.denyAuthenticated(gettext("You have to be signed out to activate account.")),t.title.set(gettext("Account activation")),this.vm.init(t)},vm:e,view:function(t,e){return this.vm.error?this.rejected(this.vm.error,e):this.success(this.vm.username,e)},success:function(t){var e=gettext("%(username)s, your account has been successfully activated!");return m(".page.page-message.page-message-success",m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon","check")),m(".message-body",[m("p.lead",interpolate(e,{username:t},!0)),m("p",gettext("You can now sign in to finish setting up your account and to participate in or start new discussions."))])])))},rejected:function(t){return m(".page.page-message.page-message-info",m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon","info_outline")),m(".message-body",[m("p.lead",gettext("Your account can't be activated at this time.")),m("p",t.detail)])])))},loading:function(t,e){return m(".page.page-loading",[e.component("loader"),m("p.lead",gettext("Activating account..."))])}};t.addService("route:activate-by-token",function(t){t.route("activate-by-token",n)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e={error:null,isReady:!1,form:null,init:function(t){this.error=null,this.user=null,this.isReady=!1;var e=t.api.endpoint("auth").endpoint("change-password");return e=e.endpoint(m.route.param("user_id")),e=e.endpoint(m.route.param("token")),e.get()},ondata:function(t,e){m.startComputation(),e.title.set(gettext("Change forgotten password")),this.form=e.form("change-password"),this.isReady=!0,m.endComputation()},onerror:function(t,e){400===t.status?(m.startComputation(),this.error=t,this.isReady=!0,m.endComputation()):e.router.errorPage(t)}},n={controller:function(t){return this.vm.init(t),{signin:function(){t.modal("sign-in")}}},vm:e,view:function(t,e){return this.vm.error?this.rejected(this.vm.error,e):this.vm.form.username?this.complete(t,this.vm.form.username,e):this.form(this.vm.form,e)},form:function(e,n){return m(".page.page-change-password",[n.component("header",{title:gettext("Change forgotten password")}),m(".container",m(".row",m(".col-md-4.col-md-offset-4",m(".well.well-form",m("form",{onsubmit:e.submit},[m(".form-group",m(".control-input",t.input({disabled:e.isBusy,value:e.password,type:"password",placeholder:gettext("Enter new password")}))),n.component("button",{"class":".btn-primary.btn-block",submit:!0,loading:e.isBusy,label:gettext("Change password")})])))))])},complete:function(t,e,n){var o=gettext("%(username)s, your password has been changed successfully.");return m(".page.page-message.page-message-success",m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon","check")),m(".message-body",[m("p.lead",interpolate(o,{username:e},!0)),m("p",gettext("You can now sign in to your account using your new password.")),m("p",n.component("button",{"class":".btn-default",submit:!1,label:gettext("Sign in"),onclick:t.signin}))])])))},rejected:function(t){return m(".page.page-message.page-message-info",m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon","info_outline")),m(".message-body",[m("p.lead",gettext("Your account can't be activated at this time.")),m("p",t.detail)])])))}};t.addService("route:change-password",function(t){t.route("change-password",n)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e=function(t){var e=[m("p.lead",t.message)];return t.help&&e.push(m("p.help",t.help)),m(".page.page-error.page-error-"+t.code,m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon",t.icon)),m(".message-body",e)])))},n={controller:function(){this.container.title.set(gettext("You are banned"))},view:function(t,e,n){
+var o=[];o.push(n.message.html?m(".lead",m.trust(n.message.html)):e?m("p.lead",e):m("p.lead",gettext("You are banned.")));var r=null;return r=n.expires_on?n.expires_on.isAfter(moment())?interpolate(gettext("This ban expires %(expires_on)s."),{expires_on:n.expires_on.fromNow()},!0):gettext("This ban has expired."):gettext("This ban is permanent."),o.push(m("p",r)),m(".page.page-error.page-error-banned",m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon","highlight_off")),m(".message-body",o)])))}},o={controller:function(){this.container.title.set(gettext("Page not available"))},view:function(t,n){return"Permission denied"===n&&(n=gettext("You don't have permission to access this page.")),e({code:403,icon:"remove_circle_outline",message:gettext("This page is not available."),help:n})}},r={controller:function(){this.container.title.set(gettext("Page not found"))},view:function(){return e({code:404,icon:"info_outline",message:gettext("Requested page could not be found."),help:gettext("The link you followed was incorrect or the page has been moved or deleted.")})}},i={controller:function(){this.container.title.set(gettext("Application error occured"))},view:function(){return e({code:500,icon:"error_outline",message:gettext("Requested page could not be displayed due to an error."),help:gettext("Please try again later or contact site staff if error persists.")})}},s={controller:function(){this.container.title.set(gettext("Lost connection with application"))},view:function(){return e({code:0,icon:"sync_problem",message:gettext("Could not connect to application."),help:gettext("This may be caused by problems with your connection or application server. Please check your internet connection and refresh page if problem persists.")})}};t.addService("route:error-pages",function(t){t.route("error:banned",n),t.route("error:403",o),t.route("error:404",r),t.route("error:500",i),t.route("error:0",s)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e={controller:function(t){return document.title=t.settings.forum_index_title||t.settings.forum_name,{activation:function(){t.router.url("request_activation")}}},view:function(t,e){return m(".container",[m("h1","Activation"),m("p","Test auth blocks"),m("p",m("a",{href:e.router.url("request_activation")},"Request activation."))])}};t.addService("route:index",function(t){t.route("index",e)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e=function(e,n){var o=e.replace(/_/g,"-");return{controller:function(n){t.get(n.settings,e+"_link")?window.location=t.get(n.settings,e+"_link"):this.vm.init(this,n)},vm:{page:null,isReady:!1,init:function(t,e){return this.isReady?void e.title.set(this.title):(e.title.set(),e.api.model("legal-page",o))},ondata:function(t,e,o){m.startComputation(),t.link?window.location=t.link:(t.title=t.title||n,this.page=t,this.isReady=!0,m.endComputation(),e.isActive&&o.title.set(this.page.title))}},view:function(t,e){return m(".page.page-legal.page-legal-"+o,[e.component("header",{title:this.vm.page.title}),m(".container",e.component("markup",this.vm.page.body))])}}};t.addService("route:legal-pages",function(t){t.route("terms-of-service",e("terms_of_service",gettext("Terms of service"))),t.route("privacy-policy",e("privacy_policy",gettext("Privacy policy")))},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e=function(){this.endpoint="send-activation",this.user=null,this.success=function(t){this.user=t},this.error=function(t,e){"already_active"===t.code?(e.alert.info(t.detail),e.modal("sign-in")):"inactive_admin"===t.code?e.alert.info(t.detail):e.alert.error(t.detail)},this.reset=function(){this.user=null}},n={controller:function(t){t.auth.denyAuthenticated(gettext("You have to be signed out to activate account.")),t.title.set(gettext("Activate your account"));var n=new e;return{vm:n,form:t.form("request-link",n)}},view:function(t,e){return t.vm.user?this.completed(t.form,t.vm,e):this.form(t.form,e)},completed:function(t,e,n){var o=gettext("%(username)s, we have sent your activation link to %(email)s.");return m(".page.page-message.page-message-success",m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon","check")),m(".message-body",[m("p.lead",gettext("Activation link has been sent.")),m("p",interpolate(o,{username:e.user.username,email:e.user.email},!0)),m("p",n.component("button",{"class":".btn-default",submit:!1,label:gettext("Request another link"),onclick:t.reset.bind(t)}))])])))},form:function(t,e){return m(".page.page-request-activation",[e.component("header",{title:gettext("Request activation link")}),m(".container",m(".row",[m(".col-md-8",[m("p",gettext("Site administrator may impose requirement on newly regitered accounts to be activated before users will be able to sign in.")),m("p",gettext("Depending on time of registration, you will be able activate your account by clicking special activation link. This link will be valid only for your browser, for seven days or until your account is activated.")),m("p",gettext('To receive this link, enter your account\'s e-mail addres in form and press "Send link" button.'))]),m(".col-md-4",e.component("request-link-form",t))]))])}};t.addService("route:request-activation",function(t){t.route("request-activation",n)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e=function(){this.endpoint="send-password-form",this.user=null,this.activation=null,this.activationMessage=null,this.success=function(t){this.user=t},this.error=function(t,e){["inactive_user","inactive_admin"].indexOf(t.code)>-1?(this.activation=t.code,this.activationMessage=t.detail):e.alert.error(t.detail)},this.reset=function(){this.user=null,this.activation=null,this.activationMessage=null}},n={controller:function(t){t.title.set(gettext("Change forgotten password"));var n=new e;return{vm:n,form:t.form("request-link",n)}},view:function(t,e){return t.vm.user?this.completed(t.form,t.vm,e):t.vm.activation?this.inactive(t.form,t.vm,e):this.form(t.form,e)},completed:function(t,e,n){var o=gettext("%(username)s, we have sent link to your password change form to %(email)s.");return m(".page.page-message.page-message-success",m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon","check")),m(".message-body",[m("p.lead",gettext("Change password form link sent.")),m("p",interpolate(o,{username:e.user.username,email:e.user.email},!0)),m("p",n.component("button",{"class":".btn-default",submit:!1,label:gettext("Request another link"),onclick:t.reset.bind(t)}))])])))},inactive:function(t,e,n){var o=null;return"inactive_user"===e.activation&&(o=m("a.btn.btn-primary",{href:n.router.url("request_activation")},gettext("Activate account"))),m(".page.page-message.page-message-info",m(".container",m(".message-panel",[m(".message-icon",m("span.material-icon","info_outline")),m(".message-body",[m("p.lead",gettext("Your account is inactive.")),m("p",e.activationMessage),m("p",[o,n.component("button",{"class":".btn-default",submit:!1,label:gettext("Request another link"),onclick:t.reset.bind(t)})])])])))},form:function(t,e){return m(".page.page-request-activation",[e.component("header",{title:gettext("Change forgotten password")}),m(".container",m(".row",[m(".col-md-8",[m("p",gettext("Because user passwords are processed in an irreversible way before being saved to database, it is not possible for us to simply send you your password.")),m("p",gettext("Instead, you can change your password using special secure form that will be available by special link valid only for your browser, for seven days or until your password is changed.")),m("p",gettext('To receive this link, enter your account\'s e-mail addres in form and press "Send link" button.'))]),m(".col-md-4",e.component("request-link-form",t))]))])}};t.addService("route:request-password-change",function(t){t.route("request-password-change",n)},{after:"routes"})}(Misago.prototype),function(t){"use strict";var e={view:function(t,e,n){var o=[m("img",{src:n.router.staticUrl("misago/img/site-logo.png"),alt:n.settings.forum_name})];return e&&o.push(e),m("a.navbar-brand",{href:n.router.url("index")},o)}};t.addService("component:navbar:desktop:brand",function(t){t.component("navbar:desktop:brand",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={controller:function(t){return{showSignIn:function(){t.modal("sign-in")}}},view:function(t,e){return m("div.nav.nav-guest",[e.component("button",{"class":".navbar-btn.btn-default",onclick:t.showSignIn,disabled:t.isBusy,label:gettext("Sign in")}),e.component("navbar:register-button",".navbar-btn.btn-primary")])}};t.addService("component:navbar:desktop:guest-nav",function(t){t.component("navbar:desktop:guest-nav",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(t,e){return m("ul.nav.navbar-nav",[e.map(function(t){return m("li",m("a",t.config||{href:t.url},t.label))})])}};t.addService("component:navbar:desktop:main-nav",function(t){t.component("navbar:desktop:main-nav",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(t,e,n){var o=null,r=null;return n.settings.forum_branding_display&&(o=n.component("navbar:desktop:brand",n.settings.forum_branding_text)),r=n.component(n.user.isAuthenticated?"navbar:desktop:user-nav":"navbar:desktop:guest-nav"),m(".container.navbar-full.hidden-xs.hidden-sm",[o,n.component("navbar:desktop:main-nav",e),r])}};t.addService("component:navbar:desktop",function(t){t.component("navbar:desktop",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={controller:function(){return{dropdownToggle:{href:"/not-yet/","data-toggle":"dropdown","data-misago-routed":"false","aria-haspopup":"true","aria-expanded":"false"}}},view:function(t,e){return m("ul.nav.navbar-nav.nav-user",[m("li.dropdown",[m('a.dropdown-toggle[role="button"]',t.dropdownToggle,e.component("user-avatar",e.user,64)),e.component("navbar:dropdown:user")])])}};t.addService("component:navbar:desktop:user-nav",function(t){t.component("navbar:desktop:user-nav",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";function e(t,e,n){n.retain=!0}var n={classes:{info:"alert-info",success:"alert-success",warning:"alert-warning",error:"alert-danger"},view:function(t,n){return m(".alerts",{config:e,"class":n.alert.isVisible?"in":"out"},m("p.alert",{"class":this.classes[n.alert.type]},n.alert.message))}};t.addService("component:alert",function(t){t.component("alert",n)},{after:"components"})}(Misago.prototype),function(t){"use strict";function e(t,e,n){n.retain=!0}var n={refresh:function(){window.location.reload()},view:function(t,n){var o="",r={config:e,"class":n.auth.isDesynced?"show":null};return n.auth.isDesynced&&(n.auth.newUser&&n.auth.newUser.isAuthenticated?(o=gettext("You have signed in as %(username)s. Please refresh this page before continuing."),o=interpolate(o,{username:n.auth.newUser.username},!0)):(o=gettext("%(username)s, you have been signed out. Please refresh this page before continuing."),o=interpolate(o,{username:n.user.username},!0))),m(".auth-changed-message",r,m("",m(".container",[m("p",o),m("p",[m('button.btn.btn-default[type="button"]',{onclick:this.refresh},gettext("Reload page")),m("span.hidden-xs.hidden-sm.text-muted",gettext("or press F5 key."))])])))}};t.addService("component:auth-changed-message",function(t){t.component("auth-changed-message",n)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(t,e){var n={disabled:e.disabled||e.loading||!1,config:e.config||null,loading:e.loading||!1,type:e.submit?"submit":"button",onclick:e.onclick||null},o='button[type="'+n.type+'"].btn';n.loading&&(o+=".btn-loading"),e.id&&(o+="#"+e.id),o+=e["class"]||"";var r=e.label;return n.loading&&(r=[r,m(".loader-compact",[m(".bounce1"),m(".bounce2"),m(".bounce3")])]),m(o,n,r)}};t.addService("component:button",function(t){t.component("button",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e=["text","password","email"],n={view:function(t,n){var o=".form-group",r=null,i=null,s=n.control.attrs.type,a=n.control.attrs.id,u=a+"_feedback",c=null,l=null,d=n.validationKey&&null!==n.validation;return n.control.attrs["aria-describedby"]="",d&&n.validation[n.validationKey]&&(l=e.indexOf(s)>=0,n.control.attrs["aria-describedby"]=u,n.validation[n.validationKey]===!0?(o+=".has-success",c=[m("span.material-icon.form-control-feedback",{"aria-hidden":"true"},"check"),m("span.sr-only#"+u,gettext("(success)"))]):(o+=".has-error",r=n.validation[n.validationKey],c=[m("span.material-icon.form-control-feedback",{"aria-hidden":"true"},"clear"),m("span.sr-only#"+u,gettext("(error)"))])),n.helpText&&(i="string"==typeof n.helpText||n.helpText instanceof String?m("p.help-block",n.helpText):n.helpText),m(o,[m("label.control-label"+(n.labelClass||""),{"for":n.labelFor||a},n.label+":"),m(n.controlClass||"",[n.control,l?c:null,r?m(".help-block.errors",r.map(function(t){return m("p",t)})):null,i])])}};t.addService("component:form-group",function(t){t.component("form-group",n)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e=function(t,e,n){n.retain=!0},n={view:function(t,n){return[n.component("auth-changed-message"),n.component("alert"),n.component("navbar"),m(".navbar-dropdown",n.dropdown.slot("navbar-dropdown")),m("#router-fixture",{config:e}),n.component("footer"),n.component("modal")]}};t.addService("component:layout",function(t){t.component("forum-layout",n)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(){return m(".loader.sk-folding-cube",[m(".sk-cube1.sk-cube"),m(".sk-cube2.sk-cube"),m(".sk-cube4.sk-cube"),m(".sk-cube3.sk-cube")])}};t.addService("component:loader",function(t){t.component("loader",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e=function(t,e,n){n.retain=!0},n={view:function(t,n){return m("article.misago-markup",{config:e},m.trust(n))}};t.addService("component:markup",function(t){t.component("markup",n)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e=function(t,e,n){n.retain=!0},n={view:function(){return m('#misago-modal.modal.fade[role="dialog"]',{config:e,tabindex:"-1","aria-labelledby":"misago-modal-label"})}};t.addService("component:modal",function(t){t.component("modal",n)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(t,e){return m(".page-header",m(".container",[m("h1",e.title)]))}};t.addService("component:header",function(t){t.component("header",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e=function(t,e,n){n.retain=!0},n=["progress-bar-danger","progress-bar-warning","progress-bar-warning","progress-bar-primary","progress-bar-success"],o=[gettext("Entered password is very weak."),gettext("Entered password is weak."),gettext("Entered password is average."),gettext("Entered password is strong."),gettext("Entered password is very strong.")],r={view:function(t,r,i){var s=i.zxcvbn.scorePassword(r.password,r.inputs),a={config:e,"class":n[s],style:"width: "+(20+20*s)+"%",role:"progressbar","aria-valuenow":s,"aria-valuemin":"0","aria-valuemax":"4"};return m(".help-block.password-strength",{key:"password-strength"},[m(".progress",m(".progress-bar",a,m("span.sr-only",o[s]))),m("p.text-small",o[s])])}};t.addService("component:password-strength",function(t){t.component("password-strength",r)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={defaultSize:100,src:function(t,e,n){var o=n.router.baseUrl+"user-avatar/";return o+=t&&t.id?t.avatar_hash+"/"+e+"/"+t.id+".png":e+".png"},view:function(t,e,n,o){var r=n||this.defaultSize;return m("img",{alt:e&&e.username?e.username:gettext("Unregistered"),width:r,height:r,src:this.src(e,r,o)})}};t.addService("component:user-avatar",function(t){t.component("user-avatar",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={style:".navbar.navbar-misago.navbar-default.navbar-static-top",mainNav:function(t){var e=[{label:gettext("Threads"),icon:"chat",url:t.router.url("index")},{label:gettext("Forums"),icon:"forum",url:"/not-yet/forums/"},{label:gettext("Users"),icon:"group",url:"/not-yet/users/"}];return e},view:function(t,e){var n=this.mainNav(e);return m("nav"+this.style+'[role="navigation"]',[e.component("navbar:desktop",n),e.component("navbar:mobile",n)])}};t.addService("component:navbar",function(t){t.component("navbar",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={controller:function(t){return{showSignIn:function(){t.modal("sign-in")}}},view:function(t,e){return m('ul.dropdown-menu.user-dropdown.dropdown-menu-right[role="menu"]',m("li.guest-preview",[m("h4",gettext("You are browsing as guest.")),m("p",gettext("Sign in or register to start and participate in discussions.")),m(".row",[m(".col-xs-6",e.component("button",{"class":".btn.btn-default.btn-block",onclick:t.showSignIn,disabled:t.isBusy,label:gettext("Sign in")})),m(".col-xs-6",e.component("navbar:register-button",".btn.btn-primary.btn-block"))])]))}};t.addService("component:navbar:dropdown:guest",function(t){t.component("navbar:dropdown:guest",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={style:".nav.navbar-nav.navbar-compact-nav.hidden-md.hidden-lg",controller:function(t,e){return{openUserMenu:function(){return e.user.isAuthenticated?e.dropdown.toggle("navbar-dropdown","navbar:dropdown:user"):e.dropdown.toggle("navbar-dropdown","navbar:dropdown:guest"),!1}}},userMenu:function(t,e){return e.user.isAuthenticated?{element:e.component("user-avatar",e.user,64),config:{onclick:t.openUserMenu,url:"/not-yet/","data-misago-routed":"false"}}:{element:e.component("user-avatar",null,64),config:{onclick:t.openUserMenu,href:"#","data-misago-routed":"false"}}},mobileNav:function(t,e,n){var o=[{element:m("img",{src:n.router.staticUrl("misago/img/site-icon.png"),alt:n.settings.forum_name}),url:n.router.url("index")}];return e.forEach(function(t){t.url!==o[0].url&&o.push(t)}),o.push(this.userMenu(t,n)),o},view:function(t,e,n){var o=this.mobileNav(t,e,n);return m("ul"+this.style+".with-"+o.length+"-items",o.map(function(t){return m("li",m("a",t.config||{href:t.url},t.element||m("span.material-icon",{title:t.label},t.icon)))}))}};t.addService("component:navbar:mobile",function(t){t.component("navbar:mobile",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={controller:function(t,e){return{isBusy:!1,showRegister:function(){if("closed"===e.settings.account_activation)e.alert.info(gettext("New registrations are currently disabled."));else{m.startComputation(),this.isBusy=!0,m.endComputation();var t=this;m.sync([e.zxcvbn.load(),e.captcha.load()]).then(function(){e.modal("register")},function(){e.alert.error(gettext("Registation is not available now due to an error."))}).then(function(){m.startComputation(),t.isBusy=!1,m.endComputation()})}}}},view:function(t,e,n){return n.component("button",{"class":e,onclick:t.showRegister.bind(t),loading:t.isBusy,label:gettext("Register")})}};t.addService("component:navbar:register-button",function(t){t.component("navbar:register-button",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={"class":".dropdown-menu.user-dropdown.dropdown-menu-right",controller:function(){return{logout:function(){var t=confirm(gettext("Are you sure you want to sign out?"));t&&$("#hidden-logout-form").submit()}}},view:function(t,e){return m("ul"+this["class"]+'[role="menu"]',[m("li.dropdown-header",m("strong",e.user.username)),m("li.divider"),m("li",m("a",{href:"/not-yet/"},[m("span.material-icon","account_circle"),gettext("See your profile")])),m("li",m("a",{href:e.router.url("options")},[m("span.material-icon","done_all"),gettext("Change options")])),m("li",m('button.btn-link[type="button"]',[m("span.material-icon","face"),gettext("Change avatar")])),m("li.divider"),m("li.dropdown-footer",m("button.btn.btn-default.btn-block",{onclick:t.logout},gettext("Logout")))])}};t.addService("component:navbar:dropdown:user",function(t){t.component("navbar:dropdown:user",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={hasNav:function(t){return-1!==[!!t.settings.forum_footnote,!!t.settings.terms_of_service,!!t.settings.terms_of_service_link,!!t.settings.privacy_policy,!!t.settings.privacy_policy_link].indexOf(!0)},view:function(t,e){var n=null;return this.hasNav(e)&&(n=e.component("footer:nav")),m("footer.forum-footer",[m(".container",m(".footer-content",[n,e.component("footer:branding")]))])}};t.addService("component:footer",function(t){t.component("footer",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(){return m("a.misago-branding[href=http://misago-project.org]",["powered by ",m("strong","misago")])}};t.addService("component:footer:branding",function(t){t.component("footer:branding",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e=function(e,n,o){var r=t.get(e.settings,n+"_link");return!r&&t.get(e.settings,n)&&(r=e.router.url(n)),r?m("li",m("a",{href:r},t.get(e.settings,n+"_title",o))):null},n={isVisible:function(t){return-1!==[!!t.forum_footnote,!!t.terms_of_service,!!t.terms_of_service_link,!!t.privacy_policy,!!t.privacy_policy_link].indexOf(!0)},view:function(t,n){var o=[];return n.settings.forum_footnote&&o.push(m("li.forum-footnote",m.trust(n.settings.forum_footnote))),o.push(e(n,"terms_of_service",gettext("Terms of service"))),o.push(e(n,"privacy_policy",gettext("Privacy policy"))),m("ul.list-inline.footer-nav",o)}};t.addService("component:footer:nav",function(t){t.component("footer:nav",n)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(e,n,o){return m(".well.well-form",m("form",{onsubmit:n.submit},[m(".form-group",m(".control-input",t.input({disabled:n.isBusy,value:n.email,placeholder:gettext("Your e-mail address")}))),o.component("button",{"class":".btn-primary.btn-block",submit:!0,loading:n.isBusy,label:gettext("Send link")})]))}};t.addService("component:request-link-form",function(t){t.component("request-link-form",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e={view:function(t,e){return m(".modal-header",[m('button.close[type="button"]',{"data-dismiss":"modal","aria-label":gettext("Close")},m("span",{"aria-hidden":"true"},m.trust("&times;"))),m("h4#misago-modal-label.modal-title",e)])}};t.addService("component:modal:header",function(t){t.component("modal:header",e)},{after:"components"})}(Misago.prototype),function(t){"use strict";var e=function(t,e,n){n.retain=!0},n=function(){document.location.reload()},o={controller:function(t,e){"active"===t.activation&&e.runloop.runOnce(n,"refresh-after-registration",1e4)},view:function(t,n,o){var r=null;return r="active"===n.activation?this.active(n):this.inactive(n),m('.modal-dialog.modal-message.modal-register[role="document"]',{config:e},m(".modal-content",[o.component("modal:header",gettext("Registration complete")),m(".modal-body",r)]))},active:function(t){var e=gettext("%(username)s, your account has been created and you were signed in.");return[m(".message-icon",m("span.material-icon","check")),m(".message-body",[m("p.lead",interpolate(e,{username:t.username},!0)),m("p",gettext("The page will refresh automatically in 10 seconds.")),m("p",m('button[type="button"].btn.btn-default',{onclick:n},gettext("Refresh page")))])]},inactive:function(t){var e=null,n=null;return"user"===t.activation?(e=gettext("%(username)s, your account has been created but you need to activate it before you will be able to sign in."),n=gettext("We have sent an e-mail to %(email)s with link that you have to click to activate your account.")):"admin"===t.activation&&(e=gettext("%(username)s, your account has been created but board administrator will have to activate it before you will be able to sign in."),n=gettext("We will send an e-mail to %(email)s when this takes place.")),[m(".message-icon",m("span.material-icon","info_outline")),m(".message-body",[m("p.lead",interpolate(e,{username:t.username},!0)),m("p",interpolate(n,{email:t.email},!0))])]}};t.addService("modal:register-complete",function(t){t.modal("register-complete",o)},{after:"modals"})}(Misago.prototype),function(t){"use strict";var e=function(t,e,n){n.retain=!0},n={controller:function(t){return{form:t.form("register")}},view:function(t,n){var o=n.captcha.component({form:t.form,labelClass:".col-md-4",controlClass:".col-md-8"}),r=null,i=n.settings.terms_of_service_link;return!i&&n.settings.terms_of_service&&(i=n.router.url("terms_of_service")),i&&(r=m("a",{href:i},m.trust(interpolate(gettext("By registering you agree to site's %(terms)s."),{terms:"<strong>"+gettext("terms and conditions")+"</strong>"},!0)))),m('.modal-dialog.modal-form.modal-register[role="document"]',{config:e},m(".modal-content",[n.component("modal:header",gettext("Register")),m("form.form-horizontal",{onsubmit:t.form.submit},[m('input[type="text"]',{name:"_username",style:"display: none"}),m('input[type="password"]',{name:"_password",style:"display: none"}),m(".modal-body",[n.component("form-group",{label:gettext("Username"),labelClass:".col-md-4",controlClass:".col-md-8",control:n.input({value:n.validate(t.form,"username"),id:"id_username",disabled:t.form.isBusy}),validation:t.form.errors,validationKey:"username"}),n.component("form-group",{label:gettext("E-mail"),labelClass:".col-md-4",controlClass:".col-md-8",control:n.input({value:n.validate(t.form,"email"),id:"id_email",disabled:t.form.isBusy}),validation:t.form.errors,validationKey:"email"}),n.component("form-group",{label:gettext("Password"),labelClass:".col-md-4",controlClass:".col-md-8",control:n.input({value:n.validate(t.form,"password"),type:"password",id:"id_password",disabled:t.form.isBusy}),validation:t.form.errors,validationKey:"password",helpText:n.component("password-strength",{inputs:[t.form.username(),t.form.email()],password:t.form.password()})}),o]),m(".modal-footer",[r,n.component("button",{"class":".btn-primary",submit:!0,loading:t.form.isBusy,label:gettext("Register account")})])])]))}};t.addService("modal:register",function(t){t.modal("register",n)},{after:"modals"})}(Misago.prototype),function(t){"use strict";function e(t,e,n){n.retain=!0}var n={controller:function(t){return{form:t.form("sign-in")}},view:function(n,o){var r=null;return n.form.showActivation&&(r=m("a.btn.btn-block.btn-success",{href:o.router.url("request_activation")},gettext("Activate account"))),m('.modal-dialog.modal-sm.modal-signin[role="document"]',{config:e},m(".modal-content",[o.component("modal:header",gettext("Sign in")),m("form",{onsubmit:n.form.submit},[m(".modal-body",[m(".form-group",m(".control-input",t.input({disabled:n.form.isBusy,value:n.form.username,placeholder:gettext("Username or e-mail")}))),m(".form-group",m(".control-input",t.input({type:"password",disabled:n.form.isBusy,value:n.form.password,placeholder:gettext("Password")})))]),m(".modal-footer",[r,o.component("button",{"class":".btn-primary.btn-block",submit:!0,loading:n.form.isBusy,label:gettext("Sign in")}),m("a.btn.btn-block.btn-default",{href:o.router.url("request_password_change")},gettext("Forgot password?"))])])]))}};t.addService("modal:sign-in",function(t){t.modal("sign-in",n)},{after:"modals"})}(Misago.prototype),function(t){"use strict";var e=function(e){var n=this;this.username=null,this.password=m.prop(""),this.validation={password:[t.validators.passwordMinLength(e.settings)]},this.clean=function(){return e.validate(this)?!0:(e.alert.error($.trim(this.password()).length?this.errors.password:gettext("Enter new password.")),!1)},this.submit=function(){var t=e.api.endpoint("auth").endpoint("change-password");t=t.endpoint(m.route.param("user_id")),t=t.endpoint(m.route.param("token")),t.post({password:n.password()}).then(function(t){n.success(t)},function(t){n.error(t)})},this.success=function(t){this.username=t.username},this.error=function(t){403===t.status&&t.ban?e.router.error403({message:"",ban:t.ban}):400===t.status?e.alert.error(t.detail):e.api.alert(t)}};t.addService("form:change-password",function(t){t.form("change-password",e)},{after:"forms"})}(Misago.prototype),function(t){"use strict";var e=function(e){var n=this;this.showActivation=!1,this.username=m.prop(""),this.email=m.prop(""),this.password=m.prop(""),this.captcha=e.captcha.value,this.errors=null,this.validation={username:[t.validators.usernameContent(),t.validators.usernameMinLength(e.settings),t.validators.usernameMaxLength(e.settings)],email:[t.validators.email()],password:[t.validators.passwordMinLength(e.settings)],captcha:e.captcha.validator()},this.clean=function(){return null===this.errors&&e.validate(this),e.captcha.clean(this),this.hasErrors()?(e.alert.error(gettext("Form contains errors.")),!1):!0},this.submit=function(){e.api.model("user").post({username:this.username(),email:this.email(),password:this.password(),captcha:this.captcha()}).then(this.success,this.error)},this.success=function(t){e.modal("register-complete",t)},this.error=function(t){400===t.status?(e.alert.error(gettext("Form contains errors.")),$.extend(n.errors,t)):e.api.alert(t)}};t.addService("form:register",function(t){t.form("register",e)},{after:"forms"})}(Misago.prototype),function(t){"use strict";var e=function(e,n){var o=this;this.email=m.prop(""),this.validation={email:[t.validators.email()]},this.clean=function(){return n.validate(this)?!0:(n.alert.error(gettext("Enter a valid email address.")),!1)},this.submit=function(){n.api.endpoint("auth").endpoint(e.endpoint).post({email:o.email()}).then(function(t){o.success(t)},function(t){o.error(t)})},this.success=function(t){e.success(t)},this.error=function(t){400===t.status?e.error(t,n):403===t.status&&t.ban?n.router.error403({message:"",ban:t.ban}):n.api.alert(t)},this.reset=function(){this.email(""),e.reset()}};t.addService("form:request-link",function(t){t.form("request-link",e)},{after:"forms"})}(Misago.prototype),function(t){"use strict";var e=function(t){var e=this;this.showActivation=!1,this.username=m.prop(""),this.password=m.prop(""),this.validation={username:[],password:[]},this.clean=function(){return t.validate(this)?!0:(t.alert.error(gettext("Fill out both fields.")),!1)},this.submit=function(){t.api.endpoint("auth").post({username:e.username(),password:e.password()}).then(function(){e.success()},function(t){e.error(t)})},this.success=function(){t.modal();var e=$("#hidden-login-form");t.ajax.refreshCsrfToken(),e.find('input[type="hidden"]').val(t.ajax.csrfToken),e.find('input[name="redirect_to"]').val(m.route()),e.find('input[name="username"]').val(this.username()),e.find('input[name="password"]').val(this.password()),e.submit()},this.error=function(n){400===n.status?"inactive_admin"===n.code?t.alert.info(n.detail):"inactive_user"===n.code?(t.alert.info(n.detail),e.showActivation=!0):"banned"===n.code?(t.modal(),t.router.error403({message:"",ban:n.detail})):t.alert.error(n.detail):t.api.alert(n)}};t.addService("form:sign-in",function(t){t.form("sign-in",e)},{after:"forms"})}(Misago.prototype),function(t,e){"use strict";var n=new e;n.url("/","index"),n.url("/activation/","request_activation"),n.url("/activation/:user_id/:token/","activate_by_token"),n.url("/forgotten-password/","request_password_change"),n.url("/forgotten-password/:user_id/:token/","change_password"),n.url("/options/","options"),n.url("/options/forum/","options_forum"),n.url("/options/email/","options_email"),n.url("/options/password/","options_password"),n.url("/terms-of-service/","terms_of_service"),n.url("/privacy-policy/","privacy_policy"),n.url("/:rest...","error:404","not_found"),t.urls=n}(Misago.prototype,Misago.prototype.UrlConf);
 //# sourceMappingURL=/misago.js.map

+ 1 - 1
misago/static/misago/js/misago.js.map

@@ -1 +1 @@
-{"version":3,"sources":["misago.js"],"names":["window","Misago","ns","Object","getPrototypeOf","this","self","_initServices","services","orderedServices","OrderedList","order","forEach","item","factory","undefined","serviceInstance","key","_destroyServices","reverse","destroy","context","SETTINGS","setup","init","fixture","get","test","api","_services","proto","prototype","addService","name","push","after","before","PermissionDenied","message","detail","status","toString","has","obj","hasOwnProperty","value","pop","returnValue","persistent","el","isInit","retain","input","kwargs","options","disabled","config","placeholder","autocomplete","element","id","type","oninput","m","withAttr","noop","stateHooks","component","loadingState","errorState","_hasLifecycleHooks","isActive","errorHandler","bind","_controller","controller","apply","arguments","_onunload","onunload","e","vm","loading","loadingHandler","_view","view","isReady","_init","initArgs","promise","then","ondata","finalArgs","i","length","f","error","items","isOrdered","_items","add","values","values_only","_order","unordered","insertItem","insertAt","ordering","indexOf","ordered","splice","index","iterations","serializeDatetime","serialized","format","deserializeDatetime","deserialized","moment","Site","_","isFinalized","_pages","addPage","page","getPages","finalize","getDefaultLink","link","startsWith","string","beginning","endsWith","tail","UrlConf","_patterns","patterns","prefixPattern","prefix","pattern","replace","include","url","loadingPage","getCsrfToken","cookie_name","document","cookie","cookieRegex","RegExp","match","split","Ajax","refreshCsrfToken","csrfToken","CSRF_COOKIE_NAME","runningGets","ajax","method","data","progress","deferred","ajax_settings","headers","X-CSRFToken","dataType","success","resolve","jqXHR","rejection","responseJSON","statusText","reject","$","preloaded","post","patch","put","ALERT_BASE_DISPLAY_TIME","ALERT_LENGTH_FACTOR","ALERT_MAX_DISPLAY_TIME","ALERT_HIDE_ANIMATION_LENGTH","Alert","isVisible","show","displayTime","runloop","runOnce","startComputation","endComputation","set","stop","info","warning","filtersUrl","filters","encodedKey","encodeURIComponent","encodedValue","join","Query","call","path","related","model","relation","endpoint","results","map","models","Api","alert","gettext","Auth","user","deserialize","isDesynced","newUser","handleAuthChange","isAuthenticated","localstore","handleUserChange","extend","syncSession","watch","denyAuthenticated","denyAnonymous","isAnonymous","NoCaptcha","load","QACaptcha","question","prop","label","labelClass","controlClass","control","validate","form","isBusy","validation","errors","validationKey","helpText","help_text","validator","ReCaptcha","included","wait","grecaptcha","reset","controlConfig","render","sitekey","settings","recaptcha_site_key","getResponse","clean","captcha","Captcha","types","no","qa","re","captcha_type","_components","argumentsArray","dropdownConfig","on","removeClass","off","Dropdown","slots","slot","toggle","getElementById","hasChildNodes","mount","addClass","boilerplate","_submit","submit","_success","_error","hasErrors","constructor","_forms","script","remote","STATIC_URL","cache","LocalStore","storage","localStorage","watchers","handleStorageEvent","newValueJson","JSON","parse","newValue","each","watcher","keyName","oldValue","callback","addEventListener","prefixKey","setItem","stringify","itemString","getItem","Modal","delegateName","hide","remove","modal","open","_modal","_modals","Models","classes","deserializers","String","json","locale","attr","Router","baseUrl","staticUrl","mediaUrl","urls","reverses","populatePatterns","urlconf","finalPattern","route","startRouting","mode","redirect","delegateElement","cleanUrl","isRelative","substr","location","protocol","host","avatarsUrl","delegateSelector","delegateClicks","currentTarget","href","preventDefault","prefixUrl","error403","ban","error404","error500","error0","errorPage","waitForFixture","router","setTimeout","_hasRouteBoilerplate","loadingView","container","onerror","_routes","RunLoop","_intervals","stopInterval","clearTimeout","run","callable","delay","result","loop","ticks","PageTitle","forum_name","title","_set_complex","completeTitle","page_label","interpolate","parent","EMAIL","USERNAME","validators","required","trim","email","minLength","limit_value","returnMessage","ngettext","show_value","maxLength","usernameMinLength","username_length_min","usernameMaxLength","username_length_max","usernameContent","passwordMinLength","password_length_min","validateField","validateForm","isValid","Zxcvbn","scorePassword","password","inputs","zxcvbn","score","Ban","html","plain","expires_on","deserializeBan","class","LegalPage","body","Rank","slug","description","css_class","is_tab","User","username","full_title","rank","avatar_hash","acl","deserializeUser","joined_on","viewModel","param","activateByToken","auth","ctrl","rejected","changePassword","signin","complete","onsubmit","onclick","error_message","help","code","icon","errorBanned","trust","expirationMessage","isAfter","fromNow","forum_index_title","activation","legalPageFactory","typeName","defaultTitle","dashedTypeName","ViewModel","requestActivation","completed","activationMessage","requestPasswordChange","inactive","activateButton","forum","authChanged","refresh","reload","button","textFields","formGroup","groupClass","controlType","attrs","controlId","feedbackId","feedbackIcon","showFeedbackIcon","isValidated","aria-hidden","for","labelFor","forumLayout","dropdown","loader","markup","content","tabindex","aria-labelledby","header","styles","labels","passwordStrength","style","role","aria-valuenow","aria-valuemin","aria-valuemax","avatar","defaultSize","src","size","finalSize","alt","width","height","data-dismiss","aria-label","registerComplete","messageHtml","active","lead","register","footnote","termsUrl","terms_of_service_link","terms_of_service","terms","showActivation","navbar","mainNav","links","showSignIn","openUserMenu","userMenu","data-misago-routed","mobileNav","mobileLinks","showRegister","account_activation","sync","logout","decision","confirm","footer","hasNav","forum_footnote","privacy_policy","privacy_policy_link","nav","branding","legalLink","legalType","brand","children","forum_branding_display","forum_branding_text","dropdownToggle","data-toggle","aria-haspopup","aria-expanded","ChangePassword","Register","RequestLink","SignIn","$form","find","val"],"mappings":"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","file":"misago.js","sourcesContent":["/* global -Misago */\n/* exported Misago */\n(function () {\n  'use strict';\n\n  window.Misago = function() {\n    var ns = Object.getPrototypeOf(this);\n    var self = this;\n\n    // Services init/destroy\n    this._initServices = function(services) {\n      var orderedServices = new ns.OrderedList(services).order(false);\n      orderedServices.forEach(function (item) {\n        var factory = null;\n        if (item.item.factory !== undefined) {\n          factory = item.item.factory;\n        } else {\n          factory = item.item;\n        }\n\n        var serviceInstance = factory(self);\n        if (serviceInstance) {\n          self[item.key] = serviceInstance;\n        }\n      });\n    };\n\n    this._destroyServices = function(services) {\n      var orderedServices = new ns.OrderedList(services).order();\n      orderedServices.reverse();\n      orderedServices.forEach(function (item) {\n        if (item.destroy !== undefined) {\n          item.destroy(self);\n        }\n      });\n    };\n\n    // Context data\n    this.context = {\n      // Empty settings\n      SETTINGS: {}\n    };\n\n    // App init/destory\n    this.setup = false;\n    this.init = function(setup, context) {\n      this.setup = {\n        fixture: ns.get(setup, 'fixture', null),\n        test: ns.get(setup, 'test', false),\n        api: ns.get(setup, 'api', '/api/')\n      };\n\n      if (context) {\n        this.context = context;\n      }\n\n      this._initServices(ns._services);\n    };\n\n    this.destroy = function() {\n      this._destroyServices(ns._services);\n    };\n  };\n\n  // Services\n  var proto = window.Misago.prototype;\n\n  proto._services = [];\n  proto.addService = function(name, factory, order) {\n    proto._services.push({\n      key: name,\n      item: factory,\n      after: proto.get(order, 'after'),\n      before: proto.get(order, 'before')\n    });\n  };\n\n  // Exceptions\n  proto.PermissionDenied = function(message) {\n    this.detail = message;\n    this.status = 403;\n\n    this.toString = function() {\n      return this.detail || 'Permission denied';\n    };\n  };\n}());\n\n(function (Misago) {\n  'use strict';\n\n  Misago.has = function(obj, key) {\n    if (obj) {\n      return obj.hasOwnProperty(key);\n    } else {\n      return false;\n    }\n  };\n\n  Misago.get = function(obj, key, value) {\n    if (Misago.has(obj, key)) {\n      return obj[key];\n    } else if (value !== undefined) {\n      return value;\n    } else {\n      return undefined;\n    }\n  };\n\n  Misago.pop = function(obj, key, value) {\n    var returnValue = Misago.get(obj, key, value);\n    if (Misago.has(obj, key)) {\n      obj[key] = null;\n    }\n    return returnValue;\n  };\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  function persistent(el, isInit, context) {\n    context.retain = true;\n  }\n\n  Misago.input = function(kwargs) {\n    var options = {\n      disabled: kwargs.disabled || false,\n      config: kwargs.config || persistent\n    };\n\n    if (kwargs.placeholder) {\n      options.placeholder = kwargs.placeholder;\n    }\n\n    if (kwargs.autocomplete === false) {\n      options.autocomplete = 'off';\n    }\n\n    var element = 'input';\n\n    if (kwargs.id) {\n      element += '#' + kwargs.id;\n      options.key = 'field-' + kwargs.id;\n    }\n\n    element += '.form-control' + (kwargs.class || '');\n    element += '[type=\"' + (kwargs.type || 'text') + '\"]';\n\n    if (kwargs.value) {\n      options.value = kwargs.value();\n      options.oninput = m.withAttr('value', kwargs.value);\n    }\n\n    return m(element, options);\n  };\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var noop = function() {};\n\n  Misago.stateHooks = function(component, loadingState, errorState) {\n    /*\n      Boilerplate for Misago components with lifecycles\n    */\n\n    // Component boilerplated (this may happen in tests)\n    if (component._hasLifecycleHooks) {\n      return component;\n    }\n    component._hasLifecycleHooks = true;\n\n    // Component active state\n    component.isActive = true;\n\n    var errorHandler = errorState.bind(component);\n\n    // Wrap controller to store lifecycle methods\n    var _controller = component.controller || noop;\n    component.controller = function() {\n      try {\n        component.isActive = true;\n        var controller = _controller.apply(component, arguments) || {};\n\n        // wrap onunload for lifestate\n        var _onunload = controller.onunload || noop;\n        controller.onunload = function() {\n          _onunload.apply(component, arguments);\n          component.isActive = false;\n        };\n\n        return controller;\n      } catch (e) {\n        errorHandler(e);\n      }\n    };\n\n    // Add state callbacks to View-Model\n    if (component.vm && component.vm.init) {\n      // setup default loading view\n      if (!component.loading) {\n        var loadingHandler = loadingState.bind(component);\n        component.loading = loadingHandler;\n      }\n\n      var _view = component.view;\n      component.view = function() {\n        if (component.vm.isReady) {\n          return _view.apply(component, arguments);\n        } else {\n          return component.loading.apply(component, arguments);\n        }\n      };\n\n      // wrap vm.init in promise handler\n      var _init = component.vm.init;\n      component.vm.init = function() {\n        var initArgs = arguments;\n        var promise = _init.apply(component.vm, initArgs);\n\n        if (promise) {\n          promise.then(function() {\n            if (component.isActive && component.vm.ondata) {\n              var finalArgs = [];\n              for (var i = 0; i < arguments.length; i++) {\n                finalArgs.push(arguments[i]);\n              }\n              for (var f = 0; f < initArgs.length; f++) {\n                finalArgs.push(initArgs[f]);\n              }\n\n              component.vm.ondata.apply(component.vm, finalArgs);\n            }\n          }, function(error) {\n            if (component.isActive) {\n              errorHandler(error);\n            }\n          });\n        }\n      };\n    }\n\n    return component;\n  };\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.OrderedList = function(items) {\n    this.isOrdered = false;\n    this._items = items || [];\n\n    this.add = function(key, item, order) {\n      this._items.push({\n        key: key,\n        item: item,\n        after: Misago.get(order, 'after'),\n        before: Misago.get(order, 'before')\n      });\n    };\n\n    this.get = function(key, value) {\n      for (var i = 0; i < this._items.length; i++) {\n        if (this._items[i].key === key) {\n          return this._items[i].item;\n        }\n      }\n\n      return value;\n    };\n\n    this.has = function(key) {\n      return this.get(key) !== undefined;\n    };\n\n    this.values = function() {\n      var values = [];\n      for (var i = 0; i < this._items.length; i++) {\n        values.push(this._items[i].item);\n      }\n      return values;\n    };\n\n    this.order = function(values_only) {\n      if (!this.isOrdered) {\n        this._items = this._order(this._items);\n        this.isOrdered = true;\n      }\n\n      if (values_only || typeof values_only === 'undefined') {\n        return this.values();\n      } else {\n        return this._items;\n      }\n    };\n\n    this._order = function(unordered) {\n      // Index of unordered items\n      var index = [];\n      unordered.forEach(function (item) {\n        index.push(item.key);\n      });\n\n      // Ordered items\n      var ordered = [];\n      var ordering = [];\n\n      // First pass: register items that\n      // don't specify their order\n      unordered.forEach(function (item) {\n        if (!item.after && !item.before) {\n          ordered.push(item);\n          ordering.push(item.key);\n        }\n      });\n\n      // Second pass: register items that\n      // specify their before to \"_end\"\n      unordered.forEach(function (item) {\n        if (item.before === \"_end\") {\n          ordered.push(item);\n          ordering.push(item.key);\n        }\n      });\n\n      // Third pass: keep iterating items\n      // until we hit iterations limit or finish\n      // ordering list\n      function insertItem(item) {\n        var insertAt = -1;\n        if (ordering.indexOf(item.key) === -1) {\n          if (item.after) {\n            insertAt = ordering.indexOf(item.after);\n            if (insertAt !== -1) {\n              insertAt += 1;\n            }\n          } else if (item.before) {\n            insertAt = ordering.indexOf(item.before);\n          }\n\n          if (insertAt !== -1) {\n            ordered.splice(insertAt, 0, item);\n            ordering.splice(insertAt, 0, item.key);\n          }\n        }\n      }\n\n      var iterations = 200;\n      while (iterations > 0 && index.length !== ordering.length) {\n        iterations -= 1;\n        unordered.forEach(insertItem);\n      }\n\n      return ordered;\n    };\n  };\n} (Misago.prototype));\n\n(function (Misago) {\n  Misago.serializeDatetime = function(serialized) {\n    return serialized ? serialized.format() : null;\n  };\n\n  Misago.deserializeDatetime = function(deserialized) {\n    return deserialized ? moment(deserialized) : null;\n  };\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.Site = function(name, _) {\n    var self = this;\n\n    this.name = name\n    this.isFinalized = false;\n    this._pages = [];\n\n    var finalize = function() {\n      if (!this.isFinalized) {\n        this.isFinalized = true;\n\n        var visible = [];\n        this._pages.forEach(function (item) {\n          if (!item.visibleIf || item.visibleIf(_)) {\n            visible.push(item);\n          }\n        });\n        this._pages = Misago.OrderedList(visible).order();\n      }\n    };\n\n    this.addPage = function(page) {\n      if (this.isFinalized) {\n        throw (this.name + \" site was initialized already and no longer accepts new pages\");\n      }\n\n      this._pages.push(page);\n    };\n\n    this.getPages = function() {\n      this.finalize();\n      return this._pages;\n    };\n\n    this.getDefaultLink = function() {\n      this.finalize();\n      return this._pages[0].link;\n    };\n  };\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.startsWith = function(string, beginning) {\n    return string.indexOf(beginning) === 0;\n  };\n\n  Misago.endsWith = function(string, tail) {\n    return string.indexOf(tail, string.length - tail.length) !== -1;\n  };\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.UrlConf = function() {\n    var self = this;\n    this._patterns = [];\n\n    this.patterns = function() {\n      return this._patterns;\n    };\n\n    var prefixPattern = function(prefix, pattern) {\n      return (prefix + pattern).replace('//', '/');\n    };\n\n    var include = function(prefix, patterns) {\n      for (var i = 0; i < patterns.length; i ++) {\n        self.url(prefixPattern(prefix, patterns[i].pattern),\n                 patterns[i].component,\n                 patterns[i].name);\n      }\n    };\n\n    this.url = function(pattern, component, name) {\n      if (pattern === '') {\n        pattern = '/';\n      }\n\n      if (component instanceof Misago.UrlConf) {\n        include(pattern, component.patterns());\n      } else {\n        this._patterns.push({\n          pattern: pattern,\n          component: component.replace(/_/g, '-'),\n          name: name || component\n        });\n      }\n    };\n  };\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.loadingPage = function(_) {\n    return m('.page.page-loading',\n      _.component('loader')\n    );\n  };\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var getCsrfToken = function(cookie_name) {\n    if (document.cookie.indexOf(cookie_name) !== -1) {\n      var cookieRegex = new RegExp(cookie_name + '\\=([^;]*)');\n      var cookie = Misago.get(document.cookie.match(cookieRegex), 0);\n      return cookie.split('=')[1];\n    } else {\n      return null;\n    }\n  };\n\n  var Ajax = function(_) {\n    this.refreshCsrfToken = function() {\n      this.csrfToken = getCsrfToken(_.context.CSRF_COOKIE_NAME);\n    };\n    this.refreshCsrfToken();\n\n    /*\n      List of GETs underway\n      We are limiting number of GETs to API to 1 per url\n    */\n    var runningGets = {};\n\n    this.ajax = function(method, url, data, progress) {\n      var promise = m.deferred();\n\n      var ajax_settings = {\n        url: url,\n        method: method,\n        headers: {\n          'X-CSRFToken': this.csrfToken\n        },\n\n        data: data || {},\n        dataType: 'json',\n\n        success: function(data) {\n          if (method === 'GET') {\n            Misago.pop(runningGets, url);\n          }\n          promise.resolve(data);\n        },\n        error: function(jqXHR) {\n          if (method === 'GET') {\n            Misago.pop(runningGets, url);\n          }\n\n          var rejection = jqXHR.responseJSON || {};\n\n          rejection.status = jqXHR.status;\n          rejection.statusText = jqXHR.statusText;\n\n          promise.reject(rejection);\n        }\n      };\n\n      if (progress) {\n        return; // not implemented... yet!\n      }\n\n      $.ajax(ajax_settings);\n      return promise.promise;\n    };\n\n    this.get = function(url) {\n      var preloaded = Misago.pop(_.context, url);\n      if (preloaded) {\n        var deferred = m.deferred();\n        deferred.resolve(preloaded);\n        return deferred.promise;\n      } else if (runningGets[url] !== undefined) {\n        return runningGets[url];\n      } else {\n        runningGets[url] = this.ajax('GET', url);\n        return runningGets[url];\n      }\n    };\n\n    this.post = function(url, data) {\n      return this.ajax('POST', url, data);\n    };\n\n    this.patch = function(url, data) {\n      return this.ajax('PATCH', url, data);\n    };\n\n    this.put = function(url, data) {\n      return this.ajax('PUT', url, data);\n    };\n\n    this.delete = function(url) {\n      return this.ajax('DELETE', url);\n    };\n  };\n\n  Misago.addService('ajax', function(_) {\n    return new Ajax(_);\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var ALERT_BASE_DISPLAY_TIME = 5 * 1000;\n  var ALERT_LENGTH_FACTOR = 70;\n  var ALERT_MAX_DISPLAY_TIME = 9 * 1000;\n  var ALERT_HIDE_ANIMATION_LENGTH = 300;\n\n  var Alert = function(_) {\n    var self = this;\n\n    this.type = '';\n    this.message = null;\n    this.isVisible = false;\n\n    var show = function(type, message) {\n      self.type = type;\n      self.message = message;\n      self.isVisible = true;\n\n      var displayTime = ALERT_BASE_DISPLAY_TIME;\n      displayTime += message.length * ALERT_LENGTH_FACTOR;\n      if (displayTime > ALERT_MAX_DISPLAY_TIME) {\n        displayTime = ALERT_MAX_DISPLAY_TIME;\n      }\n\n      _.runloop.runOnce(function () {\n        m.startComputation();\n        self.isVisible = false;\n        m.endComputation();\n      }, 'flash-message-hide', displayTime);\n    };\n\n    var set = function(type, message) {\n      _.runloop.stop('flash-message-hide');\n      _.runloop.stop('flash-message-show');\n\n      if (self.isVisible) {\n        self.isVisible = false;\n        _.runloop.runOnce(function () {\n          m.startComputation();\n          show(type, message);\n          m.endComputation();\n        }, 'flash-message-show', ALERT_HIDE_ANIMATION_LENGTH);\n      } else {\n        show(type, message);\n      }\n    };\n\n    this.info = function(message) {\n      set('info', message);\n    };\n\n    this.success = function(message) {\n      set('success', message);\n    };\n\n    this.warning = function(message) {\n      set('warning', message);\n    };\n\n    this.error = function(message) {\n      set('error', message);\n    };\n  };\n\n  Misago.addService('alert', {\n    factory: function(_) {\n      return new Alert(_);\n    }\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var filtersUrl = function(filters) {\n    if (typeof filters === 'object') {\n      var values = [];\n      for (var key in filters) {\n        if (filters.hasOwnProperty(key)) {\n          var encodedKey = encodeURIComponent(key);\n          var encodedValue = encodeURIComponent(filters[key]);\n          values.push(encodedKey + '=' + encodedValue);\n        }\n      }\n      return '?' + values.join('&');\n    } else {\n      return filters + '/';\n    }\n  };\n\n  var Query = function(_, call) {\n    this.url = call.url || _.setup.api;\n\n    if (call.path) {\n      this.url += call.path + '/';\n    } else if (call.related) {\n      this.url += call.related + '/';\n    } else {\n      this.url += call.model + 's' + '/';\n    }\n\n    if (call.filters) {\n      this.url += filtersUrl(call.filters);\n    }\n\n    if (call.model) {\n      this.related = function(model, filters) {\n        return new Query(_, {\n          url: this.url,\n          relation: call.model,\n          related: model,\n          filters: filters,\n        });\n      };\n    }\n\n    this.endpoint = function(path, filters) {\n      return new Query(_, {\n        url: this.url,\n        path: path,\n        filters: filters\n      });\n    };\n\n    this.get = function() {\n      var model = null;\n      if (call.related) {\n        model = call.relation + ':' + call.related;\n      } else if (call.model) {\n        model = call.model;\n      }\n\n      return _.ajax.get(this.url).then(function(data) {\n        if (model) {\n          if (data.results) {\n            data.results.map(function(item) {\n              return _.models.new(model, item);\n            });\n            return data;\n          } else {\n            return _.models.new(model, data);\n          }\n        } else {\n          return data;\n        }\n      });\n    };\n\n    this.post = function(data) {\n      return _.ajax.post(this.url, data);\n    };\n\n    this.patch = function(data) {\n      return _.ajax.patch(this.url, data);\n    };\n\n    this.put = function(data) {\n      return _.ajax.put(this.url, data);\n    };\n\n    this.delete = function() {\n      return _.ajax.delete(this.url);\n    };\n\n    // shortcut for get()\n    this.then = function(resolve, reject) {\n      return this.get().then(resolve, reject);\n    };\n  };\n\n  var Api = function(_) {\n    this.model = function(model, filters) {\n      return new Query(_, {\n        model: model,\n        filters: filters,\n      });\n    };\n\n    this.endpoint = function(path, filters) {\n      return new Query(_, {\n        path: path,\n        filters: filters\n      });\n    };\n\n    this.alert = function(rejection) {\n      // Shorthand for API errors\n      var message = gettext(\"Unknown error has occured.\");\n\n      if (rejection.status === 0) {\n        message = gettext(\"Lost connection with application.\");\n      }\n\n      if (rejection.status === 403) {\n        message = rejection.detail;\n        if (message === \"Permission denied\") {\n          message = gettext(\n            \"You don't have permission to perform this action.\");\n        }\n      }\n\n      if (rejection.status === 404) {\n        message = gettext(\"Action link is invalid.\");\n      }\n\n      _.alert.error(message);\n    };\n  };\n\n  Misago.addService('api', function(_) {\n    return new Api(_);\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var Auth = function(_) {\n    var self = this;\n\n    _.user = _.models.deserialize('user', _.context.user);\n\n    // Auth state synchronization across tabs\n    this.isDesynced = false; // becomes true if auth state between tabs differs\n    this.newUser = null; // becomes user obj to which we want to sync\n\n    var handleAuthChange = function(isAuthenticated) {\n      if (!self.isDesynced) {\n        m.startComputation();\n\n        // display annoying \"you were desynced\" message\n        self.isDesynced = true;\n\n        if (isAuthenticated) {\n          self.newUser = _.localstore.get('auth-user');\n        }\n\n        m.endComputation();\n      }\n    };\n\n    var handleUserChange = function(newUser) {\n      if (!self.isDesynced) {\n        m.startComputation();\n\n        if (_.user.id !== newUser.id) {\n          self.isDesynced = true;\n          self.newUser = newUser;\n        } else if (newUser) {\n          _.user = $.extend(_.user, newUser);\n        }\n\n        m.endComputation();\n      }\n    };\n\n    var syncSession = function() {\n      _.localstore.set('auth-user', _.user);\n      _.localstore.set('auth-is-authenticated', _.user.isAuthenticated);\n\n      _.localstore.watch('auth-is-authenticated', handleAuthChange);\n      _.localstore.watch('auth-user', handleUserChange);\n    };\n\n    syncSession();\n\n    // Access controls\n    this.denyAuthenticated = function(message) {\n      if (_.user.isAuthenticated) {\n        throw new Misago.PermissionDenied(\n          message || gettext(\"This page is not available to signed in users.\"));\n      }\n    };\n\n    this.denyAnonymous = function(message) {\n      if (_.user.isAnonymous) {\n        throw new Misago.PermissionDenied(\n          message || gettext(\"This page is not available to guests.\"));\n      }\n    };\n  };\n\n  Misago.addService('auth',\n  function(_) {\n    return new Auth(_);\n  },\n  {\n    after: 'model:user'\n  });\n}(Misago.prototype));\n\n/* global grecaptcha */\n(function (Misago) {\n  'use strict';\n\n  var NoCaptcha = function() {\n    var deferred = m.deferred();\n    deferred.resolve();\n\n    this.load = function() {\n      return deferred.promise;\n    };\n\n    this.value = function() {\n      return null;\n    };\n  };\n\n  var QACaptcha = function(_) {\n    var self = this;\n\n    this.loading = false;\n    this.question = null;\n    this.value = m.prop('');\n\n    var deferred = m.deferred();\n    this.load = function() {\n      this.value('');\n\n      if (!this.question && !this.loading) {\n        this.loading = true;\n\n        _.api.endpoint('captcha-question').get().then(function(question) {\n          self.question = question;\n          deferred.resolve();\n        }, function() {\n          _.api.alert(gettext('Failed to load CAPTCHA.'));\n          deferred.reject();\n        }).then(function() {\n          self.loading = true;\n        });\n      }\n\n      return deferred.promise;\n    };\n\n    this.component = function(kwargs) {\n      return _.component('form-group', {\n        label: this.question.question,\n        labelClass: kwargs.labelClass || null,\n        controlClass: kwargs.controlClass || null,\n        control: _.input({\n          value: _.validate(kwargs.form, 'captcha'),\n          id: 'id_captcha',\n          disabled: kwargs.form.isBusy\n        }),\n        validation: kwargs.form.errors,\n        validationKey: 'captcha',\n        helpText: this.question.help_text\n      });\n    };\n\n    this.validator = function() {\n      return [];\n    };\n  };\n\n  var ReCaptcha = function(_) {\n    this.included = false;\n    this.question = null;\n\n    var deferred = m.deferred();\n\n    var wait = function(promise) {\n      if (typeof grecaptcha !== \"undefined\") {\n        promise.resolve();\n      } else {\n        _.runloop.runOnce(function() {\n          wait(promise);\n        }, 'loading-grecaptcha', 150);\n      }\n    };\n\n    this.load = function() {\n      if (typeof grecaptcha !== \"undefined\") {\n        grecaptcha.reset();\n      }\n\n      if (!this.included) {\n        _.include('https://www.google.com/recaptcha/api.js', true);\n        this.included = true;\n      }\n\n      wait(deferred);\n\n      return deferred.promise;\n    };\n\n    var controlConfig = function(el, isInit, context) {\n      context.retain = true;\n\n      if (!isInit) {\n        grecaptcha.render('recaptcha', {\n          'sitekey': _.settings.recaptcha_site_key\n        });\n      }\n    };\n\n    this.component = function(kwargs) {\n      var control = m('#recaptcha', {\n        config: controlConfig\n      });\n\n      return _.component('form-group', {\n        label: gettext(\"Security test\"),\n        labelClass: kwargs.labelClass || null,\n        controlClass: kwargs.controlClass || null,\n        control: control,\n        validation: kwargs.form.errors,\n        validationKey: 'captcha'\n      });\n    };\n\n    this.value = function() {\n      if (typeof grecaptcha !== \"undefined\") {\n        return grecaptcha.getResponse();\n      } else {\n        return '';\n      }\n    };\n\n    this.clean = function(form) {\n      if (!this.value()) {\n        form.errors.captcha = [\n          gettext('This field is required.')\n        ];\n      } else {\n        form.errors.captcha = true;\n      }\n    };\n\n    this.validator = function() {\n      return [];\n    };\n  };\n\n  var Captcha = function(_) {\n    var types = {\n      'no': NoCaptcha,\n      'qa': QACaptcha,\n      're': ReCaptcha\n    };\n\n    var captcha = new types[_.settings.captcha_type](_);\n\n    this.value = captcha.value;\n\n    this.load = function() {\n      return captcha.load();\n    };\n\n    this.component = function(kwargs) {\n      if (captcha.component) {\n        return captcha.component(kwargs);\n      } else {\n        return null;\n      }\n    };\n\n    this.validator = function() {\n      if (captcha.validator) {\n        return captcha.validator();\n      } else {\n        return null;\n      }\n    };\n\n    this.clean = function(form) {\n      if (captcha.clean) {\n        captcha.clean(form);\n      } else {\n        form.errors.captcha = true;\n      }\n    };\n  };\n\n  Misago.addService('captcha', function(_) {\n    return new Captcha(_);\n  },\n  {\n    after: 'include'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var component = function(name, component) {\n    if (this._components[name]) {\n      if (arguments.length > 1) {\n        var argumentsArray = [this._components[name]];\n        for (var i = 1; i < arguments.length; i += 1) {\n          argumentsArray.push(arguments[i]);\n        }\n        argumentsArray.push(this);\n        return m.component.apply(undefined, argumentsArray);\n      } else {\n        return m.component(this._components[name], this);\n      }\n    } else if (component) {\n      this._components[name] = component;\n    } else {\n      throw '\"' + name + '\" component is not registered and can\\'t be created';\n    }\n  };\n\n  Misago.addService('components', function(_) {\n    _._components = {};\n    _.component = component;\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.addService('conf', function(_) {\n    _.settings = Misago.get(_.context, 'SETTINGS', {});\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var dropdownConfig = function(element, isInit, context) {\n    if (!isInit) {\n      context.retain = true;\n\n      $(element).on('click', function() {\n        $(element).removeClass('open');\n      });\n\n      context.onunload = function() {\n        $(element).removeClass('open');\n        $(element).off();\n      };\n    }\n  };\n\n  var Dropdown = function(_) {\n    var slots = {};\n\n    this.slot = function(name) {\n      return m('#dropdown-' + name + '.dropdown.mobile-dropdown', {\n        config: dropdownConfig\n      });\n    };\n\n    this.toggle = function(slot, component) {\n      var element = document.getElementById('dropdown-' + slot);\n\n      if (element.hasChildNodes() && slots[slot] === component) {\n        slots[slot] = null;\n        m.mount(element, null);\n        $(element).removeClass('open');\n      } else {\n        slots[slot] = component;\n        m.mount(element, _.component(component));\n        $(element).addClass('open');\n      }\n    };\n  };\n\n  Misago.addService('dropdown', {\n    factory: function(_) {\n      return new Dropdown(_);\n    }\n  },\n  {\n    before: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var boilerplate = function(form) {\n    var _submit = form.submit;\n    var _success = form.success;\n    var _error = form.error;\n\n    form.isBusy = false;\n\n    form.errors = null;\n\n    form.submit = function() {\n      if (form.isBusy) {\n        return false;\n      }\n\n      if (form.clean) {\n        if (form.clean()) {\n          form.isBusy = true;\n          _submit.apply(form);\n        }\n      } else {\n        form.isBusy = true;\n      }\n      return false;\n    };\n\n    form.success = function() {\n      m.startComputation();\n\n      _success.apply(form, arguments);\n      form.isBusy = false;\n\n      m.endComputation();\n    };\n\n    form.error = function() {\n      m.startComputation();\n\n      _error.apply(form, arguments);\n      form.isBusy = false;\n\n      m.endComputation();\n    };\n\n    form.hasErrors = function() {\n      if (form.errors === null) {\n        return false;\n      }\n\n      for (var key in form.validation) {\n        if (form.validation.hasOwnProperty(key)) {\n          if (form.errors[key] !== true) {\n            return true;\n          }\n        }\n      }\n\n      return false;\n    };\n\n    return form;\n  };\n\n  var form = function(name, constructor) {\n    if (this._forms[name]) {\n      if (constructor) {\n        return boilerplate(new this._forms[name](constructor, this));\n      } else {\n        return boilerplate(new this._forms[name](this));\n      }\n    } else {\n      this._forms[name] = constructor;\n    }\n  };\n\n  Misago.addService('forms', function(_) {\n    _._forms = {};\n    _.form = form;\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.addService('forum-layout', {\n    factory: function(_) {\n      if (_.setup.fixture) {\n        m.mount(document.getElementById(_.setup.fixture),\n                _.component('forum-layout'));\n      }\n    },\n\n    destroy: function(_) {\n      if (_.setup.fixture) {\n        m.mount(document.getElementById(_.setup.fixture), null);\n      }\n    }\n  },\n  {\n    before: 'start-routing'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var include = function(script, remote) {\n    if (!remote) {\n      script = this.context.STATIC_URL + script;\n    }\n\n    $.ajax({\n      url: script,\n      cache: true,\n      dataType: 'script'\n    });\n  };\n\n  Misago.addService('include', function(_) {\n    _.include = include;\n  },\n  {\n    after: 'conf'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var LocalStore = function() {\n    var storage = window.localStorage;\n    var prefix = '_misago_';\n    var watchers = [];\n\n    var handleStorageEvent = function(e) {\n      var newValueJson = JSON.parse(e.newValue);\n      $.each(watchers, function(i, watcher) {\n        if (watcher.keyName === e.key && e.oldValue !== e.newValue) {\n          watcher.callback(newValueJson);\n        }\n      });\n    };\n\n    window.addEventListener('storage', handleStorageEvent);\n\n    var prefixKey = function(keyName) {\n      return prefix + keyName;\n    };\n\n    this.set = function(keyName, value) {\n      storage.setItem(prefixKey(keyName), JSON.stringify(value));\n    };\n\n    this.get = function(keyName) {\n      var itemString = storage.getItem(prefixKey(keyName));\n      if (itemString) {\n        return JSON.parse(itemString);\n      } else {\n        return null;\n      }\n    };\n\n    this.watch = function(keyName, callback) {\n      watchers.push({keyName: prefixKey(keyName), callback: callback});\n    };\n\n    this.destroy = function() {\n      this.watchers = [];\n    };\n  };\n\n  Misago.addService('localstore', {\n    factory: function() {\n      return new LocalStore();\n    },\n    destroy: function(_) {\n      _.localstore.destroy();\n    }\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var Modal = function() {\n    var self = this;\n\n    var element = document.getElementById('misago-modal');\n\n    // href clicks within modal should close it\n    var delegateName = 'click.misago-modal';\n    $(element).on(delegateName, 'a', function() {\n      self.hide();\n    });\n\n    this.destroy = function() {\n      $(element).off();\n      $('body').removeClass('modal-open');\n      $('.modal-backdrop').remove();\n    };\n\n    // Open/close modal\n    var modal = $(element).modal({show: false});\n    this.open = false;\n\n    modal.on('hidden.bs.modal', function () {\n      if (self.open) {\n        m.mount(element, null);\n        this.open = false;\n      }\n    });\n\n    this.show = function(component) {\n      this.open = true;\n      m.mount(element, component);\n      modal.modal('show');\n    };\n\n    this.hide = function() {\n      modal.modal('hide');\n    };\n  };\n\n  Misago.addService('_modal', {\n    factory: function() {\n      return new Modal();\n    },\n    destroy: function(_) {\n      _._modal.destroy();\n    }\n  },\n  {\n    after: 'start-routing'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var modal = function(name, component) {\n    if (this._modals[name]) {\n      var argumentsArray = [this._modals[name]];\n      for (var i = 1; i < arguments.length; i += 1) {\n        argumentsArray.push(arguments[i]);\n      }\n      argumentsArray.push(this);\n      this._modal.show(m.component.apply(m, argumentsArray));\n    } else if (name) {\n      this._modals[name] = component;\n    } else {\n      this._modal.hide();\n    }\n  };\n\n  Misago.addService('modals', function(_) {\n    _._modals = {};\n    _.modal = modal;\n  },\n  {\n    after: '_modal'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var Models = function() {\n    this.classes = {};\n    this.deserializers = {};\n\n    this.add = function(name, kwargs) {\n      if (kwargs.class) {\n        this.classes[name] = kwargs.class;\n      }\n\n      if (kwargs.deserialize) {\n        this.deserializers[name] = kwargs.deserialize;\n      }\n    };\n\n    this.new = function(name, data) {\n      if (this.classes[name]) {\n        // Coerce ID to string\n        // This is done to avoid type comparisions gotchas\n        // later into app\n        data.id = data.id ? String(data.id) : null;\n\n        return new this.classes[name](data);\n      } else {\n        return data;\n      }\n    };\n\n    this.deserialize = function(name, json) {\n      if (this.deserializers[name]) {\n        return this.new(name, this.deserializers[name](json, this));\n      } else {\n        return this.new(name, json);\n      }\n    };\n  };\n\n  Misago.addService('models', function() {\n    return new Models();\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.addService('set-momentjs-locale', function() {\n    moment.locale($('html').attr('lang'));\n  });\n}(Misago.prototype));\n\n\n(function (Misago) {\n  'use strict';\n\n  var Router = function(_) {\n    var self = this;\n    this.baseUrl = $('base').attr('href');\n\n    var staticUrl = Misago.get(_.context, 'STATIC_URL', '/');\n    var mediaUrl = Misago.get(_.context, 'MEDIA_URL', '/');\n\n    // Routing\n    this.urls = {};\n    this.reverses = {};\n\n    var populatePatterns = function(urlconf) {\n      urlconf.patterns().forEach(function(url) {\n        var finalPattern = self.baseUrl + url.pattern;\n        finalPattern = finalPattern.replace('//', '/');\n\n        self.urls[finalPattern] = _.route(url.component);\n        self.reverses[url.name] = finalPattern;\n      });\n    };\n\n    this.startRouting = function(urlconf, fixture) {\n      populatePatterns(urlconf);\n      this.fixture = fixture;\n\n      if (_.setup.test) {\n        m.route.mode = 'search';\n      } else {\n        m.route.mode = 'pathname';\n      }\n\n      m.route(fixture, '/', this.urls);\n    };\n\n    this.url = function(name) {\n      return this.reverses[name];\n    };\n\n    this.route = function(url) {\n      m.route(url);\n    };\n\n    this.redirect = function(name) {\n      this.route(this.url(name));\n    };\n\n    // Delegate clicks\n    this.delegateElement = null;\n\n    this.cleanUrl = function(url) {\n      if (!url) { return; }\n\n      // Is link relative?\n      var isRelative = url.substr(0, 1) === '/' && url.substr(0, 2) !== '//';\n\n      // If link contains host, validate to see if its outgoing\n      if (!isRelative) {\n        var location = window.location;\n\n        // If protocol matches current one, strip it from string\n        // otherwhise stop handler\n        if (url.substr(0, 2) !== '//') {\n          var protocol = url.substr(0, location.protocol.length + 2);\n          if (protocol !== location.protocol + '//') { return; }\n          url = url.substr(location.protocol.length + 2);\n        } else {\n          url = url.substr(2);\n        }\n\n        // Host checks out?\n        if (url.substr(0, location.host.length) !== location.host) { return; }\n        url = url.substr(location.host.length);\n      }\n\n      // Is link within JS app?\n      if (url.substr(0, this.baseUrl.length) !== this.baseUrl) { return; }\n\n      // Is link to media/static/avatar server?\n      if (url.substr(0, staticUrl.length) === staticUrl) { return; }\n\n      if (url.substr(0, mediaUrl.length) === mediaUrl) { return; }\n\n      var avatarsUrl = '/user-avatar/';\n      if (url.substr(0, avatarsUrl.length) === avatarsUrl) { return; }\n\n      return url;\n    };\n\n    var delegateName = 'click.misago-router';\n    var delegateSelector = 'a:not([data-misago-routed=\"false\"])';\n\n    this.delegateClicks = function(element) {\n      this.delegateElement = element;\n      $(this.delegateElement).on(delegateName, delegateSelector, function(e) {\n        var cleanUrl = self.cleanUrl(e.currentTarget.href);\n        if (cleanUrl) {\n          if (cleanUrl != m.route()) {\n            self.route(cleanUrl);\n          }\n          e.preventDefault();\n        }\n      });\n    };\n\n    this.destroy = function() {\n      $(this.delegateElement).off(delegateName);\n    };\n\n    // Media/Static url\n    var prefixUrl = function(prefix) {\n      return function(url) {\n        return prefix + url;\n      };\n    };\n\n    this.staticUrl = prefixUrl(staticUrl);\n    this.mediaUrl = prefixUrl(mediaUrl);\n\n    // Errors\n    this.error403 = function(error) {\n      var component = null;\n      if (error.ban) {\n        component = _.route('error:banned',\n          error.detail,\n          _.models.deserialize('ban', error.ban));\n      } else {\n        component = _.route('error:403', error.detail);\n      }\n      m.mount(this.fixture, component);\n    };\n\n    this.error404 = function() {\n      m.mount(this.fixture, _.route('error:404'));\n    };\n\n    this.error500 = function() {\n      m.mount(this.fixture, _.route('error:500'));\n    };\n\n    this.error0 = function() {\n      m.mount(this.fixture, _.route('error:0'));\n    };\n\n    this.errorPage = function(error) {\n      if (error.status === 0) {\n        this.error0();\n      }\n\n      if (error.status === 500) {\n        this.error500();\n      }\n\n      if (error.status === 404) {\n        this.error404();\n      }\n\n      if (error.status === 403) {\n        this.error403(error);\n      }\n    };\n  };\n\n  Misago.addService('router', function(_) {\n    return new Router(_);\n  });\n\n  Misago.addService('start-routing', function(_) {\n    // In edge cases layout gets rendered in same frame routing starts\n    // which causes getElementById to return null and crash Mithril.js\n    var waitForFixture = function() {\n      var fixture = document.getElementById('router-fixture');\n      if (fixture) {\n        _.router.startRouting(\n          Misago.urls, document.getElementById('router-fixture'));\n        _.router.delegateClicks(document.getElementById(_.setup.fixture));\n      } else {\n        window.setTimeout(function() {\n          waitForFixture();\n        }, 10);\n      }\n    };\n    waitForFixture();\n  },\n  {\n    before: '_end'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var boilerplate = function(component) {\n    // Component already boilerplated (this may happen in tests)\n    if (component._hasRouteBoilerplate) {\n      return component;\n    }\n    component._hasRouteBoilerplate = true;\n\n    // Add lifecycle hooks\n    var loadingView = function () {\n      var _ = this.container;\n      return m('.page.page-loading',\n        _.component('loader')\n      );\n    };\n\n    var errorHandler = function(error) {\n      if (this.isActive && typeof error.status !== \"undefined\") {\n        if (this.vm && this.vm.onerror) {\n          this.vm.onerror(error, this.container);\n        } else {\n          this.container.router.errorPage(error);\n        }\n      } else {\n        throw error;\n      }\n    };\n\n    return Misago.stateHooks(component, loadingView, errorHandler);\n  };\n\n  Misago.addService('routes', function(_) {\n    _._routes = {};\n    _.route = function(name, component) {\n      if (this._routes[name]) {\n        if (arguments.length > 1) {\n          var argumentsArray = [this._routes[name]];\n          for (var i = 1; i < arguments.length; i += 1) {\n            argumentsArray.push(arguments[i]);\n          }\n          argumentsArray.push(this);\n          return m.component.apply(undefined, argumentsArray);\n        } else {\n          return m.component(this._routes[name], this);\n        }\n      } else if (component) {\n        component.container = _;\n        this._routes[name] = boilerplate(component);\n      } else {\n        throw '\"' + name + '\" route is not registered and can\\'t be created';\n      }\n    };\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var RunLoop = function(_) {\n    var self = this;\n\n    this._intervals = {};\n\n    var stopInterval = function(name) {\n      if (self._intervals[name]) {\n        window.clearTimeout(self._intervals[name]);\n        self._intervals[name] = null;\n      }\n    };\n\n    this.run = function(callable, name, delay) {\n      this._intervals[name] = window.setTimeout(function() {\n        stopInterval(name);\n        var result = callable(_);\n        if (result !== false) {\n          self.run(callable, name, delay);\n        }\n      }, delay);\n    };\n\n    this.runOnce = function(callable, name, delay) {\n      this._intervals[name] = window.setTimeout(function() {\n        stopInterval(name);\n        callable(_);\n      }, delay);\n    };\n\n    this.stop = function(name) {\n      for (var loop in this._intervals) {\n        if (!name || name === loop) {\n          stopInterval(loop);\n        }\n      }\n    };\n  };\n\n  Misago.addService('runloop', {\n    factory: function(_) {\n      return new RunLoop(_);\n    },\n    destroy: function(_) {\n      _.runloop.stop();\n    }\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.addService('start-tick', function(_) {\n    var ticks = m.prop();\n\n    _.runloop.run(function() {\n      m.startComputation();\n      // just tick once a minute so stuff gets rerendered\n      ticks(ticks() + 1);\n      // syncing dynamic timestamps, etc ect\n      m.endComputation();\n    }, 'tick', 60000);\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var PageTitle = function(forum_name) {\n    this.set = function(title) {\n      if (title) {\n        this._set_complex(title);\n      } else {\n        document.title = forum_name;\n      }\n    };\n\n    this._set_complex = function(title) {\n      if (typeof title === 'string') {\n        title = {title: title};\n      }\n\n      var completeTitle = title.title;\n\n      if (typeof title.page !== 'undefined' && title.page > 1) {\n        var page_label = interpolate(\n          gettext('page %(page)s'), { page:title.page }, true);\n        completeTitle += ' (' + page_label + ')';\n      }\n\n      if (typeof title.parent !== 'undefined') {\n        completeTitle += ' | ' + title.parent;\n      }\n\n      document.title = completeTitle + ' | ' + forum_name;\n    };\n  };\n\n  Misago.addService('page-title', function(_) {\n    _.title = new PageTitle(_.settings.forum_name);\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var EMAIL = /^(([^<>()[\\]\\.,;:\\s@\\\"]+(\\.[^<>()[\\]\\.,;:\\s@\\\"]+)*)|(\\\".+\\\"))@(([^<>()[\\]\\.,;:\\s@\\\"]+\\.)+[^<>()[\\]\\.,;:\\s@\\\"]{2,})$/i;\n  var USERNAME = new RegExp('^[0-9a-z]+$', 'i');\n\n  // Validators namespace\n  Misago.validators = {\n    required: function() {\n      return function(value) {\n        if ($.trim(value).length === 0) {\n          return gettext(\"This field is required.\");\n        }\n      };\n    },\n    email: function(message) {\n      return function(value) {\n        if (!EMAIL.test(value)) {\n          return message || gettext(\"Enter a valid email address.\");\n        }\n      };\n    },\n    minLength: function(limit_value, message) {\n      return function(value) {\n        var returnMessage = '';\n        var length = $.trim(value).length;\n\n        if (length < limit_value) {\n          if (message) {\n            returnMessage = message(limit_value, length);\n          } else {\n            returnMessage = ngettext(\n              \"Ensure this value has at least %(limit_value)s character (it has %(show_value)s).\",\n              \"Ensure this value has at least %(limit_value)s characters (it has %(show_value)s).\",\n              limit_value);\n          }\n          return interpolate(returnMessage, {\n            limit_value: limit_value,\n            show_value: length\n          }, true);\n        }\n      };\n    },\n    maxLength: function(limit_value, message) {\n      return function(value) {\n        var returnMessage = '';\n        var length = $.trim(value).length;\n\n        if (length > limit_value) {\n          if (message) {\n            returnMessage = message(limit_value, length);\n          } else {\n            returnMessage = ngettext(\n              \"Ensure this value has at most %(limit_value)s character (it has %(show_value)s).\",\n              \"Ensure this value has at most %(limit_value)s characters (it has %(show_value)s).\",\n              limit_value);\n          }\n          return interpolate(returnMessage, {\n            limit_value: limit_value,\n            show_value: length\n          }, true);\n        }\n      };\n    },\n    usernameMinLength: function(settings) {\n      var message = function(limit_value) {\n        return ngettext(\n          \"Username must be at least %(limit_value)s character long.\",\n          \"Username must be at least %(limit_value)s characters long.\",\n          limit_value);\n      };\n      return this.minLength(settings.username_length_min, message);\n    },\n    usernameMaxLength: function(settings) {\n      var message = function(limit_value) {\n        return ngettext(\n          \"Username cannot be longer than %(limit_value)s character.\",\n          \"Username cannot be longer than %(limit_value)s characters.\",\n          limit_value);\n      };\n      return this.maxLength(settings.username_length_max, message);\n    },\n    usernameContent: function() {\n      return function(value) {\n        if (!USERNAME.test($.trim(value))) {\n          return gettext(\"Username can only contain latin alphabet letters and digits.\");\n        }\n      };\n    },\n    passwordMinLength: function(settings) {\n      var message = function(limit_value) {\n        return ngettext(\n          \"Valid password must be at least %(limit_value)s character long.\",\n          \"Valid password must be at least %(limit_value)s characters long.\",\n          limit_value);\n      };\n      return this.minLength(settings.password_length_min, message);\n    }\n  };\n\n  var validateField = function(value, validators) {\n    var result = Misago.validators.required()(value);\n    var errors = [];\n\n    if (result) {\n      return [result];\n    } else {\n      for (var i in validators) {\n        result = validators[i](value);\n\n        if (result) {\n          errors.push(result);\n        }\n      }\n    }\n\n    return errors.length ? errors : true;\n  };\n\n  var validateForm = function(form) {\n    var errors = {};\n    var value = null;\n\n    var isValid = true;\n\n    for (var key in form.validation) {\n      if (form.validation.hasOwnProperty(key)) {\n        value = form[key]();\n        errors[key] = validateField(form[key](), form.validation[key]);\n        if (errors[key] !== true) {\n          isValid = false;\n        }\n      }\n    }\n\n    form.errors = errors;\n    return isValid;\n  };\n\n  var validate = function(form, name) {\n    if (name) {\n      return function(value) {\n        var errors = null;\n        if (typeof value !== 'undefined') {\n          errors = validateField(value, form.validation[name]);\n          if (errors) {\n            if (!form.errors) {\n              form.errors = {};\n            }\n            form.errors[name] = errors;\n          }\n          form[name](value);\n          return form[name](value);\n        } else {\n          return form[name]();\n        }\n      };\n    } else {\n      return validateForm(form);\n    }\n  };\n\n  Misago.addService('validate', {\n    factory: function() {\n      return validate;\n    }\n  });\n}(Misago.prototype));\n\n/* global zxcvbn */\n(function (Misago) {\n  'use strict';\n\n  var Zxcvbn = function(_) {\n    this.included = false;\n\n    this.scorePassword = function(password, inputs) {\n      // 0-4 score, the more the stronger password\n      return zxcvbn(password, inputs).score;\n    };\n\n    // loading\n    this.include = function() {\n      _.include('misago/js/zxcvbn.js');\n      this.included = true;\n    };\n\n    var wait = function(promise) {\n      if (typeof zxcvbn !== \"undefined\") {\n        promise.resolve();\n      } else {\n        _.runloop.runOnce(function() {\n          wait(promise);\n        }, 'loading-zxcvbn', 150);\n      }\n    };\n\n    var deferred = m.deferred();\n    this.load = function() {\n      if (!this.included) {\n        this.include();\n      }\n      wait(deferred);\n      return deferred.promise;\n    };\n  };\n\n  Misago.addService('zxcvbn', function(_) {\n    return new Zxcvbn(_);\n  },\n  {\n    after: 'include'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var Ban = function(data) {\n    this.message = {\n      html: data.message.html,\n      plain: data.message.plain,\n    };\n\n    this.expires_on = data.expires_on;\n  };\n\n  var deserializeBan = function(data) {\n    data.expires_on = Misago.deserializeDatetime(data.expires_on);\n\n    return data;\n  };\n\n  Misago.addService('model:ban', function(_) {\n    _.models.add('ban', {\n      class: Ban,\n      deserialize: deserializeBan\n    });\n  },\n  {\n    after: 'models'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var LegalPage = function(data) {\n    this.title = data.title;\n    this.body = data.body;\n    this.link = data.link;\n  };\n\n  Misago.addService('model:legal-page', function(_) {\n    _.models.add('legal-page', {\n      class: LegalPage\n    });\n  },\n  {\n    after: 'models'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var Rank = function(data) {\n    this.id = data.id;\n\n    this.name = data.name;\n    this.slug = data.slug;\n\n    this.description = data.description;\n\n    this.title = data.title;\n    this.css_class = data.css_class;\n\n    this.is_tab = data.is_tab;\n  };\n\n  Misago.addService('model:rank', function(_) {\n    _.models.add('rank', {\n      class: Rank\n    });\n  },\n  {\n    after: 'models'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var User = function(data) {\n    this.id = data.id;\n\n    this.isAuthenticated = !!this.id;\n    this.isAnonymous = !this.isAuthenticated;\n\n    this.username = data.username;\n    this.slug = data.slug;\n\n    this.email = data.email;\n\n    this.full_title = data.full_title;\n    this.rank = data.rank;\n\n    this.avatar_hash = data.avatar_hash;\n\n    this.acl = data.acl;\n  };\n\n  var deserializeUser = function(data, models) {\n    if (data.joined_on) {\n      data.joined_on = Misago.deserializeDatetime(data.joined_on);\n    }\n\n    if (data.rank) {\n      data.rank = models.deserialize('rank', data.rank);\n    }\n\n    return data;\n  };\n\n  Misago.addService('model:user', function(_) {\n    _.models.add('user', {\n      class: User,\n      deserialize: deserializeUser\n    });\n  },\n  {\n    after: 'model:rank'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var viewModel = {\n    error: null,\n    username: null,\n    isReady: false,\n\n    init: function(_) {\n      this.error = null;\n      this.user = null;\n      this.isReady = false;\n\n      var endpoint = _.api.endpoint('auth').endpoint('activate-account');\n      endpoint = endpoint.endpoint(m.route.param('user_id'));\n      endpoint = endpoint.endpoint(m.route.param('token'));\n\n      return endpoint.post();\n    },\n    ondata: function(data, _) {\n      m.startComputation();\n\n      _.title.set(gettext(\"Account activated\"));\n\n      this.username = data.username;\n      this.isReady = true;\n\n      m.endComputation();\n    },\n    onerror: function(error, _) {\n      if (error.status === 400) {\n        m.startComputation();\n\n        this.error = error;\n        this.isReady = true;\n\n        m.endComputation();\n      } else {\n        _.router.errorPage(error);\n      }\n    }\n  };\n\n  var activateByToken = {\n    controller: function(_) {\n      _.auth.denyAuthenticated(\n        gettext(\"You have to be signed out to activate account.\"));\n\n      _.title.set(gettext(\"Account activation\"));\n      this.vm.init(_);\n    },\n    vm: viewModel,\n    view: function(ctrl, _) {\n      if (this.vm.error) {\n        return this.rejected(this.vm.error, _);\n      } else {\n        return this.success(this.vm.username, _);\n      }\n    },\n    success: function(username) {\n      var message = gettext(\"%(username)s, your account has been successfully activated!\");\n\n      return m('.page.page-message.page-message-success',\n        m('.container',\n          m('.message-panel', [\n            m('.message-icon',\n              m('span.material-icon', 'check')\n            ),\n            m('.message-body', [\n              m('p.lead',\n                interpolate(message, {\n                  username: username\n                }, true)\n              ),\n              m('p',\n                gettext('You can now sign in to finish setting up your account and to participate in or start new discussions.')\n              )\n            ])\n          ])\n        )\n      );\n    },\n    rejected: function(error) {\n      return m('.page.page-message.page-message-info',\n        m('.container',\n          m('.message-panel', [\n            m('.message-icon',\n              m('span.material-icon', 'info_outline')\n            ),\n            m('.message-body', [\n              m('p.lead',\n                gettext(\"Your account can't be activated at this time.\")\n              ),\n              m('p',\n                error.detail\n              )\n            ])\n          ])\n        )\n      );\n    },\n    loading: function(ctrl, _) {\n      return m('.page.page-loading', [\n        _.component('loader'),\n        m('p.lead', gettext(\"Activating account...\"))\n      ]);\n    }\n  };\n\n  Misago.addService('route:activate-by-token', function(_) {\n    _.route('activate-by-token', activateByToken);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var viewModel = {\n    error: null,\n    isReady: false,\n\n    form: null,\n\n    init: function(_) {\n      this.error = null;\n      this.user = null;\n      this.isReady = false;\n\n      var endpoint = _.api.endpoint('auth').endpoint('change-password');\n      endpoint = endpoint.endpoint(m.route.param('user_id'));\n      endpoint = endpoint.endpoint(m.route.param('token'));\n\n      return endpoint.get();\n    },\n    ondata: function(data, _) {\n      m.startComputation();\n\n      _.title.set(gettext(\"Change forgotten password\"));\n\n      this.form = _.form('change-password');\n      this.isReady = true;\n\n      m.endComputation();\n    },\n    onerror: function(error, _) {\n      if (error.status === 400) {\n        m.startComputation();\n\n        this.error = error;\n        this.isReady = true;\n\n        m.endComputation();\n      } else {\n        _.router.errorPage(error);\n      }\n    }\n  };\n\n  var changePassword = {\n    controller: function(_) {\n      this.vm.init(_);\n\n      return {\n        signin: function() {\n          _.modal('sign-in');\n        }\n      };\n    },\n    vm: viewModel,\n    view: function(ctrl, _) {\n      if (this.vm.error) {\n        return this.rejected(this.vm.error, _);\n      } else {\n        if (this.vm.form.username) {\n          return this.complete(ctrl, this.vm.form.username, _);\n        } else {\n          return this.form(this.vm.form, _);\n        }\n      }\n    },\n    form: function(form, _) {\n      return m('.page.page-change-password', [\n        _.component('header', {\n          title: gettext(\"Change forgotten password\")\n        }),\n        m('.container',\n          m('.row',\n            m('.col-md-4.col-md-offset-4',\n              m('.well.well-form',\n                m('form', {onsubmit: form.submit}, [\n                  m('.form-group',\n                    m('.control-input',\n                      Misago.input({\n                        disabled: form.isBusy,\n                        value: form.password,\n                        type: 'password',\n                        placeholder: gettext(\"Enter new password\")\n                      })\n                    )\n                  ),\n                  _.component('button', {\n                    class: '.btn-primary.btn-block',\n                    submit: true,\n                    loading: form.isBusy,\n                    label: gettext(\"Change password\")\n                  })\n                ])\n              )\n            )\n          )\n        )\n      ]);\n    },\n    complete: function(ctrl, username, _) {\n      var message = gettext(\"%(username)s, your password has been changed successfully.\");\n\n      return m('.page.page-message.page-message-success',\n        m('.container',\n          m('.message-panel', [\n            m('.message-icon',\n              m('span.material-icon', 'check')\n            ),\n            m('.message-body', [\n              m('p.lead',\n                interpolate(message, {\n                  username: username\n                }, true)\n              ),\n              m('p',\n                gettext(\"You can now sign in to your account using your new password.\")\n              ),\n              m('p',\n                _.component('button', {\n                  class: '.btn-default',\n                  submit: false,\n                  label: gettext(\"Sign in\"),\n                  onclick: ctrl.signin\n                })\n              )\n            ])\n          ])\n        )\n      );\n    },\n    rejected: function(error) {\n      return m('.page.page-message.page-message-info',\n        m('.container',\n          m('.message-panel', [\n            m('.message-icon',\n              m('span.material-icon', 'info_outline')\n            ),\n            m('.message-body', [\n              m('p.lead',\n                gettext(\"Your account can't be activated at this time.\")\n              ),\n              m('p',\n                error.detail\n              )\n            ])\n          ])\n        )\n      );\n    }\n  };\n\n  Misago.addService('route:change-password', function(_) {\n    _.route('change-password', changePassword);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var errorPage = function(error) {\n    var error_message = [\n      m('p.lead', error.message)\n    ];\n\n    if (error.help) {\n      error_message.push(m('p.help', error.help));\n    }\n\n    return m('.page.page-error.page-error-' + error.code,\n      m('.container',\n        m('.message-panel', [\n          m('.message-icon',\n            m('span.material-icon', error.icon)\n          ),\n          m('.message-body', error_message)\n        ])\n      )\n    );\n  };\n\n  var errorBanned = {\n    controller: function() {\n      this.container.title.set(gettext('You are banned'));\n    },\n    view: function(ctrl, message, ban) {\n      var error_message = [];\n\n      if (ban.message.html) {\n        error_message.push(m('.lead', m.trust(ban.message.html)));\n      } else if (message) {\n        error_message.push(m('p.lead', message));\n      } else {\n        error_message.push(m('p.lead', gettext('You are banned.')));\n      }\n\n      var expirationMessage = null;\n      if (ban.expires_on) {\n        if (ban.expires_on.isAfter(moment())) {\n          expirationMessage = interpolate(\n            gettext('This ban expires %(expires_on)s.'),\n            {'expires_on': ban.expires_on.fromNow()},\n            true);\n        } else {\n          expirationMessage = gettext('This ban has expired.');\n        }\n      } else {\n        expirationMessage = gettext('This ban is permanent.');\n      }\n      error_message.push(m('p', expirationMessage));\n\n      return m('.page.page-error.page-error-banned',\n        m('.container',\n          m('.message-panel', [\n            m('.message-icon',\n              m('span.material-icon', 'highlight_off')\n            ),\n            m('.message-body', error_message)\n          ])\n        )\n      );\n    }\n  };\n\n  var error403 = {\n    controller: function() {\n      this.container.title.set(gettext('Page not available'));\n    },\n    view: function(ctrl, message) {\n      if (message === \"Permission denied\") {\n        message = gettext(\"You don't have permission to access this page.\");\n      }\n\n      return errorPage({\n        code: 403,\n        icon: 'remove_circle_outline',\n        message: gettext(\"This page is not available.\"),\n        help: message\n      });\n    }\n  };\n\n  var error404 = {\n    controller: function() {\n      this.container.title.set(gettext('Page not found'));\n    },\n    view: function() {\n      return errorPage({\n        code: 404,\n        icon: 'info_outline',\n        message: gettext(\"Requested page could not be found.\"),\n        help: gettext(\"The link you followed was incorrect or the page has been moved or deleted.\")\n      });\n    }\n  };\n\n  var error500 = {\n    controller: function() {\n      this.container.title.set(gettext('Application error occured'));\n    },\n    view: function() {\n      return errorPage({\n        code: 500,\n        icon: 'error_outline',\n        message: gettext(\"Requested page could not be displayed due to an error.\"),\n        help: gettext(\"Please try again later or contact site staff if error persists.\")\n      });\n    }\n  };\n\n  var error0 = {\n    controller: function() {\n      this.container.title.set(gettext('Lost connection with application'));\n    },\n    view: function() {\n      return errorPage({\n        code: 0,\n        icon: 'sync_problem',\n        message: gettext(\"Could not connect to application.\"),\n        help: gettext(\"This may be caused by problems with your connection or application server. Please check your internet connection and refresh page if problem persists.\")\n      });\n    }\n  };\n\n  Misago.addService('route:error-pages', function(_) {\n    _.route('error:banned', errorBanned);\n    _.route('error:403', error403);\n    _.route('error:404', error404);\n    _.route('error:500', error500);\n    _.route('error:0', error0);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var index = {\n    controller: function(_) {\n      document.title = _.settings.forum_index_title || _.settings.forum_name;\n\n      return {\n        activation: function() {\n          _.router.url('request_activation');\n        }\n      };\n    },\n    view: function(ctrl, _) {\n      return m('.container', [\n        m('h1', 'Activation'),\n        m('p', 'Test auth blocks'),\n        m('p',\n          m('a', {href: _.router.url('request_activation')},\n            'Request activation.'\n          )\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('route:index', function(_) {\n    _.route('index', index);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var legalPageFactory = function(typeName, defaultTitle) {\n    var dashedTypeName = typeName.replace(/_/g, '-');\n\n    return {\n      controller: function(_) {\n        if (Misago.get(_.settings, typeName + '_link')) {\n          window.location = Misago.get(_.settings, typeName + '_link');\n        } else {\n          this.vm.init(this, _);\n        }\n      },\n      vm: {\n        page: null,\n        isReady: false,\n        init: function(component, _) {\n          if (this.isReady) {\n            _.title.set(this.title);\n          } else {\n            _.title.set();\n            return _.api.model('legal-page', dashedTypeName);\n          }\n        },\n        ondata: function(page, component, _) {\n          m.startComputation();\n\n          if (page.link) {\n            window.location = page.link;\n          } else {\n            page.title = page.title || defaultTitle;\n            this.page = page;\n            this.isReady = true;\n\n            m.endComputation();\n\n            if (component.isActive) {\n              _.title.set(this.page.title);\n            }\n          }\n        }\n      },\n      view: function(ctrl, _) {\n        return m('.page.page-legal.page-legal-' + dashedTypeName, [\n          _.component('header', {title: this.vm.page.title}),\n          m('.container',\n            _.component('markup', this.vm.page.body)\n          )\n        ]);\n      }\n    };\n  };\n\n  Misago.addService('route:legal-pages', function(_) {\n    _.route('terms-of-service', legalPageFactory(\n      'terms_of_service', gettext('Terms of service')));\n    _.route('privacy-policy', legalPageFactory(\n      'privacy_policy', gettext('Privacy policy')));\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var ViewModel = function() {\n    this.endpoint = 'send-activation';\n    this.user = null;\n\n    this.success = function(user) {\n      this.user = user;\n    };\n\n    this.error = function(rejection, _) {\n      if (rejection.code === 'already_active') {\n        _.alert.info(rejection.detail);\n        _.modal('sign-in');\n      } else if (rejection.code === 'inactive_admin') {\n        _.alert.info(rejection.detail);\n      } else {\n        _.alert.error(rejection.detail);\n      }\n    };\n\n    this.reset = function() {\n      this.user = null;\n    };\n  };\n\n  var requestActivation = {\n    controller: function(_) {\n      _.auth.denyAuthenticated(\n        gettext(\"You have to be signed out to activate account.\"));\n\n      _.title.set(gettext(\"Activate your account\"));\n\n      var vm = new ViewModel();\n\n      return {\n        vm: vm,\n        form: _.form('request-link', vm)\n      };\n    },\n    view: function(ctrl, _) {\n      if (ctrl.vm.user) {\n        return this.completed(ctrl.form, ctrl.vm, _);\n      } else {\n        return this.form(ctrl.form, _);\n      }\n    },\n    completed: function(form, vm, _) {\n      var message = gettext(\"%(username)s, we have sent your activation link to %(email)s.\");\n\n      return m('.page.page-message.page-message-success',\n        m('.container',\n          m('.message-panel', [\n            m('.message-icon',\n              m('span.material-icon', 'check')\n            ),\n            m('.message-body', [\n              m('p.lead',\n                gettext(\"Activation link has been sent.\")\n              ),\n              m('p',\n                interpolate(message, {\n                  username: vm.user.username,\n                  email: vm.user.email\n                }, true)\n              ),\n              m('p',\n                _.component('button', {\n                  class: '.btn-default',\n                  submit: false,\n                  label: gettext(\"Request another link\"),\n                  onclick: form.reset.bind(form)\n                })\n              )\n            ])\n          ])\n        )\n      );\n    },\n    form: function(form, _) {\n      return m('.page.page-request-activation', [\n        _.component('header', {\n          title: gettext(\"Request activation link\")\n        }),\n        m('.container',\n          m('.row', [\n            m('.col-md-8', [\n              m('p',\n                gettext(\"Site administrator may impose requirement on newly regitered accounts to be activated before users will be able to sign in.\")\n              ),\n              m('p',\n                gettext(\"Depending on time of registration, you will be able activate your account by clicking special activation link. This link will be valid only for your browser, for seven days or until your account is activated.\")\n              ),\n              m('p',\n                gettext(\"To receive this link, enter your account's e-mail addres in form and press \\\"Send link\\\" button.\")\n              )\n            ]),\n            m('.col-md-4',\n              _.component('request-link-form', form)\n            )\n          ])\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('route:request-activation', function(_) {\n    _.route('request-activation', requestActivation);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var ViewModel = function() {\n    this.endpoint = 'send-password-form';\n    this.user = null;\n\n    this.activation = null;\n    this.activationMessage = null;\n\n    this.success = function(user) {\n      this.user = user;\n    };\n\n    this.error = function(rejection, _) {\n      if (['inactive_user', 'inactive_admin'].indexOf(rejection.code) > -1) {\n        this.activation = rejection.code;\n        this.activationMessage = rejection.detail;\n      } else {\n        _.alert.error(rejection.detail);\n      }\n    };\n\n    this.reset = function() {\n      this.user = null;\n      this.activation = null;\n      this.activationMessage = null;\n    };\n  };\n\n  var requestPasswordChange = {\n    controller: function(_) {\n      _.title.set(gettext(\"Change forgotten password\"));\n\n      var vm = new ViewModel();\n\n      return {\n        vm: vm,\n        form: _.form('request-link', vm)\n      };\n    },\n    view: function(ctrl, _) {\n      if (ctrl.vm.user) {\n        return this.completed(ctrl.form, ctrl.vm, _);\n      } else if (ctrl.vm.activation) {\n        return this.inactive(ctrl.form, ctrl.vm, _);\n      } else {\n        return this.form(ctrl.form, _);\n      }\n    },\n    completed: function(form, vm, _) {\n      var message = gettext(\"%(username)s, we have sent link to your password change form to %(email)s.\");\n\n      return m('.page.page-message.page-message-success',\n        m('.container',\n          m('.message-panel', [\n            m('.message-icon',\n              m('span.material-icon', 'check')\n            ),\n            m('.message-body', [\n              m('p.lead',\n                gettext(\"Change password form link sent.\")\n              ),\n              m('p',\n                interpolate(message, {\n                  username: vm.user.username,\n                  email: vm.user.email\n                }, true)\n              ),\n              m('p',\n                _.component('button', {\n                  class: '.btn-default',\n                  submit: false,\n                  label: gettext(\"Request another link\"),\n                  onclick: form.reset.bind(form)\n                })\n              )\n            ])\n          ])\n        )\n      );\n    },\n    inactive: function(form, vm, _) {\n      var activateButton = null;\n\n      if (vm.activation === 'inactive_user') {\n        activateButton = m('a.btn.btn-primary',\n          {href: _.router.url('request_activation')},\n          gettext(\"Activate account\")\n        );\n      }\n\n      return m('.page.page-message.page-message-info',\n        m('.container',\n          m('.message-panel', [\n            m('.message-icon',\n              m('span.material-icon', 'info_outline')\n            ),\n            m('.message-body', [\n              m('p.lead',\n                gettext(\"Your account is inactive.\")\n              ),\n              m('p',\n                vm.activationMessage\n              ),\n              m('p', [\n                activateButton,\n                _.component('button', {\n                  class: '.btn-default',\n                  submit: false,\n                  label: gettext(\"Request another link\"),\n                  onclick: form.reset.bind(form)\n                })\n              ])\n            ])\n          ])\n        )\n      );\n    },\n    form: function(form, _) {\n      return m('.page.page-request-activation', [\n        _.component('header', {\n          title: gettext(\"Change forgotten password\")\n        }),\n        m('.container',\n          m('.row', [\n            m('.col-md-8', [\n              m('p',\n                gettext(\"Because user passwords are processed in an irreversible way before being saved to database, it is not possible for us to simply send you your password.\")\n              ),\n              m('p',\n                gettext(\"Instead, you can change your password using special secure form that will be available by special link valid only for your browser, for seven days or until your password is changed.\")\n              ),\n              m('p',\n                gettext(\"To receive this link, enter your account's e-mail addres in form and press \\\"Send link\\\" button.\")\n              )\n            ]),\n            m('.col-md-4',\n              _.component('request-link-form', form)\n            )\n          ])\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('route:request-password-change', function(_) {\n    _.route('request-password-change', requestPasswordChange);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var forum = {\n    view: function(ctrl, _) {\n      return m('', [\n        _.component('header', {\n          title: gettext(\"Options\")\n        }),\n        m('.container',\n          m('p', 'Lorem ipsum dolor met.')\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('component:options:nav:dropdown', function(_) {\n    _.component('options:nav:dropdown', forum);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var email = {\n    controller: function(_) {\n      _.auth.denyAnonymous(\n        gettext(\"You have to be signed in to change your options.\"));\n\n      this.container.title.set({\n        title: gettext(\"E-mail\"),\n        parent: gettext(\"Options\")\n      });\n    },\n    view: function(ctrl, _) {\n      return m('.page.page-options.page-forum-options', [\n        _.component('header', {\n          title: gettext(\"Change options\")\n        }),\n        m('.container',\n          m('p', 'Lorem ipsum dolor met.')\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('route:options:email', function(_) {\n    _.route('options-email', email);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var forum = {\n    controller: function(_) {\n      _.auth.denyAnonymous(\n        gettext(\"You have to be signed in to change your options.\"));\n\n      this.container.title.set({\n        title: gettext(\"Forum options\"),\n        parent: gettext(\"Options\")\n      });\n    },\n    view: function(ctrl, _) {\n      return m('.page.page-options.page-forum-options', [\n        _.component('header', {\n          title: gettext(\"Options\")\n        }),\n        m('.container',\n          m('p', 'Lorem ipsum dolor met.')\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('route:options:forum', function(_) {\n    _.route('options-forum', forum);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var index = {\n    controller: function(_) {\n      _.auth.denyAnonymous(\n        gettext(\"You have to be signed in to change your options.\"));\n\n      _.router.redirect('options_forum');\n    }\n  };\n\n  Misago.addService('route:options', function(_) {\n    _.route('options', index);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var password = {\n    controller: function(_) {\n      _.auth.denyAnonymous(\n        gettext(\"You have to be signed in to change your options.\"));\n\n      this.container.title.set({\n        title: gettext(\"Password\"),\n        parent: gettext(\"Options\")\n      });\n    },\n    view: function(ctrl, _) {\n      return m('.page.page-options.page-forum-options', [\n        _.component('header', {\n          title: gettext(\"Change options\")\n        }),\n        m('.container',\n          m('p', 'Lorem ipsum dolor met.')\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('route:options:password', function(_) {\n    _.route('options-password', password);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var forum = {\n    view: function(ctrl, _) {\n      return m('.list-group.nav-side', [\n\n      ]);\n    }\n  };\n\n  Misago.addService('component:options:nav:side', function(_) {\n    _.component('options:nav:side', forum);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  function persistent(el, isInit, context) {\n    context.retain = true;\n  }\n\n  var alert = {\n    classes: {\n      'info': 'alert-info',\n      'success': 'alert-success',\n      'warning': 'alert-warning',\n      'error': 'alert-danger'\n    },\n    view: function(ctrl, _) {\n      return m(\n        '.alerts',\n        {\n          config: persistent,\n          class: _.alert.isVisible ? 'in' : 'out'\n        },\n        m('p.alert',\n          {\n            class: this.classes[_.alert.type]\n          },\n          _.alert.message\n        )\n      );\n    }\n  };\n\n  Misago.addService('component:alert', function(_) {\n    _.component('alert', alert);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  function persistent(el, isInit, context) {\n    context.retain = true;\n  }\n\n  var authChanged = {\n    refresh: function() {\n      window.location.reload();\n    },\n    view: function(ctrl, _) {\n      var message = '';\n\n      var options = {\n        config: persistent,\n        class: (_.auth.isDesynced ? 'show' : null)\n      };\n\n      if (_.auth.isDesynced) {\n        if (_.auth.newUser && _.auth.newUser.isAuthenticated) {\n          message = gettext(\"You have signed in as %(username)s. Please refresh this page before continuing.\");\n          message = interpolate(message, {username: _.auth.newUser.username}, true);\n        } else {\n          message = gettext(\"%(username)s, you have been signed out. Please refresh this page before continuing.\");\n          message = interpolate(message, {username: _.user.username}, true);\n        }\n      }\n\n      return m('.auth-changed-message', options,\n        m('',\n          m('.container', [\n            m('p',\n              message\n            ),\n            m('p', [\n              m('button.btn.btn-default[type=\"button\"]', {onclick: this.refresh},\n                gettext(\"Reload page\")\n              ),\n              m('span.hidden-xs.hidden-sm.text-muted',\n                gettext(\"or press F5 key.\")\n              )\n            ])\n          ])\n        )\n      );\n    }\n  };\n\n  Misago.addService('component:auth-changed-message', function(_) {\n    _.component('auth-changed-message', authChanged);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var button = {\n    view: function(ctrl, kwargs) {\n      var options = {\n        disabled: kwargs.disabled || kwargs.loading || false,\n        config: kwargs.config || null,\n        loading: kwargs.loading || false,\n        type: kwargs.submit ? 'submit' : 'button',\n        onclick: kwargs.onclick || null\n      };\n\n      var element = 'button[type=\"' + options.type + '\"].btn';\n      if (options.loading) {\n        element += '.btn-loading';\n      }\n\n      if (kwargs.id) {\n        element += '#' + kwargs.id;\n      }\n\n      element += (kwargs.class || '');\n\n      var label = kwargs.label;\n      if (options.loading) {\n        label = [\n          label,\n          m('.loader-compact', [\n            m('.bounce1'),\n            m('.bounce2'),\n            m('.bounce3')\n          ])\n        ];\n      }\n\n      return m(element, options, label);\n    },\n  };\n\n  Misago.addService('component:button', function(_) {\n    _.component('button', button);\n  },\n  {\n    after: 'components'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var textFields = ['text', 'password', 'email'];\n\n  var formGroup = {\n    view: function(ctrl, kwargs) {\n      var groupClass = '.form-group';\n      var errors = null;\n      var helpText = null;\n\n      var controlType = kwargs.control.attrs.type;\n      var controlId = kwargs.control.attrs.id;\n\n      var feedbackId = controlId + '_feedback';\n      var feedbackIcon = null;\n      var showFeedbackIcon = null;\n\n      var isValidated = kwargs.validationKey && kwargs.validation !== null;\n\n      kwargs.control.attrs['aria-describedby'] = '';\n\n      if (isValidated && kwargs.validation[kwargs.validationKey]) {\n        showFeedbackIcon = textFields.indexOf(controlType) >= 0;\n        kwargs.control.attrs['aria-describedby'] = feedbackId;\n\n        if (kwargs.validation[kwargs.validationKey] === true) {\n          groupClass += '.has-success';\n          feedbackIcon = [\n            m('span.material-icon.form-control-feedback',\n              {\n                'aria-hidden': 'true'\n              },\n              'check'\n            ),\n            m('span.sr-only#' + feedbackId, gettext(\"(success)\"))\n          ];\n        } else {\n          groupClass += '.has-error';\n          errors = kwargs.validation[kwargs.validationKey];\n          feedbackIcon = [\n            m('span.material-icon.form-control-feedback',\n              {\n                'aria-hidden': 'true'\n              },\n              'clear'\n            ),\n            m('span.sr-only#' + feedbackId, gettext(\"(error)\"))\n          ];\n        }\n      }\n\n      if (kwargs.helpText) {\n        if (typeof kwargs.helpText === 'string' ||\n            kwargs.helpText instanceof String) {\n          helpText = m('p.help-block', kwargs.helpText);\n        } else {\n          helpText = kwargs.helpText;\n        }\n      }\n\n      return m(groupClass, [\n        m('label.control-label' + (kwargs.labelClass || ''),\n          {\n            for: kwargs.labelFor || controlId\n          },\n          kwargs.label + ':'\n        ),\n        m(kwargs.controlClass || '', [\n          kwargs.control,\n          showFeedbackIcon ? feedbackIcon : null,\n          errors ? m('.help-block.errors', errors.map(function(item) {\n            return m('p', item);\n          })) : null,\n          helpText\n        ])\n      ]);\n    },\n  };\n\n  Misago.addService('component:form-group', function(_) {\n    _.component('form-group', formGroup);\n  },\n  {\n    after: 'components'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var persistent = function(el, isInit, context) {\n    context.retain = true;\n  };\n\n  var forumLayout = {\n    view: function(ctrl, _) {\n      return [\n        _.component('auth-changed-message'),\n        _.component('alert'),\n        _.component('navbar'),\n        m('.navbar-dropdown',\n          _.dropdown.slot('navbar-dropdown')\n        ),\n        m('#router-fixture', {config: persistent}),\n        _.component('footer'),\n        _.component('modal')\n      ];\n    }\n  };\n\n  Misago.addService('component:layout', function(_) {\n    _.component('forum-layout', forumLayout);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var loader = {\n    view: function() {\n      return m('.loader.sk-folding-cube', [\n        m('.sk-cube1.sk-cube'),\n        m('.sk-cube2.sk-cube'),\n        m('.sk-cube4.sk-cube'),\n        m('.sk-cube3.sk-cube')\n      ]);\n    }\n  };\n\n  Misago.addService('component:loader', function(_) {\n    _.component('loader', loader);\n  },\n  {\n    after: 'components'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var persistent = function(el, isInit, context) {\n    context.retain = true;\n  };\n\n  var markup = {\n    view: function(ctrl, content) {\n      return m('article.misago-markup', {config: persistent},\n        m.trust(content)\n      );\n    }\n  };\n\n  Misago.addService('component:markup', function(_) {\n    _.component('markup', markup);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var persistent = function(el, isInit, context) {\n    context.retain = true;\n  };\n\n  var modal = {\n    view: function() {\n      return m(\n        '#misago-modal.modal.fade[role=\"dialog\"]',\n        {\n          config: persistent,\n          tabindex: \"-1\",\n          \"aria-labelledby\": \"misago-modal-label\"\n        }\n      );\n    }\n  };\n\n  Misago.addService('component:modal', function(_) {\n    _.component('modal', modal);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var header = {\n    view: function(ctrl, options) {\n      return m('.page-header',\n        m('.container', [\n          m('h1', options.title),\n        ])\n      );\n    }\n  };\n\n  Misago.addService('component:header', function(_) {\n    _.component('header', header);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var persistent = function(el, isInit, context) {\n    context.retain = true;\n  };\n\n  var styles = [\n    'progress-bar-danger',\n    'progress-bar-warning',\n    'progress-bar-warning',\n    'progress-bar-primary',\n    'progress-bar-success'\n  ];\n\n  var labels = [\n    gettext('Entered password is very weak.'),\n    gettext('Entered password is weak.'),\n    gettext('Entered password is average.'),\n    gettext('Entered password is strong.'),\n    gettext('Entered password is very strong.')\n  ];\n\n  var passwordStrength = {\n    view: function(ctrl, kwargs, _) {\n      var score = _.zxcvbn.scorePassword(kwargs.password, kwargs.inputs);\n      var options = {\n        config: persistent,\n        class: styles[score],\n        style: \"width: \" + (20 + (20 * score)) + '%',\n        'role': \"progressbar\",\n        'aria-valuenow': score,\n        'aria-valuemin': \"0\",\n        'aria-valuemax': \"4\"\n      };\n\n      return m('.help-block.password-strength', {key: 'password-strength'}, [\n        m('.progress',\n          m('.progress-bar', options,\n            m('span.sr-only', labels[score])\n          )\n        ),\n        m('p.text-small', labels[score])\n      ]);\n    },\n  };\n\n  Misago.addService('component:password-strength', function(_) {\n    _.component('password-strength', passwordStrength);\n  },\n  {\n    after: 'components'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var avatar = {\n    defaultSize: 100,\n\n    src: function(user, size, _) {\n      var src = _.router.baseUrl + 'user-avatar/';\n\n      if (user && user.id) {\n        // just avatar hash, size and user id\n        src += user.avatar_hash + '/' + size + '/' + user.id + '.png';\n      } else {\n        // just append avatar size to file to produce no-avatar placeholder\n        src += size + '.png';\n      }\n\n      return src;\n    },\n    view: function(ctrl, user, size, _) {\n      var finalSize = size || this.defaultSize;\n      return m('img', {\n        alt: user && user.username ? user.username : gettext(\"Unregistered\"),\n        width: finalSize,\n        height: finalSize,\n        src: this.src(user, finalSize, _)\n      });\n    }\n  };\n\n  Misago.addService('component:user-avatar', function(_) {\n    _.component('user-avatar', avatar);\n  },\n  {\n    after: 'components'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var header = {\n    view: function(ctrl, title) {\n      return m('.modal-header', [\n        m('button.close[type=\"button\"]',\n          {'data-dismiss': 'modal', 'aria-label': gettext('Close')},\n          m('span', {'aria-hidden': 'true'}, m.trust('&times;'))\n        ),\n        m('h4#misago-modal-label.modal-title', title)\n      ]);\n    }\n  };\n\n  Misago.addService('component:modal:header', function(_) {\n    _.component('modal:header', header);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var persistent = function(el, isInit, context) {\n    context.retain = true;\n  };\n\n  var refresh = function() {\n    document.location.reload();\n  };\n\n  var registerComplete = {\n    controller: function(message, _) {\n      if (message.activation === 'active') {\n        _.runloop.runOnce(\n          refresh, 'refresh-after-registration', 10000);\n      }\n    },\n    view: function(ctrl, message, _) {\n      var messageHtml = null;\n\n      if (message.activation === 'active') {\n        messageHtml = this.active(message);\n      } else {\n        messageHtml = this.inactive(message);\n      }\n\n      return m('.modal-dialog.modal-message.modal-register[role=\"document\"]',\n        {config: persistent},\n        m('.modal-content', [\n          _.component('modal:header', gettext('Registration complete')),\n          m('.modal-body',\n            messageHtml\n          )\n        ])\n      );\n    },\n    active: function(message) {\n      var lead = gettext(\"%(username)s, your account has been created and you were signed in.\");\n      return [\n        m('.message-icon',\n          m('span.material-icon', 'check')\n        ),\n        m('.message-body', [\n          m('p.lead',\n            interpolate(lead, {'username': message.username}, true)\n          ),\n          m('p',\n            gettext('The page will refresh automatically in 10 seconds.')\n          ),\n          m('p',\n            m('button[type=\"button\"].btn.btn-default', {onclick: refresh},\n              gettext('Refresh page')\n            )\n          )\n        ])\n      ];\n    },\n    inactive: function(message) {\n      var lead = null;\n      var help = null;\n\n      if (message.activation === 'user') {\n        lead = gettext(\"%(username)s, your account has been created but you need to activate it before you will be able to sign in.\");\n        help = gettext(\"We have sent an e-mail to %(email)s with link that you have to click to activate your account.\");\n      } else if (message.activation === 'admin') {\n        lead = gettext(\"%(username)s, your account has been created but board administrator will have to activate it before you will be able to sign in.\");\n        help = gettext(\"We will send an e-mail to %(email)s when this takes place.\");\n      }\n\n      return [\n        m('.message-icon',\n          m('span.material-icon', 'info_outline')\n        ),\n        m('.message-body', [\n          m('p.lead',\n            interpolate(lead, {'username': message.username}, true)\n          ),\n          m('p',\n            interpolate(help, {'email': message.email}, true)\n          )\n        ])\n      ];\n    }\n  };\n\n  Misago.addService('modal:register-complete', function(_) {\n    _.modal('register-complete', registerComplete);\n  },\n  {\n    after: 'modals'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var persistent = function(el, isInit, context) {\n    context.retain = true;\n  };\n\n  var register = {\n    controller: function(_) {\n      return {\n        form: _.form('register')\n      };\n    },\n    view: function(ctrl, _) {\n      var captcha = _.captcha.component({\n        form: ctrl.form,\n\n        labelClass: '.col-md-4',\n        controlClass: '.col-md-8'\n      });\n\n      var footnote = null;\n      var termsUrl = _.settings.terms_of_service_link;\n\n      if (!termsUrl && _.settings.terms_of_service) {\n        termsUrl = _.router.url('terms_of_service');\n      }\n\n      if (termsUrl) {\n        footnote = m('a', {href: termsUrl},\n          m.trust(interpolate(gettext(\"By registering you agree to site's %(terms)s.\"), {\n            terms: '<strong>' + gettext(\"terms and conditions\") + '</strong>'\n          }, true))\n        );\n      }\n\n      return m('.modal-dialog.modal-form.modal-register[role=\"document\"]',\n        {config: persistent},\n        m('.modal-content', [\n          _.component('modal:header', gettext('Register')),\n          m('form.form-horizontal',\n          {\n            onsubmit: ctrl.form.submit\n          },\n          [\n            m('input[type=\"text\"]', {\n              name:'_username',\n              style: 'display: none'\n            }),\n            m('input[type=\"password\"]', {\n              name:'_password',\n              style: 'display: none'\n            }),\n            m('.modal-body', [\n              _.component('form-group', {\n                label: gettext(\"Username\"),\n                labelClass: '.col-md-4',\n                controlClass: '.col-md-8',\n                control: _.input({\n                  value: _.validate(ctrl.form, 'username'),\n                  id: 'id_username',\n                  disabled: ctrl.form.isBusy\n                }),\n                validation: ctrl.form.errors,\n                validationKey: 'username'\n              }),\n              _.component('form-group', {\n                label: gettext(\"E-mail\"),\n                labelClass: '.col-md-4',\n                controlClass: '.col-md-8',\n                control: _.input({\n                  value: _.validate(ctrl.form, 'email'),\n                  id: 'id_email',\n                  disabled: ctrl.form.isBusy\n                }),\n                validation: ctrl.form.errors,\n                validationKey: 'email'\n              }),\n              _.component('form-group', {\n                label: gettext(\"Password\"),\n                labelClass: '.col-md-4',\n                controlClass: '.col-md-8',\n                control: _.input({\n                  value: _.validate(ctrl.form, 'password'),\n                  type: 'password',\n                  id: 'id_password',\n                  disabled: ctrl.form.isBusy\n                }),\n                validation: ctrl.form.errors,\n                validationKey: 'password',\n                helpText: _.component('password-strength', {\n                  inputs: [\n                    ctrl.form.username(),\n                    ctrl.form.email()\n                  ],\n                  password: ctrl.form.password()\n                })\n              }),\n              captcha\n            ]),\n            m('.modal-footer', [\n              footnote,\n              _.component('button', {\n                class: '.btn-primary',\n                submit: true,\n                loading: ctrl.form.isBusy,\n                label: gettext(\"Register account\")\n              })\n            ])\n          ])\n        ])\n      );\n    }\n  };\n\n  Misago.addService('modal:register', function(_) {\n    _.modal('register', register);\n  },\n  {\n    after: 'modals'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  function persistent(el, isInit, context) {\n    context.retain = true;\n  }\n\n  var signin = {\n    controller: function(_) {\n      return {\n        form: _.form('sign-in')\n      };\n    },\n    view: function(ctrl, _) {\n      var activateButton = null;\n\n      if (ctrl.form.showActivation) {\n        activateButton = m('a.btn.btn-block.btn-success',\n          {href: _.router.url('request_activation')},\n          gettext(\"Activate account\")\n        );\n      }\n\n      return m('.modal-dialog.modal-sm.modal-signin[role=\"document\"]',\n        {config: persistent},\n        m('.modal-content', [\n          _.component('modal:header', gettext(\"Sign in\")),\n          m('form', {onsubmit: ctrl.form.submit}, [\n            m('.modal-body', [\n              m('.form-group',\n                m('.control-input',\n                  Misago.input({\n                    disabled: ctrl.form.isBusy,\n                    value: ctrl.form.username,\n                    placeholder: gettext(\"Username or e-mail\")\n                  })\n                )\n              ),\n              m('.form-group',\n                m('.control-input',\n                  Misago.input({\n                    type: 'password',\n                    disabled: ctrl.form.isBusy,\n                    value: ctrl.form.password,\n                    placeholder: gettext(\"Password\")\n                  })\n                )\n              )\n            ]),\n            m('.modal-footer', [\n              activateButton,\n              _.component('button', {\n                class: '.btn-primary.btn-block',\n                submit: true,\n                loading: ctrl.form.isBusy,\n                label: gettext(\"Sign in\")\n              }),\n              m('a.btn.btn-block.btn-default',\n                {href: _.router.url('request_password_change')},\n                gettext(\"Forgot password?\")\n              )\n            ])\n          ])\n        ])\n      );\n    }\n  };\n\n  Misago.addService('modal:sign-in', function(_) {\n    _.modal('sign-in', signin);\n  },\n  {\n    after: 'modals'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var navbar = {\n    style: '.navbar.navbar-misago.navbar-default.navbar-static-top',\n    mainNav: function(_) {\n      var links = [\n        {\n          label: gettext(\"Threads\"),\n          icon: 'chat',\n          url: _.router.url('index')\n        },\n        {\n          label: gettext(\"Forums\"),\n          icon: 'forum',\n          url: '/not-yet/forums/'\n        },\n        {\n          label: gettext(\"Users\"),\n          icon: 'group',\n          url: '/not-yet/users/'\n        }\n      ];\n\n      return links;\n    },\n    view: function(ctrl, _) {\n      var links = this.mainNav(_);\n\n      return m('nav' + this.style + '[role=\"navigation\"]', [\n        _.component('navbar:desktop', links),\n        _.component('navbar:mobile', links)\n      ]);\n    }\n  };\n\n  Misago.addService('component:navbar', function(_) {\n    _.component('navbar', navbar);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var dropdown = {\n    controller: function(_) {\n      return {\n        showSignIn: function() {\n          _.modal('sign-in');\n        }\n      };\n    },\n    view: function(ctrl, _) {\n      return m('ul.dropdown-menu.user-dropdown.dropdown-menu-right[role=\"menu\"]',\n        m('li.guest-preview', [\n          m('h4',\n            gettext(\"You are browsing as guest.\")\n          ),\n          m('p',\n            gettext('Sign in or register to start and participate in discussions.')\n          ),\n          m('.row', [\n            m('.col-xs-6',\n              _.component('button', {\n                class: '.btn.btn-default.btn-block',\n                onclick: ctrl.showSignIn,\n                disabled: ctrl.isBusy,\n                label: gettext('Sign in')\n              })\n            ),\n            m('.col-xs-6',\n              _.component(\n                'navbar:register-button', '.btn.btn-primary.btn-block')\n            )\n          ])\n        ])\n      );\n    }\n  };\n\n  Misago.addService('component:navbar:dropdown:guest', function(_) {\n    _.component('navbar:dropdown:guest', dropdown);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var navbar = {\n    style: '.nav.navbar-nav.navbar-compact-nav.hidden-md.hidden-lg',\n    controller: function(links, _) {\n      return {\n        openUserMenu: function() {\n          if (_.user.isAuthenticated) {\n            _.dropdown.toggle('navbar-dropdown', 'navbar:dropdown:user');\n          } else {\n            _.dropdown.toggle('navbar-dropdown', 'navbar:dropdown:guest');\n          }\n\n          return false;\n        }\n      };\n    },\n    userMenu: function(ctrl, _) {\n      if (_.user.isAuthenticated) {\n        return {\n          element: _.component('user-avatar', _.user, 64),\n          config: {\n            onclick: ctrl.openUserMenu,\n            url: '/not-yet/',\n\n            'data-misago-routed': 'false'\n          }\n        };\n      } else {\n        return {\n          element: _.component('user-avatar', null, 64),\n          config: {\n            onclick: ctrl.openUserMenu,\n            href: '#',\n\n            'data-misago-routed': 'false'\n          }\n        };\n      }\n    },\n    mobileNav: function(ctrl, links, _) {\n      var mobileLinks = [\n        {\n          element: m('img', {\n            src: _.router.staticUrl('misago/img/site-icon.png'),\n            alt: _.settings.forum_name\n          }),\n          url: _.router.url('index')\n        }\n      ];\n\n      links.forEach(function(link) {\n        if (link.url !== mobileLinks[0].url) {\n          mobileLinks.push(link);\n        }\n      });\n\n      mobileLinks.push(this.userMenu(ctrl, _));\n\n      return mobileLinks;\n    },\n    view: function(ctrl, links, _) {\n      var mobileLinks = this.mobileNav(ctrl, links, _);\n\n      return m('ul' + this.style + '.with-' + mobileLinks.length + '-items',\n        mobileLinks.map(function(link) {\n          return m('li',\n            m('a', link.config || {href: link.url},\n              link.element || m('span.material-icon', {title:link.label},\n                link.icon\n              )\n            )\n          );\n        })\n      );\n    }\n  };\n\n  Misago.addService('component:navbar:mobile', function(_) {\n    _.component('navbar:mobile', navbar);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var button = {\n    controller: function(style, _) {\n      return {\n        isBusy: false,\n\n        showRegister: function() {\n          if (_.settings.account_activation === 'closed') {\n            _.alert.info(gettext(\"New registrations are currently disabled.\"));\n          } else {\n            m.startComputation();\n            this.isBusy = true;\n            m.endComputation();\n\n            var self = this;\n            m.sync([\n              _.zxcvbn.load(),\n              _.captcha.load()\n            ]).then(function() {\n              _.modal('register');\n            }, function() {\n              _.alert.error(gettext('Registation is not available now due to an error.'));\n            }).then(function() {\n              m.startComputation();\n              self.isBusy = false;\n              m.endComputation();\n            });\n          }\n        }\n      };\n    },\n    view: function(ctrl, style, _) {\n      return _.component('button', {\n        class: style,\n        onclick: ctrl.showRegister.bind(ctrl),\n        loading: ctrl.isBusy,\n        label: gettext('Register')\n      });\n    }\n  };\n\n  Misago.addService('component:navbar:register-button', function(_) {\n    _.component('navbar:register-button', button);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var dropdown = {\n    class: '.dropdown-menu.user-dropdown.dropdown-menu-right',\n\n    controller: function() {\n      return {\n        logout: function() {\n          var decision = confirm(gettext(\"Are you sure you want to sign out?\"));\n          if (decision) {\n            $('#hidden-logout-form').submit();\n          }\n        }\n      };\n    },\n    view: function(ctrl, _) {\n      return m('ul' + this.class + '[role=\"menu\"]', [\n        m('li.dropdown-header',\n          m('strong',\n            _.user.username\n          )\n        ),\n        m('li.divider'),\n        m('li',\n          m('a', {href: '/not-yet/'}, [\n            m('span.material-icon',\n              'account_circle'\n            ),\n            gettext(\"See your profile\")\n          ])\n        ),\n        m('li',\n          m('a', {href: _.router.url('options')}, [\n            m('span.material-icon',\n              'done_all'\n            ),\n            gettext(\"Change options\")\n          ])\n        ),\n        m('li',\n          m('button.btn-link[type=\"button\"]', [\n            m('span.material-icon',\n              'face'\n            ),\n            gettext(\"Change avatar\")\n          ])\n        ),\n        m('li.divider'),\n        m('li.dropdown-footer',\n          m('button.btn.btn-default.btn-block', {onclick: ctrl.logout},\n            gettext(\"Logout\")\n          )\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('component:navbar:dropdown:user', function(_) {\n    _.component('navbar:dropdown:user', dropdown);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var footer = {\n    hasNav: function(_) {\n      return [\n        !!_.settings.forum_footnote,\n        !!_.settings.terms_of_service,\n        !!_.settings.terms_of_service_link,\n        !!_.settings.privacy_policy,\n        !!_.settings.privacy_policy_link\n      ].indexOf(true) !== -1;\n    },\n    view: function(ctrl, _) {\n      var nav = null;\n      if (this.hasNav(_)) {\n        nav = _.component('footer:nav');\n      }\n\n      return m('footer.forum-footer', [\n        m('.container',\n          m('.footer-content', [\n            nav,\n            _.component('footer:branding')\n          ])\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('component:footer', function(_) {\n    _.component('footer', footer);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var branding = {\n    view: function() {\n      return m('a.misago-branding[href=http://misago-project.org]', [\n        \"powered by \", m('strong', \"misago\")\n      ]);\n    }\n  };\n\n  Misago.addService('component:footer:branding', function(_) {\n    _.component('footer:branding', branding);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var legalLink = function(_, legalType, defaultTitle) {\n    var url = Misago.get(_.settings, legalType + '_link');\n    if (!url && Misago.get(_.settings, legalType)) {\n      url = _.router.url(legalType);\n    }\n\n    if (url) {\n      return m('li',\n        m('a', {href: url},\n          Misago.get(_.settings, legalType + '_title', defaultTitle)\n        )\n      );\n    } else {\n      return null;\n    }\n  };\n\n  var nav = {\n    isVisible: function(settings) {\n      return [\n        !!settings.forum_footnote,\n        !!settings.terms_of_service,\n        !!settings.terms_of_service_link,\n        !!settings.privacy_policy,\n        !!settings.privacy_policy_link\n      ].indexOf(true) !== -1;\n    },\n    view: function(ctrl, _) {\n      var items = [];\n\n      if (_.settings.forum_footnote) {\n        items.push(m('li.forum-footnote', m.trust(_.settings.forum_footnote)));\n      }\n\n      items.push(\n        legalLink(_, 'terms_of_service', gettext('Terms of service')));\n      items.push(\n        legalLink(_, 'privacy_policy', gettext('Privacy policy')));\n\n      return m('ul.list-inline.footer-nav', items);\n    }\n  };\n\n  Misago.addService('component:footer:nav', function(_) {\n    _.component('footer:nav', nav);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var form = {\n    view: function(ctrl, form, _) {\n      return m('.well.well-form',\n        m('form', {onsubmit: form.submit}, [\n          m('.form-group',\n            m('.control-input',\n              Misago.input({\n                disabled: form.isBusy,\n                value: form.email,\n                placeholder: gettext(\"Your e-mail address\")\n              })\n            )\n          ),\n          _.component('button', {\n            class: '.btn-primary.btn-block',\n            submit: true,\n            loading: form.isBusy,\n            label: gettext(\"Send link\")\n          })\n        ])\n      );\n    }\n  };\n\n  Misago.addService('component:request-link-form', function(_) {\n    _.component('request-link-form', form);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var brand = {\n    view: function(ctrl, branding, _) {\n      var children = [\n        m('img', {\n          src: _.router.staticUrl('misago/img/site-logo.png'),\n          alt: _.settings.forum_name\n        })\n      ];\n\n      if (branding) {\n        children.push(branding);\n      }\n\n      return m('a.navbar-brand', {href: _.router.url('index')}, children);\n    }\n  };\n\n  Misago.addService('component:navbar:desktop:brand', function(_) {\n    _.component('navbar:desktop:brand', brand);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var nav = {\n    controller: function(_) {\n      return {\n        showSignIn: function() {\n          _.modal('sign-in');\n        }\n      };\n    },\n    view: function(ctrl, _) {\n      return m('div.nav.nav-guest', [\n        _.component('button', {\n          class: '.navbar-btn.btn-default',\n          onclick: ctrl.showSignIn,\n          disabled: ctrl.isBusy,\n          label: gettext('Sign in')\n        }),\n        _.component('navbar:register-button', '.navbar-btn.btn-primary')\n      ]);\n    }\n  };\n\n  Misago.addService('component:navbar:desktop:guest-nav', function(_) {\n    _.component('navbar:desktop:guest-nav', nav);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var nav = {\n    view: function(ctrl, links) {\n      return m('ul.nav.navbar-nav', [\n        links.map(function(link) {\n          return m('li',\n            m(\"a\", link.config || {href: link.url},\n              link.label\n            )\n          );\n        })\n      ]);\n    }\n  };\n\n  Misago.addService('component:navbar:desktop:main-nav', function(_) {\n    _.component('navbar:desktop:main-nav', nav);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var navbar = {\n    view: function(ctrl, mainNav, _) {\n      var brand = null;\n      var user = null;\n\n      if (_.settings.forum_branding_display) {\n        brand = _.component(\n          'navbar:desktop:brand', _.settings.forum_branding_text);\n      }\n\n      if (_.user.isAuthenticated) {\n        user = _.component('navbar:desktop:user-nav');\n      } else {\n        user = _.component('navbar:desktop:guest-nav');\n      }\n\n      return m('.container.navbar-full.hidden-xs.hidden-sm', [\n        brand,\n        _.component('navbar:desktop:main-nav', mainNav),\n        user\n      ]);\n    }\n  };\n\n  Misago.addService('component:navbar:desktop', function(_) {\n    _.component('navbar:desktop', navbar);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var nav = {\n    controller: function() {\n      return {\n        dropdownToggle: {\n          href: '/not-yet/',\n\n          'data-toggle': 'dropdown',\n          'data-misago-routed': 'false',\n\n          'aria-haspopup': 'true',\n          'aria-expanded': 'false'\n        }\n      };\n    },\n    view: function(ctrl, _) {\n      return m('ul.nav.navbar-nav.nav-user', [\n        m('li.dropdown', [\n          m('a.dropdown-toggle[role=\"button\"]', ctrl.dropdownToggle,\n            _.component('user-avatar', _.user, 64)\n          ),\n          _.component('navbar:dropdown:user')\n        ])\n      ]);\n    }\n  };\n\n  Misago.addService('component:navbar:desktop:user-nav', function(_) {\n    _.component('navbar:desktop:user-nav', nav);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var ChangePassword = function(_) {\n    var self = this;\n\n    this.username = null;\n    this.password = m.prop('');\n\n    this.validation = {\n      'password': [\n        Misago.validators.passwordMinLength(_.settings)\n      ]\n    };\n\n    this.clean = function() {\n      if (!_.validate(this)) {\n        if ($.trim(this.password()).length) {\n          _.alert.error(this.errors.password);\n        } else {\n          _.alert.error(gettext(\"Enter new password.\"));\n        }\n        return false;\n      } else {\n        return true;\n      }\n    };\n\n    this.submit = function() {\n      var endpoint = _.api.endpoint('auth').endpoint('change-password');\n      endpoint = endpoint.endpoint(m.route.param('user_id'));\n      endpoint = endpoint.endpoint(m.route.param('token'));\n\n      endpoint.post({\n        password: self.password()\n      }).then(function(user) {\n        self.success(user);\n      }, function(error) {\n        self.error(error);\n      });\n    };\n\n    this.success = function(user) {\n      this.username = user.username;\n    };\n\n    this.error = function(rejection) {\n      if (rejection.status === 403 && rejection.ban) {\n        _.router.error403({\n          message: '',\n          ban: rejection.ban\n        });\n      } else if (rejection.status === 400) {\n        _.alert.error(rejection.detail);\n      } else {\n        _.api.alert(rejection);\n      }\n    };\n  };\n\n  Misago.addService('form:change-password', function(_) {\n    _.form('change-password', ChangePassword);\n  },\n  {\n    after: 'forms'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var Register = function(_) {\n    var self = this;\n\n    this.showActivation = false;\n\n    this.username = m.prop('');\n    this.email = m.prop('');\n    this.password = m.prop('');\n\n    this.captcha = _.captcha.value;\n\n    this.errors = null;\n\n    this.validation = {\n      'username': [\n        Misago.validators.usernameContent(),\n        Misago.validators.usernameMinLength(_.settings),\n        Misago.validators.usernameMaxLength(_.settings)\n      ],\n      'email': [\n        Misago.validators.email()\n      ],\n      'password': [\n        Misago.validators.passwordMinLength(_.settings)\n      ],\n      'captcha': _.captcha.validator()\n    };\n\n    this.clean = function() {\n      if (this.errors === null) {\n        _.validate(this);\n      }\n\n      _.captcha.clean(this);\n\n      if (this.hasErrors()) {\n        _.alert.error(gettext(\"Form contains errors.\"));\n        return false;\n      } else {\n        return true;\n      }\n    };\n\n    this.submit = function() {\n      _.api.model('user').post({\n        username: this.username(),\n        email: this.email(),\n        password: this.password(),\n        captcha: this.captcha()\n      }).then(this.success, this.error);\n    };\n\n    this.success = function(data) {\n      _.modal('register-complete', data);\n    };\n\n    this.error = function(rejection) {\n      if (rejection.status === 400) {\n        _.alert.error(gettext(\"Form contains errors.\"));\n        $.extend(self.errors, rejection);\n      } else {\n        _.api.alert(rejection);\n      }\n    };\n  };\n\n  Misago.addService('form:register', function(_) {\n    _.form('register', Register);\n  },\n  {\n    after: 'forms'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var RequestLink = function(vm, _) {\n    var self = this;\n\n    this.email = m.prop('');\n\n    this.validation = {\n      'email': [\n        Misago.validators.email()\n      ]\n    };\n\n    this.clean = function() {\n      if (!_.validate(this)) {\n        _.alert.error(gettext(\"Enter a valid email address.\"));\n        return false;\n      } else {\n        return true;\n      }\n    };\n\n    this.submit = function() {\n      _.api.endpoint('auth').endpoint(vm.endpoint).post({\n        email: self.email()\n      }).then(function(user) {\n        self.success(user);\n      }, function(error) {\n        self.error(error);\n      });\n    };\n\n    this.success = function(user) {\n      vm.success(user);\n    };\n\n    this.error = function(rejection) {\n      if (rejection.status === 400) {\n          vm.error(rejection, _);\n      } else if (rejection.status === 403 && rejection.ban) {\n        _.router.error403({\n          message: '',\n          ban: rejection.ban\n        });\n      } else {\n        _.api.alert(rejection);\n      }\n    };\n\n    this.reset = function() {\n      this.email('');\n      vm.reset();\n    };\n  };\n\n  Misago.addService('form:request-link', function(_) {\n    _.form('request-link', RequestLink);\n  },\n  {\n    after: 'forms'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var SignIn = function(_) {\n    var self = this;\n\n    this.showActivation = false;\n\n    this.username = m.prop('');\n    this.password = m.prop('');\n\n    this.validation = {\n      'username': [],\n      'password': []\n    };\n\n    this.clean = function() {\n      if (!_.validate(this)) {\n        _.alert.error(gettext(\"Fill out both fields.\"));\n        return false;\n      } else {\n        return true;\n      }\n    };\n\n    this.submit = function() {\n      _.api.endpoint('auth').post({\n        username: self.username(),\n        password: self.password()\n      }).then(function() {\n        self.success();\n      }, function(error) {\n        self.error(error);\n      });\n    };\n\n    this.success = function() {\n      _.modal();\n\n      var $form = $('#hidden-login-form');\n\n      // refresh CSRF token because api call to /auth/ changed it\n      _.ajax.refreshCsrfToken();\n\n      // fill out form with user credentials and submit it, this will tell\n      // misago to redirect user back to right page, and will trigger browser's\n      // key ring feature\n      $form.find('input[type=\"hidden\"]').val(_.ajax.csrfToken);\n      $form.find('input[name=\"redirect_to\"]').val(m.route());\n      $form.find('input[name=\"username\"]').val(this.username());\n      $form.find('input[name=\"password\"]').val(this.password());\n      $form.submit();\n    };\n\n    this.error = function(rejection) {\n      if (rejection.status === 400) {\n        if (rejection.code === 'inactive_admin') {\n          _.alert.info(rejection.detail);\n        } else if (rejection.code === 'inactive_user') {\n          _.alert.info(rejection.detail);\n          self.showActivation = true;\n        } else if (rejection.code === 'banned') {\n          _.modal();\n          _.router.error403({\n            message: '',\n            ban: rejection.detail\n          });\n        } else {\n          _.alert.error(rejection.detail);\n        }\n      } else {\n        _.api.alert(rejection);\n      }\n    };\n  };\n\n  Misago.addService('form:sign-in', function(_) {\n    _.form('sign-in', SignIn);\n  },\n  {\n    after: 'forms'\n  });\n} (Misago.prototype));\n\n(function (Misago, UrlConf) {\n  'use strict';\n\n  var urls = new UrlConf();\n\n  // Board index\n  urls.url('/', 'index');\n\n  // Account activation\n  urls.url('/activation/', 'request_activation');\n  urls.url('/activation/:user_id/:token/', 'activate_by_token');\n\n  // Password reset\n  urls.url('/forgotten-password/', 'request_password_change');\n  urls.url('/forgotten-password/:user_id/:token/', 'change_password');\n\n  // User control panel\n  urls.url('/options/', 'options');\n  urls.url('/options/forum/', 'options_forum');\n  urls.url('/options/email/', 'options_email');\n  urls.url('/options/password/', 'options_password');\n\n  // Legal pages\n  urls.url('/terms-of-service/', 'terms_of_service');\n  urls.url('/privacy-policy/', 'privacy_policy');\n\n  // Catch-all 404 not found route\n  urls.url('/:rest...', 'error:404', 'not_found');\n\n  Misago.urls = urls;\n} (Misago.prototype, Misago.prototype.UrlConf));\n"],"sourceRoot":"/source/"}
+{"version":3,"sources":["misago.js"],"names":["window","Misago","ns","Object","getPrototypeOf","this","self","_initServices","services","orderedServices","OrderedList","order","forEach","item","factory","undefined","serviceInstance","key","_destroyServices","reverse","destroy","context","SETTINGS","setup","init","fixture","get","test","api","_services","proto","prototype","addService","name","push","after","before","PermissionDenied","message","detail","status","toString","has","obj","hasOwnProperty","value","pop","returnValue","persistent","el","isInit","retain","input","kwargs","options","disabled","config","placeholder","autocomplete","element","id","type","oninput","m","withAttr","noop","stateHooks","component","loadingState","errorState","_hasLifecycleHooks","isActive","errorHandler","bind","_controller","controller","apply","arguments","_onunload","onunload","e","vm","loading","loadingHandler","_view","view","isReady","_init","initArgs","promise","then","ondata","finalArgs","i","length","f","error","items","isOrdered","_items","add","values","values_only","_order","unordered","insertItem","insertAt","ordering","indexOf","ordered","splice","index","iterations","Page","_","isFinalized","_sections","finalize","visible","visibleIf","addSection","section","link","getSections","getDefaultLink","serializeDatetime","serialized","format","deserializeDatetime","deserialized","moment","startsWith","string","beginning","endsWith","tail","UrlConf","_patterns","patterns","prefixPattern","prefix","pattern","replace","include","url","loadingPage","getCsrfToken","cookie_name","document","cookie","cookieRegex","RegExp","match","split","Ajax","refreshCsrfToken","csrfToken","CSRF_COOKIE_NAME","runningGets","ajax","method","data","progress","deferred","ajax_settings","headers","X-CSRFToken","dataType","success","resolve","jqXHR","rejection","responseJSON","statusText","reject","$","preloaded","post","patch","put","ALERT_BASE_DISPLAY_TIME","ALERT_LENGTH_FACTOR","ALERT_MAX_DISPLAY_TIME","ALERT_HIDE_ANIMATION_LENGTH","Alert","isVisible","show","displayTime","runloop","runOnce","startComputation","endComputation","set","stop","info","warning","filtersUrl","filters","encodedKey","encodeURIComponent","encodedValue","join","Query","call","path","related","model","relation","endpoint","results","map","models","Api","alert","gettext","Auth","user","deserialize","isDesynced","newUser","handleAuthChange","isAuthenticated","localstore","handleUserChange","extend","syncSession","watch","denyAuthenticated","denyAnonymous","isAnonymous","NoCaptcha","load","QACaptcha","question","prop","label","labelClass","controlClass","control","validate","form","isBusy","validation","errors","validationKey","helpText","help_text","validator","ReCaptcha","included","wait","grecaptcha","reset","controlConfig","render","sitekey","settings","recaptcha_site_key","getResponse","clean","captcha","Captcha","types","no","qa","re","captcha_type","_components","argumentsArray","dropdownConfig","on","removeClass","off","Dropdown","slots","slot","toggle","getElementById","hasChildNodes","mount","addClass","boilerplate","_submit","submit","_success","_error","hasErrors","constructor","_forms","script","remote","STATIC_URL","cache","LocalStore","storage","localStorage","watchers","handleStorageEvent","newValueJson","JSON","parse","newValue","each","watcher","keyName","oldValue","callback","addEventListener","prefixKey","setItem","stringify","itemString","getItem","Modal","delegateName","hide","remove","modal","open","_modal","_modals","Models","classes","deserializers","String","json","locale","attr","Router","baseUrl","staticUrl","mediaUrl","urls","reverses","populatePatterns","urlconf","finalPattern","route","startRouting","mode","redirect","delegateElement","cleanUrl","isRelative","substr","location","protocol","host","avatarsUrl","delegateSelector","delegateClicks","currentTarget","href","preventDefault","prefixUrl","error403","ban","error404","error500","error0","errorPage","waitForFixture","router","setTimeout","_hasRouteBoilerplate","loadingView","container","onerror","_routes","RunLoop","_intervals","stopInterval","clearTimeout","run","callable","delay","result","loop","ticks","PageTitle","forum_name","title","_set_complex","completeTitle","page","page_label","interpolate","parent","EMAIL","USERNAME","validators","required","trim","email","minLength","limit_value","returnMessage","ngettext","show_value","maxLength","usernameMinLength","username_length_min","usernameMaxLength","username_length_max","usernameContent","passwordMinLength","password_length_min","validateField","validateForm","isValid","Zxcvbn","scorePassword","password","inputs","zxcvbn","score","Ban","html","plain","expires_on","deserializeBan","class","LegalPage","body","Rank","slug","description","css_class","is_tab","User","username","full_title","rank","avatar_hash","acl","deserializeUser","joined_on","forum","ctrl","auth","viewModel","param","activateByToken","rejected","changePassword","signin","complete","onsubmit","onclick","error_message","help","code","icon","errorBanned","trust","expirationMessage","isAfter","fromNow","forum_index_title","activation","legalPageFactory","typeName","defaultTitle","dashedTypeName","ViewModel","requestActivation","completed","activationMessage","requestPasswordChange","inactive","activateButton","brand","branding","children","src","alt","nav","showSignIn","links","navbar","mainNav","forum_branding_display","forum_branding_text","dropdownToggle","data-toggle","data-misago-routed","aria-haspopup","aria-expanded","authChanged","refresh","reload","button","textFields","formGroup","groupClass","controlType","attrs","controlId","feedbackId","feedbackIcon","showFeedbackIcon","isValidated","aria-hidden","for","labelFor","forumLayout","dropdown","loader","markup","content","tabindex","aria-labelledby","header","styles","labels","passwordStrength","style","role","aria-valuenow","aria-valuemin","aria-valuemax","avatar","defaultSize","size","finalSize","width","height","openUserMenu","userMenu","mobileNav","mobileLinks","showRegister","account_activation","sync","logout","decision","confirm","footer","hasNav","forum_footnote","terms_of_service","terms_of_service_link","privacy_policy","privacy_policy_link","legalLink","legalType","data-dismiss","aria-label","registerComplete","messageHtml","active","lead","register","footnote","termsUrl","terms","showActivation","ChangePassword","Register","RequestLink","SignIn","$form","find","val"],"mappings":"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","file":"misago.js","sourcesContent":["/* global -Misago */\n/* exported Misago */\n(function () {\n  'use strict';\n\n  window.Misago = function() {\n    var ns = Object.getPrototypeOf(this);\n    var self = this;\n\n    // Services init/destroy\n    this._initServices = function(services) {\n      var orderedServices = new ns.OrderedList(services).order(false);\n      orderedServices.forEach(function (item) {\n        var factory = null;\n        if (item.item.factory !== undefined) {\n          factory = item.item.factory;\n        } else {\n          factory = item.item;\n        }\n\n        var serviceInstance = factory(self);\n        if (serviceInstance) {\n          self[item.key] = serviceInstance;\n        }\n      });\n    };\n\n    this._destroyServices = function(services) {\n      var orderedServices = new ns.OrderedList(services).order();\n      orderedServices.reverse();\n      orderedServices.forEach(function (item) {\n        if (item.destroy !== undefined) {\n          item.destroy(self);\n        }\n      });\n    };\n\n    // Context data\n    this.context = {\n      // Empty settings\n      SETTINGS: {}\n    };\n\n    // App init/destory\n    this.setup = false;\n    this.init = function(setup, context) {\n      this.setup = {\n        fixture: ns.get(setup, 'fixture', null),\n        test: ns.get(setup, 'test', false),\n        api: ns.get(setup, 'api', '/api/')\n      };\n\n      if (context) {\n        this.context = context;\n      }\n\n      this._initServices(ns._services);\n    };\n\n    this.destroy = function() {\n      this._destroyServices(ns._services);\n    };\n  };\n\n  // Services\n  var proto = window.Misago.prototype;\n\n  proto._services = [];\n  proto.addService = function(name, factory, order) {\n    proto._services.push({\n      key: name,\n      item: factory,\n      after: proto.get(order, 'after'),\n      before: proto.get(order, 'before')\n    });\n  };\n\n  // Exceptions\n  proto.PermissionDenied = function(message) {\n    this.detail = message;\n    this.status = 403;\n\n    this.toString = function() {\n      return this.detail || 'Permission denied';\n    };\n  };\n}());\n\n(function (Misago) {\n  'use strict';\n\n  Misago.has = function(obj, key) {\n    if (obj) {\n      return obj.hasOwnProperty(key);\n    } else {\n      return false;\n    }\n  };\n\n  Misago.get = function(obj, key, value) {\n    if (Misago.has(obj, key)) {\n      return obj[key];\n    } else if (value !== undefined) {\n      return value;\n    } else {\n      return undefined;\n    }\n  };\n\n  Misago.pop = function(obj, key, value) {\n    var returnValue = Misago.get(obj, key, value);\n    if (Misago.has(obj, key)) {\n      obj[key] = null;\n    }\n    return returnValue;\n  };\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  function persistent(el, isInit, context) {\n    context.retain = true;\n  }\n\n  Misago.input = function(kwargs) {\n    var options = {\n      disabled: kwargs.disabled || false,\n      config: kwargs.config || persistent\n    };\n\n    if (kwargs.placeholder) {\n      options.placeholder = kwargs.placeholder;\n    }\n\n    if (kwargs.autocomplete === false) {\n      options.autocomplete = 'off';\n    }\n\n    var element = 'input';\n\n    if (kwargs.id) {\n      element += '#' + kwargs.id;\n      options.key = 'field-' + kwargs.id;\n    }\n\n    element += '.form-control' + (kwargs.class || '');\n    element += '[type=\"' + (kwargs.type || 'text') + '\"]';\n\n    if (kwargs.value) {\n      options.value = kwargs.value();\n      options.oninput = m.withAttr('value', kwargs.value);\n    }\n\n    return m(element, options);\n  };\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var noop = function() {};\n\n  Misago.stateHooks = function(component, loadingState, errorState) {\n    /*\n      Boilerplate for Misago components with lifecycles\n    */\n\n    // Component boilerplated (this may happen in tests)\n    if (component._hasLifecycleHooks) {\n      return component;\n    }\n    component._hasLifecycleHooks = true;\n\n    // Component active state\n    component.isActive = true;\n\n    var errorHandler = errorState.bind(component);\n\n    // Wrap controller to store lifecycle methods\n    var _controller = component.controller || noop;\n    component.controller = function() {\n      try {\n        component.isActive = true;\n        var controller = _controller.apply(component, arguments) || {};\n\n        // wrap onunload for lifestate\n        var _onunload = controller.onunload || noop;\n        controller.onunload = function() {\n          _onunload.apply(component, arguments);\n          component.isActive = false;\n        };\n\n        return controller;\n      } catch (e) {\n        errorHandler(e);\n      }\n    };\n\n    // Add state callbacks to View-Model\n    if (component.vm && component.vm.init) {\n      // setup default loading view\n      if (!component.loading) {\n        var loadingHandler = loadingState.bind(component);\n        component.loading = loadingHandler;\n      }\n\n      var _view = component.view;\n      component.view = function() {\n        if (component.vm.isReady) {\n          return _view.apply(component, arguments);\n        } else {\n          return component.loading.apply(component, arguments);\n        }\n      };\n\n      // wrap vm.init in promise handler\n      var _init = component.vm.init;\n      component.vm.init = function() {\n        var initArgs = arguments;\n        var promise = _init.apply(component.vm, initArgs);\n\n        if (promise) {\n          promise.then(function() {\n            if (component.isActive && component.vm.ondata) {\n              var finalArgs = [];\n              for (var i = 0; i < arguments.length; i++) {\n                finalArgs.push(arguments[i]);\n              }\n              for (var f = 0; f < initArgs.length; f++) {\n                finalArgs.push(initArgs[f]);\n              }\n\n              component.vm.ondata.apply(component.vm, finalArgs);\n            }\n          }, function(error) {\n            if (component.isActive) {\n              errorHandler(error);\n            }\n          });\n        }\n      };\n    }\n\n    return component;\n  };\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.OrderedList = function(items) {\n    this.isOrdered = false;\n    this._items = items || [];\n\n    this.add = function(key, item, order) {\n      this._items.push({\n        key: key,\n        item: item,\n\n        after: Misago.get(order, 'after'),\n        before: Misago.get(order, 'before')\n      });\n    };\n\n    this.get = function(key, value) {\n      for (var i = 0; i < this._items.length; i++) {\n        if (this._items[i].key === key) {\n          return this._items[i].item;\n        }\n      }\n\n      return value;\n    };\n\n    this.has = function(key) {\n      return this.get(key) !== undefined;\n    };\n\n    this.values = function() {\n      var values = [];\n      for (var i = 0; i < this._items.length; i++) {\n        values.push(this._items[i].item);\n      }\n      return values;\n    };\n\n    this.order = function(values_only) {\n      if (!this.isOrdered) {\n        this._items = this._order(this._items);\n        this.isOrdered = true;\n      }\n\n      if (values_only || typeof values_only === 'undefined') {\n        return this.values();\n      } else {\n        return this._items;\n      }\n    };\n\n    this._order = function(unordered) {\n      // Index of unordered items\n      var index = [];\n      unordered.forEach(function (item) {\n        index.push(item.key);\n      });\n\n      // Ordered items\n      var ordered = [];\n      var ordering = [];\n\n      // First pass: register items that\n      // don't specify their order\n      unordered.forEach(function (item) {\n        if (!item.after && !item.before) {\n          ordered.push(item);\n          ordering.push(item.key);\n        }\n      });\n\n      // Second pass: register items that\n      // specify their before to \"_end\"\n      unordered.forEach(function (item) {\n        if (item.before === \"_end\") {\n          ordered.push(item);\n          ordering.push(item.key);\n        }\n      });\n\n      // Third pass: keep iterating items\n      // until we hit iterations limit or finish\n      // ordering list\n      function insertItem(item) {\n        var insertAt = -1;\n        if (ordering.indexOf(item.key) === -1) {\n          if (item.after) {\n            insertAt = ordering.indexOf(item.after);\n            if (insertAt !== -1) {\n              insertAt += 1;\n            }\n          } else if (item.before) {\n            insertAt = ordering.indexOf(item.before);\n          }\n\n          if (insertAt !== -1) {\n            ordered.splice(insertAt, 0, item);\n            ordering.splice(insertAt, 0, item.key);\n          }\n        }\n      }\n\n      var iterations = 200;\n      while (iterations > 0 && index.length !== ordering.length) {\n        iterations -= 1;\n        unordered.forEach(insertItem);\n      }\n\n      return ordered;\n    };\n  };\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.Page = function(name, _) {\n    var self = this;\n\n    this.name = name;\n    this.isFinalized = false;\n    this._sections = [];\n\n    var finalize = function() {\n      if (!self.isFinalized) {\n        self.isFinalized = true;\n\n        var visible = [];\n        self._sections.forEach(function (item) {\n          if (!item.visibleIf || item.visibleIf(_)) {\n            visible.push(item);\n          }\n        });\n        self._sections = new Misago.OrderedList(visible).order(true);\n      }\n    };\n\n    this.addSection = function(section) {\n      if (this.isFinalized) {\n        throw (this.name + \" page was initialized already and no longer accepts new sections\");\n      }\n\n      this._sections.push({\n        key: section.link,\n        item: section,\n\n        after: section.after,\n        before: section.before\n      });\n    };\n\n    this.getSections = function() {\n      finalize();\n      return this._sections;\n    };\n\n    this.getDefaultLink = function() {\n      finalize();\n      return this._sections[0].link;\n    };\n  };\n}(Misago.prototype));\n\n(function (Misago) {\n  Misago.serializeDatetime = function(serialized) {\n    return serialized ? serialized.format() : null;\n  };\n\n  Misago.deserializeDatetime = function(deserialized) {\n    return deserialized ? moment(deserialized) : null;\n  };\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.startsWith = function(string, beginning) {\n    return string.indexOf(beginning) === 0;\n  };\n\n  Misago.endsWith = function(string, tail) {\n    return string.indexOf(tail, string.length - tail.length) !== -1;\n  };\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.UrlConf = function() {\n    var self = this;\n    this._patterns = [];\n\n    this.patterns = function() {\n      return this._patterns;\n    };\n\n    var prefixPattern = function(prefix, pattern) {\n      return (prefix + pattern).replace('//', '/');\n    };\n\n    var include = function(prefix, patterns) {\n      for (var i = 0; i < patterns.length; i ++) {\n        self.url(prefixPattern(prefix, patterns[i].pattern),\n                 patterns[i].component,\n                 patterns[i].name);\n      }\n    };\n\n    this.url = function(pattern, component, name) {\n      if (pattern === '') {\n        pattern = '/';\n      }\n\n      if (component instanceof Misago.UrlConf) {\n        include(pattern, component.patterns());\n      } else {\n        this._patterns.push({\n          pattern: pattern,\n          component: component.replace(/_/g, '-'),\n          name: name || component\n        });\n      }\n    };\n  };\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.loadingPage = function(_) {\n    return m('.page.page-loading',\n      _.component('loader')\n    );\n  };\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var getCsrfToken = function(cookie_name) {\n    if (document.cookie.indexOf(cookie_name) !== -1) {\n      var cookieRegex = new RegExp(cookie_name + '\\=([^;]*)');\n      var cookie = Misago.get(document.cookie.match(cookieRegex), 0);\n      return cookie.split('=')[1];\n    } else {\n      return null;\n    }\n  };\n\n  var Ajax = function(_) {\n    this.refreshCsrfToken = function() {\n      this.csrfToken = getCsrfToken(_.context.CSRF_COOKIE_NAME);\n    };\n    this.refreshCsrfToken();\n\n    /*\n      List of GETs underway\n      We are limiting number of GETs to API to 1 per url\n    */\n    var runningGets = {};\n\n    this.ajax = function(method, url, data, progress) {\n      var promise = m.deferred();\n\n      var ajax_settings = {\n        url: url,\n        method: method,\n        headers: {\n          'X-CSRFToken': this.csrfToken\n        },\n\n        data: data || {},\n        dataType: 'json',\n\n        success: function(data) {\n          if (method === 'GET') {\n            Misago.pop(runningGets, url);\n          }\n          promise.resolve(data);\n        },\n        error: function(jqXHR) {\n          if (method === 'GET') {\n            Misago.pop(runningGets, url);\n          }\n\n          var rejection = jqXHR.responseJSON || {};\n\n          rejection.status = jqXHR.status;\n          rejection.statusText = jqXHR.statusText;\n\n          promise.reject(rejection);\n        }\n      };\n\n      if (progress) {\n        return; // not implemented... yet!\n      }\n\n      $.ajax(ajax_settings);\n      return promise.promise;\n    };\n\n    this.get = function(url) {\n      var preloaded = Misago.pop(_.context, url);\n      if (preloaded) {\n        var deferred = m.deferred();\n        deferred.resolve(preloaded);\n        return deferred.promise;\n      } else if (runningGets[url] !== undefined) {\n        return runningGets[url];\n      } else {\n        runningGets[url] = this.ajax('GET', url);\n        return runningGets[url];\n      }\n    };\n\n    this.post = function(url, data) {\n      return this.ajax('POST', url, data);\n    };\n\n    this.patch = function(url, data) {\n      return this.ajax('PATCH', url, data);\n    };\n\n    this.put = function(url, data) {\n      return this.ajax('PUT', url, data);\n    };\n\n    this.delete = function(url) {\n      return this.ajax('DELETE', url);\n    };\n  };\n\n  Misago.addService('ajax', function(_) {\n    return new Ajax(_);\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var ALERT_BASE_DISPLAY_TIME = 5 * 1000;\n  var ALERT_LENGTH_FACTOR = 70;\n  var ALERT_MAX_DISPLAY_TIME = 9 * 1000;\n  var ALERT_HIDE_ANIMATION_LENGTH = 300;\n\n  var Alert = function(_) {\n    var self = this;\n\n    this.type = '';\n    this.message = null;\n    this.isVisible = false;\n\n    var show = function(type, message) {\n      self.type = type;\n      self.message = message;\n      self.isVisible = true;\n\n      var displayTime = ALERT_BASE_DISPLAY_TIME;\n      displayTime += message.length * ALERT_LENGTH_FACTOR;\n      if (displayTime > ALERT_MAX_DISPLAY_TIME) {\n        displayTime = ALERT_MAX_DISPLAY_TIME;\n      }\n\n      _.runloop.runOnce(function () {\n        m.startComputation();\n        self.isVisible = false;\n        m.endComputation();\n      }, 'flash-message-hide', displayTime);\n    };\n\n    var set = function(type, message) {\n      _.runloop.stop('flash-message-hide');\n      _.runloop.stop('flash-message-show');\n\n      if (self.isVisible) {\n        self.isVisible = false;\n        _.runloop.runOnce(function () {\n          m.startComputation();\n          show(type, message);\n          m.endComputation();\n        }, 'flash-message-show', ALERT_HIDE_ANIMATION_LENGTH);\n      } else {\n        show(type, message);\n      }\n    };\n\n    this.info = function(message) {\n      set('info', message);\n    };\n\n    this.success = function(message) {\n      set('success', message);\n    };\n\n    this.warning = function(message) {\n      set('warning', message);\n    };\n\n    this.error = function(message) {\n      set('error', message);\n    };\n  };\n\n  Misago.addService('alert', {\n    factory: function(_) {\n      return new Alert(_);\n    }\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var filtersUrl = function(filters) {\n    if (typeof filters === 'object') {\n      var values = [];\n      for (var key in filters) {\n        if (filters.hasOwnProperty(key)) {\n          var encodedKey = encodeURIComponent(key);\n          var encodedValue = encodeURIComponent(filters[key]);\n          values.push(encodedKey + '=' + encodedValue);\n        }\n      }\n      return '?' + values.join('&');\n    } else {\n      return filters + '/';\n    }\n  };\n\n  var Query = function(_, call) {\n    this.url = call.url || _.setup.api;\n\n    if (call.path) {\n      this.url += call.path + '/';\n    } else if (call.related) {\n      this.url += call.related + '/';\n    } else {\n      this.url += call.model + 's' + '/';\n    }\n\n    if (call.filters) {\n      this.url += filtersUrl(call.filters);\n    }\n\n    if (call.model) {\n      this.related = function(model, filters) {\n        return new Query(_, {\n          url: this.url,\n          relation: call.model,\n          related: model,\n          filters: filters,\n        });\n      };\n    }\n\n    this.endpoint = function(path, filters) {\n      return new Query(_, {\n        url: this.url,\n        path: path,\n        filters: filters\n      });\n    };\n\n    this.get = function() {\n      var model = null;\n      if (call.related) {\n        model = call.relation + ':' + call.related;\n      } else if (call.model) {\n        model = call.model;\n      }\n\n      return _.ajax.get(this.url).then(function(data) {\n        if (model) {\n          if (data.results) {\n            data.results.map(function(item) {\n              return _.models.new(model, item);\n            });\n            return data;\n          } else {\n            return _.models.new(model, data);\n          }\n        } else {\n          return data;\n        }\n      });\n    };\n\n    this.post = function(data) {\n      return _.ajax.post(this.url, data);\n    };\n\n    this.patch = function(data) {\n      return _.ajax.patch(this.url, data);\n    };\n\n    this.put = function(data) {\n      return _.ajax.put(this.url, data);\n    };\n\n    this.delete = function() {\n      return _.ajax.delete(this.url);\n    };\n\n    // shortcut for get()\n    this.then = function(resolve, reject) {\n      return this.get().then(resolve, reject);\n    };\n  };\n\n  var Api = function(_) {\n    this.model = function(model, filters) {\n      return new Query(_, {\n        model: model,\n        filters: filters,\n      });\n    };\n\n    this.endpoint = function(path, filters) {\n      return new Query(_, {\n        path: path,\n        filters: filters\n      });\n    };\n\n    this.alert = function(rejection) {\n      // Shorthand for API errors\n      var message = gettext(\"Unknown error has occured.\");\n\n      if (rejection.status === 0) {\n        message = gettext(\"Lost connection with application.\");\n      }\n\n      if (rejection.status === 403) {\n        message = rejection.detail;\n        if (message === \"Permission denied\") {\n          message = gettext(\n            \"You don't have permission to perform this action.\");\n        }\n      }\n\n      if (rejection.status === 404) {\n        message = gettext(\"Action link is invalid.\");\n      }\n\n      _.alert.error(message);\n    };\n  };\n\n  Misago.addService('api', function(_) {\n    return new Api(_);\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var Auth = function(_) {\n    var self = this;\n\n    _.user = _.models.deserialize('user', _.context.user);\n\n    // Auth state synchronization across tabs\n    this.isDesynced = false; // becomes true if auth state between tabs differs\n    this.newUser = null; // becomes user obj to which we want to sync\n\n    var handleAuthChange = function(isAuthenticated) {\n      if (!self.isDesynced) {\n        m.startComputation();\n\n        // display annoying \"you were desynced\" message\n        self.isDesynced = true;\n\n        if (isAuthenticated) {\n          self.newUser = _.localstore.get('auth-user');\n        }\n\n        m.endComputation();\n      }\n    };\n\n    var handleUserChange = function(newUser) {\n      if (!self.isDesynced) {\n        m.startComputation();\n\n        if (_.user.id !== newUser.id) {\n          self.isDesynced = true;\n          self.newUser = newUser;\n        } else if (newUser) {\n          _.user = $.extend(_.user, newUser);\n        }\n\n        m.endComputation();\n      }\n    };\n\n    var syncSession = function() {\n      _.localstore.set('auth-user', _.user);\n      _.localstore.set('auth-is-authenticated', _.user.isAuthenticated);\n\n      _.localstore.watch('auth-is-authenticated', handleAuthChange);\n      _.localstore.watch('auth-user', handleUserChange);\n    };\n\n    syncSession();\n\n    // Access controls\n    this.denyAuthenticated = function(message) {\n      if (_.user.isAuthenticated) {\n        throw new Misago.PermissionDenied(\n          message || gettext(\"This page is not available to signed in users.\"));\n      }\n    };\n\n    this.denyAnonymous = function(message) {\n      if (_.user.isAnonymous) {\n        throw new Misago.PermissionDenied(\n          message || gettext(\"This page is not available to guests.\"));\n      }\n    };\n  };\n\n  Misago.addService('auth',\n  function(_) {\n    return new Auth(_);\n  },\n  {\n    after: 'model:user'\n  });\n}(Misago.prototype));\n\n/* global grecaptcha */\n(function (Misago) {\n  'use strict';\n\n  var NoCaptcha = function() {\n    var deferred = m.deferred();\n    deferred.resolve();\n\n    this.load = function() {\n      return deferred.promise;\n    };\n\n    this.value = function() {\n      return null;\n    };\n  };\n\n  var QACaptcha = function(_) {\n    var self = this;\n\n    this.loading = false;\n    this.question = null;\n    this.value = m.prop('');\n\n    var deferred = m.deferred();\n    this.load = function() {\n      this.value('');\n\n      if (!this.question && !this.loading) {\n        this.loading = true;\n\n        _.api.endpoint('captcha-question').get().then(function(question) {\n          self.question = question;\n          deferred.resolve();\n        }, function() {\n          _.api.alert(gettext('Failed to load CAPTCHA.'));\n          deferred.reject();\n        }).then(function() {\n          self.loading = true;\n        });\n      }\n\n      return deferred.promise;\n    };\n\n    this.component = function(kwargs) {\n      return _.component('form-group', {\n        label: this.question.question,\n        labelClass: kwargs.labelClass || null,\n        controlClass: kwargs.controlClass || null,\n        control: _.input({\n          value: _.validate(kwargs.form, 'captcha'),\n          id: 'id_captcha',\n          disabled: kwargs.form.isBusy\n        }),\n        validation: kwargs.form.errors,\n        validationKey: 'captcha',\n        helpText: this.question.help_text\n      });\n    };\n\n    this.validator = function() {\n      return [];\n    };\n  };\n\n  var ReCaptcha = function(_) {\n    this.included = false;\n    this.question = null;\n\n    var deferred = m.deferred();\n\n    var wait = function(promise) {\n      if (typeof grecaptcha !== \"undefined\") {\n        promise.resolve();\n      } else {\n        _.runloop.runOnce(function() {\n          wait(promise);\n        }, 'loading-grecaptcha', 150);\n      }\n    };\n\n    this.load = function() {\n      if (typeof grecaptcha !== \"undefined\") {\n        grecaptcha.reset();\n      }\n\n      if (!this.included) {\n        _.include('https://www.google.com/recaptcha/api.js', true);\n        this.included = true;\n      }\n\n      wait(deferred);\n\n      return deferred.promise;\n    };\n\n    var controlConfig = function(el, isInit, context) {\n      context.retain = true;\n\n      if (!isInit) {\n        grecaptcha.render('recaptcha', {\n          'sitekey': _.settings.recaptcha_site_key\n        });\n      }\n    };\n\n    this.component = function(kwargs) {\n      var control = m('#recaptcha', {\n        config: controlConfig\n      });\n\n      return _.component('form-group', {\n        label: gettext(\"Security test\"),\n        labelClass: kwargs.labelClass || null,\n        controlClass: kwargs.controlClass || null,\n        control: control,\n        validation: kwargs.form.errors,\n        validationKey: 'captcha'\n      });\n    };\n\n    this.value = function() {\n      if (typeof grecaptcha !== \"undefined\") {\n        return grecaptcha.getResponse();\n      } else {\n        return '';\n      }\n    };\n\n    this.clean = function(form) {\n      if (!this.value()) {\n        form.errors.captcha = [\n          gettext('This field is required.')\n        ];\n      } else {\n        form.errors.captcha = true;\n      }\n    };\n\n    this.validator = function() {\n      return [];\n    };\n  };\n\n  var Captcha = function(_) {\n    var types = {\n      'no': NoCaptcha,\n      'qa': QACaptcha,\n      're': ReCaptcha\n    };\n\n    var captcha = new types[_.settings.captcha_type](_);\n\n    this.value = captcha.value;\n\n    this.load = function() {\n      return captcha.load();\n    };\n\n    this.component = function(kwargs) {\n      if (captcha.component) {\n        return captcha.component(kwargs);\n      } else {\n        return null;\n      }\n    };\n\n    this.validator = function() {\n      if (captcha.validator) {\n        return captcha.validator();\n      } else {\n        return null;\n      }\n    };\n\n    this.clean = function(form) {\n      if (captcha.clean) {\n        captcha.clean(form);\n      } else {\n        form.errors.captcha = true;\n      }\n    };\n  };\n\n  Misago.addService('captcha', function(_) {\n    return new Captcha(_);\n  },\n  {\n    after: 'include'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var component = function(name, component) {\n    if (this._components[name]) {\n      if (arguments.length > 1) {\n        var argumentsArray = [this._components[name]];\n        for (var i = 1; i < arguments.length; i += 1) {\n          argumentsArray.push(arguments[i]);\n        }\n        argumentsArray.push(this);\n        return m.component.apply(undefined, argumentsArray);\n      } else {\n        return m.component(this._components[name], this);\n      }\n    } else if (component) {\n      this._components[name] = component;\n    } else {\n      throw '\"' + name + '\" component is not registered and can\\'t be created';\n    }\n  };\n\n  Misago.addService('components', function(_) {\n    _._components = {};\n    _.component = component;\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.addService('conf', function(_) {\n    _.settings = Misago.get(_.context, 'SETTINGS', {});\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var dropdownConfig = function(element, isInit, context) {\n    if (!isInit) {\n      context.retain = true;\n\n      $(element).on('click', function() {\n        $(element).removeClass('open');\n      });\n\n      context.onunload = function() {\n        $(element).removeClass('open');\n        $(element).off();\n      };\n    }\n  };\n\n  var Dropdown = function(_) {\n    var slots = {};\n\n    this.slot = function(name) {\n      return m('#dropdown-' + name + '.dropdown.mobile-dropdown', {\n        config: dropdownConfig\n      });\n    };\n\n    this.toggle = function(slot, component) {\n      var element = document.getElementById('dropdown-' + slot);\n\n      if (element.hasChildNodes() && slots[slot] === component) {\n        slots[slot] = null;\n        m.mount(element, null);\n        $(element).removeClass('open');\n      } else {\n        slots[slot] = component;\n        m.mount(element, _.component(component));\n        $(element).addClass('open');\n      }\n    };\n  };\n\n  Misago.addService('dropdown', {\n    factory: function(_) {\n      return new Dropdown(_);\n    }\n  },\n  {\n    before: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var boilerplate = function(form) {\n    var _submit = form.submit;\n    var _success = form.success;\n    var _error = form.error;\n\n    form.isBusy = false;\n\n    form.errors = null;\n\n    form.submit = function() {\n      if (form.isBusy) {\n        return false;\n      }\n\n      if (form.clean) {\n        if (form.clean()) {\n          form.isBusy = true;\n          _submit.apply(form);\n        }\n      } else {\n        form.isBusy = true;\n      }\n      return false;\n    };\n\n    form.success = function() {\n      m.startComputation();\n\n      _success.apply(form, arguments);\n      form.isBusy = false;\n\n      m.endComputation();\n    };\n\n    form.error = function() {\n      m.startComputation();\n\n      _error.apply(form, arguments);\n      form.isBusy = false;\n\n      m.endComputation();\n    };\n\n    form.hasErrors = function() {\n      if (form.errors === null) {\n        return false;\n      }\n\n      for (var key in form.validation) {\n        if (form.validation.hasOwnProperty(key)) {\n          if (form.errors[key] !== true) {\n            return true;\n          }\n        }\n      }\n\n      return false;\n    };\n\n    return form;\n  };\n\n  var form = function(name, constructor) {\n    if (this._forms[name]) {\n      if (constructor) {\n        return boilerplate(new this._forms[name](constructor, this));\n      } else {\n        return boilerplate(new this._forms[name](this));\n      }\n    } else {\n      this._forms[name] = constructor;\n    }\n  };\n\n  Misago.addService('forms', function(_) {\n    _._forms = {};\n    _.form = form;\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.addService('forum-layout', {\n    factory: function(_) {\n      if (_.setup.fixture) {\n        m.mount(document.getElementById(_.setup.fixture),\n                _.component('forum-layout'));\n      }\n    },\n\n    destroy: function(_) {\n      if (_.setup.fixture) {\n        m.mount(document.getElementById(_.setup.fixture), null);\n      }\n    }\n  },\n  {\n    before: 'start-routing'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var include = function(script, remote) {\n    if (!remote) {\n      script = this.context.STATIC_URL + script;\n    }\n\n    $.ajax({\n      url: script,\n      cache: true,\n      dataType: 'script'\n    });\n  };\n\n  Misago.addService('include', function(_) {\n    _.include = include;\n  },\n  {\n    after: 'conf'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var LocalStore = function() {\n    var storage = window.localStorage;\n    var prefix = '_misago_';\n    var watchers = [];\n\n    var handleStorageEvent = function(e) {\n      var newValueJson = JSON.parse(e.newValue);\n      $.each(watchers, function(i, watcher) {\n        if (watcher.keyName === e.key && e.oldValue !== e.newValue) {\n          watcher.callback(newValueJson);\n        }\n      });\n    };\n\n    window.addEventListener('storage', handleStorageEvent);\n\n    var prefixKey = function(keyName) {\n      return prefix + keyName;\n    };\n\n    this.set = function(keyName, value) {\n      storage.setItem(prefixKey(keyName), JSON.stringify(value));\n    };\n\n    this.get = function(keyName) {\n      var itemString = storage.getItem(prefixKey(keyName));\n      if (itemString) {\n        return JSON.parse(itemString);\n      } else {\n        return null;\n      }\n    };\n\n    this.watch = function(keyName, callback) {\n      watchers.push({keyName: prefixKey(keyName), callback: callback});\n    };\n\n    this.destroy = function() {\n      this.watchers = [];\n    };\n  };\n\n  Misago.addService('localstore', {\n    factory: function() {\n      return new LocalStore();\n    },\n    destroy: function(_) {\n      _.localstore.destroy();\n    }\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var Modal = function() {\n    var self = this;\n\n    var element = document.getElementById('misago-modal');\n\n    // href clicks within modal should close it\n    var delegateName = 'click.misago-modal';\n    $(element).on(delegateName, 'a', function() {\n      self.hide();\n    });\n\n    this.destroy = function() {\n      $(element).off();\n      $('body').removeClass('modal-open');\n      $('.modal-backdrop').remove();\n    };\n\n    // Open/close modal\n    var modal = $(element).modal({show: false});\n    this.open = false;\n\n    modal.on('hidden.bs.modal', function () {\n      if (self.open) {\n        m.mount(element, null);\n        this.open = false;\n      }\n    });\n\n    this.show = function(component) {\n      this.open = true;\n      m.mount(element, component);\n      modal.modal('show');\n    };\n\n    this.hide = function() {\n      modal.modal('hide');\n    };\n  };\n\n  Misago.addService('_modal', {\n    factory: function() {\n      return new Modal();\n    },\n    destroy: function(_) {\n      _._modal.destroy();\n    }\n  },\n  {\n    after: 'start-routing'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var modal = function(name, component) {\n    if (this._modals[name]) {\n      var argumentsArray = [this._modals[name]];\n      for (var i = 1; i < arguments.length; i += 1) {\n        argumentsArray.push(arguments[i]);\n      }\n      argumentsArray.push(this);\n      this._modal.show(m.component.apply(m, argumentsArray));\n    } else if (name) {\n      this._modals[name] = component;\n    } else {\n      this._modal.hide();\n    }\n  };\n\n  Misago.addService('modals', function(_) {\n    _._modals = {};\n    _.modal = modal;\n  },\n  {\n    after: '_modal'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var Models = function() {\n    this.classes = {};\n    this.deserializers = {};\n\n    this.add = function(name, kwargs) {\n      if (kwargs.class) {\n        this.classes[name] = kwargs.class;\n      }\n\n      if (kwargs.deserialize) {\n        this.deserializers[name] = kwargs.deserialize;\n      }\n    };\n\n    this.new = function(name, data) {\n      if (this.classes[name]) {\n        // Coerce ID to string\n        // This is done to avoid type comparisions gotchas\n        // later into app\n        data.id = data.id ? String(data.id) : null;\n\n        return new this.classes[name](data);\n      } else {\n        return data;\n      }\n    };\n\n    this.deserialize = function(name, json) {\n      if (this.deserializers[name]) {\n        return this.new(name, this.deserializers[name](json, this));\n      } else {\n        return this.new(name, json);\n      }\n    };\n  };\n\n  Misago.addService('models', function() {\n    return new Models();\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.addService('set-momentjs-locale', function() {\n    moment.locale($('html').attr('lang'));\n  });\n}(Misago.prototype));\n\n\n(function (Misago) {\n  'use strict';\n\n  var Router = function(_) {\n    var self = this;\n    this.baseUrl = $('base').attr('href');\n\n    var staticUrl = Misago.get(_.context, 'STATIC_URL', '/');\n    var mediaUrl = Misago.get(_.context, 'MEDIA_URL', '/');\n\n    // Routing\n    this.urls = {};\n    this.reverses = {};\n\n    var populatePatterns = function(urlconf) {\n      urlconf.patterns().forEach(function(url) {\n        var finalPattern = self.baseUrl + url.pattern;\n        finalPattern = finalPattern.replace('//', '/');\n\n        self.urls[finalPattern] = _.route(url.component);\n        self.reverses[url.name] = finalPattern;\n      });\n    };\n\n    this.startRouting = function(urlconf, fixture) {\n      populatePatterns(urlconf);\n      this.fixture = fixture;\n\n      if (_.setup.test) {\n        m.route.mode = 'search';\n      } else {\n        m.route.mode = 'pathname';\n      }\n\n      m.route(fixture, '/', this.urls);\n    };\n\n    this.url = function(name) {\n      return this.reverses[name];\n    };\n\n    this.route = function(url) {\n      m.route(url);\n    };\n\n    this.redirect = function(name) {\n      this.route(this.url(name));\n    };\n\n    // Delegate clicks\n    this.delegateElement = null;\n\n    this.cleanUrl = function(url) {\n      if (!url) { return; }\n\n      // Is link relative?\n      var isRelative = url.substr(0, 1) === '/' && url.substr(0, 2) !== '//';\n\n      // If link contains host, validate to see if its outgoing\n      if (!isRelative) {\n        var location = window.location;\n\n        // If protocol matches current one, strip it from string\n        // otherwhise stop handler\n        if (url.substr(0, 2) !== '//') {\n          var protocol = url.substr(0, location.protocol.length + 2);\n          if (protocol !== location.protocol + '//') { return; }\n          url = url.substr(location.protocol.length + 2);\n        } else {\n          url = url.substr(2);\n        }\n\n        // Host checks out?\n        if (url.substr(0, location.host.length) !== location.host) { return; }\n        url = url.substr(location.host.length);\n      }\n\n      // Is link within JS app?\n      if (url.substr(0, this.baseUrl.length) !== this.baseUrl) { return; }\n\n      // Is link to media/static/avatar server?\n      if (url.substr(0, staticUrl.length) === staticUrl) { return; }\n\n      if (url.substr(0, mediaUrl.length) === mediaUrl) { return; }\n\n      var avatarsUrl = '/user-avatar/';\n      if (url.substr(0, avatarsUrl.length) === avatarsUrl) { return; }\n\n      return url;\n    };\n\n    var delegateName = 'click.misago-router';\n    var delegateSelector = 'a:not([data-misago-routed=\"false\"])';\n\n    this.delegateClicks = function(element) {\n      this.delegateElement = element;\n      $(this.delegateElement).on(delegateName, delegateSelector, function(e) {\n        var cleanUrl = self.cleanUrl(e.currentTarget.href);\n        if (cleanUrl) {\n          if (cleanUrl != m.route()) {\n            self.route(cleanUrl);\n          }\n          e.preventDefault();\n        }\n      });\n    };\n\n    this.destroy = function() {\n      $(this.delegateElement).off(delegateName);\n    };\n\n    // Media/Static url\n    var prefixUrl = function(prefix) {\n      return function(url) {\n        return prefix + url;\n      };\n    };\n\n    this.staticUrl = prefixUrl(staticUrl);\n    this.mediaUrl = prefixUrl(mediaUrl);\n\n    // Errors\n    this.error403 = function(error) {\n      var component = null;\n      if (error.ban) {\n        component = _.route('error:banned',\n          error.detail,\n          _.models.deserialize('ban', error.ban));\n      } else {\n        component = _.route('error:403', error.detail);\n      }\n      m.mount(this.fixture, component);\n    };\n\n    this.error404 = function() {\n      m.mount(this.fixture, _.route('error:404'));\n    };\n\n    this.error500 = function() {\n      m.mount(this.fixture, _.route('error:500'));\n    };\n\n    this.error0 = function() {\n      m.mount(this.fixture, _.route('error:0'));\n    };\n\n    this.errorPage = function(error) {\n      if (error.status === 0) {\n        this.error0();\n      }\n\n      if (error.status === 500) {\n        this.error500();\n      }\n\n      if (error.status === 404) {\n        this.error404();\n      }\n\n      if (error.status === 403) {\n        this.error403(error);\n      }\n    };\n  };\n\n  Misago.addService('router', function(_) {\n    return new Router(_);\n  });\n\n  Misago.addService('start-routing', function(_) {\n    // In edge cases layout gets rendered in same frame routing starts\n    // which causes getElementById to return null and crash Mithril.js\n    var waitForFixture = function() {\n      var fixture = document.getElementById('router-fixture');\n      if (fixture) {\n        _.router.startRouting(\n          Misago.urls, document.getElementById('router-fixture'));\n        _.router.delegateClicks(document.getElementById(_.setup.fixture));\n      } else {\n        window.setTimeout(function() {\n          waitForFixture();\n        }, 10);\n      }\n    };\n    waitForFixture();\n  },\n  {\n    before: '_end'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var boilerplate = function(component) {\n    // Component already boilerplated (this may happen in tests)\n    if (component._hasRouteBoilerplate) {\n      return component;\n    }\n    component._hasRouteBoilerplate = true;\n\n    // Add lifecycle hooks\n    var loadingView = function () {\n      var _ = this.container;\n      return m('.page.page-loading',\n        _.component('loader')\n      );\n    };\n\n    var errorHandler = function(error) {\n      if (this.isActive && typeof error.status !== \"undefined\") {\n        if (this.vm && this.vm.onerror) {\n          this.vm.onerror(error, this.container);\n        } else {\n          this.container.router.errorPage(error);\n        }\n      } else {\n        throw error;\n      }\n    };\n\n    return Misago.stateHooks(component, loadingView, errorHandler);\n  };\n\n  Misago.addService('routes', function(_) {\n    _._routes = {};\n    _.route = function(name, component) {\n      if (this._routes[name]) {\n        if (arguments.length > 1) {\n          var argumentsArray = [this._routes[name]];\n          for (var i = 1; i < arguments.length; i += 1) {\n            argumentsArray.push(arguments[i]);\n          }\n          argumentsArray.push(this);\n          return m.component.apply(undefined, argumentsArray);\n        } else {\n          return m.component(this._routes[name], this);\n        }\n      } else if (component) {\n        component.container = _;\n        this._routes[name] = boilerplate(component);\n      } else {\n        throw '\"' + name + '\" route is not registered and can\\'t be created';\n      }\n    };\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var RunLoop = function(_) {\n    var self = this;\n\n    this._intervals = {};\n\n    var stopInterval = function(name) {\n      if (self._intervals[name]) {\n        window.clearTimeout(self._intervals[name]);\n        self._intervals[name] = null;\n      }\n    };\n\n    this.run = function(callable, name, delay) {\n      this._intervals[name] = window.setTimeout(function() {\n        stopInterval(name);\n        var result = callable(_);\n        if (result !== false) {\n          self.run(callable, name, delay);\n        }\n      }, delay);\n    };\n\n    this.runOnce = function(callable, name, delay) {\n      this._intervals[name] = window.setTimeout(function() {\n        stopInterval(name);\n        callable(_);\n      }, delay);\n    };\n\n    this.stop = function(name) {\n      for (var loop in this._intervals) {\n        if (!name || name === loop) {\n          stopInterval(loop);\n        }\n      }\n    };\n  };\n\n  Misago.addService('runloop', {\n    factory: function(_) {\n      return new RunLoop(_);\n    },\n    destroy: function(_) {\n      _.runloop.stop();\n    }\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  Misago.addService('start-tick', function(_) {\n    var ticks = m.prop();\n\n    _.runloop.run(function() {\n      m.startComputation();\n      // just tick once a minute so stuff gets rerendered\n      ticks(ticks() + 1);\n      // syncing dynamic timestamps, etc ect\n      m.endComputation();\n    }, 'tick', 60000);\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var PageTitle = function(forum_name) {\n    this.set = function(title) {\n      if (title) {\n        this._set_complex(title);\n      } else {\n        document.title = forum_name;\n      }\n    };\n\n    this._set_complex = function(title) {\n      if (typeof title === 'string') {\n        title = {title: title};\n      }\n\n      var completeTitle = title.title;\n\n      if (typeof title.page !== 'undefined' && title.page > 1) {\n        var page_label = interpolate(\n          gettext('page %(page)s'), { page:title.page }, true);\n        completeTitle += ' (' + page_label + ')';\n      }\n\n      if (typeof title.parent !== 'undefined') {\n        completeTitle += ' | ' + title.parent;\n      }\n\n      document.title = completeTitle + ' | ' + forum_name;\n    };\n  };\n\n  Misago.addService('page-title', function(_) {\n    _.title = new PageTitle(_.settings.forum_name);\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var EMAIL = /^(([^<>()[\\]\\.,;:\\s@\\\"]+(\\.[^<>()[\\]\\.,;:\\s@\\\"]+)*)|(\\\".+\\\"))@(([^<>()[\\]\\.,;:\\s@\\\"]+\\.)+[^<>()[\\]\\.,;:\\s@\\\"]{2,})$/i;\n  var USERNAME = new RegExp('^[0-9a-z]+$', 'i');\n\n  // Validators namespace\n  Misago.validators = {\n    required: function() {\n      return function(value) {\n        if ($.trim(value).length === 0) {\n          return gettext(\"This field is required.\");\n        }\n      };\n    },\n    email: function(message) {\n      return function(value) {\n        if (!EMAIL.test(value)) {\n          return message || gettext(\"Enter a valid email address.\");\n        }\n      };\n    },\n    minLength: function(limit_value, message) {\n      return function(value) {\n        var returnMessage = '';\n        var length = $.trim(value).length;\n\n        if (length < limit_value) {\n          if (message) {\n            returnMessage = message(limit_value, length);\n          } else {\n            returnMessage = ngettext(\n              \"Ensure this value has at least %(limit_value)s character (it has %(show_value)s).\",\n              \"Ensure this value has at least %(limit_value)s characters (it has %(show_value)s).\",\n              limit_value);\n          }\n          return interpolate(returnMessage, {\n            limit_value: limit_value,\n            show_value: length\n          }, true);\n        }\n      };\n    },\n    maxLength: function(limit_value, message) {\n      return function(value) {\n        var returnMessage = '';\n        var length = $.trim(value).length;\n\n        if (length > limit_value) {\n          if (message) {\n            returnMessage = message(limit_value, length);\n          } else {\n            returnMessage = ngettext(\n              \"Ensure this value has at most %(limit_value)s character (it has %(show_value)s).\",\n              \"Ensure this value has at most %(limit_value)s characters (it has %(show_value)s).\",\n              limit_value);\n          }\n          return interpolate(returnMessage, {\n            limit_value: limit_value,\n            show_value: length\n          }, true);\n        }\n      };\n    },\n    usernameMinLength: function(settings) {\n      var message = function(limit_value) {\n        return ngettext(\n          \"Username must be at least %(limit_value)s character long.\",\n          \"Username must be at least %(limit_value)s characters long.\",\n          limit_value);\n      };\n      return this.minLength(settings.username_length_min, message);\n    },\n    usernameMaxLength: function(settings) {\n      var message = function(limit_value) {\n        return ngettext(\n          \"Username cannot be longer than %(limit_value)s character.\",\n          \"Username cannot be longer than %(limit_value)s characters.\",\n          limit_value);\n      };\n      return this.maxLength(settings.username_length_max, message);\n    },\n    usernameContent: function() {\n      return function(value) {\n        if (!USERNAME.test($.trim(value))) {\n          return gettext(\"Username can only contain latin alphabet letters and digits.\");\n        }\n      };\n    },\n    passwordMinLength: function(settings) {\n      var message = function(limit_value) {\n        return ngettext(\n          \"Valid password must be at least %(limit_value)s character long.\",\n          \"Valid password must be at least %(limit_value)s characters long.\",\n          limit_value);\n      };\n      return this.minLength(settings.password_length_min, message);\n    }\n  };\n\n  var validateField = function(value, validators) {\n    var result = Misago.validators.required()(value);\n    var errors = [];\n\n    if (result) {\n      return [result];\n    } else {\n      for (var i in validators) {\n        result = validators[i](value);\n\n        if (result) {\n          errors.push(result);\n        }\n      }\n    }\n\n    return errors.length ? errors : true;\n  };\n\n  var validateForm = function(form) {\n    var errors = {};\n    var value = null;\n\n    var isValid = true;\n\n    for (var key in form.validation) {\n      if (form.validation.hasOwnProperty(key)) {\n        value = form[key]();\n        errors[key] = validateField(form[key](), form.validation[key]);\n        if (errors[key] !== true) {\n          isValid = false;\n        }\n      }\n    }\n\n    form.errors = errors;\n    return isValid;\n  };\n\n  var validate = function(form, name) {\n    if (name) {\n      return function(value) {\n        var errors = null;\n        if (typeof value !== 'undefined') {\n          errors = validateField(value, form.validation[name]);\n          if (errors) {\n            if (!form.errors) {\n              form.errors = {};\n            }\n            form.errors[name] = errors;\n          }\n          form[name](value);\n          return form[name](value);\n        } else {\n          return form[name]();\n        }\n      };\n    } else {\n      return validateForm(form);\n    }\n  };\n\n  Misago.addService('validate', {\n    factory: function() {\n      return validate;\n    }\n  });\n}(Misago.prototype));\n\n/* global zxcvbn */\n(function (Misago) {\n  'use strict';\n\n  var Zxcvbn = function(_) {\n    this.included = false;\n\n    this.scorePassword = function(password, inputs) {\n      // 0-4 score, the more the stronger password\n      return zxcvbn(password, inputs).score;\n    };\n\n    // loading\n    this.include = function() {\n      _.include('misago/js/zxcvbn.js');\n      this.included = true;\n    };\n\n    var wait = function(promise) {\n      if (typeof zxcvbn !== \"undefined\") {\n        promise.resolve();\n      } else {\n        _.runloop.runOnce(function() {\n          wait(promise);\n        }, 'loading-zxcvbn', 150);\n      }\n    };\n\n    var deferred = m.deferred();\n    this.load = function() {\n      if (!this.included) {\n        this.include();\n      }\n      wait(deferred);\n      return deferred.promise;\n    };\n  };\n\n  Misago.addService('zxcvbn', function(_) {\n    return new Zxcvbn(_);\n  },\n  {\n    after: 'include'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var Ban = function(data) {\n    this.message = {\n      html: data.message.html,\n      plain: data.message.plain,\n    };\n\n    this.expires_on = data.expires_on;\n  };\n\n  var deserializeBan = function(data) {\n    data.expires_on = Misago.deserializeDatetime(data.expires_on);\n\n    return data;\n  };\n\n  Misago.addService('model:ban', function(_) {\n    _.models.add('ban', {\n      class: Ban,\n      deserialize: deserializeBan\n    });\n  },\n  {\n    after: 'models'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var LegalPage = function(data) {\n    this.title = data.title;\n    this.body = data.body;\n    this.link = data.link;\n  };\n\n  Misago.addService('model:legal-page', function(_) {\n    _.models.add('legal-page', {\n      class: LegalPage\n    });\n  },\n  {\n    after: 'models'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var Rank = function(data) {\n    this.id = data.id;\n\n    this.name = data.name;\n    this.slug = data.slug;\n\n    this.description = data.description;\n\n    this.title = data.title;\n    this.css_class = data.css_class;\n\n    this.is_tab = data.is_tab;\n  };\n\n  Misago.addService('model:rank', function(_) {\n    _.models.add('rank', {\n      class: Rank\n    });\n  },\n  {\n    after: 'models'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var User = function(data) {\n    this.id = data.id;\n\n    this.isAuthenticated = !!this.id;\n    this.isAnonymous = !this.isAuthenticated;\n\n    this.username = data.username;\n    this.slug = data.slug;\n\n    this.email = data.email;\n\n    this.full_title = data.full_title;\n    this.rank = data.rank;\n\n    this.avatar_hash = data.avatar_hash;\n\n    this.acl = data.acl;\n  };\n\n  var deserializeUser = function(data, models) {\n    if (data.joined_on) {\n      data.joined_on = Misago.deserializeDatetime(data.joined_on);\n    }\n\n    if (data.rank) {\n      data.rank = models.deserialize('rank', data.rank);\n    }\n\n    return data;\n  };\n\n  Misago.addService('model:user', function(_) {\n    _.models.add('user', {\n      class: User,\n      deserialize: deserializeUser\n    });\n  },\n  {\n    after: 'model:rank'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var forum = {\n    view: function(ctrl, _) {\n      return m('', [\n        _.component('header', {\n          title: gettext(\"Options\")\n        }),\n        m('.container',\n          m('p', 'Lorem ipsum dolor met.')\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('component:options:nav:dropdown', function(_) {\n    _.component('options:nav:dropdown', forum);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var email = {\n    controller: function(_) {\n      _.auth.denyAnonymous(\n        gettext(\"You have to be signed in to change your options.\"));\n\n      this.container.title.set({\n        title: gettext(\"E-mail\"),\n        parent: gettext(\"Options\")\n      });\n    },\n    view: function(ctrl, _) {\n      return m('.page.page-options.page-forum-options', [\n        _.component('header', {\n          title: gettext(\"Change options\")\n        }),\n        m('.container',\n          m('p', 'Lorem ipsum dolor met.')\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('route:options:email', function(_) {\n    _.route('options-email', email);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var forum = {\n    controller: function(_) {\n      _.auth.denyAnonymous(\n        gettext(\"You have to be signed in to change your options.\"));\n\n      this.container.title.set({\n        title: gettext(\"Forum options\"),\n        parent: gettext(\"Options\")\n      });\n    },\n    view: function(ctrl, _) {\n      return m('.page.page-options.page-forum-options', [\n        _.component('header', {\n          title: gettext(\"Options\")\n        }),\n        m('.container',\n          m('p', 'Lorem ipsum dolor met.')\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('route:options:forum', function(_) {\n    _.route('options-forum', forum);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var index = {\n    controller: function(_) {\n      _.auth.denyAnonymous(\n        gettext(\"You have to be signed in to change your options.\"));\n\n      _.router.redirect('options_forum');\n    }\n  };\n\n  Misago.addService('route:options', function(_) {\n    _.route('options', index);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var password = {\n    controller: function(_) {\n      _.auth.denyAnonymous(\n        gettext(\"You have to be signed in to change your options.\"));\n\n      this.container.title.set({\n        title: gettext(\"Password\"),\n        parent: gettext(\"Options\")\n      });\n    },\n    view: function(ctrl, _) {\n      return m('.page.page-options.page-forum-options', [\n        _.component('header', {\n          title: gettext(\"Change options\")\n        }),\n        m('.container',\n          m('p', 'Lorem ipsum dolor met.')\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('route:options:password', function(_) {\n    _.route('options-password', password);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var forum = {\n    view: function(ctrl, _) {\n      return m('.list-group.nav-side', [\n\n      ]);\n    }\n  };\n\n  Misago.addService('component:options:nav:side', function(_) {\n    _.component('options:nav:side', forum);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var viewModel = {\n    error: null,\n    username: null,\n    isReady: false,\n\n    init: function(_) {\n      this.error = null;\n      this.user = null;\n      this.isReady = false;\n\n      var endpoint = _.api.endpoint('auth').endpoint('activate-account');\n      endpoint = endpoint.endpoint(m.route.param('user_id'));\n      endpoint = endpoint.endpoint(m.route.param('token'));\n\n      return endpoint.post();\n    },\n    ondata: function(data, _) {\n      m.startComputation();\n\n      _.title.set(gettext(\"Account activated\"));\n\n      this.username = data.username;\n      this.isReady = true;\n\n      m.endComputation();\n    },\n    onerror: function(error, _) {\n      if (error.status === 400) {\n        m.startComputation();\n\n        this.error = error;\n        this.isReady = true;\n\n        m.endComputation();\n      } else {\n        _.router.errorPage(error);\n      }\n    }\n  };\n\n  var activateByToken = {\n    controller: function(_) {\n      _.auth.denyAuthenticated(\n        gettext(\"You have to be signed out to activate account.\"));\n\n      _.title.set(gettext(\"Account activation\"));\n      this.vm.init(_);\n    },\n    vm: viewModel,\n    view: function(ctrl, _) {\n      if (this.vm.error) {\n        return this.rejected(this.vm.error, _);\n      } else {\n        return this.success(this.vm.username, _);\n      }\n    },\n    success: function(username) {\n      var message = gettext(\"%(username)s, your account has been successfully activated!\");\n\n      return m('.page.page-message.page-message-success',\n        m('.container',\n          m('.message-panel', [\n            m('.message-icon',\n              m('span.material-icon', 'check')\n            ),\n            m('.message-body', [\n              m('p.lead',\n                interpolate(message, {\n                  username: username\n                }, true)\n              ),\n              m('p',\n                gettext('You can now sign in to finish setting up your account and to participate in or start new discussions.')\n              )\n            ])\n          ])\n        )\n      );\n    },\n    rejected: function(error) {\n      return m('.page.page-message.page-message-info',\n        m('.container',\n          m('.message-panel', [\n            m('.message-icon',\n              m('span.material-icon', 'info_outline')\n            ),\n            m('.message-body', [\n              m('p.lead',\n                gettext(\"Your account can't be activated at this time.\")\n              ),\n              m('p',\n                error.detail\n              )\n            ])\n          ])\n        )\n      );\n    },\n    loading: function(ctrl, _) {\n      return m('.page.page-loading', [\n        _.component('loader'),\n        m('p.lead', gettext(\"Activating account...\"))\n      ]);\n    }\n  };\n\n  Misago.addService('route:activate-by-token', function(_) {\n    _.route('activate-by-token', activateByToken);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var viewModel = {\n    error: null,\n    isReady: false,\n\n    form: null,\n\n    init: function(_) {\n      this.error = null;\n      this.user = null;\n      this.isReady = false;\n\n      var endpoint = _.api.endpoint('auth').endpoint('change-password');\n      endpoint = endpoint.endpoint(m.route.param('user_id'));\n      endpoint = endpoint.endpoint(m.route.param('token'));\n\n      return endpoint.get();\n    },\n    ondata: function(data, _) {\n      m.startComputation();\n\n      _.title.set(gettext(\"Change forgotten password\"));\n\n      this.form = _.form('change-password');\n      this.isReady = true;\n\n      m.endComputation();\n    },\n    onerror: function(error, _) {\n      if (error.status === 400) {\n        m.startComputation();\n\n        this.error = error;\n        this.isReady = true;\n\n        m.endComputation();\n      } else {\n        _.router.errorPage(error);\n      }\n    }\n  };\n\n  var changePassword = {\n    controller: function(_) {\n      this.vm.init(_);\n\n      return {\n        signin: function() {\n          _.modal('sign-in');\n        }\n      };\n    },\n    vm: viewModel,\n    view: function(ctrl, _) {\n      if (this.vm.error) {\n        return this.rejected(this.vm.error, _);\n      } else {\n        if (this.vm.form.username) {\n          return this.complete(ctrl, this.vm.form.username, _);\n        } else {\n          return this.form(this.vm.form, _);\n        }\n      }\n    },\n    form: function(form, _) {\n      return m('.page.page-change-password', [\n        _.component('header', {\n          title: gettext(\"Change forgotten password\")\n        }),\n        m('.container',\n          m('.row',\n            m('.col-md-4.col-md-offset-4',\n              m('.well.well-form',\n                m('form', {onsubmit: form.submit}, [\n                  m('.form-group',\n                    m('.control-input',\n                      Misago.input({\n                        disabled: form.isBusy,\n                        value: form.password,\n                        type: 'password',\n                        placeholder: gettext(\"Enter new password\")\n                      })\n                    )\n                  ),\n                  _.component('button', {\n                    class: '.btn-primary.btn-block',\n                    submit: true,\n                    loading: form.isBusy,\n                    label: gettext(\"Change password\")\n                  })\n                ])\n              )\n            )\n          )\n        )\n      ]);\n    },\n    complete: function(ctrl, username, _) {\n      var message = gettext(\"%(username)s, your password has been changed successfully.\");\n\n      return m('.page.page-message.page-message-success',\n        m('.container',\n          m('.message-panel', [\n            m('.message-icon',\n              m('span.material-icon', 'check')\n            ),\n            m('.message-body', [\n              m('p.lead',\n                interpolate(message, {\n                  username: username\n                }, true)\n              ),\n              m('p',\n                gettext(\"You can now sign in to your account using your new password.\")\n              ),\n              m('p',\n                _.component('button', {\n                  class: '.btn-default',\n                  submit: false,\n                  label: gettext(\"Sign in\"),\n                  onclick: ctrl.signin\n                })\n              )\n            ])\n          ])\n        )\n      );\n    },\n    rejected: function(error) {\n      return m('.page.page-message.page-message-info',\n        m('.container',\n          m('.message-panel', [\n            m('.message-icon',\n              m('span.material-icon', 'info_outline')\n            ),\n            m('.message-body', [\n              m('p.lead',\n                gettext(\"Your account can't be activated at this time.\")\n              ),\n              m('p',\n                error.detail\n              )\n            ])\n          ])\n        )\n      );\n    }\n  };\n\n  Misago.addService('route:change-password', function(_) {\n    _.route('change-password', changePassword);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var errorPage = function(error) {\n    var error_message = [\n      m('p.lead', error.message)\n    ];\n\n    if (error.help) {\n      error_message.push(m('p.help', error.help));\n    }\n\n    return m('.page.page-error.page-error-' + error.code,\n      m('.container',\n        m('.message-panel', [\n          m('.message-icon',\n            m('span.material-icon', error.icon)\n          ),\n          m('.message-body', error_message)\n        ])\n      )\n    );\n  };\n\n  var errorBanned = {\n    controller: function() {\n      this.container.title.set(gettext('You are banned'));\n    },\n    view: function(ctrl, message, ban) {\n      var error_message = [];\n\n      if (ban.message.html) {\n        error_message.push(m('.lead', m.trust(ban.message.html)));\n      } else if (message) {\n        error_message.push(m('p.lead', message));\n      } else {\n        error_message.push(m('p.lead', gettext('You are banned.')));\n      }\n\n      var expirationMessage = null;\n      if (ban.expires_on) {\n        if (ban.expires_on.isAfter(moment())) {\n          expirationMessage = interpolate(\n            gettext('This ban expires %(expires_on)s.'),\n            {'expires_on': ban.expires_on.fromNow()},\n            true);\n        } else {\n          expirationMessage = gettext('This ban has expired.');\n        }\n      } else {\n        expirationMessage = gettext('This ban is permanent.');\n      }\n      error_message.push(m('p', expirationMessage));\n\n      return m('.page.page-error.page-error-banned',\n        m('.container',\n          m('.message-panel', [\n            m('.message-icon',\n              m('span.material-icon', 'highlight_off')\n            ),\n            m('.message-body', error_message)\n          ])\n        )\n      );\n    }\n  };\n\n  var error403 = {\n    controller: function() {\n      this.container.title.set(gettext('Page not available'));\n    },\n    view: function(ctrl, message) {\n      if (message === \"Permission denied\") {\n        message = gettext(\"You don't have permission to access this page.\");\n      }\n\n      return errorPage({\n        code: 403,\n        icon: 'remove_circle_outline',\n        message: gettext(\"This page is not available.\"),\n        help: message\n      });\n    }\n  };\n\n  var error404 = {\n    controller: function() {\n      this.container.title.set(gettext('Page not found'));\n    },\n    view: function() {\n      return errorPage({\n        code: 404,\n        icon: 'info_outline',\n        message: gettext(\"Requested page could not be found.\"),\n        help: gettext(\"The link you followed was incorrect or the page has been moved or deleted.\")\n      });\n    }\n  };\n\n  var error500 = {\n    controller: function() {\n      this.container.title.set(gettext('Application error occured'));\n    },\n    view: function() {\n      return errorPage({\n        code: 500,\n        icon: 'error_outline',\n        message: gettext(\"Requested page could not be displayed due to an error.\"),\n        help: gettext(\"Please try again later or contact site staff if error persists.\")\n      });\n    }\n  };\n\n  var error0 = {\n    controller: function() {\n      this.container.title.set(gettext('Lost connection with application'));\n    },\n    view: function() {\n      return errorPage({\n        code: 0,\n        icon: 'sync_problem',\n        message: gettext(\"Could not connect to application.\"),\n        help: gettext(\"This may be caused by problems with your connection or application server. Please check your internet connection and refresh page if problem persists.\")\n      });\n    }\n  };\n\n  Misago.addService('route:error-pages', function(_) {\n    _.route('error:banned', errorBanned);\n    _.route('error:403', error403);\n    _.route('error:404', error404);\n    _.route('error:500', error500);\n    _.route('error:0', error0);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var index = {\n    controller: function(_) {\n      document.title = _.settings.forum_index_title || _.settings.forum_name;\n\n      return {\n        activation: function() {\n          _.router.url('request_activation');\n        }\n      };\n    },\n    view: function(ctrl, _) {\n      return m('.container', [\n        m('h1', 'Activation'),\n        m('p', 'Test auth blocks'),\n        m('p',\n          m('a', {href: _.router.url('request_activation')},\n            'Request activation.'\n          )\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('route:index', function(_) {\n    _.route('index', index);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var legalPageFactory = function(typeName, defaultTitle) {\n    var dashedTypeName = typeName.replace(/_/g, '-');\n\n    return {\n      controller: function(_) {\n        if (Misago.get(_.settings, typeName + '_link')) {\n          window.location = Misago.get(_.settings, typeName + '_link');\n        } else {\n          this.vm.init(this, _);\n        }\n      },\n      vm: {\n        page: null,\n        isReady: false,\n        init: function(component, _) {\n          if (this.isReady) {\n            _.title.set(this.title);\n          } else {\n            _.title.set();\n            return _.api.model('legal-page', dashedTypeName);\n          }\n        },\n        ondata: function(page, component, _) {\n          m.startComputation();\n\n          if (page.link) {\n            window.location = page.link;\n          } else {\n            page.title = page.title || defaultTitle;\n            this.page = page;\n            this.isReady = true;\n\n            m.endComputation();\n\n            if (component.isActive) {\n              _.title.set(this.page.title);\n            }\n          }\n        }\n      },\n      view: function(ctrl, _) {\n        return m('.page.page-legal.page-legal-' + dashedTypeName, [\n          _.component('header', {title: this.vm.page.title}),\n          m('.container',\n            _.component('markup', this.vm.page.body)\n          )\n        ]);\n      }\n    };\n  };\n\n  Misago.addService('route:legal-pages', function(_) {\n    _.route('terms-of-service', legalPageFactory(\n      'terms_of_service', gettext('Terms of service')));\n    _.route('privacy-policy', legalPageFactory(\n      'privacy_policy', gettext('Privacy policy')));\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var ViewModel = function() {\n    this.endpoint = 'send-activation';\n    this.user = null;\n\n    this.success = function(user) {\n      this.user = user;\n    };\n\n    this.error = function(rejection, _) {\n      if (rejection.code === 'already_active') {\n        _.alert.info(rejection.detail);\n        _.modal('sign-in');\n      } else if (rejection.code === 'inactive_admin') {\n        _.alert.info(rejection.detail);\n      } else {\n        _.alert.error(rejection.detail);\n      }\n    };\n\n    this.reset = function() {\n      this.user = null;\n    };\n  };\n\n  var requestActivation = {\n    controller: function(_) {\n      _.auth.denyAuthenticated(\n        gettext(\"You have to be signed out to activate account.\"));\n\n      _.title.set(gettext(\"Activate your account\"));\n\n      var vm = new ViewModel();\n\n      return {\n        vm: vm,\n        form: _.form('request-link', vm)\n      };\n    },\n    view: function(ctrl, _) {\n      if (ctrl.vm.user) {\n        return this.completed(ctrl.form, ctrl.vm, _);\n      } else {\n        return this.form(ctrl.form, _);\n      }\n    },\n    completed: function(form, vm, _) {\n      var message = gettext(\"%(username)s, we have sent your activation link to %(email)s.\");\n\n      return m('.page.page-message.page-message-success',\n        m('.container',\n          m('.message-panel', [\n            m('.message-icon',\n              m('span.material-icon', 'check')\n            ),\n            m('.message-body', [\n              m('p.lead',\n                gettext(\"Activation link has been sent.\")\n              ),\n              m('p',\n                interpolate(message, {\n                  username: vm.user.username,\n                  email: vm.user.email\n                }, true)\n              ),\n              m('p',\n                _.component('button', {\n                  class: '.btn-default',\n                  submit: false,\n                  label: gettext(\"Request another link\"),\n                  onclick: form.reset.bind(form)\n                })\n              )\n            ])\n          ])\n        )\n      );\n    },\n    form: function(form, _) {\n      return m('.page.page-request-activation', [\n        _.component('header', {\n          title: gettext(\"Request activation link\")\n        }),\n        m('.container',\n          m('.row', [\n            m('.col-md-8', [\n              m('p',\n                gettext(\"Site administrator may impose requirement on newly regitered accounts to be activated before users will be able to sign in.\")\n              ),\n              m('p',\n                gettext(\"Depending on time of registration, you will be able activate your account by clicking special activation link. This link will be valid only for your browser, for seven days or until your account is activated.\")\n              ),\n              m('p',\n                gettext(\"To receive this link, enter your account's e-mail addres in form and press \\\"Send link\\\" button.\")\n              )\n            ]),\n            m('.col-md-4',\n              _.component('request-link-form', form)\n            )\n          ])\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('route:request-activation', function(_) {\n    _.route('request-activation', requestActivation);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var ViewModel = function() {\n    this.endpoint = 'send-password-form';\n    this.user = null;\n\n    this.activation = null;\n    this.activationMessage = null;\n\n    this.success = function(user) {\n      this.user = user;\n    };\n\n    this.error = function(rejection, _) {\n      if (['inactive_user', 'inactive_admin'].indexOf(rejection.code) > -1) {\n        this.activation = rejection.code;\n        this.activationMessage = rejection.detail;\n      } else {\n        _.alert.error(rejection.detail);\n      }\n    };\n\n    this.reset = function() {\n      this.user = null;\n      this.activation = null;\n      this.activationMessage = null;\n    };\n  };\n\n  var requestPasswordChange = {\n    controller: function(_) {\n      _.title.set(gettext(\"Change forgotten password\"));\n\n      var vm = new ViewModel();\n\n      return {\n        vm: vm,\n        form: _.form('request-link', vm)\n      };\n    },\n    view: function(ctrl, _) {\n      if (ctrl.vm.user) {\n        return this.completed(ctrl.form, ctrl.vm, _);\n      } else if (ctrl.vm.activation) {\n        return this.inactive(ctrl.form, ctrl.vm, _);\n      } else {\n        return this.form(ctrl.form, _);\n      }\n    },\n    completed: function(form, vm, _) {\n      var message = gettext(\"%(username)s, we have sent link to your password change form to %(email)s.\");\n\n      return m('.page.page-message.page-message-success',\n        m('.container',\n          m('.message-panel', [\n            m('.message-icon',\n              m('span.material-icon', 'check')\n            ),\n            m('.message-body', [\n              m('p.lead',\n                gettext(\"Change password form link sent.\")\n              ),\n              m('p',\n                interpolate(message, {\n                  username: vm.user.username,\n                  email: vm.user.email\n                }, true)\n              ),\n              m('p',\n                _.component('button', {\n                  class: '.btn-default',\n                  submit: false,\n                  label: gettext(\"Request another link\"),\n                  onclick: form.reset.bind(form)\n                })\n              )\n            ])\n          ])\n        )\n      );\n    },\n    inactive: function(form, vm, _) {\n      var activateButton = null;\n\n      if (vm.activation === 'inactive_user') {\n        activateButton = m('a.btn.btn-primary',\n          {href: _.router.url('request_activation')},\n          gettext(\"Activate account\")\n        );\n      }\n\n      return m('.page.page-message.page-message-info',\n        m('.container',\n          m('.message-panel', [\n            m('.message-icon',\n              m('span.material-icon', 'info_outline')\n            ),\n            m('.message-body', [\n              m('p.lead',\n                gettext(\"Your account is inactive.\")\n              ),\n              m('p',\n                vm.activationMessage\n              ),\n              m('p', [\n                activateButton,\n                _.component('button', {\n                  class: '.btn-default',\n                  submit: false,\n                  label: gettext(\"Request another link\"),\n                  onclick: form.reset.bind(form)\n                })\n              ])\n            ])\n          ])\n        )\n      );\n    },\n    form: function(form, _) {\n      return m('.page.page-request-activation', [\n        _.component('header', {\n          title: gettext(\"Change forgotten password\")\n        }),\n        m('.container',\n          m('.row', [\n            m('.col-md-8', [\n              m('p',\n                gettext(\"Because user passwords are processed in an irreversible way before being saved to database, it is not possible for us to simply send you your password.\")\n              ),\n              m('p',\n                gettext(\"Instead, you can change your password using special secure form that will be available by special link valid only for your browser, for seven days or until your password is changed.\")\n              ),\n              m('p',\n                gettext(\"To receive this link, enter your account's e-mail addres in form and press \\\"Send link\\\" button.\")\n              )\n            ]),\n            m('.col-md-4',\n              _.component('request-link-form', form)\n            )\n          ])\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('route:request-password-change', function(_) {\n    _.route('request-password-change', requestPasswordChange);\n  },\n  {\n    after: 'routes'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var brand = {\n    view: function(ctrl, branding, _) {\n      var children = [\n        m('img', {\n          src: _.router.staticUrl('misago/img/site-logo.png'),\n          alt: _.settings.forum_name\n        })\n      ];\n\n      if (branding) {\n        children.push(branding);\n      }\n\n      return m('a.navbar-brand', {href: _.router.url('index')}, children);\n    }\n  };\n\n  Misago.addService('component:navbar:desktop:brand', function(_) {\n    _.component('navbar:desktop:brand', brand);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var nav = {\n    controller: function(_) {\n      return {\n        showSignIn: function() {\n          _.modal('sign-in');\n        }\n      };\n    },\n    view: function(ctrl, _) {\n      return m('div.nav.nav-guest', [\n        _.component('button', {\n          class: '.navbar-btn.btn-default',\n          onclick: ctrl.showSignIn,\n          disabled: ctrl.isBusy,\n          label: gettext('Sign in')\n        }),\n        _.component('navbar:register-button', '.navbar-btn.btn-primary')\n      ]);\n    }\n  };\n\n  Misago.addService('component:navbar:desktop:guest-nav', function(_) {\n    _.component('navbar:desktop:guest-nav', nav);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var nav = {\n    view: function(ctrl, links) {\n      return m('ul.nav.navbar-nav', [\n        links.map(function(link) {\n          return m('li',\n            m(\"a\", link.config || {href: link.url},\n              link.label\n            )\n          );\n        })\n      ]);\n    }\n  };\n\n  Misago.addService('component:navbar:desktop:main-nav', function(_) {\n    _.component('navbar:desktop:main-nav', nav);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var navbar = {\n    view: function(ctrl, mainNav, _) {\n      var brand = null;\n      var user = null;\n\n      if (_.settings.forum_branding_display) {\n        brand = _.component(\n          'navbar:desktop:brand', _.settings.forum_branding_text);\n      }\n\n      if (_.user.isAuthenticated) {\n        user = _.component('navbar:desktop:user-nav');\n      } else {\n        user = _.component('navbar:desktop:guest-nav');\n      }\n\n      return m('.container.navbar-full.hidden-xs.hidden-sm', [\n        brand,\n        _.component('navbar:desktop:main-nav', mainNav),\n        user\n      ]);\n    }\n  };\n\n  Misago.addService('component:navbar:desktop', function(_) {\n    _.component('navbar:desktop', navbar);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var nav = {\n    controller: function() {\n      return {\n        dropdownToggle: {\n          href: '/not-yet/',\n\n          'data-toggle': 'dropdown',\n          'data-misago-routed': 'false',\n\n          'aria-haspopup': 'true',\n          'aria-expanded': 'false'\n        }\n      };\n    },\n    view: function(ctrl, _) {\n      return m('ul.nav.navbar-nav.nav-user', [\n        m('li.dropdown', [\n          m('a.dropdown-toggle[role=\"button\"]', ctrl.dropdownToggle,\n            _.component('user-avatar', _.user, 64)\n          ),\n          _.component('navbar:dropdown:user')\n        ])\n      ]);\n    }\n  };\n\n  Misago.addService('component:navbar:desktop:user-nav', function(_) {\n    _.component('navbar:desktop:user-nav', nav);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  function persistent(el, isInit, context) {\n    context.retain = true;\n  }\n\n  var alert = {\n    classes: {\n      'info': 'alert-info',\n      'success': 'alert-success',\n      'warning': 'alert-warning',\n      'error': 'alert-danger'\n    },\n    view: function(ctrl, _) {\n      return m(\n        '.alerts',\n        {\n          config: persistent,\n          class: _.alert.isVisible ? 'in' : 'out'\n        },\n        m('p.alert',\n          {\n            class: this.classes[_.alert.type]\n          },\n          _.alert.message\n        )\n      );\n    }\n  };\n\n  Misago.addService('component:alert', function(_) {\n    _.component('alert', alert);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  function persistent(el, isInit, context) {\n    context.retain = true;\n  }\n\n  var authChanged = {\n    refresh: function() {\n      window.location.reload();\n    },\n    view: function(ctrl, _) {\n      var message = '';\n\n      var options = {\n        config: persistent,\n        class: (_.auth.isDesynced ? 'show' : null)\n      };\n\n      if (_.auth.isDesynced) {\n        if (_.auth.newUser && _.auth.newUser.isAuthenticated) {\n          message = gettext(\"You have signed in as %(username)s. Please refresh this page before continuing.\");\n          message = interpolate(message, {username: _.auth.newUser.username}, true);\n        } else {\n          message = gettext(\"%(username)s, you have been signed out. Please refresh this page before continuing.\");\n          message = interpolate(message, {username: _.user.username}, true);\n        }\n      }\n\n      return m('.auth-changed-message', options,\n        m('',\n          m('.container', [\n            m('p',\n              message\n            ),\n            m('p', [\n              m('button.btn.btn-default[type=\"button\"]', {onclick: this.refresh},\n                gettext(\"Reload page\")\n              ),\n              m('span.hidden-xs.hidden-sm.text-muted',\n                gettext(\"or press F5 key.\")\n              )\n            ])\n          ])\n        )\n      );\n    }\n  };\n\n  Misago.addService('component:auth-changed-message', function(_) {\n    _.component('auth-changed-message', authChanged);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var button = {\n    view: function(ctrl, kwargs) {\n      var options = {\n        disabled: kwargs.disabled || kwargs.loading || false,\n        config: kwargs.config || null,\n        loading: kwargs.loading || false,\n        type: kwargs.submit ? 'submit' : 'button',\n        onclick: kwargs.onclick || null\n      };\n\n      var element = 'button[type=\"' + options.type + '\"].btn';\n      if (options.loading) {\n        element += '.btn-loading';\n      }\n\n      if (kwargs.id) {\n        element += '#' + kwargs.id;\n      }\n\n      element += (kwargs.class || '');\n\n      var label = kwargs.label;\n      if (options.loading) {\n        label = [\n          label,\n          m('.loader-compact', [\n            m('.bounce1'),\n            m('.bounce2'),\n            m('.bounce3')\n          ])\n        ];\n      }\n\n      return m(element, options, label);\n    },\n  };\n\n  Misago.addService('component:button', function(_) {\n    _.component('button', button);\n  },\n  {\n    after: 'components'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var textFields = ['text', 'password', 'email'];\n\n  var formGroup = {\n    view: function(ctrl, kwargs) {\n      var groupClass = '.form-group';\n      var errors = null;\n      var helpText = null;\n\n      var controlType = kwargs.control.attrs.type;\n      var controlId = kwargs.control.attrs.id;\n\n      var feedbackId = controlId + '_feedback';\n      var feedbackIcon = null;\n      var showFeedbackIcon = null;\n\n      var isValidated = kwargs.validationKey && kwargs.validation !== null;\n\n      kwargs.control.attrs['aria-describedby'] = '';\n\n      if (isValidated && kwargs.validation[kwargs.validationKey]) {\n        showFeedbackIcon = textFields.indexOf(controlType) >= 0;\n        kwargs.control.attrs['aria-describedby'] = feedbackId;\n\n        if (kwargs.validation[kwargs.validationKey] === true) {\n          groupClass += '.has-success';\n          feedbackIcon = [\n            m('span.material-icon.form-control-feedback',\n              {\n                'aria-hidden': 'true'\n              },\n              'check'\n            ),\n            m('span.sr-only#' + feedbackId, gettext(\"(success)\"))\n          ];\n        } else {\n          groupClass += '.has-error';\n          errors = kwargs.validation[kwargs.validationKey];\n          feedbackIcon = [\n            m('span.material-icon.form-control-feedback',\n              {\n                'aria-hidden': 'true'\n              },\n              'clear'\n            ),\n            m('span.sr-only#' + feedbackId, gettext(\"(error)\"))\n          ];\n        }\n      }\n\n      if (kwargs.helpText) {\n        if (typeof kwargs.helpText === 'string' ||\n            kwargs.helpText instanceof String) {\n          helpText = m('p.help-block', kwargs.helpText);\n        } else {\n          helpText = kwargs.helpText;\n        }\n      }\n\n      return m(groupClass, [\n        m('label.control-label' + (kwargs.labelClass || ''),\n          {\n            for: kwargs.labelFor || controlId\n          },\n          kwargs.label + ':'\n        ),\n        m(kwargs.controlClass || '', [\n          kwargs.control,\n          showFeedbackIcon ? feedbackIcon : null,\n          errors ? m('.help-block.errors', errors.map(function(item) {\n            return m('p', item);\n          })) : null,\n          helpText\n        ])\n      ]);\n    },\n  };\n\n  Misago.addService('component:form-group', function(_) {\n    _.component('form-group', formGroup);\n  },\n  {\n    after: 'components'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var persistent = function(el, isInit, context) {\n    context.retain = true;\n  };\n\n  var forumLayout = {\n    view: function(ctrl, _) {\n      return [\n        _.component('auth-changed-message'),\n        _.component('alert'),\n        _.component('navbar'),\n        m('.navbar-dropdown',\n          _.dropdown.slot('navbar-dropdown')\n        ),\n        m('#router-fixture', {config: persistent}),\n        _.component('footer'),\n        _.component('modal')\n      ];\n    }\n  };\n\n  Misago.addService('component:layout', function(_) {\n    _.component('forum-layout', forumLayout);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var loader = {\n    view: function() {\n      return m('.loader.sk-folding-cube', [\n        m('.sk-cube1.sk-cube'),\n        m('.sk-cube2.sk-cube'),\n        m('.sk-cube4.sk-cube'),\n        m('.sk-cube3.sk-cube')\n      ]);\n    }\n  };\n\n  Misago.addService('component:loader', function(_) {\n    _.component('loader', loader);\n  },\n  {\n    after: 'components'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var persistent = function(el, isInit, context) {\n    context.retain = true;\n  };\n\n  var markup = {\n    view: function(ctrl, content) {\n      return m('article.misago-markup', {config: persistent},\n        m.trust(content)\n      );\n    }\n  };\n\n  Misago.addService('component:markup', function(_) {\n    _.component('markup', markup);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var persistent = function(el, isInit, context) {\n    context.retain = true;\n  };\n\n  var modal = {\n    view: function() {\n      return m(\n        '#misago-modal.modal.fade[role=\"dialog\"]',\n        {\n          config: persistent,\n          tabindex: \"-1\",\n          \"aria-labelledby\": \"misago-modal-label\"\n        }\n      );\n    }\n  };\n\n  Misago.addService('component:modal', function(_) {\n    _.component('modal', modal);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var header = {\n    view: function(ctrl, options) {\n      return m('.page-header',\n        m('.container', [\n          m('h1', options.title),\n        ])\n      );\n    }\n  };\n\n  Misago.addService('component:header', function(_) {\n    _.component('header', header);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var persistent = function(el, isInit, context) {\n    context.retain = true;\n  };\n\n  var styles = [\n    'progress-bar-danger',\n    'progress-bar-warning',\n    'progress-bar-warning',\n    'progress-bar-primary',\n    'progress-bar-success'\n  ];\n\n  var labels = [\n    gettext('Entered password is very weak.'),\n    gettext('Entered password is weak.'),\n    gettext('Entered password is average.'),\n    gettext('Entered password is strong.'),\n    gettext('Entered password is very strong.')\n  ];\n\n  var passwordStrength = {\n    view: function(ctrl, kwargs, _) {\n      var score = _.zxcvbn.scorePassword(kwargs.password, kwargs.inputs);\n      var options = {\n        config: persistent,\n        class: styles[score],\n        style: \"width: \" + (20 + (20 * score)) + '%',\n        'role': \"progressbar\",\n        'aria-valuenow': score,\n        'aria-valuemin': \"0\",\n        'aria-valuemax': \"4\"\n      };\n\n      return m('.help-block.password-strength', {key: 'password-strength'}, [\n        m('.progress',\n          m('.progress-bar', options,\n            m('span.sr-only', labels[score])\n          )\n        ),\n        m('p.text-small', labels[score])\n      ]);\n    },\n  };\n\n  Misago.addService('component:password-strength', function(_) {\n    _.component('password-strength', passwordStrength);\n  },\n  {\n    after: 'components'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var avatar = {\n    defaultSize: 100,\n\n    src: function(user, size, _) {\n      var src = _.router.baseUrl + 'user-avatar/';\n\n      if (user && user.id) {\n        // just avatar hash, size and user id\n        src += user.avatar_hash + '/' + size + '/' + user.id + '.png';\n      } else {\n        // just append avatar size to file to produce no-avatar placeholder\n        src += size + '.png';\n      }\n\n      return src;\n    },\n    view: function(ctrl, user, size, _) {\n      var finalSize = size || this.defaultSize;\n      return m('img', {\n        alt: user && user.username ? user.username : gettext(\"Unregistered\"),\n        width: finalSize,\n        height: finalSize,\n        src: this.src(user, finalSize, _)\n      });\n    }\n  };\n\n  Misago.addService('component:user-avatar', function(_) {\n    _.component('user-avatar', avatar);\n  },\n  {\n    after: 'components'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var navbar = {\n    style: '.navbar.navbar-misago.navbar-default.navbar-static-top',\n    mainNav: function(_) {\n      var links = [\n        {\n          label: gettext(\"Threads\"),\n          icon: 'chat',\n          url: _.router.url('index')\n        },\n        {\n          label: gettext(\"Forums\"),\n          icon: 'forum',\n          url: '/not-yet/forums/'\n        },\n        {\n          label: gettext(\"Users\"),\n          icon: 'group',\n          url: '/not-yet/users/'\n        }\n      ];\n\n      return links;\n    },\n    view: function(ctrl, _) {\n      var links = this.mainNav(_);\n\n      return m('nav' + this.style + '[role=\"navigation\"]', [\n        _.component('navbar:desktop', links),\n        _.component('navbar:mobile', links)\n      ]);\n    }\n  };\n\n  Misago.addService('component:navbar', function(_) {\n    _.component('navbar', navbar);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var dropdown = {\n    controller: function(_) {\n      return {\n        showSignIn: function() {\n          _.modal('sign-in');\n        }\n      };\n    },\n    view: function(ctrl, _) {\n      return m('ul.dropdown-menu.user-dropdown.dropdown-menu-right[role=\"menu\"]',\n        m('li.guest-preview', [\n          m('h4',\n            gettext(\"You are browsing as guest.\")\n          ),\n          m('p',\n            gettext('Sign in or register to start and participate in discussions.')\n          ),\n          m('.row', [\n            m('.col-xs-6',\n              _.component('button', {\n                class: '.btn.btn-default.btn-block',\n                onclick: ctrl.showSignIn,\n                disabled: ctrl.isBusy,\n                label: gettext('Sign in')\n              })\n            ),\n            m('.col-xs-6',\n              _.component(\n                'navbar:register-button', '.btn.btn-primary.btn-block')\n            )\n          ])\n        ])\n      );\n    }\n  };\n\n  Misago.addService('component:navbar:dropdown:guest', function(_) {\n    _.component('navbar:dropdown:guest', dropdown);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var navbar = {\n    style: '.nav.navbar-nav.navbar-compact-nav.hidden-md.hidden-lg',\n    controller: function(links, _) {\n      return {\n        openUserMenu: function() {\n          if (_.user.isAuthenticated) {\n            _.dropdown.toggle('navbar-dropdown', 'navbar:dropdown:user');\n          } else {\n            _.dropdown.toggle('navbar-dropdown', 'navbar:dropdown:guest');\n          }\n\n          return false;\n        }\n      };\n    },\n    userMenu: function(ctrl, _) {\n      if (_.user.isAuthenticated) {\n        return {\n          element: _.component('user-avatar', _.user, 64),\n          config: {\n            onclick: ctrl.openUserMenu,\n            url: '/not-yet/',\n\n            'data-misago-routed': 'false'\n          }\n        };\n      } else {\n        return {\n          element: _.component('user-avatar', null, 64),\n          config: {\n            onclick: ctrl.openUserMenu,\n            href: '#',\n\n            'data-misago-routed': 'false'\n          }\n        };\n      }\n    },\n    mobileNav: function(ctrl, links, _) {\n      var mobileLinks = [\n        {\n          element: m('img', {\n            src: _.router.staticUrl('misago/img/site-icon.png'),\n            alt: _.settings.forum_name\n          }),\n          url: _.router.url('index')\n        }\n      ];\n\n      links.forEach(function(link) {\n        if (link.url !== mobileLinks[0].url) {\n          mobileLinks.push(link);\n        }\n      });\n\n      mobileLinks.push(this.userMenu(ctrl, _));\n\n      return mobileLinks;\n    },\n    view: function(ctrl, links, _) {\n      var mobileLinks = this.mobileNav(ctrl, links, _);\n\n      return m('ul' + this.style + '.with-' + mobileLinks.length + '-items',\n        mobileLinks.map(function(link) {\n          return m('li',\n            m('a', link.config || {href: link.url},\n              link.element || m('span.material-icon', {title:link.label},\n                link.icon\n              )\n            )\n          );\n        })\n      );\n    }\n  };\n\n  Misago.addService('component:navbar:mobile', function(_) {\n    _.component('navbar:mobile', navbar);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var button = {\n    controller: function(style, _) {\n      return {\n        isBusy: false,\n\n        showRegister: function() {\n          if (_.settings.account_activation === 'closed') {\n            _.alert.info(gettext(\"New registrations are currently disabled.\"));\n          } else {\n            m.startComputation();\n            this.isBusy = true;\n            m.endComputation();\n\n            var self = this;\n            m.sync([\n              _.zxcvbn.load(),\n              _.captcha.load()\n            ]).then(function() {\n              _.modal('register');\n            }, function() {\n              _.alert.error(gettext('Registation is not available now due to an error.'));\n            }).then(function() {\n              m.startComputation();\n              self.isBusy = false;\n              m.endComputation();\n            });\n          }\n        }\n      };\n    },\n    view: function(ctrl, style, _) {\n      return _.component('button', {\n        class: style,\n        onclick: ctrl.showRegister.bind(ctrl),\n        loading: ctrl.isBusy,\n        label: gettext('Register')\n      });\n    }\n  };\n\n  Misago.addService('component:navbar:register-button', function(_) {\n    _.component('navbar:register-button', button);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var dropdown = {\n    class: '.dropdown-menu.user-dropdown.dropdown-menu-right',\n\n    controller: function() {\n      return {\n        logout: function() {\n          var decision = confirm(gettext(\"Are you sure you want to sign out?\"));\n          if (decision) {\n            $('#hidden-logout-form').submit();\n          }\n        }\n      };\n    },\n    view: function(ctrl, _) {\n      return m('ul' + this.class + '[role=\"menu\"]', [\n        m('li.dropdown-header',\n          m('strong',\n            _.user.username\n          )\n        ),\n        m('li.divider'),\n        m('li',\n          m('a', {href: '/not-yet/'}, [\n            m('span.material-icon',\n              'account_circle'\n            ),\n            gettext(\"See your profile\")\n          ])\n        ),\n        m('li',\n          m('a', {href: _.router.url('options')}, [\n            m('span.material-icon',\n              'done_all'\n            ),\n            gettext(\"Change options\")\n          ])\n        ),\n        m('li',\n          m('button.btn-link[type=\"button\"]', [\n            m('span.material-icon',\n              'face'\n            ),\n            gettext(\"Change avatar\")\n          ])\n        ),\n        m('li.divider'),\n        m('li.dropdown-footer',\n          m('button.btn.btn-default.btn-block', {onclick: ctrl.logout},\n            gettext(\"Logout\")\n          )\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('component:navbar:dropdown:user', function(_) {\n    _.component('navbar:dropdown:user', dropdown);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var footer = {\n    hasNav: function(_) {\n      return [\n        !!_.settings.forum_footnote,\n        !!_.settings.terms_of_service,\n        !!_.settings.terms_of_service_link,\n        !!_.settings.privacy_policy,\n        !!_.settings.privacy_policy_link\n      ].indexOf(true) !== -1;\n    },\n    view: function(ctrl, _) {\n      var nav = null;\n      if (this.hasNav(_)) {\n        nav = _.component('footer:nav');\n      }\n\n      return m('footer.forum-footer', [\n        m('.container',\n          m('.footer-content', [\n            nav,\n            _.component('footer:branding')\n          ])\n        )\n      ]);\n    }\n  };\n\n  Misago.addService('component:footer', function(_) {\n    _.component('footer', footer);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var branding = {\n    view: function() {\n      return m('a.misago-branding[href=http://misago-project.org]', [\n        \"powered by \", m('strong', \"misago\")\n      ]);\n    }\n  };\n\n  Misago.addService('component:footer:branding', function(_) {\n    _.component('footer:branding', branding);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var legalLink = function(_, legalType, defaultTitle) {\n    var url = Misago.get(_.settings, legalType + '_link');\n    if (!url && Misago.get(_.settings, legalType)) {\n      url = _.router.url(legalType);\n    }\n\n    if (url) {\n      return m('li',\n        m('a', {href: url},\n          Misago.get(_.settings, legalType + '_title', defaultTitle)\n        )\n      );\n    } else {\n      return null;\n    }\n  };\n\n  var nav = {\n    isVisible: function(settings) {\n      return [\n        !!settings.forum_footnote,\n        !!settings.terms_of_service,\n        !!settings.terms_of_service_link,\n        !!settings.privacy_policy,\n        !!settings.privacy_policy_link\n      ].indexOf(true) !== -1;\n    },\n    view: function(ctrl, _) {\n      var items = [];\n\n      if (_.settings.forum_footnote) {\n        items.push(m('li.forum-footnote', m.trust(_.settings.forum_footnote)));\n      }\n\n      items.push(\n        legalLink(_, 'terms_of_service', gettext('Terms of service')));\n      items.push(\n        legalLink(_, 'privacy_policy', gettext('Privacy policy')));\n\n      return m('ul.list-inline.footer-nav', items);\n    }\n  };\n\n  Misago.addService('component:footer:nav', function(_) {\n    _.component('footer:nav', nav);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var form = {\n    view: function(ctrl, form, _) {\n      return m('.well.well-form',\n        m('form', {onsubmit: form.submit}, [\n          m('.form-group',\n            m('.control-input',\n              Misago.input({\n                disabled: form.isBusy,\n                value: form.email,\n                placeholder: gettext(\"Your e-mail address\")\n              })\n            )\n          ),\n          _.component('button', {\n            class: '.btn-primary.btn-block',\n            submit: true,\n            loading: form.isBusy,\n            label: gettext(\"Send link\")\n          })\n        ])\n      );\n    }\n  };\n\n  Misago.addService('component:request-link-form', function(_) {\n    _.component('request-link-form', form);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var header = {\n    view: function(ctrl, title) {\n      return m('.modal-header', [\n        m('button.close[type=\"button\"]',\n          {'data-dismiss': 'modal', 'aria-label': gettext('Close')},\n          m('span', {'aria-hidden': 'true'}, m.trust('&times;'))\n        ),\n        m('h4#misago-modal-label.modal-title', title)\n      ]);\n    }\n  };\n\n  Misago.addService('component:modal:header', function(_) {\n    _.component('modal:header', header);\n  },\n  {\n    after: 'components'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var persistent = function(el, isInit, context) {\n    context.retain = true;\n  };\n\n  var refresh = function() {\n    document.location.reload();\n  };\n\n  var registerComplete = {\n    controller: function(message, _) {\n      if (message.activation === 'active') {\n        _.runloop.runOnce(\n          refresh, 'refresh-after-registration', 10000);\n      }\n    },\n    view: function(ctrl, message, _) {\n      var messageHtml = null;\n\n      if (message.activation === 'active') {\n        messageHtml = this.active(message);\n      } else {\n        messageHtml = this.inactive(message);\n      }\n\n      return m('.modal-dialog.modal-message.modal-register[role=\"document\"]',\n        {config: persistent},\n        m('.modal-content', [\n          _.component('modal:header', gettext('Registration complete')),\n          m('.modal-body',\n            messageHtml\n          )\n        ])\n      );\n    },\n    active: function(message) {\n      var lead = gettext(\"%(username)s, your account has been created and you were signed in.\");\n      return [\n        m('.message-icon',\n          m('span.material-icon', 'check')\n        ),\n        m('.message-body', [\n          m('p.lead',\n            interpolate(lead, {'username': message.username}, true)\n          ),\n          m('p',\n            gettext('The page will refresh automatically in 10 seconds.')\n          ),\n          m('p',\n            m('button[type=\"button\"].btn.btn-default', {onclick: refresh},\n              gettext('Refresh page')\n            )\n          )\n        ])\n      ];\n    },\n    inactive: function(message) {\n      var lead = null;\n      var help = null;\n\n      if (message.activation === 'user') {\n        lead = gettext(\"%(username)s, your account has been created but you need to activate it before you will be able to sign in.\");\n        help = gettext(\"We have sent an e-mail to %(email)s with link that you have to click to activate your account.\");\n      } else if (message.activation === 'admin') {\n        lead = gettext(\"%(username)s, your account has been created but board administrator will have to activate it before you will be able to sign in.\");\n        help = gettext(\"We will send an e-mail to %(email)s when this takes place.\");\n      }\n\n      return [\n        m('.message-icon',\n          m('span.material-icon', 'info_outline')\n        ),\n        m('.message-body', [\n          m('p.lead',\n            interpolate(lead, {'username': message.username}, true)\n          ),\n          m('p',\n            interpolate(help, {'email': message.email}, true)\n          )\n        ])\n      ];\n    }\n  };\n\n  Misago.addService('modal:register-complete', function(_) {\n    _.modal('register-complete', registerComplete);\n  },\n  {\n    after: 'modals'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var persistent = function(el, isInit, context) {\n    context.retain = true;\n  };\n\n  var register = {\n    controller: function(_) {\n      return {\n        form: _.form('register')\n      };\n    },\n    view: function(ctrl, _) {\n      var captcha = _.captcha.component({\n        form: ctrl.form,\n\n        labelClass: '.col-md-4',\n        controlClass: '.col-md-8'\n      });\n\n      var footnote = null;\n      var termsUrl = _.settings.terms_of_service_link;\n\n      if (!termsUrl && _.settings.terms_of_service) {\n        termsUrl = _.router.url('terms_of_service');\n      }\n\n      if (termsUrl) {\n        footnote = m('a', {href: termsUrl},\n          m.trust(interpolate(gettext(\"By registering you agree to site's %(terms)s.\"), {\n            terms: '<strong>' + gettext(\"terms and conditions\") + '</strong>'\n          }, true))\n        );\n      }\n\n      return m('.modal-dialog.modal-form.modal-register[role=\"document\"]',\n        {config: persistent},\n        m('.modal-content', [\n          _.component('modal:header', gettext('Register')),\n          m('form.form-horizontal',\n          {\n            onsubmit: ctrl.form.submit\n          },\n          [\n            m('input[type=\"text\"]', {\n              name:'_username',\n              style: 'display: none'\n            }),\n            m('input[type=\"password\"]', {\n              name:'_password',\n              style: 'display: none'\n            }),\n            m('.modal-body', [\n              _.component('form-group', {\n                label: gettext(\"Username\"),\n                labelClass: '.col-md-4',\n                controlClass: '.col-md-8',\n                control: _.input({\n                  value: _.validate(ctrl.form, 'username'),\n                  id: 'id_username',\n                  disabled: ctrl.form.isBusy\n                }),\n                validation: ctrl.form.errors,\n                validationKey: 'username'\n              }),\n              _.component('form-group', {\n                label: gettext(\"E-mail\"),\n                labelClass: '.col-md-4',\n                controlClass: '.col-md-8',\n                control: _.input({\n                  value: _.validate(ctrl.form, 'email'),\n                  id: 'id_email',\n                  disabled: ctrl.form.isBusy\n                }),\n                validation: ctrl.form.errors,\n                validationKey: 'email'\n              }),\n              _.component('form-group', {\n                label: gettext(\"Password\"),\n                labelClass: '.col-md-4',\n                controlClass: '.col-md-8',\n                control: _.input({\n                  value: _.validate(ctrl.form, 'password'),\n                  type: 'password',\n                  id: 'id_password',\n                  disabled: ctrl.form.isBusy\n                }),\n                validation: ctrl.form.errors,\n                validationKey: 'password',\n                helpText: _.component('password-strength', {\n                  inputs: [\n                    ctrl.form.username(),\n                    ctrl.form.email()\n                  ],\n                  password: ctrl.form.password()\n                })\n              }),\n              captcha\n            ]),\n            m('.modal-footer', [\n              footnote,\n              _.component('button', {\n                class: '.btn-primary',\n                submit: true,\n                loading: ctrl.form.isBusy,\n                label: gettext(\"Register account\")\n              })\n            ])\n          ])\n        ])\n      );\n    }\n  };\n\n  Misago.addService('modal:register', function(_) {\n    _.modal('register', register);\n  },\n  {\n    after: 'modals'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  function persistent(el, isInit, context) {\n    context.retain = true;\n  }\n\n  var signin = {\n    controller: function(_) {\n      return {\n        form: _.form('sign-in')\n      };\n    },\n    view: function(ctrl, _) {\n      var activateButton = null;\n\n      if (ctrl.form.showActivation) {\n        activateButton = m('a.btn.btn-block.btn-success',\n          {href: _.router.url('request_activation')},\n          gettext(\"Activate account\")\n        );\n      }\n\n      return m('.modal-dialog.modal-sm.modal-signin[role=\"document\"]',\n        {config: persistent},\n        m('.modal-content', [\n          _.component('modal:header', gettext(\"Sign in\")),\n          m('form', {onsubmit: ctrl.form.submit}, [\n            m('.modal-body', [\n              m('.form-group',\n                m('.control-input',\n                  Misago.input({\n                    disabled: ctrl.form.isBusy,\n                    value: ctrl.form.username,\n                    placeholder: gettext(\"Username or e-mail\")\n                  })\n                )\n              ),\n              m('.form-group',\n                m('.control-input',\n                  Misago.input({\n                    type: 'password',\n                    disabled: ctrl.form.isBusy,\n                    value: ctrl.form.password,\n                    placeholder: gettext(\"Password\")\n                  })\n                )\n              )\n            ]),\n            m('.modal-footer', [\n              activateButton,\n              _.component('button', {\n                class: '.btn-primary.btn-block',\n                submit: true,\n                loading: ctrl.form.isBusy,\n                label: gettext(\"Sign in\")\n              }),\n              m('a.btn.btn-block.btn-default',\n                {href: _.router.url('request_password_change')},\n                gettext(\"Forgot password?\")\n              )\n            ])\n          ])\n        ])\n      );\n    }\n  };\n\n  Misago.addService('modal:sign-in', function(_) {\n    _.modal('sign-in', signin);\n  },\n  {\n    after: 'modals'\n  });\n}(Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var ChangePassword = function(_) {\n    var self = this;\n\n    this.username = null;\n    this.password = m.prop('');\n\n    this.validation = {\n      'password': [\n        Misago.validators.passwordMinLength(_.settings)\n      ]\n    };\n\n    this.clean = function() {\n      if (!_.validate(this)) {\n        if ($.trim(this.password()).length) {\n          _.alert.error(this.errors.password);\n        } else {\n          _.alert.error(gettext(\"Enter new password.\"));\n        }\n        return false;\n      } else {\n        return true;\n      }\n    };\n\n    this.submit = function() {\n      var endpoint = _.api.endpoint('auth').endpoint('change-password');\n      endpoint = endpoint.endpoint(m.route.param('user_id'));\n      endpoint = endpoint.endpoint(m.route.param('token'));\n\n      endpoint.post({\n        password: self.password()\n      }).then(function(user) {\n        self.success(user);\n      }, function(error) {\n        self.error(error);\n      });\n    };\n\n    this.success = function(user) {\n      this.username = user.username;\n    };\n\n    this.error = function(rejection) {\n      if (rejection.status === 403 && rejection.ban) {\n        _.router.error403({\n          message: '',\n          ban: rejection.ban\n        });\n      } else if (rejection.status === 400) {\n        _.alert.error(rejection.detail);\n      } else {\n        _.api.alert(rejection);\n      }\n    };\n  };\n\n  Misago.addService('form:change-password', function(_) {\n    _.form('change-password', ChangePassword);\n  },\n  {\n    after: 'forms'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var Register = function(_) {\n    var self = this;\n\n    this.showActivation = false;\n\n    this.username = m.prop('');\n    this.email = m.prop('');\n    this.password = m.prop('');\n\n    this.captcha = _.captcha.value;\n\n    this.errors = null;\n\n    this.validation = {\n      'username': [\n        Misago.validators.usernameContent(),\n        Misago.validators.usernameMinLength(_.settings),\n        Misago.validators.usernameMaxLength(_.settings)\n      ],\n      'email': [\n        Misago.validators.email()\n      ],\n      'password': [\n        Misago.validators.passwordMinLength(_.settings)\n      ],\n      'captcha': _.captcha.validator()\n    };\n\n    this.clean = function() {\n      if (this.errors === null) {\n        _.validate(this);\n      }\n\n      _.captcha.clean(this);\n\n      if (this.hasErrors()) {\n        _.alert.error(gettext(\"Form contains errors.\"));\n        return false;\n      } else {\n        return true;\n      }\n    };\n\n    this.submit = function() {\n      _.api.model('user').post({\n        username: this.username(),\n        email: this.email(),\n        password: this.password(),\n        captcha: this.captcha()\n      }).then(this.success, this.error);\n    };\n\n    this.success = function(data) {\n      _.modal('register-complete', data);\n    };\n\n    this.error = function(rejection) {\n      if (rejection.status === 400) {\n        _.alert.error(gettext(\"Form contains errors.\"));\n        $.extend(self.errors, rejection);\n      } else {\n        _.api.alert(rejection);\n      }\n    };\n  };\n\n  Misago.addService('form:register', function(_) {\n    _.form('register', Register);\n  },\n  {\n    after: 'forms'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var RequestLink = function(vm, _) {\n    var self = this;\n\n    this.email = m.prop('');\n\n    this.validation = {\n      'email': [\n        Misago.validators.email()\n      ]\n    };\n\n    this.clean = function() {\n      if (!_.validate(this)) {\n        _.alert.error(gettext(\"Enter a valid email address.\"));\n        return false;\n      } else {\n        return true;\n      }\n    };\n\n    this.submit = function() {\n      _.api.endpoint('auth').endpoint(vm.endpoint).post({\n        email: self.email()\n      }).then(function(user) {\n        self.success(user);\n      }, function(error) {\n        self.error(error);\n      });\n    };\n\n    this.success = function(user) {\n      vm.success(user);\n    };\n\n    this.error = function(rejection) {\n      if (rejection.status === 400) {\n          vm.error(rejection, _);\n      } else if (rejection.status === 403 && rejection.ban) {\n        _.router.error403({\n          message: '',\n          ban: rejection.ban\n        });\n      } else {\n        _.api.alert(rejection);\n      }\n    };\n\n    this.reset = function() {\n      this.email('');\n      vm.reset();\n    };\n  };\n\n  Misago.addService('form:request-link', function(_) {\n    _.form('request-link', RequestLink);\n  },\n  {\n    after: 'forms'\n  });\n} (Misago.prototype));\n\n(function (Misago) {\n  'use strict';\n\n  var SignIn = function(_) {\n    var self = this;\n\n    this.showActivation = false;\n\n    this.username = m.prop('');\n    this.password = m.prop('');\n\n    this.validation = {\n      'username': [],\n      'password': []\n    };\n\n    this.clean = function() {\n      if (!_.validate(this)) {\n        _.alert.error(gettext(\"Fill out both fields.\"));\n        return false;\n      } else {\n        return true;\n      }\n    };\n\n    this.submit = function() {\n      _.api.endpoint('auth').post({\n        username: self.username(),\n        password: self.password()\n      }).then(function() {\n        self.success();\n      }, function(error) {\n        self.error(error);\n      });\n    };\n\n    this.success = function() {\n      _.modal();\n\n      var $form = $('#hidden-login-form');\n\n      // refresh CSRF token because api call to /auth/ changed it\n      _.ajax.refreshCsrfToken();\n\n      // fill out form with user credentials and submit it, this will tell\n      // misago to redirect user back to right page, and will trigger browser's\n      // key ring feature\n      $form.find('input[type=\"hidden\"]').val(_.ajax.csrfToken);\n      $form.find('input[name=\"redirect_to\"]').val(m.route());\n      $form.find('input[name=\"username\"]').val(this.username());\n      $form.find('input[name=\"password\"]').val(this.password());\n      $form.submit();\n    };\n\n    this.error = function(rejection) {\n      if (rejection.status === 400) {\n        if (rejection.code === 'inactive_admin') {\n          _.alert.info(rejection.detail);\n        } else if (rejection.code === 'inactive_user') {\n          _.alert.info(rejection.detail);\n          self.showActivation = true;\n        } else if (rejection.code === 'banned') {\n          _.modal();\n          _.router.error403({\n            message: '',\n            ban: rejection.detail\n          });\n        } else {\n          _.alert.error(rejection.detail);\n        }\n      } else {\n        _.api.alert(rejection);\n      }\n    };\n  };\n\n  Misago.addService('form:sign-in', function(_) {\n    _.form('sign-in', SignIn);\n  },\n  {\n    after: 'forms'\n  });\n} (Misago.prototype));\n\n(function (Misago, UrlConf) {\n  'use strict';\n\n  var urls = new UrlConf();\n\n  // Board index\n  urls.url('/', 'index');\n\n  // Account activation\n  urls.url('/activation/', 'request_activation');\n  urls.url('/activation/:user_id/:token/', 'activate_by_token');\n\n  // Password reset\n  urls.url('/forgotten-password/', 'request_password_change');\n  urls.url('/forgotten-password/:user_id/:token/', 'change_password');\n\n  // User control panel\n  urls.url('/options/', 'options');\n  urls.url('/options/forum/', 'options_forum');\n  urls.url('/options/email/', 'options_email');\n  urls.url('/options/password/', 'options_password');\n\n  // Legal pages\n  urls.url('/terms-of-service/', 'terms_of_service');\n  urls.url('/privacy-policy/', 'privacy_policy');\n\n  // Catch-all 404 not found route\n  urls.url('/:rest...', 'error:404', 'not_found');\n\n  Misago.urls = urls;\n} (Misago.prototype, Misago.prototype.UrlConf));\n"],"sourceRoot":"/source/"}

+ 0 - 127
misago/users/sites.py

@@ -1,127 +0,0 @@
-class Site(object):
-    """
-    Misago user sites controller
-
-    Allows for adding custom views to User CP, Users Lists and User Profile
-    """
-    def __init__(self, name):
-        self._finalized = False
-        self.name = name
-        self._unsorted_list = []
-        self._sorted_list = []
-
-    def assert_site_is_finalized(self):
-        if not self._finalized:
-            self._finalized = True
-            self._finalize_site()
-
-    def _finalize_site(self):
-        iterations = 0
-        while self._unsorted_list:
-            iterations += 1
-            if iterations > 512:
-                message = ("%s site hierarchy is invalid or too complex "
-                           "to resolve. pages left: %s" % self._unsorted_list)
-                raise ValueError(message)
-
-            for index, page in enumerate(self._unsorted_list):
-                if page['after']:
-                    page_added = self._insert_page(page, after=page['after'])
-                elif page['before']:
-                    page_added = self._insert_page(page, before=page['before'])
-                else:
-                    page_added = self._insert_page(page)
-
-                if page_added:
-                    del self._unsorted_list[index]
-                    break
-
-    def _insert_page(self, inserted_page, after=None, before=None):
-        if after:
-            new_sorted_list = []
-            for index, page in enumerate(self._sorted_list):
-                new_sorted_list.append(page)
-                if page['link'] == after:
-                    new_sorted_list.append(inserted_page)
-                    self._sorted_list = new_sorted_list
-                    return True
-            else:
-                return False
-        elif before:
-            new_sorted_list = []
-            for index, page in enumerate(self._sorted_list):
-                if page['link'] == before:
-                    new_sorted_list.append(inserted_page)
-                    new_sorted_list.append(page)
-                    self._sorted_list = new_sorted_list
-                    return True
-                else:
-                    new_sorted_list.append(page)
-            else:
-                return False
-        else:
-            self._sorted_list.append(inserted_page)
-            return True
-
-    def add_page(self, link, name, icon=None, after=None, before=None,
-                 visible_if=None, badge=None):
-        if self._finalized:
-            message = ("%s site was initialized already and no longer "
-                       "accepts new pages")
-            raise RuntimeError(message % self.name)
-
-        if after and before:
-            raise ValueError("after and before arguments are exclusive")
-
-        self._unsorted_list.append({
-            'link': link,
-            'name': name,
-            'icon': icon,
-            'after': after,
-            'before': before,
-            'badge': badge,
-            'visible_if': visible_if,
-            })
-
-    def _active_link_name(self, request):
-        namespace = request.resolver_match.namespace
-        url_name = request.resolver_match.url_name
-
-        if namespace:
-            active_link = '%s:%s' % (namespace, url_name)
-        else:
-            active_link = url_name
-        return active_link
-
-    def get_pages(self, request, profile=None):
-        self.assert_site_is_finalized()
-        active_link = self._active_link_name(request)
-        visible_pages = []
-
-        if profile:
-            test_args = (request, profile)
-        else:
-            test_args = (request,)
-
-        for page_definition in self._sorted_list:
-            page = page_definition.copy()
-
-            is_visible = True
-            if page['visible_if']:
-                is_visible = page['visible_if'](*test_args)
-
-            if is_visible:
-                if page['badge']:
-                    page['badge'] = page['badge'](*test_args)
-                page['is_active'] = active_link.startswith(page['link'])
-                visible_pages.append(page)
-        return visible_pages
-
-    def get_default_link(self):
-        self.assert_site_is_finalized()
-        return self._sorted_list[0]['link']
-
-
-usercp = Site('usercp')
-users_list = Site('users list')
-user_profile = Site('user profile')

+ 0 - 26
misago/users/tests/test_sites.py

@@ -1,26 +0,0 @@
-from django.test import TestCase
-from misago.users.sites import Site
-
-
-class SiteTests(TestCase):
-    def setUp(self):
-        self.site = Site('test')
-
-    def test_sites(self):
-        """add_page adds page to site"""
-        self.site.add_page(link='misago:user_posts',
-                           name='Posts',
-                           after='misago:user_threads')
-        self.site.add_page(link='misago:user_threads',
-                           name='Threads')
-        self.site.add_page(link='misago:user_follows',
-                           name='Follows',
-                           before='misago:user_posts')
-
-        self.site.assert_site_is_finalized()
-        sorted_pages = self.site._sorted_list
-        self.assertEqual(sorted_pages[0]['name'], 'Threads')
-        self.assertEqual(sorted_pages[1]['name'], 'Follows')
-        self.assertEqual(sorted_pages[2]['name'], 'Posts')
-
-        self.assertEqual(self.site.get_default_link(), 'misago:user_threads')