mirror of
https://github.com/flarum/framework.git
synced 2024-11-25 09:41:49 +08:00
Code Split
This commit is contained in:
parent
c006931798
commit
008206738f
|
@ -8,4 +8,4 @@
|
|||
*/
|
||||
|
||||
export * from './src/common';
|
||||
export * from './src/admin';
|
||||
export * from './src/admin';
|
||||
|
|
26
js/dist/admin.js
vendored
26
js/dist/admin.js
vendored
File diff suppressed because one or more lines are too long
1
js/dist/admin.js.map
vendored
1
js/dist/admin.js.map
vendored
File diff suppressed because one or more lines are too long
2
js/dist/admin/flarum-core.js
vendored
Normal file
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
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
2
js/dist/admin/flarum-core~runtime.js
vendored
Normal 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
|
1
js/dist/admin/flarum-core~runtime.js.map
vendored
Normal file
1
js/dist/admin/flarum-core~runtime.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
js/dist/common/common.js
vendored
Normal file
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
1
js/dist/common/common.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
js/dist/common/components/TextEditor.js
vendored
Normal file
2
js/dist/common/components/TextEditor.js
vendored
Normal 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
|
1
js/dist/common/components/TextEditor.js.map
vendored
Normal file
1
js/dist/common/components/TextEditor.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
53
js/dist/forum.js
vendored
53
js/dist/forum.js
vendored
File diff suppressed because one or more lines are too long
1
js/dist/forum.js.map
vendored
1
js/dist/forum.js.map
vendored
File diff suppressed because one or more lines are too long
2
js/dist/forum/components/DiscussionComposer.js
vendored
Normal file
2
js/dist/forum/components/DiscussionComposer.js
vendored
Normal 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
|
1
js/dist/forum/components/DiscussionComposer.js.map
vendored
Normal file
1
js/dist/forum/components/DiscussionComposer.js.map
vendored
Normal 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":""}
|
2
js/dist/forum/components/DiscussionsUserPage.js
vendored
Normal file
2
js/dist/forum/components/DiscussionsUserPage.js
vendored
Normal 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
|
1
js/dist/forum/components/DiscussionsUserPage.js.map
vendored
Normal file
1
js/dist/forum/components/DiscussionsUserPage.js.map
vendored
Normal 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":""}
|
2
js/dist/forum/components/EditUserModal.js
vendored
Normal file
2
js/dist/forum/components/EditUserModal.js
vendored
Normal 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
|
1
js/dist/forum/components/EditUserModal.js.map
vendored
Normal file
1
js/dist/forum/components/EditUserModal.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
js/dist/forum/components/ForgotPasswordModal.js
vendored
Normal file
2
js/dist/forum/components/ForgotPasswordModal.js
vendored
Normal 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
|
1
js/dist/forum/components/ForgotPasswordModal.js.map
vendored
Normal file
1
js/dist/forum/components/ForgotPasswordModal.js.map
vendored
Normal 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
2
js/dist/forum/components/IndexPage.js
vendored
Normal 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
|
1
js/dist/forum/components/IndexPage.js.map
vendored
Normal file
1
js/dist/forum/components/IndexPage.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
js/dist/forum/components/LogInModal.js
vendored
Normal file
2
js/dist/forum/components/LogInModal.js
vendored
Normal 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
|
1
js/dist/forum/components/LogInModal.js.map
vendored
Normal file
1
js/dist/forum/components/LogInModal.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
js/dist/forum/components/NotificationList.js
vendored
Normal file
2
js/dist/forum/components/NotificationList.js
vendored
Normal 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
|
1
js/dist/forum/components/NotificationList.js.map
vendored
Normal file
1
js/dist/forum/components/NotificationList.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
js/dist/forum/components/PostStream.js
vendored
Normal file
2
js/dist/forum/components/PostStream.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
js/dist/forum/components/PostStream.js.map
vendored
Normal file
1
js/dist/forum/components/PostStream.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
js/dist/forum/components/PostsUserPage.js
vendored
Normal file
2
js/dist/forum/components/PostsUserPage.js
vendored
Normal 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
|
1
js/dist/forum/components/PostsUserPage.js.map
vendored
Normal file
1
js/dist/forum/components/PostsUserPage.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
js/dist/forum/components/SettingsPage.js
vendored
Normal file
2
js/dist/forum/components/SettingsPage.js
vendored
Normal 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
|
1
js/dist/forum/components/SettingsPage.js.map
vendored
Normal file
1
js/dist/forum/components/SettingsPage.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
js/dist/forum/components/SignUpModal.js
vendored
Normal file
2
js/dist/forum/components/SignUpModal.js
vendored
Normal 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
|
1
js/dist/forum/components/SignUpModal.js.map
vendored
Normal file
1
js/dist/forum/components/SignUpModal.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
3
js/dist/forum/flarum-core.js
vendored
Normal file
3
js/dist/forum/flarum-core.js
vendored
Normal file
File diff suppressed because one or more lines are too long
28
js/dist/forum/flarum-core.js.LICENSE.txt
vendored
Normal file
28
js/dist/forum/flarum-core.js.LICENSE.txt
vendored
Normal 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
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
2
js/dist/forum/flarum-core~runtime.js
vendored
Normal 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
|
1
js/dist/forum/flarum-core~runtime.js.map
vendored
Normal file
1
js/dist/forum/flarum-core~runtime.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
3
js/dist/forum/vendor.js
vendored
Normal file
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
24
js/dist/forum/vendor.js.LICENSE.txt
vendored
Normal 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
1
js/dist/forum/vendor.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -8,4 +8,4 @@
|
|||
*/
|
||||
|
||||
export * from './src/common';
|
||||
export * from './src/forum';
|
||||
export * from './src/forum';
|
||||
|
|
7271
js/package-lock.json
generated
7271
js/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -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",
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -29,7 +29,7 @@ export default function humanTime(time: Date): string {
|
|||
ago = d.format('ll');
|
||||
}
|
||||
} else {
|
||||
ago = d.fromNow();
|
||||
ago = '5 days';
|
||||
}
|
||||
|
||||
return ago;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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' : '') })}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 });
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 },
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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 });
|
||||
},
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
"strict": true,
|
||||
"noImplicitReturns": false,
|
||||
"noImplicitAny": false,
|
||||
"module": "es2015",
|
||||
"module": "esnext",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"esModuleInterop": true,
|
||||
|
|
|
@ -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'
|
||||
};
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
@import "brands";
|
||||
@import "regular";
|
||||
@import "solid";
|
||||
@fa-font-path: "./fonts";
|
||||
@fa-font-path: "../fonts";
|
||||
|
||||
@import "normalize";
|
||||
@import "print";
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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).')';
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
}
|
||||
}
|
||||
|
|
70
src/Frontend/Compiler/Source/FolderSource.php
Normal file
70
src/Frontend/Compiler/Source/FolderSource.php
Normal 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';
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user