From feffe53a860e240868234b305e85abd7ec6c9e92 Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Sat, 4 Jun 2016 18:05:46 +0930 Subject: [PATCH] Add ability to upload a logo + favicon, and add custom header HTML MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #268. Not going to bother with a preview SVG or anything fancy for now – we can think about that as part of #746. Right now it's just good to finally get this functionality in! Also need to think about apple-touch-icon, msTile stuff, and social sharing image. Not sure if this is all too much for core, but it's definitely too much for the current Appearance page layout. Again, something to think about as part of #746. Code is a bit rough around the edges, but figured there's not much point in using the command bus properly since #870. --- js/admin/dist/app.js | 314 ++++++++++++++---- js/admin/src/components/AppearancePage.js | 30 ++ .../src/components/EditCustomHeaderModal.js | 24 ++ js/admin/src/components/UploadImageButton.js | 97 ++++++ js/forum/src/components/AvatarEditor.js | 2 +- less/admin/AppearancePage.less | 8 +- less/lib/App.less | 4 + less/lib/Button.less | 2 +- src/Api/ApiServiceProvider.php | 28 ++ .../Controller/DeleteFaviconController.php | 63 ++++ src/Api/Controller/DeleteLogoController.php | 63 ++++ .../Controller/UploadFaviconController.php | 90 +++++ src/Api/Controller/UploadLogoController.php | 83 +++++ src/Api/Serializer/ForumSerializer.php | 71 ++-- views/admin.blade.php | 7 +- views/app.blade.php | 6 + views/forum.blade.php | 11 +- 17 files changed, 811 insertions(+), 92 deletions(-) create mode 100644 js/admin/src/components/EditCustomHeaderModal.js create mode 100644 js/admin/src/components/UploadImageButton.js create mode 100644 src/Api/Controller/DeleteFaviconController.php create mode 100644 src/Api/Controller/DeleteLogoController.php create mode 100644 src/Api/Controller/UploadFaviconController.php create mode 100644 src/Api/Controller/UploadLogoController.php diff --git a/js/admin/dist/app.js b/js/admin/dist/app.js index 6a7e2e317..fa20c7ee1 100644 --- a/js/admin/dist/app.js +++ b/js/admin/dist/app.js @@ -17488,10 +17488,10 @@ System.register('flarum/components/AlertManager', ['flarum/Component', 'flarum/c });; 'use strict'; -System.register('flarum/components/AppearancePage', ['flarum/components/Page', 'flarum/components/Button', 'flarum/components/Switch', 'flarum/components/EditCustomCssModal', 'flarum/utils/saveSettings'], function (_export, _context) { +System.register('flarum/components/AppearancePage', ['flarum/components/Page', 'flarum/components/Button', 'flarum/components/Switch', 'flarum/components/EditCustomCssModal', 'flarum/components/EditCustomHeaderModal', 'flarum/components/UploadImageButton', 'flarum/utils/saveSettings'], function (_export, _context) { "use strict"; - var Page, Button, Switch, EditCustomCssModal, saveSettings, AppearancePage; + var Page, Button, Switch, EditCustomCssModal, EditCustomHeaderModal, UploadImageButton, saveSettings, AppearancePage; return { setters: [function (_flarumComponentsPage) { Page = _flarumComponentsPage.default; @@ -17501,6 +17501,10 @@ System.register('flarum/components/AppearancePage', ['flarum/components/Page', ' Switch = _flarumComponentsSwitch.default; }, function (_flarumComponentsEditCustomCssModal) { EditCustomCssModal = _flarumComponentsEditCustomCssModal.default; + }, function (_flarumComponentsEditCustomHeaderModal) { + EditCustomHeaderModal = _flarumComponentsEditCustomHeaderModal.default; + }, function (_flarumComponentsUploadImageButton) { + UploadImageButton = _flarumComponentsUploadImageButton.default; }, function (_flarumUtilsSaveSettings) { saveSettings = _flarumUtilsSaveSettings.default; }], @@ -17572,6 +17576,57 @@ System.register('flarum/components/AppearancePage', ['flarum/components/Page', ' }) ) ), + m( + 'fieldset', + null, + m( + 'legend', + null, + app.translator.trans('core.admin.appearance.logo_heading') + ), + m( + 'div', + { className: 'helpText' }, + app.translator.trans('core.admin.appearance.logo_text') + ), + m(UploadImageButton, { name: 'logo' }) + ), + m( + 'fieldset', + null, + m( + 'legend', + null, + app.translator.trans('core.admin.appearance.favicon_heading') + ), + m( + 'div', + { className: 'helpText' }, + app.translator.trans('core.admin.appearance.favicon_text') + ), + m(UploadImageButton, { name: 'favicon' }) + ), + m( + 'fieldset', + null, + m( + 'legend', + null, + app.translator.trans('core.admin.appearance.custom_header_heading') + ), + m( + 'div', + { className: 'helpText' }, + app.translator.trans('core.admin.appearance.custom_header_text') + ), + Button.component({ + className: 'Button', + children: app.translator.trans('core.admin.appearance.edit_header_button'), + onclick: function onclick() { + return app.modal.show(new EditCustomHeaderModal()); + } + }) + ), m( 'fieldset', null, @@ -18232,21 +18287,17 @@ System.register('flarum/components/Dropdown', ['flarum/Component', 'flarum/helpe });; 'use strict'; -System.register('flarum/components/EditCustomCssModal', ['flarum/components/Modal', 'flarum/components/Button', 'flarum/utils/saveSettings'], function (_export, _context) { +System.register('flarum/components/EditCustomCssModal', ['flarum/components/SettingsModal'], function (_export, _context) { "use strict"; - var Modal, Button, saveSettings, EditCustomCssModal; + var SettingsModal, EditCustomCssModal; return { - setters: [function (_flarumComponentsModal) { - Modal = _flarumComponentsModal.default; - }, function (_flarumComponentsButton) { - Button = _flarumComponentsButton.default; - }, function (_flarumUtilsSaveSettings) { - saveSettings = _flarumUtilsSaveSettings.default; + setters: [function (_flarumComponentsSettingsModal) { + SettingsModal = _flarumComponentsSettingsModal.default; }], execute: function () { - EditCustomCssModal = function (_Modal) { - babelHelpers.inherits(EditCustomCssModal, _Modal); + EditCustomCssModal = function (_SettingsModal) { + babelHelpers.inherits(EditCustomCssModal, _SettingsModal); function EditCustomCssModal() { babelHelpers.classCallCheck(this, EditCustomCssModal); @@ -18254,11 +18305,6 @@ System.register('flarum/components/EditCustomCssModal', ['flarum/components/Moda } babelHelpers.createClass(EditCustomCssModal, [{ - key: 'init', - value: function init() { - this.customLess = m.prop(app.data.settings.custom_less || ''); - } - }, { key: 'className', value: function className() { return 'EditCustomCssModal Modal--large'; @@ -18269,53 +18315,26 @@ System.register('flarum/components/EditCustomCssModal', ['flarum/components/Moda return app.translator.trans('core.admin.edit_css.title'); } }, { - key: 'content', - value: function content() { - return m( + key: 'form', + value: function form() { + return [m( + 'p', + null, + app.translator.trans('core.admin.edit_css.customize_text', { a: m('a', { href: 'https://github.com/flarum/core/tree/master/less', target: '_blank' }) }) + ), m( 'div', - { className: 'Modal-body' }, - m( - 'p', - null, - app.translator.trans('core.admin.edit_css.customize_text', { a: m('a', { href: 'https://github.com/flarum/core/tree/master/less', target: '_blank' }) }) - ), - m( - 'div', - { className: 'Form' }, - m( - 'div', - { className: 'Form-group' }, - m('textarea', { className: 'FormControl', rows: '30', value: this.customLess(), onchange: m.withAttr('value', this.customLess) }) - ), - m( - 'div', - { className: 'Form-group' }, - Button.component({ - className: 'Button Button--primary', - type: 'submit', - children: app.translator.trans('core.admin.edit_css.submit_button'), - loading: this.loading - }) - ) - ) - ); + { className: 'Form-group' }, + m('textarea', { className: 'FormControl', rows: '30', bidi: this.setting('custom_less') }) + )]; } }, { - key: 'onsubmit', - value: function onsubmit(e) { - e.preventDefault(); - - this.loading = true; - - saveSettings({ - custom_less: this.customLess() - }).then(function () { - return window.location.reload(); - }); + key: 'onsaved', + value: function onsaved() { + window.location.reload(); } }]); return EditCustomCssModal; - }(Modal); + }(SettingsModal); _export('default', EditCustomCssModal); } @@ -18323,6 +18342,61 @@ System.register('flarum/components/EditCustomCssModal', ['flarum/components/Moda });; 'use strict'; +System.register('flarum/components/EditCustomHeaderModal', ['flarum/components/SettingsModal'], function (_export, _context) { + "use strict"; + + var SettingsModal, EditCustomHeaderModal; + return { + setters: [function (_flarumComponentsSettingsModal) { + SettingsModal = _flarumComponentsSettingsModal.default; + }], + execute: function () { + EditCustomHeaderModal = function (_SettingsModal) { + babelHelpers.inherits(EditCustomHeaderModal, _SettingsModal); + + function EditCustomHeaderModal() { + babelHelpers.classCallCheck(this, EditCustomHeaderModal); + return babelHelpers.possibleConstructorReturn(this, Object.getPrototypeOf(EditCustomHeaderModal).apply(this, arguments)); + } + + babelHelpers.createClass(EditCustomHeaderModal, [{ + key: 'className', + value: function className() { + return 'EditCustomHeaderModal Modal--large'; + } + }, { + key: 'title', + value: function title() { + return app.translator.trans('core.admin.edit_header.title'); + } + }, { + key: 'form', + value: function form() { + return [m( + 'p', + null, + app.translator.trans('core.admin.edit_header.customize_text') + ), m( + 'div', + { className: 'Form-group' }, + m('textarea', { className: 'FormControl', rows: '30', bidi: this.setting('custom_header') }) + )]; + } + }, { + key: 'onsaved', + value: function onsaved() { + window.location.reload(); + } + }]); + return EditCustomHeaderModal; + }(SettingsModal); + + _export('default', EditCustomHeaderModal); + } + }; +});; +'use strict'; + System.register('flarum/components/EditGroupModal', ['flarum/components/Modal', 'flarum/components/Button', 'flarum/components/Badge', 'flarum/models/Group'], function (_export, _context) { "use strict"; @@ -20651,7 +20725,12 @@ System.register('flarum/components/SettingsModal', ['flarum/components/Modal', ' this.loading = true; - saveSettings(this.dirty()).then(this.hide.bind(this), this.loaded.bind(this)); + saveSettings(this.dirty()).then(this.onsaved.bind(this), this.loaded.bind(this)); + } + }, { + key: 'onsaved', + value: function onsaved() { + this.hide(); } }]); return SettingsModal; @@ -20767,6 +20846,122 @@ System.register('flarum/components/Switch', ['flarum/components/Checkbox'], func } }; });; +'use strict'; + +System.register('flarum/components/UploadImageButton', ['flarum/components/Button'], function (_export, _context) { + "use strict"; + + var Button, UploadImageButton; + return { + setters: [function (_flarumComponentsButton) { + Button = _flarumComponentsButton.default; + }], + execute: function () { + UploadImageButton = function (_Button) { + babelHelpers.inherits(UploadImageButton, _Button); + + function UploadImageButton() { + babelHelpers.classCallCheck(this, UploadImageButton); + return babelHelpers.possibleConstructorReturn(this, Object.getPrototypeOf(UploadImageButton).apply(this, arguments)); + } + + babelHelpers.createClass(UploadImageButton, [{ + key: 'init', + value: function init() { + this.loading = false; + } + }, { + key: 'view', + value: function view() { + this.props.loading = this.loading; + this.props.className = (this.props.className || '') + ' Button'; + + if (app.data.settings[this.props.name + '_path']) { + this.props.onclick = this.remove.bind(this); + this.props.children = app.translator.trans('core.admin.upload_image.remove_button'); + + return m( + 'div', + null, + m( + 'p', + null, + m('img', { src: app.forum.attribute(this.props.name + 'Url'), alt: '' }) + ), + m( + 'p', + null, + babelHelpers.get(Object.getPrototypeOf(UploadImageButton.prototype), 'view', this).call(this) + ) + ); + } else { + this.props.onclick = this.upload.bind(this); + this.props.children = app.translator.trans('core.admin.upload_image.upload_button'); + } + + return babelHelpers.get(Object.getPrototypeOf(UploadImageButton.prototype), 'view', this).call(this); + } + }, { + key: 'upload', + value: function upload() { + var _this2 = this; + + if (this.loading) return; + + var $input = $(''); + + $input.appendTo('body').hide().click().on('change', function (e) { + var data = new FormData(); + data.append(_this2.props.name, $(e.target)[0].files[0]); + + _this2.loading = true; + m.redraw(); + + app.request({ + method: 'POST', + url: _this2.resourceUrl(), + serialize: function serialize(raw) { + return raw; + }, + data: data + }).then(_this2.success.bind(_this2), _this2.failure.bind(_this2)); + }); + } + }, { + key: 'remove', + value: function remove() { + this.loading = true; + m.redraw(); + + app.request({ + method: 'DELETE', + url: this.resourceUrl() + }).then(this.success.bind(this), this.failure.bind(this)); + } + }, { + key: 'resourceUrl', + value: function resourceUrl() { + return app.forum.attribute('apiUrl') + '/' + this.props.name; + } + }, { + key: 'success', + value: function success(response) { + window.location.reload(); + } + }, { + key: 'failure', + value: function failure(response) { + this.loading = false; + m.redraw(); + } + }]); + return UploadImageButton; + }(Button); + + _export('default', UploadImageButton); + } + }; +});; "use strict"; System.register("flarum/extend", [], function (_export, _context) { @@ -22435,6 +22630,7 @@ System.register('flarum/Translator', ['flarum/models/User', 'flarum/helpers/user case 'vi': case 'zh': return 0; + case 'af': case 'az': case 'bn': diff --git a/js/admin/src/components/AppearancePage.js b/js/admin/src/components/AppearancePage.js index a6baa7c7a..92bbc1b93 100644 --- a/js/admin/src/components/AppearancePage.js +++ b/js/admin/src/components/AppearancePage.js @@ -2,6 +2,8 @@ import Page from 'flarum/components/Page'; import Button from 'flarum/components/Button'; import Switch from 'flarum/components/Switch'; import EditCustomCssModal from 'flarum/components/EditCustomCssModal'; +import EditCustomHeaderModal from 'flarum/components/EditCustomHeaderModal'; +import UploadImageButton from 'flarum/components/UploadImageButton'; import saveSettings from 'flarum/utils/saveSettings'; export default class AppearancePage extends Page { @@ -51,6 +53,34 @@ export default class AppearancePage extends Page { +
+ {app.translator.trans('core.admin.appearance.logo_heading')} +
+ {app.translator.trans('core.admin.appearance.logo_text')} +
+ +
+ +
+ {app.translator.trans('core.admin.appearance.favicon_heading')} +
+ {app.translator.trans('core.admin.appearance.favicon_text')} +
+ +
+ +
+ {app.translator.trans('core.admin.appearance.custom_header_heading')} +
+ {app.translator.trans('core.admin.appearance.custom_header_text')} +
+ {Button.component({ + className: 'Button', + children: app.translator.trans('core.admin.appearance.edit_header_button'), + onclick: () => app.modal.show(new EditCustomHeaderModal()) + })} +
+
{app.translator.trans('core.admin.appearance.custom_styles_heading')}
diff --git a/js/admin/src/components/EditCustomHeaderModal.js b/js/admin/src/components/EditCustomHeaderModal.js new file mode 100644 index 000000000..9d8fb27c5 --- /dev/null +++ b/js/admin/src/components/EditCustomHeaderModal.js @@ -0,0 +1,24 @@ +import SettingsModal from 'flarum/components/SettingsModal'; + +export default class EditCustomHeaderModal extends SettingsModal { + className() { + return 'EditCustomHeaderModal Modal--large'; + } + + title() { + return app.translator.trans('core.admin.edit_header.title'); + } + + form() { + return [ +

{app.translator.trans('core.admin.edit_header.customize_text')}

, +
+