Code Split

This commit is contained in:
KyrneDev 2021-04-20 16:50:40 -07:00
parent c006931798
commit 008206738f
No known key found for this signature in database
GPG Key ID: 7CEC4039F04A192C
84 changed files with 1900 additions and 6482 deletions

View File

@ -8,4 +8,4 @@
*/
export * from './src/common';
export * from './src/admin';
export * from './src/admin';

26
js/dist/admin.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
js/dist/admin/flarum-core.js vendored Normal file

File diff suppressed because one or more lines are too long

1
js/dist/admin/flarum-core.js.map vendored Normal file

File diff suppressed because one or more lines are too long

2
js/dist/admin/flarum-core~runtime.js vendored Normal file
View File

@ -0,0 +1,2 @@
(()=>{"use strict";var e,r={},t={};function o(e){var n=t[e];if(void 0!==n)return n.exports;var l=t[e]={exports:{}};return r[e].call(l.exports,l,l.exports,o),l.exports}o.m=r,e=[],o.O=(r,t,n,l)=>{if(!t){var a=1/0;for(f=0;f<e.length;f++){for(var[t,n,l]=e[f],i=!0,u=0;u<t.length;u++)(!1&l||a>=l)&&Object.keys(o.O).every((e=>o.O[e](t[u])))?t.splice(u--,1):(i=!1,l<a&&(a=l));i&&(e.splice(f--,1),r=n())}return r}l=l||0;for(var f=e.length;f>0&&e[f-1][2]>l;f--)e[f]=e[f-1];e[f]=[t,n,l]},o.n=e=>{var r=e&&e.__esModule?()=>e.default:()=>e;return o.d(r,{a:r}),r},o.d=(e,r)=>{for(var t in r)o.o(r,t)&&!o.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:r[t]})},o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),o.o=(e,r)=>Object.prototype.hasOwnProperty.call(e,r),o.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e={120:0};o.O.j=r=>0===e[r];var r=(r,t)=>{var n,l,[a,i,u]=t,f=0;for(n in i)o.o(i,n)&&(o.m[n]=i[n]);for(u&&u(o),r&&r(t);f<a.length;f++)l=a[f],o.o(e,l)&&e[l]&&e[l][0](),e[a[f]]=0;o.O()},t=self.webpackChunkflarum_core=self.webpackChunkflarum_core||[];t.forEach(r.bind(null,0)),t.push=r.bind(null,t.push.bind(t))})(),o.O()})();
//# sourceMappingURL=flarum-core~runtime.js.map

File diff suppressed because one or more lines are too long

2
js/dist/common/common.js vendored Normal file

File diff suppressed because one or more lines are too long

1
js/dist/common/common.js.map vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
(self.webpackChunkflarum_core=self.webpackChunkflarum_core||[]).push([[247],{7681:(t,i,o)=>{"use strict";o.r(i),o.d(i,{default:()=>u});var e=o(1788),r=o(6366),s=o(7037),n=o(1698),a=o(5462),l=o(4967),u=function(t){function i(){return t.apply(this,arguments)||this}(0,e.Z)(i,t);var o=i.prototype;return o.oninit=function(i){t.prototype.oninit.call(this,i),this.value=this.attrs.value||"",this.disabled=!!this.attrs.disabled},o.view=function(){return m("div",{className:"TextEditor"},m("div",{className:"TextEditor-editorContainer"}),m("ul",{className:"TextEditor-controls Composer-footer"},(0,n.Z)(this.controlItems().toArray()),m("li",{className:"TextEditor-toolbar"},this.toolbarItems().toArray())))},o.oncreate=function(i){t.prototype.oncreate.call(this,i),this.attrs.composer.editor=this.buildEditor(this.$(".TextEditor-editorContainer")[0])},o.onupdate=function(){var t=!!this.attrs.disabled;this.disabled!==t&&(this.disabled=t,this.attrs.composer.editor.disabled(t))},o.buildEditorParams=function(){var t=this;return{classNames:["FormControl","Composer-flexible","TextEditor-editor"],disabled:this.disabled,placeholder:this.attrs.placeholder||"",value:this.value,oninput:this.oninput.bind(this),inputListeners:[],onsubmit:function(){t.onsubmit(),m.redraw()}}},o.buildEditor=function(t){return new l.Z(t,this.buildEditorParams())},o.controlItems=function(){var t=new s.Z;return t.add("submit",a.Z.component({icon:"fas fa-paper-plane",className:"Button Button--primary",itemClassName:"App-primaryControl",onclick:this.onsubmit.bind(this)},this.attrs.submitLabel)),this.attrs.preview&&t.add("preview",a.Z.component({icon:"far fa-eye",className:"Button Button--icon",onclick:this.attrs.preview,title:app.translator.trans("core.forum.composer.preview_tooltip"),oncreate:function(t){return $(t.dom).tooltip()}})),t},o.toolbarItems=function(){return new s.Z},o.oninput=function(t){this.value=t,this.attrs.onchange(this.value)},o.onsubmit=function(){this.attrs.onsubmit(this.value)},i}(r.Z)}}]);
//# sourceMappingURL=TextEditor.js.map

File diff suppressed because one or more lines are too long

53
js/dist/forum.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
(self.webpackChunkflarum_core=self.webpackChunkflarum_core||[]).push([[437],{2099:(t,s,e)=>{"use strict";e.r(s),e.d(s,{default:()=>a});var o=e(1788),i=e(8098),r=e(8165),n=e(9015),a=function(t){function s(){return t.apply(this,arguments)||this}(0,o.Z)(s,t),s.initAttrs=function(s){t.initAttrs.call(this,s),s.placeholder=s.placeholder||(0,r.Z)(app.translator.trans("core.forum.composer_discussion.body_placeholder")),s.submitLabel=s.submitLabel||app.translator.trans("core.forum.composer_discussion.submit_button"),s.confirmExit=s.confirmExit||(0,r.Z)(app.translator.trans("core.forum.composer_discussion.discard_confirmation")),s.titlePlaceholder=s.titlePlaceholder||(0,r.Z)(app.translator.trans("core.forum.composer_discussion.title_placeholder")),s.className="ComposerBody--discussion"};var e=s.prototype;return e.oninit=function(s){t.prototype.oninit.call(this,s),this.composer.fields.title=this.composer.fields.title||(0,n.Z)(""),this.title=this.composer.fields.title},e.headerItems=function(){var s=t.prototype.headerItems.call(this);return s.add("title",m("h3",null,app.translator.trans("core.forum.composer_discussion.title")),100),s.add("discussionTitle",m("h3",null,m("input",{className:"FormControl",bidi:this.title,placeholder:this.attrs.titlePlaceholder,disabled:!!this.attrs.disabled,onkeydown:this.onkeydown.bind(this)}))),s},e.onkeydown=function(t){13===t.which&&(t.preventDefault(),this.composer.editor.moveCursorTo(0)),t.redraw=!1},e.hasChanges=function(){return this.title()||this.composer.fields.content()},e.data=function(){return{title:this.title(),content:this.composer.fields.content()}},e.onsubmit=function(){var t=this;this.loading=!0;var s=this.data();app.store.createRecord("discussions").save(s).then((function(s){t.composer.hide(),app.discussions.refresh({deferClear:!0}),m.route.set(app.route.discussion(s))}),this.loaded.bind(this))},s}(i.Z)}}]);
//# sourceMappingURL=DiscussionComposer.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["webpack://@flarum/core/./src/forum/components/DiscussionComposer.js"],"names":["DiscussionComposer","initAttrs","attrs","placeholder","extractText","app","translator","trans","submitLabel","confirmExit","titlePlaceholder","className","oninit","vnode","this","composer","fields","title","Stream","headerItems","items","add","bidi","disabled","onkeydown","bind","e","which","preventDefault","editor","moveCursorTo","redraw","hasChanges","content","data","onsubmit","loading","store","createRecord","save","then","discussion","hide","discussions","refresh","deferClear","m","route","set","loaded","ComposerBody"],"mappings":"mLAeqBA,E,6EACZC,UAAP,SAAiBC,GACf,EAAMD,UAAN,UAAgBC,GAEhBA,EAAMC,YAAcD,EAAMC,cAAeC,OAAYC,IAAIC,WAAWC,MAAM,oDAC1EL,EAAMM,YAAcN,EAAMM,aAAeH,IAAIC,WAAWC,MAAM,gDAC9DL,EAAMO,YAAcP,EAAMO,cAAeL,OAAYC,IAAIC,WAAWC,MAAM,wDAC1EL,EAAMQ,iBAAmBR,EAAMQ,mBAAoBN,OAAYC,IAAIC,WAAWC,MAAM,qDACpFL,EAAMS,UAAY,4B,2BAGpBC,OAAA,SAAOC,GACL,YAAMD,OAAN,UAAaC,GAEbC,KAAKC,SAASC,OAAOC,MAAQH,KAAKC,SAASC,OAAOC,QAASC,OAAO,IAOlEJ,KAAKG,MAAQH,KAAKC,SAASC,OAAOC,O,EAGpCE,YAAA,WACE,IAAMC,EAAQ,EAAH,UAASD,YAAT,WAiBX,OAfAC,EAAMC,IAAI,QAAS,YAAKhB,IAAIC,WAAWC,MAAM,yCAA+C,KAE5Fa,EAAMC,IACJ,kBACA,YACE,WACEV,UAAU,cACVW,KAAMR,KAAKG,MACXd,YAAaW,KAAKZ,MAAMQ,iBACxBa,WAAYT,KAAKZ,MAAMqB,SACvBC,UAAWV,KAAKU,UAAUC,KAAKX,UAK9BM,G,EASTI,UAAA,SAAUE,GACQ,KAAZA,EAAEC,QAEJD,EAAEE,iBACFd,KAAKC,SAASc,OAAOC,aAAa,IAGpCJ,EAAEK,QAAS,G,EAGbC,WAAA,WACE,OAAOlB,KAAKG,SAAWH,KAAKC,SAASC,OAAOiB,W,EAQ9CC,KAAA,WACE,MAAO,CACLjB,MAAOH,KAAKG,QACZgB,QAASnB,KAAKC,SAASC,OAAOiB,Y,EAIlCE,SAAA,WAAW,WACTrB,KAAKsB,SAAU,EAEf,IAAMF,EAAOpB,KAAKoB,OAElB7B,IAAIgC,MACDC,aAAa,eACbC,KAAKL,GACLM,MAAK,SAACC,GACL,EAAK1B,SAAS2B,OACdrC,IAAIsC,YAAYC,QAAQ,CAAEC,YAAY,IACtCC,EAAEC,MAAMC,IAAI3C,IAAI0C,MAAMN,WAAWA,MAChC3B,KAAKmC,OAAOxB,KAAKX,Q,GAzFsBoC","file":"forum/components/DiscussionComposer.js","sourcesContent":["import ComposerBody from './ComposerBody';\nimport extractText from '../../common/utils/extractText';\nimport Stream from '../../common/utils/Stream';\n\n/**\n * The `DiscussionComposer` component displays the composer content for starting\n * a new discussion. It adds a text field as a header control so the user can\n * enter the title of their discussion. It also overrides the `submit` and\n * `willExit` actions to account for the title.\n *\n * ### Attrs\n *\n * - All of the attrs for ComposerBody\n * - `titlePlaceholder`\n */\nexport default class DiscussionComposer extends ComposerBody {\n static initAttrs(attrs) {\n super.initAttrs(attrs);\n\n attrs.placeholder = attrs.placeholder || extractText(app.translator.trans('core.forum.composer_discussion.body_placeholder'));\n attrs.submitLabel = attrs.submitLabel || app.translator.trans('core.forum.composer_discussion.submit_button');\n attrs.confirmExit = attrs.confirmExit || extractText(app.translator.trans('core.forum.composer_discussion.discard_confirmation'));\n attrs.titlePlaceholder = attrs.titlePlaceholder || extractText(app.translator.trans('core.forum.composer_discussion.title_placeholder'));\n attrs.className = 'ComposerBody--discussion';\n }\n\n oninit(vnode) {\n super.oninit(vnode);\n\n this.composer.fields.title = this.composer.fields.title || Stream('');\n\n /**\n * The value of the title input.\n *\n * @type {Function}\n */\n this.title = this.composer.fields.title;\n }\n\n headerItems() {\n const items = super.headerItems();\n\n items.add('title', <h3>{app.translator.trans('core.forum.composer_discussion.title')}</h3>, 100);\n\n items.add(\n 'discussionTitle',\n <h3>\n <input\n className=\"FormControl\"\n bidi={this.title}\n placeholder={this.attrs.titlePlaceholder}\n disabled={!!this.attrs.disabled}\n onkeydown={this.onkeydown.bind(this)}\n />\n </h3>\n );\n\n return items;\n }\n\n /**\n * Handle the title input's keydown event. When the return key is pressed,\n * move the focus to the start of the text editor.\n *\n * @param {Event} e\n */\n onkeydown(e) {\n if (e.which === 13) {\n // Return\n e.preventDefault();\n this.composer.editor.moveCursorTo(0);\n }\n\n e.redraw = false;\n }\n\n hasChanges() {\n return this.title() || this.composer.fields.content();\n }\n\n /**\n * Get the data to submit to the server when the discussion is saved.\n *\n * @return {Object}\n */\n data() {\n return {\n title: this.title(),\n content: this.composer.fields.content(),\n };\n }\n\n onsubmit() {\n this.loading = true;\n\n const data = this.data();\n\n app.store\n .createRecord('discussions')\n .save(data)\n .then((discussion) => {\n this.composer.hide();\n app.discussions.refresh({ deferClear: true });\n m.route.set(app.route.discussion(discussion));\n }, this.loaded.bind(this));\n }\n}\n"],"sourceRoot":""}

View File

@ -0,0 +1,2 @@
(self.webpackChunkflarum_core=self.webpackChunkflarum_core||[]).push([[799],{3928:(t,e,s)=>{"use strict";s.r(e),s.d(e,{default:()=>i});var n=s(1788),r=s(5308),o=s(2415),a=s(93),i=function(t){function e(){return t.apply(this,arguments)||this}(0,n.Z)(e,t);var s=e.prototype;return s.oninit=function(e){t.prototype.oninit.call(this,e),this.loadUser(m.route.param("username"))},s.show=function(e){t.prototype.show.call(this,e),this.state=new a.Z({q:"author:"+e.username(),sort:"newest"}),this.state.refresh()},s.content=function(){return m("div",{className:"DiscussionsUserPage"},o.Z.component({state:this.state}))},e}(r.Z)}}]);
//# sourceMappingURL=DiscussionsUserPage.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["webpack://@flarum/core/./src/forum/components/DiscussionsUserPage.js"],"names":["DiscussionsUserPage","oninit","vnode","this","loadUser","m","route","param","show","user","state","DiscussionListState","q","username","sort","refresh","content","className","DiscussionList","UserPage"],"mappings":"iLAQqBA,E,sGACnBC,OAAA,SAAOC,GACL,YAAMD,OAAN,UAAaC,GAEbC,KAAKC,SAASC,EAAEC,MAAMC,MAAM,c,EAG9BC,KAAA,SAAKC,GACH,YAAMD,KAAN,UAAWC,GAEXN,KAAKO,MAAQ,IAAIC,IAAoB,CACnCC,EAAG,UAAYH,EAAKI,WACpBC,KAAM,WAGRX,KAAKO,MAAMK,W,EAGbC,QAAA,WACE,OAAO,SAAKC,UAAU,uBAAuBC,cAAyB,CAAER,MAAOP,KAAKO,U,GAnBvCS","file":"forum/components/DiscussionsUserPage.js","sourcesContent":["import UserPage from './UserPage';\nimport DiscussionList from './DiscussionList';\nimport DiscussionListState from '../states/DiscussionListState';\n\n/**\n * The `DiscussionsUserPage` component shows a discussion list inside of a user\n * page.\n */\nexport default class DiscussionsUserPage extends UserPage {\n oninit(vnode) {\n super.oninit(vnode);\n\n this.loadUser(m.route.param('username'));\n }\n\n show(user) {\n super.show(user);\n\n this.state = new DiscussionListState({\n q: 'author:' + user.username(),\n sort: 'newest',\n });\n\n this.state.refresh();\n }\n\n content() {\n return <div className=\"DiscussionsUserPage\">{DiscussionList.component({ state: this.state })}</div>;\n }\n}\n"],"sourceRoot":""}

View File

@ -0,0 +1,2 @@
(self.webpackChunkflarum_core=self.webpackChunkflarum_core||[]).push([[352],{9106:(s,r,t)=>{"use strict";t.r(r),t.d(r,{default:()=>p});var e=t(1788),a=t(8292),i=t(5462),n=t(512),o=t(442),d=t(8165),u=t(7037),l=t(9015),p=function(s){function r(){return s.apply(this,arguments)||this}(0,e.Z)(r,s);var t=r.prototype;return t.oninit=function(r){var t=this;s.prototype.oninit.call(this,r);var e=this.attrs.user;this.username=(0,l.Z)(e.username()||""),this.email=(0,l.Z)(e.email()||""),this.isEmailConfirmed=(0,l.Z)(e.isEmailConfirmed()||!1),this.setPassword=(0,l.Z)(!1),this.password=(0,l.Z)(e.password()||""),this.groups={},app.store.all("groups").filter((function(s){return-1===[o.Z.GUEST_ID,o.Z.MEMBER_ID].indexOf(s.id())})).forEach((function(s){return t.groups[s.id()]=(0,l.Z)(-1!==e.groups().indexOf(s))}))},t.className=function(){return"EditUserModal Modal--small"},t.title=function(){return app.translator.trans("core.forum.edit_user.title")},t.content=function(){var s=this.fields().toArray();return m("div",{className:"Modal-body"},s.length>1?m("div",{className:"Form"},this.fields().toArray()):app.translator.trans("core.forum.edit_user.nothing_available"))},t.fields=function(){var s=this,r=new u.Z;return app.session.user.canEditCredentials()&&(r.add("username",m("div",{className:"Form-group"},m("label",null,app.translator.trans("core.forum.edit_user.username_heading")),m("input",{className:"FormControl",placeholder:(0,d.Z)(app.translator.trans("core.forum.edit_user.username_label")),bidi:this.username,disabled:this.nonAdminEditingAdmin()})),40),app.session.user!==this.attrs.user&&(r.add("email",m("div",{className:"Form-group"},m("label",null,app.translator.trans("core.forum.edit_user.email_heading")),m("div",null,m("input",{className:"FormControl",placeholder:(0,d.Z)(app.translator.trans("core.forum.edit_user.email_label")),bidi:this.email,disabled:this.nonAdminEditingAdmin()})),!this.isEmailConfirmed()&&this.userIsAdmin(app.session.user)?m("div",null,i.Z.component({className:"Button Button--block",loading:this.loading,onclick:this.activate.bind(this)},app.translator.trans("core.forum.edit_user.activate_button"))):""),30),r.add("password",m("div",{className:"Form-group"},m("label",null,app.translator.trans("core.forum.edit_user.password_heading")),m("div",null,m("label",{className:"checkbox"},m("input",{type:"checkbox",onchange:function(r){s.setPassword(r.target.checked),m.redraw.sync(),r.target.checked&&s.$("[name=password]").select(),r.redraw=!1},disabled:this.nonAdminEditingAdmin()}),app.translator.trans("core.forum.edit_user.set_password_label")),this.setPassword()?m("input",{className:"FormControl",type:"password",name:"password",placeholder:(0,d.Z)(app.translator.trans("core.forum.edit_user.password_label")),bidi:this.password,disabled:this.nonAdminEditingAdmin()}):"")),20))),app.session.user.canEditGroups()&&r.add("groups",m("div",{className:"Form-group EditUserModal-groups"},m("label",null,app.translator.trans("core.forum.edit_user.groups_heading")),m("div",null,Object.keys(this.groups).map((function(s){return app.store.getById("groups",s)})).map((function(r){return m("label",{className:"checkbox"},m("input",{type:"checkbox",bidi:s.groups[r.id()],disabled:r.id()===o.Z.ADMINISTRATOR_ID&&(s.attrs.user===app.session.user||!s.userIsAdmin(app.session.user))}),n.Z.component({group:r,label:""})," ",r.nameSingular())})))),10),r.add("submit",m("div",{className:"Form-group"},i.Z.component({className:"Button Button--primary",type:"submit",loading:this.loading},app.translator.trans("core.forum.edit_user.submit_button"))),-10),r},t.activate=function(){var s=this;this.loading=!0;var r={username:this.username(),isEmailConfirmed:!0};this.attrs.user.save(r,{errorHandler:this.onerror.bind(this)}).then((function(){s.isEmailConfirmed(!0),s.loading=!1,m.redraw()})).catch((function(){s.loading=!1,m.redraw()}))},t.data=function(){var s=this,r={relationships:{}};return this.attrs.user.canEditCredentials()&&!this.nonAdminEditingAdmin()&&(r.username=this.username(),app.session.user!==this.attrs.user&&(r.email=this.email()),this.setPassword()&&(r.password=this.password())),this.attrs.user.canEditGroups()&&(r.relationships.groups=Object.keys(this.groups).filter((function(r){return s.groups[r]()})).map((function(s){return app.store.getById("groups",s)}))),r},t.onsubmit=function(s){var r=this;s.preventDefault(),this.loading=!0,this.attrs.user.save(this.data(),{errorHandler:this.onerror.bind(this)}).then(this.hide.bind(this)).catch((function(){r.loading=!1,m.redraw()}))},t.nonAdminEditingAdmin=function(){return this.userIsAdmin(this.attrs.user)&&!this.userIsAdmin(app.session.user)},t.userIsAdmin=function(s){return s.groups().some((function(s){return s.id()===o.Z.ADMINISTRATOR_ID}))},r}(a.Z)}}]);
//# sourceMappingURL=EditUserModal.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
(self.webpackChunkflarum_core=self.webpackChunkflarum_core||[]).push([[502],{5999:(t,o,r)=>{"use strict";r.r(o),r.d(o,{default:()=>l});var a=r(1788),s=r(8292),e=r(5462),n=r(8165),i=r(9015),l=function(t){function o(){return t.apply(this,arguments)||this}(0,a.Z)(o,t);var r=o.prototype;return r.oninit=function(o){t.prototype.oninit.call(this,o),this.email=(0,i.Z)(this.attrs.email||""),this.success=!1},r.className=function(){return"ForgotPasswordModal Modal--small"},r.title=function(){return app.translator.trans("core.forum.forgot_password.title")},r.content=function(){return this.success?m("div",{className:"Modal-body"},m("div",{className:"Form Form--centered"},m("p",{className:"helpText"},app.translator.trans("core.forum.forgot_password.email_sent_message")),m("div",{className:"Form-group"},m(e.Z,{className:"Button Button--primary Button--block",onclick:this.hide.bind(this)},app.translator.trans("core.forum.forgot_password.dismiss_button"))))):m("div",{className:"Modal-body"},m("div",{className:"Form Form--centered"},m("p",{className:"helpText"},app.translator.trans("core.forum.forgot_password.text")),m("div",{className:"Form-group"},m("input",{className:"FormControl",name:"email",type:"email",placeholder:(0,n.Z)(app.translator.trans("core.forum.forgot_password.email_placeholder")),bidi:this.email,disabled:this.loading})),m("div",{className:"Form-group"},e.Z.component({className:"Button Button--primary Button--block",type:"submit",loading:this.loading},app.translator.trans("core.forum.forgot_password.submit_button")))))},r.onsubmit=function(t){var o=this;t.preventDefault(),this.loading=!0,app.request({method:"POST",url:app.forum.attribute("apiUrl")+"/forgot",body:{email:this.email()},errorHandler:this.onerror.bind(this)}).then((function(){o.success=!0,o.alert=null})).catch((function(){})).then(this.loaded.bind(this))},r.onerror=function(o){404===o.status&&(o.alert.content=app.translator.trans("core.forum.forgot_password.not_found_message")),t.prototype.onerror.call(this,o)},o}(s.Z)}}]);
//# sourceMappingURL=ForgotPasswordModal.js.map

View File

@ -0,0 +1 @@
{"version":3,"sources":["webpack://@flarum/core/./src/forum/components/ForgotPasswordModal.js"],"names":["ForgotPasswordModal","oninit","vnode","this","email","Stream","attrs","success","className","title","app","translator","trans","content","onclick","hide","bind","name","type","placeholder","extractText","bidi","disabled","loading","Button","onsubmit","e","preventDefault","request","method","url","forum","attribute","body","errorHandler","onerror","then","alert","loaded","error","status","Modal"],"mappings":"6LAaqBA,E,sGACnBC,OAAA,SAAOC,GACL,YAAMD,OAAN,UAAaC,GAObC,KAAKC,OAAQC,OAAOF,KAAKG,MAAMF,OAAS,IAOxCD,KAAKI,SAAU,G,EAGjBC,UAAA,WACE,MAAO,oC,EAGTC,MAAA,WACE,OAAOC,IAAIC,WAAWC,MAAM,qC,EAG9BC,QAAA,WACE,OAAIV,KAAKI,QAEL,SAAKC,UAAU,cACb,SAAKA,UAAU,uBACb,OAAGA,UAAU,YAAYE,IAAIC,WAAWC,MAAM,kDAC9C,SAAKJ,UAAU,cACb,EAAC,IAAD,CAAQA,UAAU,uCAAuCM,QAASX,KAAKY,KAAKC,KAAKb,OAC9EO,IAAIC,WAAWC,MAAM,iDAShC,SAAKJ,UAAU,cACb,SAAKA,UAAU,uBACb,OAAGA,UAAU,YAAYE,IAAIC,WAAWC,MAAM,oCAC9C,SAAKJ,UAAU,cACb,WACEA,UAAU,cACVS,KAAK,QACLC,KAAK,QACLC,aAAaC,OAAYV,IAAIC,WAAWC,MAAM,iDAC9CS,KAAMlB,KAAKC,MACXkB,SAAUnB,KAAKoB,WAGnB,SAAKf,UAAU,cACZgB,cACC,CACEhB,UAAW,uCACXU,KAAM,SACNK,QAASpB,KAAKoB,SAEhBb,IAAIC,WAAWC,MAAM,iD,EAQjCa,SAAA,SAASC,GAAG,WACVA,EAAEC,iBAEFxB,KAAKoB,SAAU,EAEfb,IACGkB,QAAQ,CACPC,OAAQ,OACRC,IAAKpB,IAAIqB,MAAMC,UAAU,UAAY,UACrCC,KAAM,CAAE7B,MAAOD,KAAKC,SACpB8B,aAAc/B,KAAKgC,QAAQnB,KAAKb,QAEjCiC,MAAK,WACJ,EAAK7B,SAAU,EACf,EAAK8B,MAAQ,QATjB,OAWS,eACND,KAAKjC,KAAKmC,OAAOtB,KAAKb,Q,EAG3BgC,QAAA,SAAQI,GACe,MAAjBA,EAAMC,SACRD,EAAMF,MAAMxB,QAAUH,IAAIC,WAAWC,MAAM,iDAG7C,YAAMuB,QAAN,UAAcI,I,GAjG+BE","file":"forum/components/ForgotPasswordModal.js","sourcesContent":["import Modal from '../../common/components/Modal';\nimport Button from '../../common/components/Button';\nimport extractText from '../../common/utils/extractText';\nimport Stream from '../../common/utils/Stream';\n\n/**\n * The `ForgotPasswordModal` component displays a modal which allows the user to\n * enter their email address and request a link to reset their password.\n *\n * ### Attrs\n *\n * - `email`\n */\nexport default class ForgotPasswordModal extends Modal {\n oninit(vnode) {\n super.oninit(vnode);\n\n /**\n * The value of the email input.\n *\n * @type {Function}\n */\n this.email = Stream(this.attrs.email || '');\n\n /**\n * Whether or not the password reset email was sent successfully.\n *\n * @type {Boolean}\n */\n this.success = false;\n }\n\n className() {\n return 'ForgotPasswordModal Modal--small';\n }\n\n title() {\n return app.translator.trans('core.forum.forgot_password.title');\n }\n\n content() {\n if (this.success) {\n return (\n <div className=\"Modal-body\">\n <div className=\"Form Form--centered\">\n <p className=\"helpText\">{app.translator.trans('core.forum.forgot_password.email_sent_message')}</p>\n <div className=\"Form-group\">\n <Button className=\"Button Button--primary Button--block\" onclick={this.hide.bind(this)}>\n {app.translator.trans('core.forum.forgot_password.dismiss_button')}\n </Button>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"Modal-body\">\n <div className=\"Form Form--centered\">\n <p className=\"helpText\">{app.translator.trans('core.forum.forgot_password.text')}</p>\n <div className=\"Form-group\">\n <input\n className=\"FormControl\"\n name=\"email\"\n type=\"email\"\n placeholder={extractText(app.translator.trans('core.forum.forgot_password.email_placeholder'))}\n bidi={this.email}\n disabled={this.loading}\n />\n </div>\n <div className=\"Form-group\">\n {Button.component(\n {\n className: 'Button Button--primary Button--block',\n type: 'submit',\n loading: this.loading,\n },\n app.translator.trans('core.forum.forgot_password.submit_button')\n )}\n </div>\n </div>\n </div>\n );\n }\n\n onsubmit(e) {\n e.preventDefault();\n\n this.loading = true;\n\n app\n .request({\n method: 'POST',\n url: app.forum.attribute('apiUrl') + '/forgot',\n body: { email: this.email() },\n errorHandler: this.onerror.bind(this),\n })\n .then(() => {\n this.success = true;\n this.alert = null;\n })\n .catch(() => {})\n .then(this.loaded.bind(this));\n }\n\n onerror(error) {\n if (error.status === 404) {\n error.alert.content = app.translator.trans('core.forum.forgot_password.not_found_message');\n }\n\n super.onerror(error);\n }\n}\n"],"sourceRoot":""}

2
js/dist/forum/components/IndexPage.js vendored Normal file
View File

@ -0,0 +1,2 @@
(self.webpackChunkflarum_core=self.webpackChunkflarum_core||[]).push([[847],{5785:(s,e,a)=>{"use strict";a.r(e),a.d(e,{default:()=>v});var t=a(1788),o=a(6156),n=a(3340),r=a(7037),i=a(1698),c=a(2415),p=a(9499),l=a(6801),u=a(8777),d=a(5462),h=a(7971),f=a(6317),v=function(s){function e(){return s.apply(this,arguments)||this}(0,t.Z)(e,s);var o=e.prototype;return o.oninit=function(a){s.prototype.oninit.call(this,a),app.previous.matches(l.Z)&&(this.lastDiscussion=app.previous.get("discussion")),app.previous.matches(e)&&app.discussions.clear(),app.discussions.refreshParams(app.search.params()),app.history.push("index",app.translator.trans("core.forum.header.back_to_index_tooltip")),this.bodyClass="App--index",this.scrollTopOnCreate=!1},o.view=function(){return m("div",{className:"IndexPage"},this.hero(),m("div",{className:"container"},m("div",{className:"sideNavContainer"},m("nav",{className:"IndexPage-nav sideNav"},m("ul",null,(0,i.Z)(this.sidebarItems().toArray()))),m("div",{className:"IndexPage-results sideNavOffset"},m("div",{className:"IndexPage-toolbar"},m("ul",{className:"IndexPage-toolbar-view"},(0,i.Z)(this.viewItems().toArray())),m("ul",{className:"IndexPage-toolbar-action"},(0,i.Z)(this.actionItems().toArray()))),m(c.Z,{state:app.discussions})))))},o.setTitle=function(){app.setTitle(app.translator.trans("core.forum.index.meta_title_text")),app.setTitleCount(0)},o.oncreate=function(e){s.prototype.oncreate.call(this,e),this.setTitle();var a=app.cache.heroHeight,t=app.cache.heroHeight=this.$(".Hero").outerHeight()||0,o=app.cache.scrollTop;if($("#app").css("min-height",$(window).height()+t),null!=app.previous.type&&("desktop"==app.screen()||"desktop-hd"==app.screen()||this.lastDiscussion?$(window).scrollTop(o-a+t):$(window).scrollTop(0),this.lastDiscussion)){var n=this.$('li[data-id="'+this.lastDiscussion.id()+'"] .DiscussionListItem');if(n.length){var r=$("#header").outerHeight(),i=$(window).height(),c=n.offset().top,p=c+n.outerHeight();(c<o+r||p>o+i)&&$(window).scrollTop(c-r)}}},o.onbeforeremove=function(){app.cache.scrollTop=$(window).scrollTop()},o.onremove=function(){s.prototype.onremove.call(this),$("#app").css("min-height","")},o.hero=function(){return p.Z.component()},o.sidebarItems=function(){var s=this,e=new r.Z,a=app.forum.attribute("canStartDiscussion")||!app.session.user;return e.add("newDiscussion",d.Z.component({icon:"fas fa-edit",className:"Button Button--primary IndexPage-newDiscussion",itemClassName:"App-primaryControl",onclick:function(){return s.newDiscussionAction().catch((function(){}))},disabled:!a},app.translator.trans(a?"core.forum.index.start_discussion_button":"core.forum.index.cannot_start_discussion_button"))),e.add("nav",f.Z.component({buttonClassName:"Button",className:"App-titleControl",accessibleToggleLabel:app.translator.trans("core.forum.index.toggle_sidenav_dropdown_accessible_label")},this.navItems(this).toArray())),e},o.navItems=function(){var s=new r.Z,e=app.search.stickyParams();return s.add("allDiscussions",h.Z.component({href:app.route("index",e),icon:"far fa-comments"},app.translator.trans("core.forum.index.all_discussions_link")),100),s},o.viewItems=function(){var s=new r.Z,e=app.discussions.sortMap(),a={};for(var t in e)a[t]=app.translator.trans("core.forum.index_sort."+t+"_button");return s.add("sort",u.Z.component({buttonClassName:"Button",label:a[app.search.params().sort]||Object.keys(e).map((function(s){return a[s]}))[0],accessibleToggleLabel:app.translator.trans("core.forum.index_sort.toggle_dropdown_accessible_label")},Object.keys(a).map((function(s){var t=a[s],o=(app.search.params().sort||Object.keys(e)[0])===s;return d.Z.component({icon:!o||"fas fa-check",onclick:app.search.changeSort.bind(app.search,s),active:o},t)})))),s},o.actionItems=function(){var s=new r.Z;return s.add("refresh",d.Z.component({title:app.translator.trans("core.forum.index.refresh_tooltip"),icon:"fas fa-sync",className:"Button Button--icon",onclick:function(){app.discussions.refresh(),app.session.user&&(app.store.find("users",app.session.user.id()),m.redraw())}})),app.session.user&&s.add("markAllAsRead",d.Z.component({title:app.translator.trans("core.forum.index.mark_all_as_read_tooltip"),icon:"fas fa-check",className:"Button Button--icon",onclick:this.markAllAsRead.bind(this)})),s},o.newDiscussionAction=function(){var s=function(){return a.e(460).then(a.bind(a,5127))},e=function(){return a.e(437).then(a.bind(a,2099))};return new Promise((function(a,t){return app.session.user?(app.composer.load(e,{user:app.session.user}),app.composer.show(),a(app.composer)):(app.modal.show(s),t())}))},o.markAllAsRead=function(){confirm(app.translator.trans("core.forum.index.mark_all_as_read_confirmation"))&&app.session.user.save({markedAllAsReadAt:new Date})},e}(n.Z);(0,o.Z)(v,"providesInitialSearch",!0)}}]);
//# sourceMappingURL=IndexPage.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
(self.webpackChunkflarum_core=self.webpackChunkflarum_core||[]).push([[460],{5127:(t,o,i)=>{"use strict";i.r(o),i.d(o,{default:()=>c});var n=i(1788),r=i(8292),a=i(5462),e=i(6349),s=i(8165),l=i(7037),d=i(9015),c=function(t){function o(){return t.apply(this,arguments)||this}(0,n.Z)(o,t);var r=o.prototype;return r.oninit=function(o){t.prototype.oninit.call(this,o),this.identification=(0,d.Z)(this.attrs.identification||""),this.password=(0,d.Z)(this.attrs.password||""),this.remember=(0,d.Z)(!!this.attrs.remember)},r.className=function(){return"LogInModal Modal--small"},r.title=function(){return app.translator.trans("core.forum.log_in.title")},r.content=function(){return[m("div",{className:"Modal-body"},this.body()),m("div",{className:"Modal-footer"},this.footer())]},r.body=function(){return[m(e.Z,null),m("div",{className:"Form Form--centered"},this.fields().toArray())]},r.fields=function(){var t=new l.Z;return t.add("identification",m("div",{className:"Form-group"},m("input",{className:"FormControl",name:"identification",type:"text",placeholder:(0,s.Z)(app.translator.trans("core.forum.log_in.username_or_email_placeholder")),bidi:this.identification,disabled:this.loading})),30),t.add("password",m("div",{className:"Form-group"},m("input",{className:"FormControl",name:"password",type:"password",placeholder:(0,s.Z)(app.translator.trans("core.forum.log_in.password_placeholder")),bidi:this.password,disabled:this.loading})),20),t.add("remember",m("div",{className:"Form-group"},m("div",null,m("label",{className:"checkbox"},m("input",{type:"checkbox",bidi:this.remember,disabled:this.loading}),app.translator.trans("core.forum.log_in.remember_me_label")))),10),t.add("submit",m("div",{className:"Form-group"},a.Z.component({className:"Button Button--primary Button--block",type:"submit",loading:this.loading},app.translator.trans("core.forum.log_in.submit_button"))),-10),t},r.footer=function(){return[m("p",{className:"LogInModal-forgotPassword"},m("a",{onclick:this.forgotPassword.bind(this)},app.translator.trans("core.forum.log_in.forgot_password_link"))),app.forum.attribute("allowSignUp")?m("p",{className:"LogInModal-signUp"},app.translator.trans("core.forum.log_in.sign_up_text",{a:m("a",{onclick:this.signUp.bind(this)})})):""]},r.forgotPassword=function(){var t=this.identification(),o=-1!==t.indexOf("@")?{email:t}:void 0;app.modal.show((function(){return i.e(502).then(i.bind(i,5999))}),o)},r.signUp=function(){var t={password:this.password()},o=this.identification();t[-1!==o.indexOf("@")?"email":"username"]=o,app.modal.show((function(){return i.e(395).then(i.bind(i,6999))}),t)},r.onready=function(){this.$("[name="+(this.identification()?"password":"identification")+"]").select()},r.onsubmit=function(t){t.preventDefault(),this.loading=!0;var o=this.identification(),i=this.password(),n=this.remember();app.session.login({identification:o,password:i,remember:n},{errorHandler:this.onerror.bind(this)}).then((function(){return window.location.reload()}),this.loaded.bind(this))},r.onerror=function(o){401===o.status&&(o.alert.content=app.translator.trans("core.forum.log_in.invalid_login_message")),t.prototype.onerror.call(this,o)},o}(r.Z)}}]);
//# sourceMappingURL=LogInModal.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
(self.webpackChunkflarum_core=self.webpackChunkflarum_core||[]).push([[77],{2047:(t,i,n)=>{"use strict";n.r(i),n.d(i,{default:()=>h});var o=n(1788),s=n(6366),a=n(1698),e=n(5462),r=n(9236),c=n(2232),u=n(2242),l=n(6149),f=n(5052),p=n(7603),d=function(t){function i(){return t.apply(this,arguments)||this}(0,o.Z)(i,t);var n=i.prototype;return n.icon=function(){return"fas fa-pencil-alt"},n.href=function(){var t=this.attrs.notification;return app.route.discussion(t.subject(),t.content().postNumber)},n.content=function(){return app.translator.trans("core.forum.notifications.discussion_renamed_text",{user:this.attrs.notification.fromUser()})},i}(function(t){function i(){return t.apply(this,arguments)||this}(0,o.Z)(i,t);var n=i.prototype;return n.view=function(){var t=this,i=this.attrs.notification,n=this.href();return m(r.Z,{className:"Notification Notification--"+i.contentType()+" "+(i.isRead()?"":"unread"),href:n,external:n.includes("://"),onclick:this.markAsRead.bind(this)},!i.isRead()&&e.Z.component({className:"Notification-action Button Button--icon Button--link",icon:"fas fa-check",title:app.translator.trans("core.forum.notifications.mark_as_read_tooltip"),onclick:function(i){i.preventDefault(),i.stopPropagation(),t.markAsRead()}}),(0,l.Z)(i.fromUser()),(0,f.Z)(this.icon(),{className:"Notification-icon"}),m("span",{className:"Notification-content"},this.content()),(0,p.Z)(i.createdAt()),m("div",{className:"Notification-excerpt"},this.excerpt()))},n.icon=function(){},n.href=function(){},n.content=function(){},n.excerpt=function(){},n.markAsRead=function(){this.attrs.notification.isRead()||(app.session.user.pushAttributes({unreadNotificationCount:app.session.user.unreadNotificationCount()-1}),this.attrs.notification.save({isRead:!0}))},i}(s.Z)),h=function(t){function i(){return t.apply(this,arguments)||this}(0,o.Z)(i,t);var n=i.prototype;return n.view=function(){var t=this,i=this.attrs.state,n=i.getNotificationPages();return m("div",{className:"NotificationList"},m("div",{className:"NotificationList-header"},m("div",{className:"App-primaryControl"},e.Z.component({className:"Button Button--icon Button--link",icon:"fas fa-check",title:app.translator.trans("core.forum.notifications.mark_all_as_read_tooltip"),onclick:i.markAllAsRead.bind(i)})),m("h4",{className:"App-titleControl App-titleControl--text"},app.translator.trans("core.forum.notifications.title"))),m("div",{className:"NotificationList-content"},n.length?n.map((function(i){var n=[],o={};return i.forEach((function(t){var i=t.subject();if(void 0!==i){var s=!1;i instanceof u.Z?s=i:i&&i.discussion&&(s=i.discussion());var a=s?s.id():0;o[a]=o[a]||{discussion:s,notifications:[]},o[a].notifications.push(t),-1===n.indexOf(o[a])&&n.push(o[a])}})),n.map((function(i){var n=i.discussion&&i.discussion.badges().toArray();return m("div",{className:"NotificationGroup"},i.discussion?m(r.Z,{className:"NotificationGroup-header",href:app.route.discussion(i.discussion)},n&&n.length?m("ul",{className:"NotificationGroup-badges badges"},(0,a.Z)(n)):"",i.discussion.title()):m("div",{className:"NotificationGroup-header"},app.forum.attribute("title")),m("ul",{className:"NotificationGroup-content"},i.notifications.map((function(i){var n=t.notificationComponents()[i.contentType()];return n?m("li",null,n.component({notification:i})):""}))))}))})):"",i.isLoading()?m(c.Z,{className:"LoadingIndicator--block"}):n.length?"":m("div",{className:"NotificationList-empty"},app.translator.trans("core.forum.notifications.empty_text"))))},n.notificationComponents=function(){return{discussionRenamed:d}},n.oncreate=function(i){t.prototype.oncreate.call(this,i),this.$notifications=this.$(".NotificationList-content"),this.$scrollParent=this.inPanel()?this.$notifications:$(window),this.boundScrollHandler=this.scrollHandler.bind(this),this.$scrollParent.on("scroll",this.boundScrollHandler)},n.onremove=function(){this.$scrollParent.off("scroll",this.boundScrollHandler)},n.scrollHandler=function(){var t=this.attrs.state,i=this.inPanel()?this.$scrollParent[0]:document.documentElement,n=Math.abs(i.scrollHeight-i.scrollTop-i.clientHeight)<=1;t.hasMoreResults()&&!t.isLoading()&&n&&t.loadMore()},n.inPanel=function(){return"auto"===this.$notifications.css("overflow")},i}(s.Z)}}]);
//# sourceMappingURL=NotificationList.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
(self.webpackChunkflarum_core=self.webpackChunkflarum_core||[]).push([[28],{1565:(t,s,e)=>{"use strict";e.d(s,{Z:()=>p});var i=e(1788),n=e(1795),o=e(1749),r=e(474),a=e(431),l=e(75),c=e(7037),h=e(1698),u=e(5462),d=e(108),p=function(t){function s(){return t.apply(this,arguments)||this}(0,i.Z)(s,t);var n=s.prototype;return n.oninit=function(s){var e=this;t.prototype.oninit.call(this,s),this.revealContent=!1,this.cardVisible=!1,this.subtree.check((function(){return e.cardVisible}),(function(){return e.isEditing()}),(function(){return e.revealContent}))},n.content=function(){return t.prototype.content.call(this).concat([m("header",{className:"Post-header"},m("ul",null,(0,h.Z)(this.headerItems().toArray()))),m("div",{className:"Post-body"},this.isEditing()?m(d.Z,{className:"Post-preview",composer:app.composer}):m.trust(this.attrs.post.contentHtml()))])},n.refreshContent=function(){var t=this.isEditing()?"":this.attrs.post.contentHtml();this.contentHtml!==t&&this.$(".Post-body script").each((function(){var t=document.createElement("script");t.textContent=this.textContent,Array.from(this.attributes).forEach((function(s){return t.setAttribute(s.name,s.value)})),this.parentNode.replaceChild(t,this)})),this.contentHtml=t},n.oncreate=function(s){t.prototype.oncreate.call(this,s),this.refreshContent()},n.onupdate=function(s){t.prototype.onupdate.call(this,s),this.refreshContent()},n.isEditing=function(){var t=this;Promise.resolve().then(e.bind(e,4588)).then((function(s){return app.composer.bodyMatches(s.default,{post:t.attrs.post})}))},n.elementAttrs=function(){var s=this.attrs.post,e=t.prototype.elementAttrs.call(this);return e.className=(e.className||"")+" "+(0,o.Z)({CommentPost:!0,"Post--hidden":s.isHidden(),"Post--edited":s.isEdited(),revealContent:this.revealContent,editing:this.isEditing()}),e},n.toggleContent=function(){this.revealContent=!this.revealContent},n.headerItems=function(){var t=this,s=new c.Z,e=this.attrs.post;return s.add("user",r.Z.component({post:e,cardVisible:this.cardVisible,oncardshow:function(){t.cardVisible=!0,m.redraw()},oncardhide:function(){t.cardVisible=!1,m.redraw()}}),100),s.add("meta",a.Z.component({post:e})),e.isEdited()&&!e.isHidden()&&s.add("edited",l.Z.component({post:e})),e.isHidden()&&s.add("toggle",u.Z.component({className:"Button Button--default Button--more",icon:"fas fa-ellipsis-h",onclick:this.toggleContent.bind(this)})),s},s}(n.Z)},4958:(t,s,e)=>{"use strict";e.r(s),e.d(s,{default:()=>h});var i=e(1788),n=e(5308),o=e(2232),r=e(5462),a=e(9236),l=e(4389),c=e(1565),h=function(t){function s(){return t.apply(this,arguments)||this}(0,i.Z)(s,t);var e=s.prototype;return e.oninit=function(s){t.prototype.oninit.call(this,s),this.loading=!0,this.moreResults=!1,this.posts=[],this.loadLimit=20,this.loadUser(m.route.param("username"))},e.content=function(){return 0!==this.posts.length||this.loading?(this.loading?t=m(o.Z,null):this.moreResults&&(t=m("div",{className:"PostsUserPage-loadMore"},m(r.Z,{className:"Button",onclick:this.loadMore.bind(this)},app.translator.trans("core.forum.user.posts_load_more_button")))),m("div",{className:"PostsUserPage"},m("ul",{className:"PostsUserPage-list"},this.posts.map((function(t){return m("li",null,m("div",{className:"PostsUserPage-discussion"},app.translator.trans("core.forum.user.in_discussion_text",{discussion:m(a.Z,{href:app.route.post(t)},t.discussion().title())})),m(c.Z,{post:t}))}))),m("div",{className:"PostsUserPage-loadMore"},t))):m("div",{className:"PostsUserPage"},m(l.Z,{text:app.translator.trans("core.forum.user.posts_empty_text")}));var t},e.show=function(s){t.prototype.show.call(this,s),this.refresh()},e.refresh=function(){this.loading=!0,this.posts=[],m.redraw(),this.loadResults().then(this.parseResults.bind(this))},e.loadResults=function(t){return app.store.find("posts",{filter:{author:this.user.username(),type:"comment"},page:{offset:t,limit:this.loadLimit},sort:"-createdAt"})},e.loadMore=function(){this.loading=!0,this.loadResults(this.posts.length).then(this.parseResults.bind(this))},e.parseResults=function(t){return this.loading=!1,[].push.apply(this.posts,t),this.moreResults=t.length>=this.loadLimit,m.redraw(),t},s}(n.Z)}}]);
//# sourceMappingURL=PostsUserPage.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
(self.webpackChunkflarum_core=self.webpackChunkflarum_core||[]).push([[826],{7839:(t,e,n)=>{"use strict";n.r(e),n.d(e,{default:()=>y});var i=n(1788),a=n(5308),o=n(7037),r=n(4435),s=n(5462),c=n(9226),l=n(6366),u=n(9699),f=n(5052),d=function(t){function e(){return t.apply(this,arguments)||this}(0,i.Z)(e,t);var n=e.prototype;return n.oninit=function(e){t.prototype.oninit.call(this,e),this.methods=this.notificationMethods().toArray(),this.loading={},this.types=this.notificationTypes().toArray()},n.view=function(){var t=this,e=this.attrs.user.preferences();return m("table",{className:"NotificationGrid"},m("thead",null,m("tr",null,m("td",null),this.methods.map((function(e){return m("th",{className:"NotificationGrid-groupToggle",onclick:t.toggleMethod.bind(t,e.name)},(0,f.Z)(e.icon)," ",e.label)})))),m("tbody",null,this.types.map((function(n){return m("tr",null,m("td",{className:"NotificationGrid-groupToggle",onclick:t.toggleType.bind(t,n.name)},(0,f.Z)(n.icon)," ",n.label),t.methods.map((function(i){var a=t.preferenceKey(n.name,i.name);return m("td",{className:"NotificationGrid-checkbox"},m(u.Z,{state:!!e[a],loading:t.loading[a],disabled:!(a in e),onchange:t.toggle.bind(t,[a])}))})))}))))},n.oncreate=function(e){t.prototype.oncreate.call(this,e),this.$("thead .NotificationGrid-groupToggle").bind("mouseenter mouseleave",(function(t){var e=parseInt($(this).index(),10)+1;$(this).parents("table").find("td:nth-child("+e+")").toggleClass("highlighted","mouseenter"===t.type)})),this.$("tbody .NotificationGrid-groupToggle").bind("mouseenter mouseleave",(function(t){$(this).parent().find("td").toggleClass("highlighted","mouseenter"===t.type)}))},n.toggle=function(t){var e=this,n=this.attrs.user,i=n.preferences(),a=!i[t[0]];t.forEach((function(t){e.loading[t]=!0,i[t]=a})),m.redraw(),n.save({preferences:i}).then((function(){t.forEach((function(t){return e.loading[t]=!1})),m.redraw()}))},n.toggleMethod=function(t){var e=this,n=this.types.map((function(n){return e.preferenceKey(n.name,t)})).filter((function(t){return t in e.attrs.user.preferences()}));this.toggle(n)},n.toggleType=function(t){var e=this,n=this.methods.map((function(n){return e.preferenceKey(t,n.name)})).filter((function(t){return t in e.attrs.user.preferences()}));this.toggle(n)},n.preferenceKey=function(t,e){return"notify_"+t+"_"+e},n.notificationMethods=function(){var t=new o.Z;return t.add("alert",{name:"alert",icon:"fas fa-bell",label:app.translator.trans("core.forum.settings.notify_by_web_heading")}),t.add("email",{name:"email",icon:"far fa-envelope",label:app.translator.trans("core.forum.settings.notify_by_email_heading")}),t},n.notificationTypes=function(){var t=new o.Z;return t.add("discussionRenamed",{name:"discussionRenamed",icon:"fas fa-pencil-alt",label:app.translator.trans("core.forum.settings.notify_discussion_renamed_label")}),t},e}(l.Z),p=n(631),h=n(4338),g=n(1698),y=function(t){function e(){return t.apply(this,arguments)||this}(0,i.Z)(e,t);var n=e.prototype;return n.oninit=function(e){t.prototype.oninit.call(this,e),this.show(app.session.user),app.setTitle(app.translator.trans("core.forum.settings.title"))},n.content=function(){return m("div",{className:"SettingsPage"},m("ul",null,(0,g.Z)(this.settingsItems().toArray())))},n.settingsItems=function(){var t=this,e=new o.Z;return["account","notifications","privacy"].forEach((function(n){e.add(n,m(c.Z,{className:"Settings-"+n,label:app.translator.trans("core.forum.settings."+n+"_heading")},t[n+"Items"]().toArray()))})),e},n.accountItems=function(){var t=new o.Z;return t.add("changePassword",m(s.Z,{className:"Button",onclick:function(){return app.modal.show(p.Z)}},app.translator.trans("core.forum.settings.change_password_button"))),t.add("changeEmail",m(s.Z,{className:"Button",onclick:function(){return app.modal.show(h.Z)}},app.translator.trans("core.forum.settings.change_email_button"))),t},n.notificationsItems=function(){var t=new o.Z;return t.add("notificationGrid",m(d,{user:this.user})),t},n.privacyItems=function(){var t=this,e=new o.Z;return e.add("discloseOnline",m(r.Z,{state:this.user.preferences().discloseOnline,onchange:function(e){t.discloseOnlineLoading=!0,t.user.savePreferences({discloseOnline:e}).then((function(){t.discloseOnlineLoading=!1,m.redraw()}))},loading:this.discloseOnlineLoading},app.translator.trans("core.forum.settings.privacy_disclose_online_label"))),e},e}(a.Z)}}]);
//# sourceMappingURL=SettingsPage.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
(self.webpackChunkflarum_core=self.webpackChunkflarum_core||[]).push([[395],{6999:(t,a,s)=>{"use strict";s.r(a),s.d(a,{default:()=>u});var r=s(1788),e=s(8292),i=s(5462),o=s(6349),n=s(8165),l=s(7037),d=s(9015),u=function(t){function a(){return t.apply(this,arguments)||this}(0,r.Z)(a,t);var e=a.prototype;return e.oninit=function(a){t.prototype.oninit.call(this,a),this.username=(0,d.Z)(this.attrs.username||""),this.email=(0,d.Z)(this.attrs.email||""),this.password=(0,d.Z)(this.attrs.password||"")},e.className=function(){return"Modal--small SignUpModal"},e.title=function(){return app.translator.trans("core.forum.sign_up.title")},e.content=function(){return[m("div",{className:"Modal-body"},this.body()),m("div",{className:"Modal-footer"},this.footer())]},e.isProvided=function(t){return this.attrs.provided&&-1!==this.attrs.provided.indexOf(t)},e.body=function(){return[this.attrs.token?"":m(o.Z,null),m("div",{className:"Form Form--centered"},this.fields().toArray())]},e.fields=function(){var t=new l.Z;return t.add("username",m("div",{className:"Form-group"},m("input",{className:"FormControl",name:"username",type:"text",placeholder:(0,n.Z)(app.translator.trans("core.forum.sign_up.username_placeholder")),bidi:this.username,disabled:this.loading||this.isProvided("username")})),30),t.add("email",m("div",{className:"Form-group"},m("input",{className:"FormControl",name:"email",type:"email",placeholder:(0,n.Z)(app.translator.trans("core.forum.sign_up.email_placeholder")),bidi:this.email,disabled:this.loading||this.isProvided("email")})),20),this.attrs.token||t.add("password",m("div",{className:"Form-group"},m("input",{className:"FormControl",name:"password",type:"password",placeholder:(0,n.Z)(app.translator.trans("core.forum.sign_up.password_placeholder")),bidi:this.password,disabled:this.loading})),10),t.add("submit",m("div",{className:"Form-group"},m(i.Z,{className:"Button Button--primary Button--block",type:"submit",loading:this.loading},app.translator.trans("core.forum.sign_up.submit_button"))),-10),t},e.footer=function(){return[m("p",{className:"SignUpModal-logIn"},app.translator.trans("core.forum.sign_up.log_in_text",{a:m("a",{onclick:this.logIn.bind(this)})}))]},e.logIn=function(){var t={identification:this.email()||this.username(),password:this.password()};app.modal.show((function(){return s.e(460).then(s.bind(s,5127))}),t)},e.onready=function(){this.attrs.username&&!this.attrs.email?this.$("[name=email]").select():this.$("[name=username]").select()},e.onsubmit=function(t){t.preventDefault(),this.loading=!0;var a=this.submitData();app.request({url:app.forum.attribute("baseUrl")+"/register",method:"POST",body:a,errorHandler:this.onerror.bind(this)}).then((function(){return window.location.reload()}),this.loaded.bind(this))},e.submitData=function(){var t={username:this.username(),email:this.email()};return this.attrs.token?t.token=this.attrs.token:t.password=this.password(),t},a}(e.Z)}}]);
//# sourceMappingURL=SignUpModal.js.map

File diff suppressed because one or more lines are too long

3
js/dist/forum/flarum-core.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,28 @@
/*!
* Block below copied from Protovis: http://mbostock.github.com/protovis/
* Copyright 2010 Stanford Visualization Group
* Licensed under the BSD License: http://www.opensource.org/licenses/bsd-license.php
*/
/*!
* Color Thief v2.0
* by Lokesh Dhakar - http://www.lokeshdhakar.com
*
* Thanks
* ------
* Nick Rabinowitz - For creating quantize.js.
* John Schulz - For clean up and optimization. @JFSIII
* Nathan Spady - For adding drag and drop support to the demo page.
*
* License
* -------
* Copyright 2011, 2015 Lokesh Dhakar
* Released under the MIT license
* https://raw.githubusercontent.com/lokesh/color-thief/master/LICENSE
*
*/
/*!
* quantize.js Copyright 2008 Nick Rabinowitz.
* Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
*/

1
js/dist/forum/flarum-core.js.map vendored Normal file

File diff suppressed because one or more lines are too long

2
js/dist/forum/flarum-core~runtime.js vendored Normal file
View File

@ -0,0 +1,2 @@
(()=>{"use strict";var e,o,r,t={},n={};function a(e){var o=n[e];if(void 0!==o)return o.exports;var r=n[e]={exports:{}};return t[e].call(r.exports,r,r.exports,a),r.exports}a.m=t,e=[],a.O=(o,r,t,n)=>{if(!r){var s=1/0;for(l=0;l<e.length;l++){for(var[r,t,n]=e[l],i=!0,u=0;u<r.length;u++)(!1&n||s>=n)&&Object.keys(a.O).every((e=>a.O[e](r[u])))?r.splice(u--,1):(i=!1,n<s&&(s=n));i&&(e.splice(l--,1),o=t())}return o}n=n||0;for(var l=e.length;l>0&&e[l-1][2]>n;l--)e[l]=e[l-1];e[l]=[r,t,n]},a.n=e=>{var o=e&&e.__esModule?()=>e.default:()=>e;return a.d(o,{a:o}),o},a.d=(e,o)=>{for(var r in o)a.o(o,r)&&!a.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:o[r]})},a.f={},a.e=e=>Promise.all(Object.keys(a.f).reduce(((o,r)=>(a.f[r](e,o),o)),[])),a.u=e=>({28:"forum/components/PostsUserPage",77:"forum/components/NotificationList",247:"common/components/TextEditor",352:"forum/components/EditUserModal",395:"forum/components/SignUpModal",437:"forum/components/DiscussionComposer",460:"forum/components/LogInModal",502:"forum/components/ForgotPasswordModal",563:"forum/components/PostStream",799:"forum/components/DiscussionsUserPage",826:"forum/components/SettingsPage",847:"forum/components/IndexPage"}[e]+".js"),a.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),a.o=(e,o)=>Object.prototype.hasOwnProperty.call(e,o),o={},r="flarum.core:",a.l=(e,t,n,s)=>{if(o[e])o[e].push(t);else{var i,u;if(void 0!==n)for(var l=document.getElementsByTagName("script"),c=0;c<l.length;c++){var f=l[c];if(f.getAttribute("src")==e||f.getAttribute("data-webpack")==r+n){i=f;break}}i||(u=!0,(i=document.createElement("script")).charset="utf-8",i.timeout=120,a.nc&&i.setAttribute("nonce",a.nc),i.setAttribute("data-webpack",r+n),i.src=e),o[e]=[t];var d=(r,t)=>{i.onerror=i.onload=null,clearTimeout(m);var n=o[e];if(delete o[e],i.parentNode&&i.parentNode.removeChild(i),n&&n.forEach((e=>e(t))),r)return r(t)},m=setTimeout(d.bind(null,void 0,{type:"timeout",target:i}),12e4);i.onerror=d.bind(null,i.onerror),i.onload=d.bind(null,i.onload),u&&document.head.appendChild(i)}},a.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.p="/assets/",(()=>{var e={638:0};a.f.j=(o,r)=>{var t=a.o(e,o)?e[o]:void 0;if(0!==t)if(t)r.push(t[2]);else if(638!=o){var n=new Promise(((r,n)=>t=e[o]=[r,n]));r.push(t[2]=n);var s=a.p+a.u(o),i=new Error;a.l(s,(r=>{if(a.o(e,o)&&(0!==(t=e[o])&&(e[o]=void 0),t)){var n=r&&("load"===r.type?"missing":r.type),s=r&&r.target&&r.target.src;i.message="Loading chunk "+o+" failed.\n("+n+": "+s+")",i.name="ChunkLoadError",i.type=n,i.request=s,t[1](i)}}),"chunk-"+o,o)}else e[o]=0},a.O.j=o=>0===e[o];var o=(o,r)=>{var t,n,[s,i,u]=r,l=0;for(t in i)a.o(i,t)&&(a.m[t]=i[t]);for(u&&u(a),o&&o(r);l<s.length;l++)n=s[l],a.o(e,n)&&e[n]&&e[n][0](),e[s[l]]=0;a.O()},r=self.webpackChunkflarum_core=self.webpackChunkflarum_core||[];r.forEach(o.bind(null,0)),r.push=o.bind(null,r.push.bind(r))})(),a.O()})();
//# sourceMappingURL=flarum-core~runtime.js.map

File diff suppressed because one or more lines are too long

3
js/dist/forum/vendor.js vendored Normal file

File diff suppressed because one or more lines are too long

24
js/dist/forum/vendor.js.LICENSE.txt vendored Normal file
View File

@ -0,0 +1,24 @@
/*!
* Sizzle CSS Selector Engine v2.3.6
* https://sizzlejs.com/
*
* Copyright JS Foundation and other contributors
* Released under the MIT license
* https://js.foundation/
*
* Date: 2021-02-16
*/
/*!
* jQuery JavaScript Library v3.6.0
* https://jquery.com/
*
* Includes Sizzle.js
* https://sizzlejs.com/
*
* Copyright OpenJS Foundation and other contributors
* Released under the MIT license
* https://jquery.org/license
*
* Date: 2021-03-02T17:08Z
*/

1
js/dist/forum/vendor.js.map vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -8,4 +8,4 @@
*/
export * from './src/common';
export * from './src/forum';
export * from './src/forum';

7271
js/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -16,19 +16,23 @@
"textarea-caret": "^3.1.0"
},
"devDependencies": {
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-syntax-top-level-await": "^7.12.13",
"@babel/preset-typescript": "^7.13.0",
"@types/jquery": "^3.5.5",
"@types/lodash-es": "^4.17.4",
"@types/mithril": "^2.0.7",
"@types/punycode": "^2.1.0",
"@types/textarea-caret": "^3.0.0",
"babel-plugin-add-module-exports": "^1.0.4",
"bundlewatch": "^0.3.2",
"flarum-webpack-config": "0.1.0-beta.10",
"husky": "^4.3.8",
"prettier": "^2.2.1",
"webpack": "^4.46.0",
"webpack-cli": "^3.3.12",
"webpack-merge": "^4.2.2"
"terser-webpack-plugin": "~5.1.1",
"webpack": "~5.33.2",
"webpack-cli": "~4.6.0",
"webpack-merge": "~5.7.3"
},
"scripts": {
"dev": "webpack --mode development --watch",

View File

@ -57,8 +57,7 @@ import ModalManager from './components/ModalManager';
import Button from './components/Button';
import Modal from './components/Modal';
import GroupBadge from './components/GroupBadge';
import TextEditor from './components/TextEditor';
import TextEditorButton from './components/TextEditorButton';
//import TextEditorButton from './components/TextEditorButton';
import Model from './Model';
import Application from './Application';
import fullTime from './helpers/fullTime';
@ -134,8 +133,8 @@ export default {
'components/Button': Button,
'components/Modal': Modal,
'components/GroupBadge': GroupBadge,
'components/TextEditor': TextEditor,
'components/TextEditorButton': TextEditorButton,
//'components/TextEditor': TextEditor,
//'components/TextEditorButton': TextEditorButton,
Model: Model,
Application: Application,
'helpers/fullTime': fullTime,

View File

@ -1,4 +1,4 @@
import Mithril from 'mithril';
import Component from '../Component';
/**
* Generates a route resolver for a given component.
@ -7,7 +7,7 @@ import Mithril from 'mithril';
* - It sets a key on the component so a rerender will be triggered on route change.
*/
export default class DefaultResolver {
component: Mithril.Component;
component: Component | Function;
routeName: string;
constructor(component, routeName) {
@ -31,8 +31,13 @@ export default class DefaultResolver {
};
}
onmatch(args, requestedPath, route) {
return this.component;
async onmatch(args, requestedPath, route) {
if (typeof this.component.component === 'function') {
return this.component;
} else {
const component = await this.component();
return component.default;
}
}
render(vnode) {

View File

@ -10,12 +10,17 @@ export default class ModalManagerState {
*
* @public
*/
show(componentClass, attrs) {
async show(componentClass, attrs) {
// Breaking Change Compliance Warning, Remove in Beta 15.
if (!(componentClass.prototype instanceof Modal)) {
// This is duplicated so that if the error is caught, an error message still shows up in the debug console.
console.error('The ModalManager can only show Modals');
throw new Error('The ModalManager can only show Modals');
if (typeof componentClass === 'function') {
const componentResolver = await componentClass();
componentClass = componentResolver.default;
} else {
// This is duplicated so that if the error is caught, an error message still shows up in the debug console.
console.error('The ModalManager can only show Modals');
throw new Error('The ModalManager can only show Modals');
}
}
if (componentClass.init) {
// This is duplicated so that if the error is caught, an error message still shows up in the debug console.

View File

@ -29,7 +29,7 @@ export default function humanTime(time: Date): string {
ago = d.format('ll');
}
} else {
ago = d.fromNow();
ago = '5 days';
}
return ago;

View File

@ -1,13 +1,9 @@
import History from './utils/History';
import Pane from './utils/Pane';
import DiscussionPage from './components/DiscussionPage';
import SignUpModal from './components/SignUpModal';
import HeaderPrimary from './components/HeaderPrimary';
import HeaderSecondary from './components/HeaderSecondary';
import Composer from './components/Composer';
import DiscussionRenamedNotification from './components/DiscussionRenamedNotification';
import CommentPost from './components/CommentPost';
import DiscussionRenamedPost from './components/DiscussionRenamedPost';
import routes from './routes';
import alertEmailConfirmation from './utils/alertEmailConfirmation';
import Application from '../common/Application';
@ -19,24 +15,6 @@ import ComposerState from './states/ComposerState';
import isSafariMobile from './utils/isSafariMobile';
export default class ForumApplication extends Application {
/**
* A map of notification types to their components.
*
* @type {Object}
*/
notificationComponents = {
discussionRenamed: DiscussionRenamedNotification,
};
/**
* A map of post types to their components.
*
* @type {Object}
*/
postComponents = {
comment: CommentPost,
discussionRenamed: DiscussionRenamedPost,
};
/**
* An object which controls the state of the page's side pane.
*
@ -153,8 +131,8 @@ export default class ForumApplication extends Application {
* @param {Discussion} discussion
* @return {Boolean}
*/
viewingDiscussion(discussion) {
return this.current.matches(DiscussionPage, { discussion });
async viewingDiscussion(discussion) {
return this.current.matches(DiscussionPage.default, { discussion });
}
/**
@ -174,6 +152,8 @@ export default class ForumApplication extends Application {
if (payload.loggedIn) {
window.location.reload();
} else {
const SignUpModal = () => import(/* webpackChunkName: "forum/components/SignUpModal" */ './components/SignUpModal');
this.modal.show(SignUpModal, payload);
}
}

View File

@ -15,61 +15,61 @@ import NotificationListState from './states/NotificationListState';
import PostStreamState from './states/PostStreamState';
import SearchState from './states/SearchState';
import AffixedSidebar from './components/AffixedSidebar';
import DiscussionPage from './components/DiscussionPage';
//import DiscussionPage from './components/DiscussionPage';
import DiscussionListPane from './components/DiscussionListPane';
import LogInModal from './components/LogInModal';
import ComposerBody from './components/ComposerBody';
import ForgotPasswordModal from './components/ForgotPasswordModal';
import Notification from './components/Notification';
//import LogInModal from './components/LogInModal';
//import ComposerBody from './components/ComposerBody';
//import ForgotPasswordModal from './components/ForgotPasswordModal';
//import Notification from './components/Notification';
import LogInButton from './components/LogInButton';
import DiscussionsUserPage from './components/DiscussionsUserPage';
import Composer from './components/Composer';
//import DiscussionsUserPage from './components/DiscussionsUserPage';
//import Composer from './components/Composer';
import SessionDropdown from './components/SessionDropdown';
import HeaderPrimary from './components/HeaderPrimary';
import PostEdited from './components/PostEdited';
import PostStream from './components/PostStream';
//import PostStream from './components/PostStream';
import ChangePasswordModal from './components/ChangePasswordModal';
import IndexPage from './components/IndexPage';
import DiscussionRenamedNotification from './components/DiscussionRenamedNotification';
//import IndexPage from './components/IndexPage';
//import DiscussionRenamedNotification from './components/DiscussionRenamedNotification';
import DiscussionsSearchSource from './components/DiscussionsSearchSource';
import HeaderSecondary from './components/HeaderSecondary';
import ComposerButton from './components/ComposerButton';
import DiscussionList from './components/DiscussionList';
import ReplyPlaceholder from './components/ReplyPlaceholder';
//import ReplyPlaceholder from './components/ReplyPlaceholder';
import AvatarEditor from './components/AvatarEditor';
import Post from './components/Post';
import SettingsPage from './components/SettingsPage';
//import SettingsPage from './components/SettingsPage';
import TerminalPost from './components/TerminalPost';
import ChangeEmailModal from './components/ChangeEmailModal';
import NotificationsDropdown from './components/NotificationsDropdown';
import UserPage from './components/UserPage';
//import UserPage from './components/UserPage';
import PostUser from './components/PostUser';
import UserCard from './components/UserCard';
import UsersSearchSource from './components/UsersSearchSource';
import NotificationGrid from './components/NotificationGrid';
//import NotificationGrid from './components/NotificationGrid';
import PostPreview from './components/PostPreview';
import EventPost from './components/EventPost';
import DiscussionHero from './components/DiscussionHero';
import PostMeta from './components/PostMeta';
import EditUserModal from './components/EditUserModal';
//import EditUserModal from './components/EditUserModal';
import SearchSource from './components/SearchSource';
import DiscussionRenamedPost from './components/DiscussionRenamedPost';
import DiscussionComposer from './components/DiscussionComposer';
//import DiscussionRenamedPost from './components/DiscussionRenamedPost';
//import DiscussionComposer from './components/DiscussionComposer';
import LogInButtons from './components/LogInButtons';
import NotificationList from './components/NotificationList';
//import NotificationList from './components/NotificationList';
import WelcomeHero from './components/WelcomeHero';
import SignUpModal from './components/SignUpModal';
import CommentPost from './components/CommentPost';
//import SignUpModal from './components/SignUpModal';
//import CommentPost from './components/CommentPost';
import ComposerPostPreview from './components/ComposerPostPreview';
import ReplyComposer from './components/ReplyComposer';
import NotificationsPage from './components/NotificationsPage';
import PostStreamScrubber from './components/PostStreamScrubber';
import EditPostComposer from './components/EditPostComposer';
//import ReplyComposer from './components/ReplyComposer';
//import NotificationsPage from './components/NotificationsPage';
//import PostStreamScrubber from './components/PostStreamScrubber';
//import EditPostComposer from './components/EditPostComposer';
import RenameDiscussionModal from './components/RenameDiscussionModal';
import Search from './components/Search';
import DiscussionListItem from './components/DiscussionListItem';
//import DiscussionListItem from './components/DiscussionListItem';
import LoadingPost from './components/LoadingPost';
import PostsUserPage from './components/PostsUserPage';
//import PostsUserPage from './components/PostsUserPage';
import DiscussionPageResolver from './resolvers/DiscussionPageResolver';
import BasicEditorDriver from '../common/utils/BasicEditorDriver';
import routes from './routes';
@ -92,61 +92,61 @@ export default Object.assign(compat, {
'states/PostStreamState': PostStreamState,
'states/SearchState': SearchState,
'components/AffixedSidebar': AffixedSidebar,
'components/DiscussionPage': DiscussionPage,
//'components/DiscussionPage': DiscussionPage,
'components/DiscussionListPane': DiscussionListPane,
'components/LogInModal': LogInModal,
'components/ComposerBody': ComposerBody,
'components/ForgotPasswordModal': ForgotPasswordModal,
'components/Notification': Notification,
//'components/LogInModal': LogInModal,
//'components/ComposerBody': ComposerBody,
//'components/ForgotPasswordModal': ForgotPasswordModal,
//'components/Notification': Notification,
'components/LogInButton': LogInButton,
'components/DiscussionsUserPage': DiscussionsUserPage,
'components/Composer': Composer,
//'components/DiscussionsUserPage': DiscussionsUserPage,
//'components/Composer': Composer,
'components/SessionDropdown': SessionDropdown,
'components/HeaderPrimary': HeaderPrimary,
'components/PostEdited': PostEdited,
'components/PostStream': PostStream,
//'components/PostStream': PostStream,
'components/ChangePasswordModal': ChangePasswordModal,
'components/IndexPage': IndexPage,
'components/DiscussionRenamedNotification': DiscussionRenamedNotification,
//'components/IndexPage': IndexPage,
//'components/DiscussionRenamedNotification': DiscussionRenamedNotification,
'components/DiscussionsSearchSource': DiscussionsSearchSource,
'components/HeaderSecondary': HeaderSecondary,
'components/ComposerButton': ComposerButton,
'components/DiscussionList': DiscussionList,
'components/ReplyPlaceholder': ReplyPlaceholder,
//'components/ReplyPlaceholder': ReplyPlaceholder,
'components/AvatarEditor': AvatarEditor,
'components/Post': Post,
'components/SettingsPage': SettingsPage,
//'components/SettingsPage': SettingsPage,
'components/TerminalPost': TerminalPost,
'components/ChangeEmailModal': ChangeEmailModal,
'components/NotificationsDropdown': NotificationsDropdown,
'components/UserPage': UserPage,
//'components/UserPage': UserPage,
'components/PostUser': PostUser,
'components/UserCard': UserCard,
'components/UsersSearchSource': UsersSearchSource,
'components/NotificationGrid': NotificationGrid,
//'components/NotificationGrid': NotificationGrid,
'components/PostPreview': PostPreview,
'components/EventPost': EventPost,
'components/DiscussionHero': DiscussionHero,
'components/PostMeta': PostMeta,
'components/EditUserModal': EditUserModal,
//'components/EditUserModal': EditUserModal,
'components/SearchSource': SearchSource,
'components/DiscussionRenamedPost': DiscussionRenamedPost,
'components/DiscussionComposer': DiscussionComposer,
//'components/DiscussionRenamedPost': DiscussionRenamedPost,
//'components/DiscussionComposer': DiscussionComposer,
'components/LogInButtons': LogInButtons,
'components/NotificationList': NotificationList,
//'components/NotificationList': NotificationList,
'components/WelcomeHero': WelcomeHero,
'components/SignUpModal': SignUpModal,
'components/CommentPost': CommentPost,
//'components/SignUpModal': SignUpModal,
//'components/CommentPost': CommentPost,
'components/ComposerPostPreview': ComposerPostPreview,
'components/ReplyComposer': ReplyComposer,
'components/NotificationsPage': NotificationsPage,
'components/PostStreamScrubber': PostStreamScrubber,
'components/EditPostComposer': EditPostComposer,
//'components/ReplyComposer': ReplyComposer,
//'components/NotificationsPage': NotificationsPage,
//'components/PostStreamScrubber': PostStreamScrubber,
//'components/EditPostComposer': EditPostComposer,
'components/RenameDiscussionModal': RenameDiscussionModal,
'components/Search': Search,
'components/DiscussionListItem': DiscussionListItem,
//'components/DiscussionListItem': DiscussionListItem,
'components/LoadingPost': LoadingPost,
'components/PostsUserPage': PostsUserPage,
//'components/PostsUserPage': PostsUserPage,
'resolvers/DiscussionPageResolver': DiscussionPageResolver,
routes: routes,
ForumApplication: ForumApplication,

View File

@ -3,7 +3,6 @@ import classList from '../../common/utils/classList';
import PostUser from './PostUser';
import PostMeta from './PostMeta';
import PostEdited from './PostEdited';
import EditPostComposer from './EditPostComposer';
import ItemList from '../../common/utils/ItemList';
import listItems from '../../common/helpers/listItems';
import Button from '../../common/components/Button';
@ -87,7 +86,9 @@ export default class CommentPost extends Post {
}
isEditing() {
return app.composer.bodyMatches(EditPostComposer, { post: this.attrs.post });
import(/* webpackChunkName: "forum/components/EditPostComposer" */ './EditPostComposer').then((EditPostComposer) => {
return app.composer.bodyMatches(EditPostComposer.default, { post: this.attrs.post });
});
}
elementAttrs() {

View File

@ -1,7 +1,6 @@
import Component from '../../common/Component';
import LoadingIndicator from '../../common/components/LoadingIndicator';
import ConfirmDocumentUnload from '../../common/components/ConfirmDocumentUnload';
import TextEditor from '../../common/components/TextEditor';
import avatar from '../../common/helpers/avatar';
import listItems from '../../common/helpers/listItems';
import ItemList from '../../common/utils/ItemList';
@ -34,7 +33,13 @@ export default class ComposerBody extends Component {
*
* @type {Boolean}
*/
this.loading = false;
this.loading = true;
import(/* webpackChunkName: "common/components/TextEditor" */ '../../common/components/TextEditor').then((TextEditor) => {
this.TextEditor = TextEditor.default;
this.loading = false;
m.redraw();
});
// Let the composer state know to ask for confirmation under certain
// circumstances, if the body supports / requires it and has a corresponding
@ -47,6 +52,8 @@ export default class ComposerBody extends Component {
}
view() {
const TextEditor = this.TextEditor;
return (
<ConfirmDocumentUnload when={this.hasChanges.bind(this)}>
<div className={'ComposerBody ' + (this.attrs.className || '')}>
@ -54,16 +61,18 @@ export default class ComposerBody extends Component {
<div className="ComposerBody-content">
<ul className="ComposerBody-header">{listItems(this.headerItems().toArray())}</ul>
<div className="ComposerBody-editor">
{TextEditor.component({
submitLabel: this.attrs.submitLabel,
placeholder: this.attrs.placeholder,
disabled: this.loading || this.attrs.disabled,
composer: this.composer,
preview: this.jumpToPreview && this.jumpToPreview.bind(this),
onchange: this.composer.fields.content,
onsubmit: this.onsubmit.bind(this),
value: this.composer.fields.content(),
})}
{TextEditor
? TextEditor.component({
submitLabel: this.attrs.submitLabel,
placeholder: this.attrs.placeholder,
disabled: this.loading || this.attrs.disabled,
composer: this.composer,
preview: this.jumpToPreview && this.jumpToPreview.bind(this),
onchange: this.composer.fields.content,
onsubmit: this.onsubmit.bind(this),
value: this.composer.fields.content(),
})
: ''}
</div>
</div>
{LoadingIndicator.component({ className: 'ComposerBody-loading' + (this.loading ? ' active' : '') })}

View File

@ -2,7 +2,6 @@ import Page from '../../common/components/Page';
import ItemList from '../../common/utils/ItemList';
import DiscussionHero from './DiscussionHero';
import DiscussionListPane from './DiscussionListPane';
import PostStream from './PostStream';
import PostStreamScrubber from './PostStreamScrubber';
import LoadingIndicator from '../../common/components/LoadingIndicator';
import SplitDropdown from '../../common/components/SplitDropdown';
@ -69,6 +68,8 @@ export default class DiscussionPage extends Page {
view() {
const discussion = this.discussion;
const PostStream = this.PostStream;
return (
<div className="DiscussionPage">
<DiscussionListPane state={app.discussions} />
@ -81,11 +82,11 @@ export default class DiscussionPage extends Page {
<ul>{listItems(this.sidebarItems().toArray())}</ul>
</nav>
<div className="DiscussionPage-stream">
{PostStream.component({
discussion,
stream: this.stream,
onPositionChange: this.positionChanged.bind(this),
})}
{PostStream ? (
<PostStream discussion={discussion} stream={this.stream} onPositionChange={this.positionChanged.bind(this)} />
) : (
LoadingIndicator.component({ className: 'LoadingIndicator--block' })
)}
</div>
</div>,
]
@ -99,6 +100,11 @@ export default class DiscussionPage extends Page {
* Load the discussion from the API or use the preloaded one.
*/
load() {
import(/* webpackChunkName: "forum/components/PostStream" */ './PostStream').then((PostStream) => {
this.PostStream = PostStream.default;
m.redraw();
});
const preloadedDiscussion = app.preloadedApiDocument();
if (preloadedDiscussion) {
// We must wrap this in a setTimeout because if we are mounting this

View File

@ -1,7 +1,5 @@
import Component from '../../common/Component';
import Button from '../../common/components/Button';
import LogInModal from './LogInModal';
import SignUpModal from './SignUpModal';
import SessionDropdown from './SessionDropdown';
import SelectDropdown from '../../common/components/SelectDropdown';
import NotificationsDropdown from './NotificationsDropdown';
@ -27,6 +25,9 @@ export default class HeaderSecondary extends Component {
items() {
const items = new ItemList();
const LogInModal = () => import(/* webpackChunkName: "forum/components/LogInModal" */ './LogInModal');
const SignUpModal = () => import(/* webpackChunkName: "forum/components/SignUpModal" */ './SignUpModal');
items.add('search', Search.component({ state: app.search }), 30);
if (app.forum.attribute('showLanguageSelector') && Object.keys(app.data.locales).length > 1) {

View File

@ -4,8 +4,6 @@ import ItemList from '../../common/utils/ItemList';
import listItems from '../../common/helpers/listItems';
import DiscussionList from './DiscussionList';
import WelcomeHero from './WelcomeHero';
import DiscussionComposer from './DiscussionComposer';
import LogInModal from './LogInModal';
import DiscussionPage from './DiscussionPage';
import Dropdown from '../../common/components/Dropdown';
import Button from '../../common/components/Button';
@ -295,6 +293,9 @@ export default class IndexPage extends Page {
* @return {Promise}
*/
newDiscussionAction() {
const LogInModal = () => import(/* webpackChunkName: "forum/components/LogInModal" */ './LogInModal');
const DiscussionComposer = () => import(/* webpackChunkName: "forum/components/DiscussionComposer" */ './DiscussionComposer');
return new Promise((resolve, reject) => {
if (app.session.user) {
app.composer.load(DiscussionComposer, { user: app.session.user });

View File

@ -1,6 +1,4 @@
import Modal from '../../common/components/Modal';
import ForgotPasswordModal from './ForgotPasswordModal';
import SignUpModal from './SignUpModal';
import Button from '../../common/components/Button';
import LogInButtons from './LogInButtons';
import extractText from '../../common/utils/extractText';
@ -142,6 +140,8 @@ export default class LogInModal extends Modal {
* @public
*/
forgotPassword() {
const ForgotPasswordModal = () => import(/* webpackChunkName: "forum/components/ForgotPasswordModal" */ './ForgotPasswordModal');
const email = this.identification();
const attrs = email.indexOf('@') !== -1 ? { email } : undefined;
@ -155,6 +155,8 @@ export default class LogInModal extends Modal {
* @public
*/
signUp() {
const SignUpModal = () => import(/* webpackChunkName: "forum/components/SignUpModal" */ './SignUpModal');
const attrs = { password: this.password() };
const identification = this.identification();
attrs[identification.indexOf('@') !== -1 ? 'email' : 'username'] = identification;

View File

@ -4,6 +4,7 @@ import Button from '../../common/components/Button';
import Link from '../../common/components/Link';
import LoadingIndicator from '../../common/components/LoadingIndicator';
import Discussion from '../../common/models/Discussion';
import DiscussionRenamedNotification from './DiscussionRenamedNotification';
/**
* The `NotificationList` component displays a list of the logged-in user's
@ -74,7 +75,7 @@ export default class NotificationList extends Component {
<ul className="NotificationGroup-content">
{group.notifications.map((notification) => {
const NotificationComponent = app.notificationComponents[notification.contentType()];
const NotificationComponent = this.notificationComponents()[notification.contentType()];
return NotificationComponent ? <li>{NotificationComponent.component({ notification })}</li> : '';
})}
</ul>
@ -95,6 +96,17 @@ export default class NotificationList extends Component {
);
}
/**
* A map of notification types to their components.
*
* @type {Object}
*/
notificationComponents() {
return {
discussionRenamed: DiscussionRenamedNotification,
};
}
oncreate(vnode) {
super.oncreate(vnode);

View File

@ -1,6 +1,5 @@
import Dropdown from '../../common/components/Dropdown';
import icon from '../../common/helpers/icon';
import NotificationList from './NotificationList';
export default class NotificationsDropdown extends Dropdown {
static initAttrs(attrs) {
@ -38,14 +37,21 @@ export default class NotificationsDropdown extends Dropdown {
}
getMenu() {
const NotificationList = this.NotificationList;
return (
<div className={'Dropdown-menu ' + this.attrs.menuClassName} onclick={this.menuClick.bind(this)}>
{this.showing ? NotificationList.component({ state: this.attrs.state }) : ''}
{this.showing && NotificationList ? <NotificationList state={this.attrs.state} /> : ''}
</div>
);
}
onclick() {
import(/* webpackChunkName: "forum/components/NotificationList" */ './NotificationList').then((NotificationList) => {
this.NotificationList = NotificationList.default;
m.redraw();
});
if (app.drawer.isOpen()) {
this.goToRoute();
} else {

View File

@ -1,5 +1,4 @@
import Page from '../../common/components/Page';
import NotificationList from './NotificationList';
/**
* The `NotificationsPage` component shows the notifications list. It is only
@ -11,16 +10,19 @@ export default class NotificationsPage extends Page {
app.history.push('notifications');
import(/* webpackChunkName: "forum/components/NotificationList" */ './NotificationList').then((NotificationList) => {
this.NotificationList = NotificationList.default;
m.redraw();
});
app.notifications.load();
this.bodyClass = 'App--notifications';
}
view() {
return (
<div className="NotificationsPage">
<NotificationList state={app.notifications}></NotificationList>
</div>
);
const NotificationList = this.NotificationList;
return <div className="NotificationsPage">{NotificationList ? <NotificationList state={app.notifications} /> : ''}</div>;
}
}

View File

@ -3,6 +3,8 @@ import ScrollListener from '../../common/utils/ScrollListener';
import PostLoading from './LoadingPost';
import ReplyPlaceholder from './ReplyPlaceholder';
import Button from '../../common/components/Button';
import CommentPost from './CommentPost';
import DiscussionRenamedPost from './DiscussionRenamedPost';
/**
* The `PostStream` component displays an infinitely-scrollable wall of posts in
@ -25,6 +27,18 @@ export default class PostStream extends Component {
this.scrollListener = new ScrollListener(this.onscroll.bind(this));
}
/**
* A map of post types to their components.
*
* @type {Object}
*/
postComponents() {
return {
comment: CommentPost,
discussionRenamed: DiscussionRenamedPost,
};
}
view() {
let lastTime;
@ -45,7 +59,7 @@ export default class PostStream extends Component {
if (post) {
const time = post.createdAt();
const PostComponent = app.postComponents[post.contentType()];
const PostComponent = this.postComponents()[post.contentType()];
content = PostComponent ? PostComponent.component({ post }) : '';
attrs.key = 'post' + post.id();

View File

@ -1,5 +1,4 @@
import Modal from '../../common/components/Modal';
import LogInModal from './LogInModal';
import Button from '../../common/components/Button';
import LogInButtons from './LogInButtons';
import extractText from '../../common/utils/extractText';
@ -138,6 +137,8 @@ export default class SignUpModal extends Modal {
* @public
*/
logIn() {
const LogInModal = () => import(/* webpackChunkName: "forum/components/LogInModal" */ './LogInModal');
const attrs = {
identification: this.email() || this.username(),
password: this.password(),

View File

@ -92,7 +92,10 @@ export default class UserCard extends Component {
);
}
items.add('joined', app.translator.trans('core.forum.user.joined_date_text', { ago: humanTime(user.joinTime()) }));
items.add(
'joined',
<span className="UserCard-joinedAt">{app.translator.trans('core.forum.user.joined_date_text', { ago: humanTime(user.joinTime()) })}</span>
);
return items;
}

View File

@ -1,10 +1,6 @@
import IndexPage from './components/IndexPage';
import DiscussionPage from './components/DiscussionPage';
import PostsUserPage from './components/PostsUserPage';
import DiscussionsUserPage from './components/DiscussionsUserPage';
import SettingsPage from './components/SettingsPage';
import NotificationsPage from './components/NotificationsPage';
import DiscussionPageResolver from './resolvers/DiscussionPageResolver';
import DiscussionPage from './components/DiscussionPage';
import NotificationsPage from './components/NotificationsPage';
/**
* The `routes` initializer defines the forum app's routes.
@ -12,6 +8,11 @@ import DiscussionPageResolver from './resolvers/DiscussionPageResolver';
* @param {App} app
*/
export default function (app) {
const IndexPage = () => import(/* webpackChunkName: "forum/components/IndexPage" */ './components/IndexPage');
const PostsUserPage = () => import(/* webpackChunkName: "forum/components/PostsUserPage" */ './components/PostsUserPage');
const DiscussionsUserPage = () => import(/* webpackChunkName: "forum/components/DiscussionsUserPage" */ './components/DiscussionsUserPage');
const SettingsPage = () => import(/* webpackChunkName: "forum/components/SettingsPage" */ './components/SettingsPage');
app.routes = {
index: { path: '/all', component: IndexPage },

View File

@ -1,3 +1,4 @@
import Component from '../../common/Component';
import subclassOf from '../../common/utils/subclassOf';
import Stream from '../../common/utils/Stream';
import ReplyComposer from '../components/ReplyComposer';
@ -40,10 +41,15 @@ class ComposerState {
/**
* Load a content component into the composer.
*
* @param {ComposerBody} componentClass
* @param {ComposerBody|Function} componentClass
* @public
*/
load(componentClass, attrs) {
async load(componentClass, attrs) {
if (!(componentClass instanceof Component)) {
const componentResolver = await componentClass();
componentClass = componentResolver.default;
}
const body = { componentClass, attrs };
if (this.preventExit()) return;

View File

@ -1,6 +1,4 @@
import DiscussionPage from '../components/DiscussionPage';
import ReplyComposer from '../components/ReplyComposer';
import LogInModal from '../components/LogInModal';
import Button from '../../common/components/Button';
import Separator from '../../common/components/Separator';
import RenameDiscussionModal from '../components/RenameDiscussionModal';
@ -181,15 +179,19 @@ export default {
* @return {Promise}
*/
replyAction(goToLast, forceRefresh) {
return new Promise((resolve, reject) => {
const LogInModal = () => import(/* webpackChunkName: "forum/components/LogInModal" */ '../components/LogInModal');
const ReplyComposer = () => import(/* webpackChunkName: "forum/components/ReplyComposer" */ '../components/ReplyComposer');
return new Promise(async (resolve, reject) => {
if (app.session.user) {
if (this.canReply()) {
if (!app.composer.composingReplyTo(this) || forceRefresh) {
app.composer.load(ReplyComposer, {
await app.composer.load(ReplyComposer, {
user: app.session.user,
discussion: this,
});
}
console.log('hi');
app.composer.show();
if (goToLast && app.viewingDiscussion(this) && !app.composer.isFullScreen()) {

View File

@ -1,6 +1,5 @@
import Button from '../../common/components/Button';
import Separator from '../../common/components/Separator';
import EditUserModal from '../components/EditUserModal';
import UserPage from '../components/UserPage';
import ItemList from '../../common/utils/ItemList';
@ -138,6 +137,8 @@ export default {
* @param {User} user
*/
editAction(user) {
const EditUserModal = () => import(/* webpackChunkName: "forum/components/EditUserModal" */ '../components/EditUserModal');
app.modal.show(EditUserModal, { user });
},
};

View File

@ -8,7 +8,7 @@
"strict": true,
"noImplicitReturns": false,
"noImplicitAny": false,
"module": "es2015",
"module": "esnext",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"esModuleInterop": true,

View File

@ -1,16 +1,154 @@
const config = require('flarum-webpack-config');
const merge = require('webpack-merge');
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const TerserPlugin = require("terser-webpack-plugin");
module.exports = merge(config(), {
output: {
library: 'flarum.core',
},
module.exports = function(options = {}) {
return {
// Set up entry points for each of the forum + admin apps, but only
// if they exist.
entry: function() {
const entries = {};
// temporary TS configuration
resolve: {
extensions: ['.ts', '.tsx', '.js', '.json'],
},
});
for (const app of ['forum', 'admin']) {
const file = path.resolve(process.cwd(), app+'.js');
if (fs.existsSync(file)) {
const entry = `/${app}/${require(path.resolve(process.cwd(), 'package.json')).name.replace('@', '').replace('/', '-')}`
entries[entry] = file;
}
}
module.exports['module'].rules[0].test = /\.(tsx?|js)$/;
module.exports['module'].rules[0].use.options.presets.push('@babel/preset-typescript');
return entries;
}(),
resolve: {
extensions: ['.ts', '.tsx', '.js', '.json'],
},
optimization: {
runtimeChunk: {
name: entrypoint => `${entrypoint.name}~runtime`
},
splitChunks: {
chunks: 'all',
minChunks: 2,
maxInitialRequests: Infinity,
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
name(module, entry) {
return `${entry[0].name.match(/[^\/]*\/[^\/]*/)[0]}/vendor`;
}
},
common: {
test: /[\\/]common[\\/]/,
priority: -20,
reuseExistingChunk: true,
name: '/common/common'
},
},
},
/**minimizer: [new TerserPlugin({
test: /\.(tsx?|js)$/,
parallel: true,
terserOptions: {
ecma: 8,
warnings: false,
parse: {
ecma: 8,
},
compress: {
warnings: false,
comparisons: false,
},
mangle: {
safari10: true,
},
module: false,
output: {
ecma: 5,
comments: false,
ascii_only: true,
},
toplevel: false,
nameCache: null,
ie8: false,
keep_classnames: undefined,
keep_fnames: false,
safari10: false,
},
})],**/
},
module: {
rules: [
{
test: /\.(tsx?|js)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', {modules: false, loose: true}],
['@babel/preset-react'],
['@babel/preset-typescript']
],
plugins: [
['@babel/plugin-transform-runtime', {useESModules: true}],
['@babel/plugin-proposal-class-properties'],
['@babel/plugin-transform-react-jsx', {pragma: 'm'}],
['@babel/plugin-transform-object-assign'],
['@babel/plugin-syntax-dynamic-import']
]
}
}
}
]
},
output: {
path: path.resolve(process.cwd(), 'dist'),
library: 'flarum.core',
libraryTarget: 'assign',
chunkFilename: '[name].js',
publicPath: "/assets/",
filename: '[name].js',
devtoolNamespace: require(path.resolve(process.cwd(), 'package.json')).name
},
externals: [
{
'@flarum/core/forum': 'flarum.core',
'@flarum/core/admin': 'flarum.core',
'jquery': 'jQuery'
},
function() {
const externals = {};
if (options.useExtensions) {
for (const extension of options.useExtensions) {
externals['@'+extension] =
externals['@'+extension+'/forum'] =
externals['@'+extension+'/admin'] = "flarum.extensions['"+extension+"']";
}
}
return externals;
}(),
// Support importing old-style core modules.
function(context, request, callback) {
let matches;
if ((matches = /^flarum\/(.+)$/.exec(request))) {
return callback(null, 'root flarum.core.compat[\'' + matches[1] + '\']');
}
callback();
}
],
devtool: 'source-map'
};
};

View File

@ -2,7 +2,7 @@
@import "brands";
@import "regular";
@import "solid";
@fa-font-path: "./fonts";
@fa-font-path: "../fonts";
@import "normalize";
@import "print";

View File

@ -96,13 +96,10 @@ class Frontend implements ExtenderInterface
$container->resolving($abstract, function (Assets $assets) use ($moduleName) {
if ($this->js) {
$assets->js(function (SourceCollector $sources) use ($moduleName) {
$sources->addString(function () {
return 'var module={}';
});
$sources->addFile($this->js);
$sources->addString(function () use ($moduleName) {
/**$sources->addString(function () use ($moduleName) {
return "flarum.extensions['$moduleName']=module.exports";
});
});**/
$sources->addFile($this->js, $moduleName);
});
}

View File

@ -101,14 +101,26 @@ class ForumServiceProvider extends AbstractServiceProvider
$assets = $this->container->make('flarum.assets.factory')('forum');
$assets->js(function (SourceCollector $sources) {
$sources->addFile(__DIR__.'/../../js/dist/forum.js');
/**$sources->addFile(__DIR__ . '/../../js/dist/common/common.js');
$files = glob(__DIR__ . '/../../js/dist/forum/' . '*.js', GLOB_BRACE);
foreach ($files as $filename) {
if (substr($filename,-4) !== '.map') {
$sources->addFile($filename);
}
}**/
$sources->addDirectory(__DIR__ . '/../../js/dist/forum');
$sources->addDirectory(__DIR__ . '/../../js/dist/common');
$sources->addString(function () {
return $this->container->make(Formatter::class)->getJs();
});
});
$assets->css(function (SourceCollector $sources) {
$sources->addFile(__DIR__.'/../../less/forum.less');
$sources->addFile(__DIR__ . '/../../less/forum.less');
$sources->addString(function () {
return $this->container->make(SettingsRepositoryInterface::class)->get('custom_less', '');
});
@ -130,7 +142,7 @@ class ForumServiceProvider extends AbstractServiceProvider
*/
public function boot()
{
$this->loadViewsFrom(__DIR__.'/../../views', 'flarum.forum');
$this->loadViewsFrom(__DIR__ . '/../../views', 'flarum.forum');
$this->container->make('view')->share([
'translator' => $this->container->make(TranslatorInterface::class),
@ -190,7 +202,7 @@ class ForumServiceProvider extends AbstractServiceProvider
{
$factory = $this->container->make(RouteHandlerFactory::class);
$callback = include __DIR__.'/routes.php';
$callback = include __DIR__ . '/routes.php';
$callback($routes, $factory);
}

View File

@ -46,7 +46,7 @@ class AddTranslations
$sources->addString(function () use ($locale) {
$translations = $this->getTranslations($locale);
return 'flarum.core.app.translator.addTranslations('.json_encode($translations).')';
return 'app.translator.addTranslations('.json_encode($translations).')';
});
});
}

View File

@ -102,7 +102,7 @@ class Assets
public function makeJs(): JsCompiler
{
$compiler = $this->makeJsCompiler($this->name.'.js');
$compiler = $this->makeJsCompiler($this->name, 'js');
$this->populate($compiler, 'js');
@ -111,7 +111,7 @@ class Assets
public function makeCss(): LessCompiler
{
$compiler = $this->makeLessCompiler($this->name.'.css');
$compiler = $this->makeLessCompiler($this->name, 'css');
$this->populate($compiler, 'css');
@ -120,7 +120,7 @@ class Assets
public function makeLocaleJs(string $locale): JsCompiler
{
$compiler = $this->makeJsCompiler($this->name.'-'.$locale.'.js');
$compiler = $this->makeJsCompiler($this->name, 'js-'.$locale);
$this->populate($compiler, 'localeJs', $locale);
@ -129,21 +129,21 @@ class Assets
public function makeLocaleCss(string $locale): LessCompiler
{
$compiler = $this->makeLessCompiler($this->name.'-'.$locale.'.css');
$compiler = $this->makeLessCompiler($this->name, 'css-'.$locale);
$this->populate($compiler, 'localeCss', $locale);
return $compiler;
}
protected function makeJsCompiler(string $filename)
protected function makeJsCompiler(string $name, string $type): JsCompiler
{
return new JsCompiler($this->assetsDir, $filename);
return new JsCompiler($this->assetsDir, $name, $type);
}
protected function makeLessCompiler(string $filename): LessCompiler
protected function makeLessCompiler(string $name, string $type): LessCompiler
{
$compiler = new LessCompiler($this->assetsDir, $filename);
$compiler = new LessCompiler($this->assetsDir, $name, $type);
if ($this->cacheDir) {
$compiler->setCacheDir($this->cacheDir.'/less');

View File

@ -14,12 +14,12 @@ interface CompilerInterface
/**
* @return string
*/
public function getFilename(): string;
public function getName(): string;
/**
* @param string $filename
* @param string $name
*/
public function setFilename(string $filename);
public function setName(string $name);
/**
* @param callable $callback
@ -29,9 +29,9 @@ interface CompilerInterface
public function commit();
/**
* @return string|null
* @return array
*/
public function getUrl(): ?string;
public function getUrls(): array;
public function flush();
}

View File

@ -11,6 +11,8 @@ namespace Flarum\Frontend\Compiler;
use axy\sourcemap\SourceMap;
use Flarum\Frontend\Compiler\Source\FileSource;
use Flarum\Frontend\Compiler\Source\FolderSource;
use Illuminate\Support\Arr;
class JsCompiler extends RevisionCompiler
{
@ -23,49 +25,89 @@ class JsCompiler extends RevisionCompiler
return false;
}
$mapFile = $file.'.map';
$directory = $this->name . '/';
$mapFile = $file . '.map';
$map = new SourceMap();
$map->file = $mapFile;
$output = [];
if (!$this->type) {
$output[] = 'var module={};';
}
$line = 0;
// For each of the sources, get their content and add it to the
// output. For file sources, if a sourcemap is present, add it to
// the output sourcemap.
// output. For folder sources, add all the files contained in that folder.
foreach ($sources as $source) {
$content = $source->getContent();
if ($source instanceof FileSource) {
$sourceMap = $source->getPath().'.map';
if (file_exists($sourceMap)) {
$map->concat($sourceMap, $line);
if ($source instanceof FolderSource) {
foreach ($content as $file) {
$filepath = $source->getPath() . '/' . $file;
if (is_dir($filepath)) {
$this->levelN($filepath, $source, $file);
} else {
if (pathinfo($filepath, PATHINFO_EXTENSION) !== 'js') {
$this->assetsDir->put($source->getDirectoryName() . '/' . $file, file_get_contents($filepath));
} else {
$content = file_get_contents($filepath);
$cacheDifferentiator = hash('crc32b', serialize(array_merge($source->getCacheDifferentiator(), [$content])));
$this->putFile($source->getDirectoryName() . '/' . $file, $cacheDifferentiator, $content);
}
}
}
}
$content = $this->format($content);
$output[] = $content;
$line += substr_count($content, "\n") + 1;
} else {
if ($source instanceof FileSource) {
$sourceMap = $source->getPath() . '.map';
if (file_exists($sourceMap)) {
$map->concat($sourceMap, $line);
}
}
$content = $this->format($content);
$output[] = $content;
$line += substr_count($content, "\n") + 1;
}
}
$cacheDifferentiator = hash('crc32b', serialize($output));
$this->putFile($this->name . '/' . $this->name .'-' . $this->type . '.js', $cacheDifferentiator, $output);
// Add a comment to the end of our file to point to the sourcemap
// we just constructed. We will then store the JS file and the map
// in our asset directory.
$output[] = '//# sourceMappingURL='.$this->assetsDir->url($mapFile);
$output[] = '//# sourceMappingURL=' . $this->assetsDir->url($mapFile);
$this->assetsDir->put($file, implode("\n", $output));
$this->assetsDir->put($mapFile, json_encode($map, JSON_UNESCAPED_SLASHES));
$this->assetsDir->put($directory . $mapFile, json_encode($map, JSON_UNESCAPED_SLASHES));
return true;
}
private function levelN($filepath, $source, $file)
{
$this->assetsDir->makeDirectory($file);
foreach (array_diff(scandir($filepath), ['.', '..']) as $levelNFile) {
$filepath2 = $filepath . '/' . $levelNFile;
if (is_dir($filepath2)) {
$this->levelN($filepath2, $source, $file . '/' . $levelNFile);
} else {
$this->assetsDir->put($source->getDirectoryName() . '/' . $file . '/' . $levelNFile, file_get_contents($filepath2));
}
}
}
/**
* {@inheritdoc}
*/
protected function format(string $string): string
{
return preg_replace('~//# sourceMappingURL.*$~m', '', $string)."\n";
return preg_replace('~//# sourceMappingURL.*$~m', '', $string) . "\n";
}
/**
@ -75,7 +117,7 @@ class JsCompiler extends RevisionCompiler
{
parent::delete($file);
if ($this->assetsDir->has($mapFile = $file.'.map')) {
if ($this->assetsDir->has($mapFile = $file . '.map')) {
$this->assetsDir->delete($mapFile);
}
}

View File

@ -20,6 +20,10 @@ class RevisionCompiler implements CompilerInterface
const EMPTY_REVISION = 'empty';
protected $ignoredDirectories = [
'fonts'
];
/**
* @var Filesystem
*/
@ -28,7 +32,12 @@ class RevisionCompiler implements CompilerInterface
/**
* @var string
*/
protected $filename;
protected $name;
/**
* @var string
*/
protected $type = '';
/**
* @var callable[]
@ -37,28 +46,30 @@ class RevisionCompiler implements CompilerInterface
/**
* @param Filesystem $assetsDir
* @param string $filename
* @param string $name
* @param string $type
*/
public function __construct(Filesystem $assetsDir, string $filename)
public function __construct(Filesystem $assetsDir, string $name, string $type)
{
$this->assetsDir = $assetsDir;
$this->filename = $filename;
$this->name = $name;
$this->type = $type;
}
/**
* {@inheritdoc}
*/
public function getFilename(): string
public function getName(): string
{
return $this->filename;
return $this->name;
}
/**
* {@inheritdoc}
*/
public function setFilename(string $filename)
public function setName(string $name)
{
$this->filename = $filename;
$this->name = $name;
}
/**
@ -68,28 +79,7 @@ class RevisionCompiler implements CompilerInterface
{
$sources = $this->getSources();
$oldRevision = $this->getRevision();
$newRevision = $this->calculateRevision($sources);
$oldFile = $oldRevision ? $this->getFilenameForRevision($oldRevision) : null;
if ($oldRevision !== $newRevision || ($oldFile && ! $this->assetsDir->has($oldFile))) {
$newFile = $this->getFilenameForRevision($newRevision);
if (! $this->save($newFile, $sources)) {
// If no file was written (because the sources were empty), we
// will set the revision to a special value so that we can tell
// that this file does not have a URL.
$newRevision = static::EMPTY_REVISION;
}
$this->putRevision($newRevision);
if ($oldFile && $oldFile !== $newFile) {
$this->delete($oldFile);
}
}
$this->save($this->name, $sources);
}
/**
@ -117,27 +107,39 @@ class RevisionCompiler implements CompilerInterface
/**
* {@inheritdoc}
*/
public function getUrl(): ?string
public function getUrls(): array
{
$revision = $this->getRevision();
if (! $revision) {
if (!$revision) {
$this->commit();
$revision = $this->getRevision();
if (! $revision) {
return null;
if (empty($revision)) {
return [];
}
}
if ($revision === static::EMPTY_REVISION) {
return null;
return [];
}
$file = $this->getFilenameForRevision($revision);
$manifest = json_decode($this->assetsDir->read(static::REV_MANIFEST), true);
return $this->assetsDir->url($file);
$appResources = array_merge(Arr::get($manifest, $this->name));
$urls = [];
if (!empty($appResources[$this->type])) {
foreach ($appResources[$this->type] as $revision => $target) {
$ext = pathinfo($target, PATHINFO_EXTENSION);
$file = substr_replace($target, '-' . $revision, -strlen($ext) - 1, 0);
$urls[] = $this->assetsDir->url($file);
}
}
return $urls;
}
/**
@ -148,7 +150,7 @@ class RevisionCompiler implements CompilerInterface
protected function save(string $file, array $sources): bool
{
if ($content = $this->compile($sources)) {
$this->assetsDir->put($file, $content);
$this->putFile($this->name.'/'.$file.'.'.$this->type, hash('crc32b', serialize([$content])), $content);
return true;
}
@ -181,47 +183,50 @@ class RevisionCompiler implements CompilerInterface
}
/**
* Get the filename for the given revision.
*
* @param string $revision
* @return string
* @return array
*/
protected function getFilenameForRevision(string $revision): string
{
$ext = pathinfo($this->filename, PATHINFO_EXTENSION);
return substr_replace($this->filename, '-'.$revision, -strlen($ext) - 1, 0);
}
/**
* @return string|null
*/
protected function getRevision(): ?string
protected function getRevision(): array
{
if ($this->assetsDir->has(static::REV_MANIFEST)) {
$manifest = json_decode($this->assetsDir->read(static::REV_MANIFEST), true);
return Arr::get($manifest, $this->filename);
return (array) Arr::get($manifest, $this->name);
}
return null;
return [];
}
/**
* @param string|null $revision
* @param string $location
* @param $cacheDifferentiator
* @param $content
*/
protected function putRevision(?string $revision)
protected function putFile(string $location, $cacheDifferentiator, $content)
{
if ($this->assetsDir->has(static::REV_MANIFEST)) {
$manifest = json_decode($this->assetsDir->read(static::REV_MANIFEST), true);
} else {
$manifest = [];
}
if ($revision) {
$manifest[$this->filename] = $revision;
if (!isset($manifest[$this->name])) {
$manifest[$this->name] = [];
}
if (!isset($manifest[$this->name][$this->type])) {
$manifest[$this->name][$this->type] = [];
}
if ($location) {
$ext = pathinfo($location, PATHINFO_EXTENSION);
$filename = substr_replace($location, '-'.$cacheDifferentiator, -strlen($ext) - 1, 0);
$this->assetsDir->put($filename, $content);
$manifest[$this->name][$this->type][$cacheDifferentiator] = $location;
} else {
unset($manifest[$this->filename]);
unset($manifest[$this->name][$this->type]);
}
$this->assetsDir->put(static::REV_MANIFEST, json_encode($manifest));
@ -254,22 +259,18 @@ class RevisionCompiler implements CompilerInterface
*/
public function flush()
{
if ($revision = $this->getRevision()) {
$file = $this->getFilenameForRevision($revision);
$path = $this->assetsDir->getAdapter()->getPathPrefix();
$files = array_diff(scandir($path), ['.', '..']);
$this->delete($file);
$this->putRevision(null);
}
}
/**
* @param string $file
*/
protected function delete(string $file)
{
if ($this->assetsDir->has($file)) {
$this->assetsDir->delete($file);
foreach($files as $file) {
if (!in_array($file, $this->ignoredItems)) {
$filePath = $this->assetsDir->getAdapter()->getPathPrefix() . '/' . $file;
if (is_dir($filePath)) {
$this->assetsDir->deleteDirectory($file);
} else {
$this->assetsDir->delete($file);
}
}
}
}
}

View File

@ -19,15 +19,22 @@ class FileSource implements SourceInterface
protected $path;
/**
* @param string $path
* @var string|null
*/
public function __construct(string $path)
protected $moduleName;
/**
* @param string $path
* @param string|null $moduleName
*/
public function __construct(string $path, ?string $moduleName)
{
if (! file_exists($path)) {
throw new InvalidArgumentException("File not found at path: $path");
}
$this->path = $path;
$this->moduleName = $moduleName;
}
/**
@ -53,4 +60,14 @@ class FileSource implements SourceInterface
{
return $this->path;
}
public function getFilename(): string
{
return pathinfo($this->path)['basename'];
}
public function getModuleName(): string
{
return $this->moduleName ?: 'core';
}
}

View File

@ -0,0 +1,70 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Frontend\Compiler\Source;
use InvalidArgumentException;
class FolderSource implements SourceInterface
{
/**
* @var string
*/
protected $path;
/**
* @var string|null
*/
protected $moduleName;
/**
* @param string $path
* @param string|null $moduleName
*/
public function __construct(string $path, ?string $moduleName)
{
if (! is_dir($path)) {
throw new InvalidArgumentException("Folder not found at path: $path");
}
$this->path = $path;
$this->moduleName = $moduleName;
}
/**
* @return string
*/
public function getPath(): string
{
return $this->path;
}
public function getDirectoryName(): string
{
return pathinfo($this->path)['basename'];
}
public function getContent(): array
{
return array_diff(scandir($this->path), ['.', '..']);
}
/**
* @return mixed
*/
public function getCacheDifferentiator()
{
return [$this->path, filemtime($this->path)];
}
public function getModuleName(): string
{
return $this->moduleName ?: 'core';
}
}

View File

@ -18,11 +18,19 @@ class SourceCollector
/**
* @param string $file
* @param string|null $moduleName
* @return $this
*/
public function addFile(string $file)
public function addFile(string $file, string $moduleName = null)
{
$this->sources[] = new FileSource($file);
$this->sources[] = new FileSource($file, $moduleName);
return $this;
}
public function addDirectory(string $directory, string $moduleName = null)
{
$this->sources[] = new FolderSource($directory, $moduleName);
return $this;
}

View File

@ -12,9 +12,9 @@ namespace Flarum\Frontend\Compiler\Source;
interface SourceInterface
{
/**
* @return string
* @return string|array
*/
public function getContent(): string;
public function getContent();
/**
* @return mixed

View File

@ -69,8 +69,8 @@ class Assets
*/
private function getUrls(array $compilers)
{
return array_filter(array_map(function (CompilerInterface $compiler) {
return $compiler->getUrl();
}, $compilers));
return call_user_func_array('array_merge', array_filter(array_map(function (CompilerInterface $compiler) {
return (array) $compiler->getUrls();
}, $compilers)));
}
}

View File

@ -25,9 +25,9 @@
document.getElementById('flarum-loading').style.display = 'none';
try {
flarum.core.app.load(@json($payload));
flarum.core.app.bootExtensions(flarum.extensions);
flarum.core.app.boot();
app.load(@json($payload));
app.bootExtensions(flarum.extensions);
app.boot();
} catch (e) {
var error = document.getElementById('flarum-loading-error');
error.innerHTML += document.getElementById('flarum-content').textContent;