From f7fe8ca569b40662039290df749d2837257dbedb Mon Sep 17 00:00:00 2001 From: Davis Date: Sun, 23 Oct 2016 08:41:43 +0000 Subject: [PATCH] Major Fixes Working --- .eslintrc | 52 +- .gitignore | 7 + bootstrap.php | 3 +- js/admin/dist/extension.js | 58 +- js/admin/package.json | 6 +- .../components/SocialProfileSettingsModal.js | 12 +- js/admin/src/main.js | 6 +- js/forum/dist/extension.js | 655 ++++++++++-------- js/forum/package.json | 4 +- js/forum/src/components/DeleteButtonModal.js | 96 +++ .../src/components/IconSelectorComponent.js | 50 +- js/forum/src/components/SocialButtonsModal.js | 190 +++-- .../src/components/WebsiteInputComponent.js | 119 ++-- js/forum/src/main.js | 179 +++-- less/forum/extension.less | 24 +- locale/en.yml | 2 + locale/fr.yml | 4 +- locale/ru.yml | 4 +- ...1_14_000000_create_socialbuttons_table.php | 2 - ..._20_000000_create_socialbuttons_column.php | 33 +- ..._21_000000_migrate_data_to_user_column.php | 30 + ..._10_22_000000_drop_socialbuttons_table.php | 25 + .../EditSocialButtonsController.php | 40 -- .../GetSocialButtonsController.php | 35 - .../GetSocialButtonsSerializer.php | 35 - .../Serializers/SocialButtonsSerializer.php | 25 - src/Commands/SaveSocialSettings.php | 26 - src/Commands/SaveSocialSettingsHandler.php | 58 -- ...Editted.php => UserButtonsWereChanged.php} | 63 +- src/Listeners/AddApiAttributes.php | 30 - src/Listeners/AddClientAssets.php | 12 +- src/Listeners/AddUserProfileAttributes.php | 36 + src/Listeners/LoadSettingsFromDatabase.php | 6 +- src/Listeners/UpdateProfileInDatabase.php | 101 +++ src/ProfileValidator.php | 88 +++ src/Repository/UserSocialRepository.php | 26 - 36 files changed, 1177 insertions(+), 965 deletions(-) create mode 100644 .gitignore create mode 100644 js/forum/src/components/DeleteButtonModal.js rename src/Buttons.php => migrations/2016_10_20_000000_create_socialbuttons_column.php (56%) create mode 100644 migrations/2016_10_21_000000_migrate_data_to_user_column.php create mode 100644 migrations/2016_10_22_000000_drop_socialbuttons_table.php delete mode 100644 src/Api/Controllers/EditSocialButtonsController.php delete mode 100644 src/Api/Controllers/GetSocialButtonsController.php delete mode 100644 src/Api/Serializers/GetSocialButtonsSerializer.php delete mode 100644 src/Api/Serializers/SocialButtonsSerializer.php delete mode 100644 src/Commands/SaveSocialSettings.php delete mode 100644 src/Commands/SaveSocialSettingsHandler.php rename src/Events/{SocialProfileEditted.php => UserButtonsWereChanged.php} (51%) delete mode 100755 src/Listeners/AddApiAttributes.php create mode 100644 src/Listeners/AddUserProfileAttributes.php create mode 100644 src/Listeners/UpdateProfileInDatabase.php create mode 100644 src/ProfileValidator.php delete mode 100644 src/Repository/UserSocialRepository.php diff --git a/.eslintrc b/.eslintrc index e15e70d..293600c 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,18 +1,36 @@ { - "extends": "eslint-config-airbnb", - "rules": { - "import/no-unresolved": "off", - "import/no-extraneous-dependencies": "off", - "react/jsx-filename-extension": ["error", { "extensions": [".js", ".jsx"] }], - "react/react-in-jsx-scope": "off", - "react/prop-types": "off", - "import/extensions": ["error", "never"] - }, - "env": { - "jquery": true - }, - "globals": { - "app": false, - "m": false - } -} + "extends": "eslint-config-airbnb", + "rules": { + "class-methods-use-this": "off", + "func-names": "off", + "no-param-reassign": "off", + "import/no-unresolved": "off", + "import/no-extraneous-dependencies": "off", + "import/extensions": ["error", "never"], + "react/jsx-filename-extension": ["error", { "extensions": [".js"] }], + "react/react-in-jsx-scope": "off", + "react/prop-types": "off", + "react/sort-comp": ["error", { + "order": [ + "/^constructor$/", + "/^init$/", + "/^initProps$/", + "static-methods", + "/^content$/", + "/^view$/", + "/^config$/", + "everything-else", + "/^onsubmit$/", + "/^onerror$/" + ] + }] + }, + "env": { + "jquery": true, + "browser": true + }, + "globals": { + "app": false, + "m": false + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e548ebe --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/vendor +composer.phar +.DS_Store +Thumbs.db +bower_components +node_modules +*.js.old diff --git a/bootstrap.php b/bootstrap.php index 25f5f3e..1eb565d 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -15,5 +15,6 @@ return function (Dispatcher $events) { $events->subscribe(Listeners\AddClientAssets::class); $events->subscribe(Listeners\LoadSettingsFromDatabase::class); - $events->subscribe(Listeners\AddApiAttributes::class); + $events->subscribe(Listeners\AddUserProfileAttributes::class); + $events->subscribe(Listeners\UpdateProfileInDatabase::class); }; diff --git a/js/admin/dist/extension.js b/js/admin/dist/extension.js index eb1c69c..9febf08 100644 --- a/js/admin/dist/extension.js +++ b/js/admin/dist/extension.js @@ -1,24 +1,26 @@ -System.register('davis/socialprofile/components/SocialProfileSettingsModal', ['flarum/components/SettingsModal'], function (_export) { - 'use strict'; +'use strict'; - var SettingsModal, AnimatedTagSettingsModal; +System.register('Davis/SocialProfile/components/SocialProfileSettingsModal', ['flarum/components/SettingsModal'], function (_export, _context) { + "use strict"; + + var SettingsModal, SocialProfileSettingsModal; return { setters: [function (_flarumComponentsSettingsModal) { - SettingsModal = _flarumComponentsSettingsModal['default']; + SettingsModal = _flarumComponentsSettingsModal.default; }], execute: function () { - AnimatedTagSettingsModal = (function (_SettingsModal) { - babelHelpers.inherits(AnimatedTagSettingsModal, _SettingsModal); + SocialProfileSettingsModal = function (_SettingsModal) { + babelHelpers.inherits(SocialProfileSettingsModal, _SettingsModal); - function AnimatedTagSettingsModal() { - babelHelpers.classCallCheck(this, AnimatedTagSettingsModal); - babelHelpers.get(Object.getPrototypeOf(AnimatedTagSettingsModal.prototype), 'constructor', this).apply(this, arguments); + function SocialProfileSettingsModal() { + babelHelpers.classCallCheck(this, SocialProfileSettingsModal); + return babelHelpers.possibleConstructorReturn(this, (SocialProfileSettingsModal.__proto__ || Object.getPrototypeOf(SocialProfileSettingsModal)).apply(this, arguments)); } - babelHelpers.createClass(AnimatedTagSettingsModal, [{ + babelHelpers.createClass(SocialProfileSettingsModal, [{ key: 'className', value: function className() { - return 'AnimatedTagSettingsModal Modal--small'; + return 'SocialProfileSettingsModal Modal--small'; } }, { key: 'title', @@ -28,42 +30,38 @@ System.register('davis/socialprofile/components/SocialProfileSettingsModal', ['f }, { key: 'form', value: function form() { - return [m( + return m( 'div', { className: 'Form-group' }, m( 'label', - null, + { htmlFor: 'test' }, app.translator.trans('davis-socialprofile.admin.test') ), - m('input', { type: 'text', className: 'FormControl', bidi: this.setting('davis.socialprofile.test') }) - )]; + m('input', { name: 'test', type: 'text', className: 'FormControl', bidi: this.setting('davis.socialprofile.test') }) + ); } }]); - return AnimatedTagSettingsModal; - })(SettingsModal); + return SocialProfileSettingsModal; + }(SettingsModal); - _export('default', AnimatedTagSettingsModal); + _export('default', SocialProfileSettingsModal); } }; });; -System.register('davis/socialprofile/main', ['flarum/extend', 'flarum/app', 'davis/socialprofile/components/SocialProfileSettingsModal'], function (_export) { - 'use strict'; +'use strict'; + +System.register('Davis/SocialProfile/main', ['flarum/app'], function (_export, _context) { + "use strict"; - var extend, app, SocialProfileSettingsModal; + var app; return { - setters: [function (_flarumExtend) { - extend = _flarumExtend.extend; - }, function (_flarumApp) { - app = _flarumApp['default']; - }, function (_davisSocialprofileComponentsSocialProfileSettingsModal) { - SocialProfileSettingsModal = _davisSocialprofileComponentsSocialProfileSettingsModal['default']; + setters: [function (_flarumApp) { + app = _flarumApp.default; }], execute: function () { - app.initializers.add('davis-socialprofile', function (app) { - //app.extensionSettings['davis-socialprofile'] = () => app.modal.show(new SocialProfileSettingsModal()); - }); + app.initializers.add('Davis-SocialProfile', function () {}); } }; }); \ No newline at end of file diff --git a/js/admin/package.json b/js/admin/package.json index e0cad46..2bdaf6a 100644 --- a/js/admin/package.json +++ b/js/admin/package.json @@ -1,7 +1,7 @@ { "private": true, "devDependencies": { - "gulp": "^3.8.11", - "flarum-gulp": "^0.2.0" + "gulp": "^3.9.1", + "flarum-gulp": "dav-is/flarum-gulp#patch-1" } -} +} \ No newline at end of file diff --git a/js/admin/src/components/SocialProfileSettingsModal.js b/js/admin/src/components/SocialProfileSettingsModal.js index 19dabff..5f7e75f 100644 --- a/js/admin/src/components/SocialProfileSettingsModal.js +++ b/js/admin/src/components/SocialProfileSettingsModal.js @@ -1,8 +1,8 @@ import SettingsModal from 'flarum/components/SettingsModal'; -export default class AnimatedTagSettingsModal extends SettingsModal { +export default class SocialProfileSettingsModal extends SettingsModal { className() { - return 'AnimatedTagSettingsModal Modal--small'; + return 'SocialProfileSettingsModal Modal--small'; } title() { @@ -10,11 +10,11 @@ export default class AnimatedTagSettingsModal extends SettingsModal { } form() { - return [ + return (
- - + +
- ]; + ); } } diff --git a/js/admin/src/main.js b/js/admin/src/main.js index c1898b6..41cf065 100644 --- a/js/admin/src/main.js +++ b/js/admin/src/main.js @@ -1,7 +1,5 @@ -import { extend } from 'flarum/extend'; import app from 'flarum/app'; -import SocialProfileSettingsModal from 'Davis/SocialProfile/components/SocialProfileSettingsModal'; -app.initializers.add('Davis-SocialProfile', app => { - //app.extensionSettings['davis-socialprofile'] = () => app.modal.show(new SocialProfileSettingsModal()); +app.initializers.add('Davis-SocialProfile', () => { + }); diff --git a/js/forum/dist/extension.js b/js/forum/dist/extension.js index b686d24..79fee1a 100644 --- a/js/forum/dist/extension.js +++ b/js/forum/dist/extension.js @@ -1,6 +1,129 @@ 'use strict'; +System.register('Davis/SocialProfile/components/DeleteButtonModal', ['flarum/components/Modal', 'flarum/components/Button'], function (_export, _context) { + "use strict"; + + var Modal, Button, DeleteButtonModal; + return { + setters: [function (_flarumComponentsModal) { + Modal = _flarumComponentsModal.default; + }, function (_flarumComponentsButton) { + Button = _flarumComponentsButton.default; + }], + execute: function () { + DeleteButtonModal = function (_Modal) { + babelHelpers.inherits(DeleteButtonModal, _Modal); + + function DeleteButtonModal() { + babelHelpers.classCallCheck(this, DeleteButtonModal); + return babelHelpers.possibleConstructorReturn(this, (DeleteButtonModal.__proto__ || Object.getPrototypeOf(DeleteButtonModal)).apply(this, arguments)); + } + + babelHelpers.createClass(DeleteButtonModal, [{ + key: 'init', + value: function init() { + var _this2 = this; + + babelHelpers.get(DeleteButtonModal.prototype.__proto__ || Object.getPrototypeOf(DeleteButtonModal.prototype), 'init', this).call(this); + + this.buttons = []; + this.index = this.props.index; + var buttons = JSON.parse(this.props.user.data.attributes.socialButtons || '[]'); + this.button = buttons[this.index]; + + buttons.forEach(function (button, index) { + _this2.createButtonObject(index, button); + }); + } + }, { + key: 'className', + value: function className() { + return 'SocialButtonsModal Modal--small'; + } + }, { + key: 'title', + value: function title() { + return app.translator.trans('davis-socialprofile.forum.edit.deletetitle'); + } + }, { + key: 'content', + value: function content() { + $('.Modal-content').css('overflow', 'visible'); + return [m('div', { className: 'Modal-body' }, [m('div', { className: 'Form' }, [m('h3', { className: 'SocialProfile-title' }, this.button.title), m('p', { className: 'SocialProfile-url' }, this.button.url), m('div', { className: 'Form-group', id: 'submit-button-group' }, [Button.component({ + type: 'submit', + className: 'Button Button--primary EditSocialButtons-delete', + loading: this.loading, + children: app.translator.trans('davis-socialprofile.forum.edit.delete') + })])])])]; + } + }, { + key: 'data', + value: function data() { + var buttons = []; + + this.buttons.forEach(function (button, index) { + if (button.title() !== '') { + buttons[index] = {}; + buttons[index].title = button.title(); + buttons[index].url = button.url(); + buttons[index].icon = button.icon(); + buttons[index].favicon = button.favicon(); + } + }); + + return { + socialButtons: JSON.stringify(buttons) + }; + } + }, { + key: 'onsubmit', + value: function onsubmit(e) { + var _this3 = this; + + e.preventDefault(); + + this.loading = true; + this.buttons.splice(this.index, 1); + + this.props.user.save(this.data(), { errorHandler: this.onerror.bind(this) }).then(this.hide.bind(this)).then($('#app').trigger('refreshSocialButtons', [this.data().socialButtons])).catch(function () { + _this3.loading = false; + m.redraw(); + }); + } + }, { + key: 'createButtonObject', + value: function createButtonObject(key) { + var button = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + if (button == null) { + this.buttons[key] = {}; + this.buttons[key].index = m.prop(key); + this.buttons[key].favicon = m.prop('none'); + this.buttons[key].title = m.prop(''); + this.buttons[key].url = m.prop(''); + this.buttons[key].icon = m.prop('globe'); + } else { + this.buttons[key] = {}; + this.buttons[key].index = m.prop(key); + this.buttons[key].favicon = m.prop(button.favicon); + this.buttons[key].title = m.prop(button.title); + this.buttons[key].url = m.prop(button.url); + this.buttons[key].icon = m.prop(button.icon); + } + } + }]); + return DeleteButtonModal; + }(Modal); + + _export('default', DeleteButtonModal); + } + }; +});; +'use strict'; + System.register('Davis/SocialProfile/components/IconSelectorComponent', ['flarum/components/Dropdown', 'flarum/utils/ItemList', 'flarum/helpers/icon'], function (_export, _context) { + "use strict"; + var Dropdown, ItemList, icon, IconSelectorComponent; return { setters: [function (_flarumComponentsDropdown) { @@ -16,16 +139,16 @@ System.register('Davis/SocialProfile/components/IconSelectorComponent', ['flarum function IconSelectorComponent() { babelHelpers.classCallCheck(this, IconSelectorComponent); - return babelHelpers.possibleConstructorReturn(this, Object.getPrototypeOf(IconSelectorComponent).apply(this, arguments)); + return babelHelpers.possibleConstructorReturn(this, (IconSelectorComponent.__proto__ || Object.getPrototypeOf(IconSelectorComponent)).apply(this, arguments)); } babelHelpers.createClass(IconSelectorComponent, [{ key: 'init', value: function init() { - babelHelpers.get(Object.getPrototypeOf(IconSelectorComponent.prototype), 'init', this).call(this); + babelHelpers.get(IconSelectorComponent.prototype.__proto__ || Object.getPrototypeOf(IconSelectorComponent.prototype), 'init', this).call(this); this.icons = { - 'social': ["fa-globe", 'fa-amazon', 'fa-angellist', 'fa-apple', 'fa-behance', 'fa-bitbucket', 'fa-codepen', 'fa-connectdevelop', 'fa-dashcube', 'fa-delicious', 'fa-deviantart', 'fa-digg', 'fa-dribbble', 'fa-dropbox', 'fa-drupal', 'fa-facebook', 'fa-flickr', 'fa-foursquare', 'fa-get-pocket', 'fa-git', 'fa-github', 'fa-github-alt', 'fa-gittip', 'fa-google', 'fa-google-plus', 'fa-google-wallet', 'fa-gratipay', 'fa-hacker-news', 'fa-instagram', 'fa-ioxhost', 'fa-joomla', 'fa-jsfiddle', 'fa-lastfm', 'fa-leanpub', 'fa-linkedin', 'fa-meanpath', 'fa-medium', 'fa-odnoklassniki', 'fa-opencart', 'fa-pagelines', 'fa-paypal', 'fa-pied-piper-alt', 'fa-pinterest-p', 'fa-qq', 'fa-reddit', 'fa-renren', 'fa-sellsy', 'fa-share-alt', 'fa-shirtsinbulk', 'fa-simplybuilt', 'fa-skyatlas', 'fa-skype', 'fa-slack', 'fa-slideshare', 'fa-soundcloud', 'fa-spotify', 'fa-stack-exchange', 'fa-stack-overflow', 'fa-steam', 'fa-stumbleupon', 'fa-tencent-weibo', 'fa-trello', 'fa-tripadvisor', 'fa-tumblr', 'fa-twitch', 'fa-twitter', 'fa-viacoin', 'fa-vimeo', 'fa-vine', 'fa-vk', 'fa-wechat', 'fa-weibo', 'fa-weixin', 'fa-whatsapp', 'fa-wordpress', 'fa-xing', 'fa-y-combinator', 'fa-yelp', 'fa-youtube-play'] + social: ['fa-globe', 'fa-amazon', 'fa-angellist', 'fa-apple', 'fa-behance', 'fa-bitbucket', 'fa-codepen', 'fa-connectdevelop', 'fa-dashcube', 'fa-delicious', 'fa-deviantart', 'fa-digg', 'fa-dribbble', 'fa-dropbox', 'fa-drupal', 'fa-facebook', 'fa-flickr', 'fa-foursquare', 'fa-get-pocket', 'fa-git', 'fa-github', 'fa-github-alt', 'fa-gittip', 'fa-google', 'fa-google-plus', 'fa-google-wallet', 'fa-gratipay', 'fa-hacker-news', 'fa-instagram', 'fa-ioxhost', 'fa-joomla', 'fa-jsfiddle', 'fa-lastfm', 'fa-leanpub', 'fa-linkedin', 'fa-meanpath', 'fa-medium', 'fa-odnoklassniki', 'fa-opencart', 'fa-pagelines', 'fa-paypal', 'fa-pied-piper-alt', 'fa-pinterest-p', 'fa-qq', 'fa-reddit', 'fa-renren', 'fa-sellsy', 'fa-share-alt', 'fa-shirtsinbulk', 'fa-simplybuilt', 'fa-skyatlas', 'fa-skype', 'fa-slack', 'fa-slideshare', 'fa-soundcloud', 'fa-spotify', 'fa-stack-exchange', 'fa-stack-overflow', 'fa-steam', 'fa-stumbleupon', 'fa-tencent-weibo', 'fa-trello', 'fa-tripadvisor', 'fa-tumblr', 'fa-twitch', 'fa-twitter', 'fa-viacoin', 'fa-vimeo', 'fa-vine', 'fa-vk', 'fa-wechat', 'fa-weibo', 'fa-weixin', 'fa-whatsapp', 'fa-wordpress', 'fa-xing', 'fa-y-combinator', 'fa-yelp', 'fa-youtube-play'] }; } }, { @@ -33,20 +156,20 @@ System.register('Davis/SocialProfile/components/IconSelectorComponent', ['flarum value: function view() { var _this2 = this; - $(".iconpicker-image-" + this.props.index()).error(function () { + $('.iconpicker-image-' + this.props.index()).error(function () { _this2.props.favicon('none'); - _this2.props.selection(_this2.icons['social'][0]); + _this2.props.selection(_this2.icons.social[0]); m.redraw(); }); this.props.children = this.items().toArray(); - return babelHelpers.get(Object.getPrototypeOf(IconSelectorComponent.prototype), 'view', this).call(this); + return babelHelpers.get(IconSelectorComponent.prototype.__proto__ || Object.getPrototypeOf(IconSelectorComponent.prototype), 'view', this).call(this); } }, { key: 'getButtonContent', value: function getButtonContent() { - return [/^favicon(-\w+)?$/.test(this.props.selection()) ? [m('img', { 'class': this.props.selection() == 'favicon-grey' ? 'social-greyscale-button' : 'social-button', style: 'width: 14px;height: 14px;', src: this.props.favicon() })] : icon(this.props.selection().replace('fa-', ''), {}), this.props.caretIcon ? icon(this.props.caretIcon, { className: 'Button-caret' }) : '']; + return [/^favicon(-\w+)?$/.test(this.props.selection()) ? [m('img', { className: this.props.selection() === 'favicon-grey' ? 'social-greyscale-button' : 'social-button', style: { width: '14px', height: '14px' }, alt: 'favicon', src: this.props.favicon() })] : icon(this.props.selection().replace('fa-', ''), {}), this.props.caretIcon ? icon(this.props.caretIcon, { className: 'Button-caret' }) : '']; } }, { key: 'items', @@ -55,37 +178,31 @@ System.register('Davis/SocialProfile/components/IconSelectorComponent', ['flarum var items = new ItemList(); - if (this.props.favicon() != 'none') { + if (this.props.favicon() !== 'none') { items.add('favicon', m('div', { onclick: function onclick() { _this3.props.selection('favicon');m.redraw(); - }, role: "button", href: "#", class: "iconpicker-item " + (this.props.selection() == 'favicon' ? "iconpicker--highlighted" : ""), title: 'Favicon' }, [m('img', { 'class': "iconpicker-image-" + this.props.index(), style: 'width: 14px;height: 14px;margin: 0 2px 0 2px;', src: this.props.favicon() })]), 102); + }, role: 'button', href: '#', class: 'iconpicker-item ' + (this.props.selection() === 'favicon' ? 'iconpicker--highlighted' : ''), title: 'Favicon' }, [m('img', { className: 'iconpicker-image-' + this.props.index(), alt: 'favicon', style: { width: '14px', height: '14px', margin: '0 2px 0 2px' }, src: this.props.favicon() })]), 102); items.add('favicon-grey', m('div', { onclick: function onclick() { _this3.props.selection('favicon-grey');m.redraw(); - }, role: "button", href: "#", class: "iconpicker-item-invt " + (this.props.selection() == 'favicon-grey' ? "iconpicker--highlighted" : ""), title: 'Grey Favicon' }, [m('img', { 'class': "social-greyscale-button iconpicker-image-" + this.props.index(), style: 'width: 14px;height: 14px;margin: 0 2px 0 2px;', src: this.props.favicon() })]), 101); + }, role: 'button', href: '#', class: 'iconpicker-item-invt ' + (this.props.selection() === 'favicon-grey' ? 'iconpicker--highlighted' : ''), title: 'Grey Favicon' }, [m('img', { className: 'social-greyscale-button iconpicker-image-' + this.props.index(), alt: 'favicon', style: { width: '14px', height: '14px', margin: '0 2px 0 2px' }, src: this.props.favicon() })]), 101); } - var _loop = function _loop(k) { - highlighted = m.prop(); - - if (_this3.props.selection() == _this3.icons['social'][k]) { + this.icons.social.forEach(function (curIcon) { + var highlighted = m.prop(); + if (_this3.props.selection() === curIcon) { highlighted('iconpicker--highlighted'); } - items.add(_this3.icons['social'][k], m('div', { onclick: function onclick() { - _this3.props.selection(_this3.icons['social'][k]);m.redraw(); - }, role: "button", href: "#", class: "iconpicker-item " + highlighted(), title: '.' + _this3.icons['social'][k] }, [icon(_this3.icons['social'][k].replace('fa-', ''), { className: 'social-icon' })]), 100); - }; - - for (var k in this.icons['social']) { - var highlighted; + items.add(curIcon, m('div', { onclick: function onclick() { + _this3.props.selection(curIcon);m.redraw(); + }, role: 'button', href: '#', class: 'iconpicker-item ' + highlighted(), title: '.' + curIcon }, [icon(curIcon.replace('fa-', ''), { className: 'social-icon' })]), 100); + }); - _loop(k); - } return items; } }], [{ key: 'initProps', value: function initProps(props) { - babelHelpers.get(Object.getPrototypeOf(IconSelectorComponent), 'initProps', this).call(this, props); + babelHelpers.get(IconSelectorComponent.__proto__ || Object.getPrototypeOf(IconSelectorComponent), 'initProps', this).call(this, props); props.className = 'icondropdown'; props.buttonClassName = 'Button Button--icon'; @@ -101,15 +218,15 @@ System.register('Davis/SocialProfile/components/IconSelectorComponent', ['flarum });; 'use strict'; -System.register('Davis/SocialProfile/components/SocialButtonsModal', ['flarum/components/Modal', 'flarum/components/Button', 'flarum/utils/string', 'Davis/SocialProfile/components/WebsiteInputComponent'], function (_export, _context) { - var Modal, Button, slug, WebsiteInputComponent, SocialButtonsModal; +System.register('Davis/SocialProfile/components/SocialButtonsModal', ['flarum/components/Modal', 'flarum/components/Button', 'Davis/SocialProfile/components/WebsiteInputComponent'], function (_export, _context) { + "use strict"; + + var Modal, Button, WebsiteInputComponent, SocialButtonsModal; return { setters: [function (_flarumComponentsModal) { Modal = _flarumComponentsModal.default; }, function (_flarumComponentsButton) { Button = _flarumComponentsButton.default; - }, function (_flarumUtilsString) { - slug = _flarumUtilsString.slug; }, function (_DavisSocialProfileComponentsWebsiteInputComponent) { WebsiteInputComponent = _DavisSocialProfileComponentsWebsiteInputComponent.default; }], @@ -119,25 +236,27 @@ System.register('Davis/SocialProfile/components/SocialButtonsModal', ['flarum/co function SocialButtonsModal() { babelHelpers.classCallCheck(this, SocialButtonsModal); - return babelHelpers.possibleConstructorReturn(this, Object.getPrototypeOf(SocialButtonsModal).apply(this, arguments)); + return babelHelpers.possibleConstructorReturn(this, (SocialButtonsModal.__proto__ || Object.getPrototypeOf(SocialButtonsModal)).apply(this, arguments)); } babelHelpers.createClass(SocialButtonsModal, [{ key: 'init', value: function init() { + var _this2 = this; - babelHelpers.get(Object.getPrototypeOf(SocialButtonsModal.prototype), 'init', this).call(this); + babelHelpers.get(SocialButtonsModal.prototype.__proto__ || Object.getPrototypeOf(SocialButtonsModal.prototype), 'init', this).call(this); this.buttons = []; - if (this.props.data == true) { - this.createButtonObject(0); - } else { - for (var k in this.props.data) { - if (this.props.data[k]['title'] != "") { - var button = this.props.data[k]; - this.createButtonObject(k, button); + var buttons = JSON.parse(this.props.user.data.attributes.socialButtons || '[]'); + + if (buttons.length) { + buttons.forEach(function (button, index) { + if (button.title !== '') { + _this2.createButtonObject(index, button); } - } + }); + } else { + this.createButtonObject(0); } } }, { @@ -153,27 +272,33 @@ System.register('Davis/SocialProfile/components/SocialButtonsModal', ['flarum/co }, { key: 'content', value: function content() { - var _this2 = this; + var _this3 = this; $('.Modal-content').css('overflow', 'visible'); return [m('div', { className: 'Modal-body' }, [m('div', { className: 'Form' }, [this.buttons.map(function (button) { - return [WebsiteInputComponent.component({ - button: button - })]; - }), m('div', { className: 'Form-group', id: 'submit-button-group' }, [m('div', { className: 'Button Button--primary EditSocialButtons-add', style: 'margin-left: 1%;', + return WebsiteInputComponent.component({ button: button }); + }), m('div', { className: 'Form-group', id: 'submit-button-group' }, [m('div', { + className: 'Button Button--primary EditSocialButtons-add', + style: 'margin-left: 1%;', onclick: function onclick() { - _this2.createButtonObject(_this2.buttons.length); + _this3.createButtonObject(_this3.buttons.length); m.redraw(); - $('#socialgroup' + (_this2.buttons.length - 1)).delay(150).slideDown(); - } }, [m('i', { className: 'fa fa-fw fa-plus' })]), m('div', { className: 'Button Button--primary EditSocialButtons-del', style: 'margin-left: 1%;', + $('document').ready(function () { + $('#socialgroup-' + (_this3.buttons.length - 1)).slideDown(); + }); + } + }, [m('i', { className: 'fa fa-fw fa-plus' })]), m('div', { + className: 'Button Button--primary EditSocialButtons-del', + style: 'margin-left: 1%;', onclick: function onclick() { - var curdel = _this2.buttons.length - 1; - $('#socialgroup' + curdel).slideUp('normal', function () { - _this2.buttons.splice(curdel, 1); + var curdel = _this3.buttons.length - 1; + $('#socialgroup-' + curdel).slideUp('normal', function () { + _this3.buttons.splice(curdel, 1); m.redraw(); }); - } }, [m('i', { className: 'fa fa-fw fa-minus' })]), Button.component({ + } + }, [m('i', { className: 'fa fa-fw fa-minus' })]), Button.component({ type: 'submit', style: 'float: right;', className: 'Button Button--primary EditSocialButtons-save', @@ -181,61 +306,59 @@ System.register('Davis/SocialProfile/components/SocialButtonsModal', ['flarum/co children: app.translator.trans('davis-socialprofile.forum.edit.submit') })])])])]; } + }, { + key: 'data', + value: function data() { + var buttons = []; + + this.buttons.forEach(function (button, index) { + if (button.title() !== '') { + buttons[index] = {}; + buttons[index].title = button.title(); + buttons[index].url = button.url(); + buttons[index].icon = button.icon(); + buttons[index].favicon = button.favicon(); + } + }); + + return { + socialButtons: JSON.stringify(buttons) + }; + } }, { key: 'onsubmit', value: function onsubmit(e) { - var _this3 = this; + var _this4 = this; e.preventDefault(); this.loading = true; - this.finbuttons = []; - for (var k in this.buttons) { - if (this.buttons[k].title() != "") { - var number = this.finbuttons.length; - this.finbuttons[number] = {}; - this.finbuttons[number].title = m.prop(this.buttons[k].title()); - this.finbuttons[number].url = m.prop(this.buttons[k].url()); - this.finbuttons[number].icon = m.prop(this.buttons[k].icon()); - this.finbuttons[number].favicon = m.prop(this.buttons[k].favicon()); - } - } - this.finbuttons = JSON.stringify(this.finbuttons); - var data = new FormData(); - data.append('buttons', this.finbuttons); - app.request({ - method: 'POST', - url: app.forum.attribute('apiUrl') + '/profile/socialbuttons', - serialize: function serialize(raw) { - return raw; - }, - data: data - }).then(function () { - $('#app').trigger("refreshSocialButtons", [_this3.finbuttons]); - _this3.hide(); - }, function (response) { - _this3.loading = false; - _this3.handleErrors(response); + + this.props.user.save(this.data(), { errorHandler: this.onerror.bind(this) }).then(this.hide.bind(this)).then($('#app').trigger('refreshSocialButtons', [this.data().socialButtons])).catch(function () { + _this4.loading = false; + m.redraw(); }); } }, { key: 'createButtonObject', value: function createButtonObject(key) { - var button = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; + var button = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; if (button == null) { - button = {}; - button['favicon'] = 'none'; - button['title'] = ''; - button['url'] = ''; - button['icon'] = 'globe'; + this.buttons[key] = {}; + this.buttons[key].index = m.prop(key); + this.buttons[key].favicon = m.prop('none'); + this.buttons[key].title = m.prop(''); + this.buttons[key].url = m.prop(''); + this.buttons[key].icon = m.prop('globe'); + } else { + this.buttons[key] = {}; + this.buttons[key].index = m.prop(key); + this.buttons[key].favicon = m.prop(button.favicon); + this.buttons[key].title = m.prop(button.title); + this.buttons[key].url = m.prop(button.url); + this.buttons[key].icon = m.prop(button.icon); } - this.buttons[key] = {}; - this.buttons[key].index = m.prop(key); - this.buttons[key].favicon = m.prop(button["favicon"]); - this.buttons[key].title = m.prop(button["title"]); - this.buttons[key].url = m.prop(button["url"]); - this.buttons[key].icon = m.prop(button["icon"]); } }]); return SocialButtonsModal; @@ -247,13 +370,13 @@ System.register('Davis/SocialProfile/components/SocialButtonsModal', ['flarum/co });; 'use strict'; -System.register('Davis/SocialProfile/components/WebsiteInputComponent', ['flarum/Component', 'flarum/utils/extract', 'Davis/SocialProfile/components/IconSelectorComponent'], function (_export, _context) { - var Component, extract, IconSelectorComponent, WebsiteInputComponent; +System.register('Davis/SocialProfile/components/WebsiteInputComponent', ['flarum/Component', 'Davis/SocialProfile/components/IconSelectorComponent'], function (_export, _context) { + "use strict"; + + var Component, IconSelectorComponent, WebsiteInputComponent; return { setters: [function (_flarumComponent) { Component = _flarumComponent.default; - }, function (_flarumUtilsExtract) { - extract = _flarumUtilsExtract.default; }, function (_DavisSocialProfileComponentsIconSelectorComponent) { IconSelectorComponent = _DavisSocialProfileComponentsIconSelectorComponent.default; }], @@ -263,13 +386,13 @@ System.register('Davis/SocialProfile/components/WebsiteInputComponent', ['flarum function WebsiteInputComponent() { babelHelpers.classCallCheck(this, WebsiteInputComponent); - return babelHelpers.possibleConstructorReturn(this, Object.getPrototypeOf(WebsiteInputComponent).apply(this, arguments)); + return babelHelpers.possibleConstructorReturn(this, (WebsiteInputComponent.__proto__ || Object.getPrototypeOf(WebsiteInputComponent)).apply(this, arguments)); } babelHelpers.createClass(WebsiteInputComponent, [{ key: 'init', value: function init() { - babelHelpers.get(Object.getPrototypeOf(WebsiteInputComponent.prototype), 'init', this).call(this); + babelHelpers.get(WebsiteInputComponent.prototype.__proto__ || Object.getPrototypeOf(WebsiteInputComponent.prototype), 'init', this).call(this); this.button = this.props.button; } @@ -278,63 +401,59 @@ System.register('Davis/SocialProfile/components/WebsiteInputComponent', ['flarum value: function view() { var _this2 = this; - return m( - 'div', - { - className: 'Form-group form-group-social', - id: 'socialgroup' + this.button.index() - }, - m('input', { - className: 'SocialFormControl SocialTitle', - placeholder: app.translator.trans('davis-socialprofile.forum.edit.title'), - value: this.button.title(), - oninput: m.withAttr('value', this.button.title) }), - IconSelectorComponent.component({ - selection: this.button.icon, - favicon: this.button.favicon, - index: this.button.index - }), - m('input', { - className: 'SocialFormControl Socialurl', - placeholder: app.translator.trans('davis-socialprofile.forum.edit.url'), - value: this.button.url(), - oninput: m.withAttr('value', function (value) { - _this2.button.url(value); - clearTimeout(_this2.waittilfinsihed); - if (_this2.button.icon() !== 'fa-circle-o-notch fa-spin') { - _this2.button.icon('fa-circle-o-notch fa-spin'); + return m('div', { + className: 'Form-group form-group-social', + id: 'socialgroup-' + this.button.index() + }, [m('input', { + className: 'SocialFormControl SocialTitle', + placeholder: app.translator.trans('davis-socialprofile.forum.edit.title'), + tabIndex: (this.button.index() + 1) * 2 - 1, + value: this.button.title(), + onchange: m.withAttr('value', this.button.title) + }), IconSelectorComponent.component({ + selection: this.button.icon, + favicon: this.button.favicon, + index: this.button.index + }), m('input', { + className: 'SocialFormControl Socialurl', + placeholder: app.translator.trans('davis-socialprofile.forum.edit.url'), + tabIndex: (this.button.index() + 1) * 2, + value: this.button.url(), + onchange: m.withAttr('value', function (value) { + _this2.button.url(value); + clearTimeout(_this2.waittilfinsihed); + if (_this2.button.icon() !== 'fa-circle-o-notch fa-spin') { + _this2.button.icon('fa-circle-o-notch fa-spin'); + _this2.button.favicon('none'); + } + _this2.waittilfinsihed = setTimeout(function () { + var urlpattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/; + + if (urlpattern.test(_this2.button.url().toLowerCase())) { + var iconurl = _this2.button.url().replace(/(:\/\/[^\/]+).*$/, '$1') + '\n /favicon.ico'; + _this2.button.favicon(iconurl); + _this2.button.icon('favicon'); + m.redraw(); + } else { + _this2.button.icon('fa-globe'); _this2.button.favicon('none'); + m.redraw(); } - _this2.waittilfinsihed = setTimeout(function () { - var urlpattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/; - if (urlpattern.test(_this2.button.url().toLowerCase())) { - var iconurl = _this2.button.url().replace(/(:\/\/[^\/]+).*$/, '$1') + '/favicon.ico'; - _this2.button.favicon(iconurl); - _this2.button.icon('favicon'); - m.redraw(); - } else { - _this2.button.icon('fa-globe'); - _this2.button.favicon('none'); - m.redraw(); - } - }, 1000); - }) - }), - m('input', { - className: 'SocialFormControl SocialIcon', - id: 'icon' + this.button.index(), - style: 'display: none', - value: this.button.icon(), - onchange: m.withAttr('value', this.button.icon) - }), - m('input', { - className: 'SocialFormControl Socialfavicon', - id: 'favicon' + this.button.index(), - style: 'display: none', - value: this.button.favicon(), - onchange: m.withAttr('value', this.button.favicon) + }, 1000); }) - ); + }), m('input', { + className: 'SocialFormControl SocialIcon', + id: 'icon' + this.button.index(), + style: { display: 'none' }, + value: this.button.icon(), + onchange: m.withAttr('value', this.button.icon) + }), m('input', { + className: 'SocialFormControl Socialfavicon', + id: 'favicon' + this.button.index(), + style: { display: 'none' }, + value: this.button.favicon(), + onchange: m.withAttr('value', this.button.favicon) + })]); } }]); return WebsiteInputComponent; @@ -346,136 +465,114 @@ System.register('Davis/SocialProfile/components/WebsiteInputComponent', ['flarum });; 'use strict'; -System.register('Davis/SocialProfile/main', ['flarum/app', 'flarum/extend', 'flarum/components/UserCard', 'flarum/components/Badge', 'Davis/SocialProfile/components/SocialButtonsModal'], function (_export, _context) { - var app, extend, UserCard, Badge, SocialButtonsModal; - return { - setters: [function (_flarumApp) { - app = _flarumApp.default; - }, function (_flarumExtend) { - extend = _flarumExtend.extend; - }, function (_flarumComponentsUserCard) { - UserCard = _flarumComponentsUserCard.default; - }, function (_flarumComponentsBadge) { - Badge = _flarumComponentsBadge.default; - }, function (_DavisSocialProfileComponentsSocialButtonsModal) { - SocialButtonsModal = _DavisSocialProfileComponentsSocialButtonsModal.default; - }], - execute: function () { - - app.initializers.add('davis-socialprofile-forum', function () { - - extend(UserCard.prototype, 'init', function () { - var _this = this; - - var user = this.props.user; - var apiUrl = app.forum.attribute('apiUrl') + '/profile/socialbutton/' + user.data.id; - this.buttonsArray = null; //Indicate we haven't retrieved the user's buttons - //Get buttons from database - app.request({ method: "GET", url: apiUrl }).then(function (result) { - //Test if user has set their buttons up already - if (result.data.attributes.hasOwnProperty("buttons")) { - //Test if buttons have been set up, but the array is empty - if (result.data.attributes.buttons == "[]") { - //Since there are no buttons set, we have a blank slate - _this.buttonsArray = true; //Indicate we have retrieved the user's buttons - _this.isBlankSlate = true; //Indicate we don't have any buttons - } else { - //The buttons array must not be empty, so lets set it - _this.buttonsArray = JSON.parse(result.data.attributes.buttons); - _this.isBlankSlate = false; //Indicate we do have buttons - } - } else { - //This user has never set their buttons - _this.buttonsArray = true; //Indicate we have retrieved the user's buttons - _this.isBlankSlate = true; //Indicate we don't have any buttons - } - user.freshness = new Date(); //Tell Mithril we have new data - m.redraw(); //Refresh the DOM - }); - - //If the buttons have been edited, we need to refresh them - $('#app').on('refreshSocialButtons', function (e, buttons) { - var user = _this.props.user; //Then is our user - _this.buttonsArray = JSON.parse(buttons); //Parse the saved array from editing - _this.isBlankSlate = false; //Indicate we do really have buttons - user.freshness = new Date(); //Tell Mithril we have new data - m.redraw(); //Refresh DOM - }); - }); +System.register('Davis/SocialProfile/main', ['flarum/app', 'flarum/Model', 'flarum/models/User', 'flarum/extend', 'flarum/components/UserCard', 'flarum/components/Badge', 'Davis/SocialProfile/components/SocialButtonsModal', 'Davis/SocialProfile/components/DeleteButtonModal'], function (_export, _context) { + "use strict"; + + var app, Model, User, extend, UserCard, Badge, SocialButtonsModal, DeleteButtonModal; + return { + setters: [function (_flarumApp) { + app = _flarumApp.default; + }, function (_flarumModel) { + Model = _flarumModel.default; + }, function (_flarumModelsUser) { + User = _flarumModelsUser.default; + }, function (_flarumExtend) { + extend = _flarumExtend.extend; + }, function (_flarumComponentsUserCard) { + UserCard = _flarumComponentsUserCard.default; + }, function (_flarumComponentsBadge) { + Badge = _flarumComponentsBadge.default; + }, function (_DavisSocialProfileComponentsSocialButtonsModal) { + SocialButtonsModal = _DavisSocialProfileComponentsSocialButtonsModal.default; + }, function (_DavisSocialProfileComponentsDeleteButtonModal) { + DeleteButtonModal = _DavisSocialProfileComponentsDeleteButtonModal.default; + }], + execute: function () { - extend(UserCard.prototype, 'infoItems', function (items) { - var _this2 = this; - - // If request hasn't loaded yet, don't add any items. - if (!this.buttonsArray) return; - - //If there are buttons, add them - if (!this.isBlankSlate) { - var _loop = function _loop(k) { - var selectedButton = _this2.buttonsArray[k]; //Set constant for easier selection - //Ensure the button has a title, icon, and url - if (selectedButton["title"] !== "" && selectedButton["icon"] !== "" && selectedButton["url"] !== "") { - //If the button is using a favicon, make sure it is displayed - if (selectedButton['icon'] == 'favicon' || selectedButton['icon'] == 'favicon-grey') { - buttonStyle = 'background-image: url("' + selectedButton['favicon'] + '");background-size: 60%;background-position: 50% 50%;background-repeat: no-repeat;'; - //If the favicon is set to greyscale, make sure it is displayed - if (selectedButton['icon'] == 'favicon-grey') { - buttonClass = selectedButton["icon"] + '-' + k + ' social-button social-greyscale-button'; - } else { - buttonClass = selectedButton["icon"] + '-' + k + ' social-button'; - } - } else { - buttonStyle = ''; - buttonClass = selectedButton["icon"] + '-' + k + ' social-button'; - } - //Acctually add the button - items.add(buttonClass, Badge.component({ - type: "social social-icon-" + k, - icon: selectedButton["icon"].replace('fa-', ''), - label: selectedButton["title"], - style: buttonStyle, - onclick: function onclick() { - window.open(selectedButton["url"], '_blank'); - } - })); - } - }; - - //Loop through the buttonsArray - for (var k in this.buttonsArray) { - var buttonStyle, buttonClass; - - _loop(k); - } - //Add the edit buttons at the end, as long as it's their own profile - if (app.session.user === app.current.user && app.session.user !== undefined && app.current.user !== undefined) { - //Add the settings button - items.add('settings social-button', Badge.component({ - type: "social social-settings", - icon: 'cog', - label: app.translator.trans('davis-socialprofile.forum.edit.edit'), - onclick: function onclick() { - app.modal.show(new SocialButtonsModal({ data: _this2.buttonsArray })); //Show the edit modal - } - }), -1); - } - //It turns out they don't have any buttons + app.initializers.add('davis-socialprofile-forum', function () { + User.prototype.socialButtons = Model.attribute('socialButtons'); + + extend(UserCard.prototype, 'init', function () { + var _this = this; + + $('#app').on('refreshSocialButtons', function (e, buttons) { + _this.buttons = JSON.parse(buttons || '[]'); + _this.props.user.data.attributes.socialButtons = JSON.parse(buttons || '[]'); + _this.props.user.freshness = new Date(); + m.redraw(); + }); + }); + + extend(UserCard.prototype, 'infoItems', function (items) { + var _this2 = this; + + this.isSelf = app.session.user === this.props.user; + this.canEdit = app.session.user ? app.session.user.data.attributes.canEdit : false; + this.buttons = JSON.parse(this.props.user.data.attributes.socialButtons || '[]'); + + if (this.buttons.length) { + this.buttons.forEach(function (button, index) { + if (button.title !== '' && button.icon !== '' && button.url !== '') { + var buttonStyle = ''; + var buttonClassName = ''; + + if (button.icon === 'favicon' || button.icon === 'favicon-grey') { + buttonStyle = 'background-image: url("' + button.favicon + '");background-size: 60%;background-position: 50% 50%;background-repeat: no-repeat;'; + if (button.icon === 'favicon-grey') { + buttonClassName = button.icon + '-' + index + ' social-button social-greyscale-button'; + } else { + buttonClassName = button.icon + '-' + index + ' social-button'; + } + } else { + buttonStyle = ''; + buttonClassName = button.icon + '-' + index + ' social-button'; + } + items.add('' + buttonClassName + (_this2.deleting ? ' social-button--highlightable' : ''), Badge.component({ + type: 'social social-icon-' + index, + icon: button.icon.replace('fa-', ''), + label: button.title, + style: buttonStyle, + onclick: function onclick() { + if (_this2.deleting) { + app.modal.show(new DeleteButtonModal({ user: _this2.props.user, index: index })); } else { - //Add an add button only if its their own profile - if (app.session.user === app.current.user && app.session.user !== undefined && app.current.user !== undefined) { - //Add the add button - items.add('settings social-button', Badge.component({ - type: "social null-social-settings", - icon: "plus", - label: app.translator.trans('davis-socialprofile.forum.edit.add'), - onclick: function onclick() { - app.modal.show(new SocialButtonsModal({ data: _this2.buttonsArray })); - } - }), -1); - } - } - }); + window.open(button.url, '_blank'); + } + } + })); + } }); - } - }; + if (this.isSelf) { + items.add('settings social-button', Badge.component({ + type: 'social social-settings', + icon: 'cog', + label: app.translator.trans('davis-socialprofile.forum.edit.edit'), + onclick: function onclick() { + app.modal.show(new SocialButtonsModal({ user: _this2.props.user })); + } + }), -1); + } else if (this.canEdit) { + items.add('settings social-button', Badge.component({ + type: 'social social-moderate ' + (this.deleting ? 'social-moderate--highlighted' : ''), + icon: 'exclamation-triangle', + label: app.translator.trans('davis-socialprofile.forum.edit.delete'), + onclick: function onclick() { + _this2.deleting = !_this2.deleting; + } + }), -1); + } + } else if (this.isSelf) { + items.add('settings social-button', Badge.component({ + type: 'social null-social-settings', + icon: 'plus', + label: app.translator.trans('davis-socialprofile.forum.edit.add'), + onclick: function onclick() { + app.modal.show(new SocialButtonsModal({ user: _this2.props.user })); + } + }), -1); + } + }); + }); + } + }; }); \ No newline at end of file diff --git a/js/forum/package.json b/js/forum/package.json index 34e1b71..2bdaf6a 100644 --- a/js/forum/package.json +++ b/js/forum/package.json @@ -1,7 +1,7 @@ { "private": true, "devDependencies": { - "gulp": "^3.8.11", - "flarum-gulp": "^0.2.0" + "gulp": "^3.9.1", + "flarum-gulp": "dav-is/flarum-gulp#patch-1" } } \ No newline at end of file diff --git a/js/forum/src/components/DeleteButtonModal.js b/js/forum/src/components/DeleteButtonModal.js new file mode 100644 index 0000000..8d1051e --- /dev/null +++ b/js/forum/src/components/DeleteButtonModal.js @@ -0,0 +1,96 @@ +import Modal from 'flarum/components/Modal'; +import Button from 'flarum/components/Button'; + +export default class DeleteButtonModal extends Modal { + init() { + super.init(); + + this.buttons = []; + this.index = this.props.index; + const buttons = JSON.parse(this.props.user.data.attributes.socialButtons || '[]'); + this.button = buttons[this.index]; + + buttons.forEach((button, index) => { + this.createButtonObject(index, button); + }); + } + + className() { + return 'SocialButtonsModal Modal--small'; + } + + title() { + return app.translator.trans('davis-socialprofile.forum.edit.deletetitle'); + } + + content() { + $('.Modal-content').css('overflow', 'visible'); + return [ + m('div', { className: 'Modal-body' }, [ + m('div', { className: 'Form' }, [ + m('h3', { className: 'SocialProfile-title' }, this.button.title), + m('p', { className: 'SocialProfile-url' }, this.button.url), + m('div', { className: 'Form-group', id: 'submit-button-group' }, [ + Button.component({ + type: 'submit', + className: 'Button Button--primary EditSocialButtons-delete', + loading: this.loading, + children: app.translator.trans('davis-socialprofile.forum.edit.delete'), + }), + ]), + ]), + ]), + ]; + } + + data() { + const buttons = []; + + this.buttons.forEach((button, index) => { + if (button.title() !== '') { + buttons[index] = {}; + buttons[index].title = button.title(); + buttons[index].url = button.url(); + buttons[index].icon = button.icon(); + buttons[index].favicon = button.favicon(); + } + }); + + return { + socialButtons: JSON.stringify(buttons), + }; + } + + onsubmit(e) { + e.preventDefault(); + + this.loading = true; + this.buttons.splice(this.index, 1); + + this.props.user.save(this.data(), { errorHandler: this.onerror.bind(this) }) + .then(this.hide.bind(this)) + .then($('#app').trigger('refreshSocialButtons', [this.data().socialButtons])) + .catch(() => { + this.loading = false; + m.redraw(); + }); + } + + createButtonObject(key, button = null) { + if (button == null) { + this.buttons[key] = {}; + this.buttons[key].index = m.prop(key); + this.buttons[key].favicon = m.prop('none'); + this.buttons[key].title = m.prop(''); + this.buttons[key].url = m.prop(''); + this.buttons[key].icon = m.prop('globe'); + } else { + this.buttons[key] = {}; + this.buttons[key].index = m.prop(key); + this.buttons[key].favicon = m.prop(button.favicon); + this.buttons[key].title = m.prop(button.title); + this.buttons[key].url = m.prop(button.url); + this.buttons[key].icon = m.prop(button.icon); + } + } +} diff --git a/js/forum/src/components/IconSelectorComponent.js b/js/forum/src/components/IconSelectorComponent.js index 3bc46b2..cac4d9f 100644 --- a/js/forum/src/components/IconSelectorComponent.js +++ b/js/forum/src/components/IconSelectorComponent.js @@ -10,24 +10,23 @@ export default class IconSelectorComponent extends Dropdown { props.buttonClassName = 'Button Button--icon'; props.menuClassName = 'social-dropdown-menu'; } - + init() { super.init(); - + this.icons = { - 'social': - ["fa-globe", 'fa-amazon', 'fa-angellist', 'fa-apple', 'fa-behance', 'fa-bitbucket', 'fa-codepen', 'fa-connectdevelop', 'fa-dashcube', 'fa-delicious', 'fa-deviantart', 'fa-digg', 'fa-dribbble', 'fa-dropbox', 'fa-drupal', 'fa-facebook', 'fa-flickr', 'fa-foursquare', 'fa-get-pocket', 'fa-git', 'fa-github', 'fa-github-alt', 'fa-gittip', 'fa-google', 'fa-google-plus', 'fa-google-wallet', 'fa-gratipay', 'fa-hacker-news', 'fa-instagram', 'fa-ioxhost', 'fa-joomla', 'fa-jsfiddle', 'fa-lastfm', 'fa-leanpub', 'fa-linkedin', 'fa-meanpath', 'fa-medium', 'fa-odnoklassniki', 'fa-opencart', 'fa-pagelines', 'fa-paypal', 'fa-pied-piper-alt', 'fa-pinterest-p', 'fa-qq', 'fa-reddit', 'fa-renren', 'fa-sellsy', 'fa-share-alt', 'fa-shirtsinbulk', 'fa-simplybuilt', 'fa-skyatlas', 'fa-skype', 'fa-slack', 'fa-slideshare', 'fa-soundcloud', 'fa-spotify', 'fa-stack-exchange', 'fa-stack-overflow', 'fa-steam', 'fa-stumbleupon', 'fa-tencent-weibo', 'fa-trello', 'fa-tripadvisor', 'fa-tumblr', 'fa-twitch', 'fa-twitter', 'fa-viacoin', 'fa-vimeo', 'fa-vine', 'fa-vk', 'fa-wechat', 'fa-weibo', 'fa-weixin', 'fa-whatsapp', 'fa-wordpress', 'fa-xing', 'fa-y-combinator', 'fa-yelp', 'fa-youtube-play' ], + social: + ['fa-globe', 'fa-amazon', 'fa-angellist', 'fa-apple', 'fa-behance', 'fa-bitbucket', 'fa-codepen', 'fa-connectdevelop', 'fa-dashcube', 'fa-delicious', 'fa-deviantart', 'fa-digg', 'fa-dribbble', 'fa-dropbox', 'fa-drupal', 'fa-facebook', 'fa-flickr', 'fa-foursquare', 'fa-get-pocket', 'fa-git', 'fa-github', 'fa-github-alt', 'fa-gittip', 'fa-google', 'fa-google-plus', 'fa-google-wallet', 'fa-gratipay', 'fa-hacker-news', 'fa-instagram', 'fa-ioxhost', 'fa-joomla', 'fa-jsfiddle', 'fa-lastfm', 'fa-leanpub', 'fa-linkedin', 'fa-meanpath', 'fa-medium', 'fa-odnoklassniki', 'fa-opencart', 'fa-pagelines', 'fa-paypal', 'fa-pied-piper-alt', 'fa-pinterest-p', 'fa-qq', 'fa-reddit', 'fa-renren', 'fa-sellsy', 'fa-share-alt', 'fa-shirtsinbulk', 'fa-simplybuilt', 'fa-skyatlas', 'fa-skype', 'fa-slack', 'fa-slideshare', 'fa-soundcloud', 'fa-spotify', 'fa-stack-exchange', 'fa-stack-overflow', 'fa-steam', 'fa-stumbleupon', 'fa-tencent-weibo', 'fa-trello', 'fa-tripadvisor', 'fa-tumblr', 'fa-twitch', 'fa-twitter', 'fa-viacoin', 'fa-vimeo', 'fa-vine', 'fa-vk', 'fa-wechat', 'fa-weibo', 'fa-weixin', 'fa-whatsapp', 'fa-wordpress', 'fa-xing', 'fa-y-combinator', 'fa-yelp', 'fa-youtube-play'], }; } view() { - - $(".iconpicker-image-"+this.props.index()).error(() => { + $(`.iconpicker-image-${this.props.index()}`).error(() => { this.props.favicon('none'); - this.props.selection(this.icons['social'][0]); + this.props.selection(this.icons.social[0]); m.redraw(); }); - + this.props.children = this.items().toArray(); return super.view(); @@ -35,33 +34,34 @@ export default class IconSelectorComponent extends Dropdown { getButtonContent() { return [ - (/^favicon(-\w+)?$/.test(this.props.selection())) ? [] : icon(this.props.selection().replace('fa-', ''), {}), - this.props.caretIcon ? icon(this.props.caretIcon, {className: 'Button-caret'}) : '' + (/^favicon(-\w+)?$/.test(this.props.selection())) ? [favicon] : icon(this.props.selection().replace('fa-', ''), {}), + this.props.caretIcon ? icon(this.props.caretIcon, { className: 'Button-caret' }) : '', ]; } - + items() { const items = new ItemList(); - - if(this.props.favicon() != 'none') { - items.add('favicon',( - m('div', {onclick: () => {this.props.selection('favicon'); m.redraw();}, role: "button", href: "#", class: "iconpicker-item "+(this.props.selection() == 'favicon' ? "iconpicker--highlighted" : ""), title: 'Favicon'}, [])), + + if (this.props.favicon() !== 'none') { + items.add('favicon', ( + m('div', { onclick: () => { this.props.selection('favicon'); m.redraw(); }, role: 'button', href: '#', class: `iconpicker-item ${this.props.selection() === 'favicon' ? 'iconpicker--highlighted' : ''}`, title: 'Favicon' }, [favicon])), 102 ); - items.add('favicon-grey',( - m('div', {onclick: () => {this.props.selection('favicon-grey'); m.redraw();}, role: "button", href: "#", class: "iconpicker-item-invt "+(this.props.selection() == 'favicon-grey' ? "iconpicker--highlighted" : ""), title: 'Grey Favicon'}, [])), + items.add('favicon-grey', ( + m('div', { onclick: () => { this.props.selection('favicon-grey'); m.redraw(); }, role: 'button', href: '#', class: `iconpicker-item-invt ${this.props.selection() === 'favicon-grey' ? 'iconpicker--highlighted' : ''}`, title: 'Grey Favicon' }, [favicon])), 101 ); } - - for(const k in this.icons['social']) { - var highlighted = m.prop(); - if (this.props.selection() == this.icons['social'][k]) { highlighted('iconpicker--highlighted'); } - items.add(this.icons['social'][k],( - m('div', {onclick: () => {this.props.selection(this.icons['social'][k]); m.redraw();}, role: "button", href: "#", class: "iconpicker-item " + highlighted(), title: '.'+this.icons['social'][k]}, [icon(this.icons['social'][k].replace('fa-', ''), {className: 'social-icon'})])), + + this.icons.social.forEach((curIcon) => { + const highlighted = m.prop(); + if (this.props.selection() === curIcon) { highlighted('iconpicker--highlighted'); } + items.add(curIcon, ( + m('div', { onclick: () => { this.props.selection(curIcon); m.redraw(); }, role: 'button', href: '#', class: `iconpicker-item ${highlighted()}`, title: `.${curIcon}` }, [icon(curIcon.replace('fa-', ''), { className: 'social-icon' })])), 100 ); - } + }); + return items; } -} \ No newline at end of file +} diff --git a/js/forum/src/components/SocialButtonsModal.js b/js/forum/src/components/SocialButtonsModal.js index 85078f4..af63da5 100644 --- a/js/forum/src/components/SocialButtonsModal.js +++ b/js/forum/src/components/SocialButtonsModal.js @@ -1,23 +1,22 @@ import Modal from 'flarum/components/Modal'; import Button from 'flarum/components/Button'; -import { slug } from 'flarum/utils/string'; import WebsiteInputComponent from 'Davis/SocialProfile/components/WebsiteInputComponent'; export default class SocialButtonsModal extends Modal { init() { - super.init(); this.buttons = []; - if (this.props.data == true) { - this.createButtonObject(0); - } else { - for(var k in this.props.data) { - if(this.props.data[k]['title'] != "") { - const button = this.props.data[k]; - this.createButtonObject(k, button); + const buttons = JSON.parse(this.props.user.data.attributes.socialButtons || '[]'); + + if (buttons.length) { + buttons.forEach((button, index) => { + if (button.title !== '') { + this.createButtonObject(index, button); } - } + }); + } else { + this.createButtonObject(0); } } @@ -31,99 +30,96 @@ export default class SocialButtonsModal extends Modal { content() { $('.Modal-content').css('overflow', 'visible'); - return [ - m('div', {className: 'Modal-body'}, [ - m('div', {className: 'Form'}, [ - this.buttons.map((button) => { - return [ - WebsiteInputComponent.component({ - button: button, - }), - ]; - }), - m('div', {className: 'Form-group', id: 'submit-button-group'}, [ - m('div', {className: 'Button Button--primary EditSocialButtons-add', style: 'margin-left: 1%;', - onclick: () => { - this.createButtonObject(this.buttons.length); - - m.redraw(); - $('#socialgroup'+(this.buttons.length - 1)).delay(150).slideDown(); - }}, [ - m('i', {className: 'fa fa-fw fa-plus'}) - ]), - m('div', {className: 'Button Button--primary EditSocialButtons-del', style: 'margin-left: 1%;', - onclick: () => { - var curdel = (this.buttons.length - 1); - $('#socialgroup'+curdel).slideUp('normal', () => { - this.buttons.splice(curdel, 1); - m.redraw(); - }); - }}, [ - m('i', {className: 'fa fa-fw fa-minus'}) - ]), - Button.component({ - type: 'submit', - style: 'float: right;', - className: 'Button Button--primary EditSocialButtons-save', - loading: this.loading, - children: app.translator.trans('davis-socialprofile.forum.edit.submit') - }), - ]), - ]), - ]), - ]; + return [ + m('div', { className: 'Modal-body' }, [ + m('div', { className: 'Form' }, [ + this.buttons.map(button => WebsiteInputComponent.component({ button })), + m('div', { className: 'Form-group', id: 'submit-button-group' }, [ + m('div', { + className: 'Button Button--primary EditSocialButtons-add', + style: 'margin-left: 1%;', + onclick: () => { + this.createButtonObject(this.buttons.length); + + m.redraw(); + $('document').ready(() => { $(`#socialgroup-${this.buttons.length - 1}`).slideDown(); }); + }, + }, [ + m('i', { className: 'fa fa-fw fa-plus' }), + ]), + m('div', { + className: 'Button Button--primary EditSocialButtons-del', + style: 'margin-left: 1%;', + onclick: () => { + const curdel = (this.buttons.length - 1); + $(`#socialgroup-${curdel}`).slideUp('normal', () => { + this.buttons.splice(curdel, 1); + m.redraw(); + }); + }, + }, [ + m('i', { className: 'fa fa-fw fa-minus' }), + ]), + Button.component({ + type: 'submit', + style: 'float: right;', + className: 'Button Button--primary EditSocialButtons-save', + loading: this.loading, + children: app.translator.trans('davis-socialprofile.forum.edit.submit'), + }), + ]), + ]), + ]), + ]; } - onsubmit(e) { - - e.preventDefault(); - - this.loading = true; - this.finbuttons = []; - for(var k in this.buttons) { - if (this.buttons[k].title() != "") { - var number = this.finbuttons.length - this.finbuttons[number] = {}; - this.finbuttons[number].title = m.prop(this.buttons[k].title()); - this.finbuttons[number].url = m.prop(this.buttons[k].url()); - this.finbuttons[number].icon = m.prop(this.buttons[k].icon()); - this.finbuttons[number].favicon = m.prop(this.buttons[k].favicon()); - } + data() { + const buttons = []; + + this.buttons.forEach((button, index) => { + if (button.title() !== '') { + buttons[index] = {}; + buttons[index].title = button.title(); + buttons[index].url = button.url(); + buttons[index].icon = button.icon(); + buttons[index].favicon = button.favicon(); } - this.finbuttons = JSON.stringify(this.finbuttons); - const data = new FormData(); - data.append('buttons', this.finbuttons); - app.request({ - method: 'POST', - url: app.forum.attribute('apiUrl') + '/profile/socialbuttons', - serialize: raw => raw, - data - }).then( - () => { - $('#app').trigger("refreshSocialButtons", [this.finbuttons]); - this.hide(); - }, - response => { - this.loading = false; - this.handleErrors(response); - } - ); + }); + return { + socialButtons: JSON.stringify(buttons), + }; } - + + onsubmit(e) { + e.preventDefault(); + + this.loading = true; + + this.props.user.save(this.data(), { errorHandler: this.onerror.bind(this) }) + .then(this.hide.bind(this)) + .then($('#app').trigger('refreshSocialButtons', [this.data().socialButtons])) + .catch(() => { + this.loading = false; + m.redraw(); + }); + } + createButtonObject(key, button = null) { if (button == null) { - button = {}; - button['favicon'] = 'none'; - button['title'] = ''; - button['url'] = ''; - button['icon'] = 'globe'; + this.buttons[key] = {}; + this.buttons[key].index = m.prop(key); + this.buttons[key].favicon = m.prop('none'); + this.buttons[key].title = m.prop(''); + this.buttons[key].url = m.prop(''); + this.buttons[key].icon = m.prop('globe'); + } else { + this.buttons[key] = {}; + this.buttons[key].index = m.prop(key); + this.buttons[key].favicon = m.prop(button.favicon); + this.buttons[key].title = m.prop(button.title); + this.buttons[key].url = m.prop(button.url); + this.buttons[key].icon = m.prop(button.icon); } - this.buttons[key] = {}; - this.buttons[key].index = m.prop(key); - this.buttons[key].favicon = m.prop(button["favicon"]); - this.buttons[key].title = m.prop(button["title"]); - this.buttons[key].url = m.prop(button["url"]); - this.buttons[key].icon = m.prop(button["icon"]); } -} \ No newline at end of file +} diff --git a/js/forum/src/components/WebsiteInputComponent.js b/js/forum/src/components/WebsiteInputComponent.js index d92df8c..5908067 100644 --- a/js/forum/src/components/WebsiteInputComponent.js +++ b/js/forum/src/components/WebsiteInputComponent.js @@ -1,49 +1,49 @@ import Component from 'flarum/Component'; -import extract from 'flarum/utils/extract'; import IconSelectorComponent from 'Davis/SocialProfile/components/IconSelectorComponent'; - + export default class WebsiteInputComponent extends Component { - init(){ + init() { super.init(); - + this.button = this.props.button; } - + view() { - - return ( -
- - - {IconSelectorComponent.component({ - selection: this.button.icon, - favicon: this.button.favicon, - index: this.button.index - })} - { - this.button.url(value); - clearTimeout(this.waittilfinsihed); - if(this.button.icon() !== 'fa-circle-o-notch fa-spin') { - this.button.icon('fa-circle-o-notch fa-spin'); - this.button.favicon('none'); - } - this.waittilfinsihed = setTimeout(() => { - var urlpattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/; - if(urlpattern.test(this.button.url().toLowerCase())) { - var iconurl = (this.button.url().replace(/(:\/\/[^\/]+).*$/, '$1') + '/favicon.ico'); + return m('div', { + className: 'Form-group form-group-social', + id: `socialgroup-${this.button.index()}`, + }, [ + m('input', { + className: 'SocialFormControl SocialTitle', + placeholder: app.translator.trans('davis-socialprofile.forum.edit.title'), + tabIndex: ((this.button.index() + 1) * 2) - 1, + value: this.button.title(), + onchange: m.withAttr('value', this.button.title), + }), + IconSelectorComponent.component({ + selection: this.button.icon, + favicon: this.button.favicon, + index: this.button.index, + }), + m('input', { + className: 'SocialFormControl Socialurl', + placeholder: app.translator.trans('davis-socialprofile.forum.edit.url'), + tabIndex: ((this.button.index() + 1) * 2), + value: this.button.url(), + onchange: m.withAttr('value', (value) => { + this.button.url(value); + clearTimeout(this.waittilfinsihed); + if (this.button.icon() !== 'fa-circle-o-notch fa-spin') { + this.button.icon('fa-circle-o-notch fa-spin'); + this.button.favicon('none'); + } + this.waittilfinsihed = setTimeout(() => { + const urlpattern = + /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])?/; + + if (urlpattern.test(this.button.url().toLowerCase())) { + const iconurl = (`${this.button.url().replace(/(:\/\/[^\/]+).*$/, '$1')} + /favicon.ico`); this.button.favicon(iconurl); this.button.icon('favicon'); m.redraw(); @@ -52,26 +52,23 @@ export default class WebsiteInputComponent extends Component { this.button.favicon('none'); m.redraw(); } - }, 1000); - })} - > - - -
- ); + }, 1000); + }), + }), + m('input', { + className: 'SocialFormControl SocialIcon', + id: `icon${this.button.index()}`, + style: { display: 'none' }, + value: this.button.icon(), + onchange: m.withAttr('value', this.button.icon), + }), + m('input', { + className: 'SocialFormControl Socialfavicon', + id: `favicon${this.button.index()}`, + style: { display: 'none' }, + value: this.button.favicon(), + onchange: m.withAttr('value', this.button.favicon), + }), + ]); } -} \ No newline at end of file +} diff --git a/js/forum/src/main.js b/js/forum/src/main.js index 48a7916..58976f6 100644 --- a/js/forum/src/main.js +++ b/js/forum/src/main.js @@ -1,112 +1,89 @@ import app from 'flarum/app'; +import Model from 'flarum/Model'; +import User from 'flarum/models/User'; import { extend } from 'flarum/extend'; import UserCard from 'flarum/components/UserCard'; import Badge from 'flarum/components/Badge'; import SocialButtonsModal from 'Davis/SocialProfile/components/SocialButtonsModal'; +import DeleteButtonModal from 'Davis/SocialProfile/components/DeleteButtonModal'; -app.initializers.add('davis-socialprofile-forum', function() { +app.initializers.add('davis-socialprofile-forum', () => { + User.prototype.socialButtons = Model.attribute('socialButtons'); - extend(UserCard.prototype, 'init', function() { - var user = this.props.user; - var apiUrl = app.forum.attribute('apiUrl') + '/profile/socialbutton/' + user.data.id; - this.buttonsArray = null; //Indicate we haven't retrieved the user's buttons - //Get buttons from database - app.request({method: "GET", url: apiUrl}).then(result => { - //Test if user has set their buttons up already - if(result.data.attributes.hasOwnProperty("buttons")) { - //Test if buttons have been set up, but the array is empty - if (result.data.attributes.buttons == "[]") { - //Since there are no buttons set, we have a blank slate - this.buttonsArray = true; //Indicate we have retrieved the user's buttons - this.isBlankSlate = true; //Indicate we don't have any buttons + extend(UserCard.prototype, 'init', function () { + $('#app').on('refreshSocialButtons', (e, buttons) => { + this.buttons = JSON.parse(buttons || '[]'); + this.props.user.data.attributes.socialButtons = JSON.parse(buttons || '[]'); + this.props.user.freshness = new Date(); + m.redraw(); + }); + }); + + extend(UserCard.prototype, 'infoItems', function (items) { + this.isSelf = (app.session.user === this.props.user); + this.canEdit = app.session.user ? app.session.user.data.attributes.canEdit : false; + this.buttons = JSON.parse(this.props.user.data.attributes.socialButtons || '[]'); + + if (this.buttons.length) { + this.buttons.forEach((button, index) => { + if (button.title !== '' && button.icon !== '' && button.url !== '') { + let buttonStyle = ''; + let buttonClassName = ''; + + if (button.icon === 'favicon' || button.icon === 'favicon-grey') { + buttonStyle = `background-image: url("${button.favicon}");background-size: 60%;background-position: 50% 50%;background-repeat: no-repeat;`; + if (button.icon === 'favicon-grey') { + buttonClassName = `${button.icon}-${index} social-button social-greyscale-button`; } else { - //The buttons array must not be empty, so lets set it - this.buttonsArray = JSON.parse(result.data.attributes.buttons); - this.isBlankSlate = false; //Indicate we do have buttons + buttonClassName = `${button.icon}-${index} social-button`; } - } else { - //This user has never set their buttons - this.buttonsArray = true; //Indicate we have retrieved the user's buttons - this.isBlankSlate = true; //Indicate we don't have any buttons + } else { + buttonStyle = ''; + buttonClassName = `${button.icon}-${index} social-button`; + } + items.add(`${buttonClassName}${this.deleting ? ' social-button--highlightable' : ''}`, Badge.component({ + type: `social social-icon-${index}`, + icon: button.icon.replace('fa-', ''), + label: button.title, + style: buttonStyle, + onclick: () => { + if (this.deleting) { + app.modal.show(new DeleteButtonModal({ user: this.props.user, index })); + } else { + window.open(button.url, '_blank'); + } + }, + })); } - user.freshness = new Date(); //Tell Mithril we have new data - m.redraw(); //Refresh the DOM }); - - //If the buttons have been edited, we need to refresh them - $('#app').on('refreshSocialButtons', (e, buttons)=>{ - var user = this.props.user; //Then is our user - this.buttonsArray = JSON.parse(buttons); //Parse the saved array from editing - this.isBlankSlate = false; //Indicate we do really have buttons - user.freshness = new Date(); //Tell Mithril we have new data - m.redraw(); //Refresh DOM - }); - }); - - extend(UserCard.prototype, 'infoItems', function(items) { - - // If request hasn't loaded yet, don't add any items. - if (!this.buttonsArray) return; - - //If there are buttons, add them - if (!this.isBlankSlate) { - //Loop through the buttonsArray - for (const k in this.buttonsArray) { - const selectedButton = this.buttonsArray[k]; //Set constant for easier selection - //Ensure the button has a title, icon, and url - if (selectedButton["title"] !== "" && selectedButton["icon"] !== "" && selectedButton["url"] !== "") { - var buttonStyle, buttonClass; - //If the button is using a favicon, make sure it is displayed - if (selectedButton['icon'] == 'favicon' || selectedButton['icon'] == 'favicon-grey') { - buttonStyle = 'background-image: url("'+selectedButton['favicon']+'");background-size: 60%;background-position: 50% 50%;background-repeat: no-repeat;'; - //If the favicon is set to greyscale, make sure it is displayed - if (selectedButton['icon'] == 'favicon-grey') { - buttonClass = selectedButton["icon"] + '-' + k + ' social-button social-greyscale-button'; - } else { - buttonClass = selectedButton["icon"] + '-' + k + ' social-button'; - } - } else { - buttonStyle = ''; - buttonClass = selectedButton["icon"] + '-' + k + ' social-button'; - } - //Acctually add the button - items.add(buttonClass , Badge.component({ - type: "social social-icon-" + k, - icon: selectedButton["icon"].replace('fa-', ''), - label: selectedButton["title"], - style: buttonStyle, - onclick: function() { - window.open(selectedButton["url"],'_blank'); - } - })); - } - } - //Add the edit buttons at the end, as long as it's their own profile - if (app.session.user === app.current.user && app.session.user !== undefined && app.current.user !== undefined) { - //Add the settings button - items.add('settings social-button', Badge.component({ - type: "social social-settings", - icon: 'cog', - label: app.translator.trans('davis-socialprofile.forum.edit.edit'), - onclick: () => { - app.modal.show(new SocialButtonsModal({data: this.buttonsArray})); //Show the edit modal - } - }), -1); - } - //It turns out they don't have any buttons - } else { - //Add an add button only if its their own profile - if (app.session.user === app.current.user && app.session.user !== undefined && app.current.user !== undefined) { - //Add the add button - items.add('settings social-button', Badge.component({ - type: "social null-social-settings", - icon: "plus", - label: app.translator.trans('davis-socialprofile.forum.edit.add'), - onclick: () => { - app.modal.show(new SocialButtonsModal({data: this.buttonsArray})); - } - }), -1); - } - } - }); -}); \ No newline at end of file + if (this.isSelf) { + items.add('settings social-button', Badge.component({ + type: 'social social-settings', + icon: 'cog', + label: app.translator.trans('davis-socialprofile.forum.edit.edit'), + onclick: () => { + app.modal.show(new SocialButtonsModal({ user: this.props.user })); + }, + }), -1); + } else if (this.canEdit) { + items.add('settings social-button', Badge.component({ + type: `social social-moderate ${this.deleting ? 'social-moderate--highlighted' : ''}`, + icon: 'exclamation-triangle', + label: app.translator.trans('davis-socialprofile.forum.edit.delete'), + onclick: () => { + this.deleting = !this.deleting; + }, + }), -1); + } + } else if (this.isSelf) { + items.add('settings social-button', Badge.component({ + type: 'social null-social-settings', + icon: 'plus', + label: app.translator.trans('davis-socialprofile.forum.edit.add'), + onclick: () => { + app.modal.show(new SocialButtonsModal({ user: this.props.user })); + }, + }), -1); + } + }); +}); diff --git a/less/forum/extension.less b/less/forum/extension.less index fa53242..f728a02 100644 --- a/less/forum/extension.less +++ b/less/forum/extension.less @@ -27,7 +27,7 @@ border-radius: 3px; font-size: 14px; box-shadow: 0 0 0 1px #ddd; - color: inherit; + color: #111; } .iconpicker-item-invt { float: left; @@ -62,7 +62,7 @@ top: 100% !important; overflow: auto; max-height: 45vh !important; - min-width: 189px !important; + min-width: 190px !important; z-index: 2055; float: left; background-color: #fff; @@ -91,8 +91,13 @@ -webkit-appearance: none; } .Socialurl { - margin-left: 1%; - width: 82.5%; + margin-left: 3px; + width: 260px; +} +@media (max-width: 767px) { + .Socialurl { + width: 293px; + } } .social-greyscale-button { -webkit-filter: grayscale(1) contrast(2) brightness(2); @@ -104,6 +109,17 @@ .icondropdown > button > i { display: inline-block !important; } +.social-moderate--highlighted > .Badge-icon { + color: #F22613; + transition: .5s; + font-size: 23px; + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; +} +.social-button--highlightable:hover { + border-radius: 4px; + background: #F22613; +} .fa-spin { -webkit-animation: fa-spin 2s infinite linear; animation: fa-spin 2s infinite linear; diff --git a/locale/en.yml b/locale/en.yml index d5b5966..37d855b 100644 --- a/locale/en.yml +++ b/locale/en.yml @@ -7,5 +7,7 @@ davis-socialprofile: title: "Title" url: "Url" submit: "Save" + delete: "Delete" + deletetitle: "Delete Button" admin: test: "Test" diff --git a/locale/fr.yml b/locale/fr.yml index 73c726a..e1b37b5 100644 --- a/locale/fr.yml +++ b/locale/fr.yml @@ -7,5 +7,5 @@ davis-socialprofile: title: "Titre" url: "Url" submit: "Sauvegarder" - admin: - test: "Test" + delete: "Effacer" + deletetitle: "Bouton Supprimer" diff --git a/locale/ru.yml b/locale/ru.yml index 74bcb2d..f4ae224 100644 --- a/locale/ru.yml +++ b/locale/ru.yml @@ -7,5 +7,5 @@ davis-socialprofile: title: "Надпись" url: "Url" submit: "Сохранить" - admin: - test: "Test" + delete: "Удалить" + deletetitle: "кнопка удаления" diff --git a/migrations/2016_01_14_000000_create_socialbuttons_table.php b/migrations/2016_01_14_000000_create_socialbuttons_table.php index 0828c94..fe2194c 100644 --- a/migrations/2016_01_14_000000_create_socialbuttons_table.php +++ b/migrations/2016_01_14_000000_create_socialbuttons_table.php @@ -8,8 +8,6 @@ * For the full copyright and license information, please view the MIT license */ -namespace Davis\SocialProfile\Migration; - use Flarum\Database\Migration; use Illuminate\Database\Schema\Blueprint; diff --git a/src/Buttons.php b/migrations/2016_10_20_000000_create_socialbuttons_column.php similarity index 56% rename from src/Buttons.php rename to migrations/2016_10_20_000000_create_socialbuttons_column.php index fb94e0c..1144573 100644 --- a/src/Buttons.php +++ b/migrations/2016_10_20_000000_create_socialbuttons_column.php @@ -1,18 +1,15 @@ - - * - * For the full copyright and license information, please view the MIT license - */ - -namespace Davis\SocialProfile; - -use Flarum\Database\AbstractModel; - -class Buttons extends AbstractModel -{ - protected $table = 'socialbuttons'; -} + + * + * For the full copyright and license information, please view the MIT license + */ + +use Flarum\Database\Migration; + +return Migration::addColumns('users', [ + 'social_buttons' => ['longText', 'nullable' => true], +]); diff --git a/migrations/2016_10_21_000000_migrate_data_to_user_column.php b/migrations/2016_10_21_000000_migrate_data_to_user_column.php new file mode 100644 index 0000000..f16dec4 --- /dev/null +++ b/migrations/2016_10_21_000000_migrate_data_to_user_column.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the MIT license + */ + +use Illuminate\Database\ConnectionInterface; + +return [ + 'up' => function (ConnectionInterface $db) { + $results = $db->table('socialbuttons')->get(); + foreach ($results as $result) { + $db->table('users') + ->where('id', $result->user_id) + ->update(['social_buttons' => $result->buttons]); + } + }, + 'down' => function (ConnectionInterface $db) { + $results = $db->table('users')->select('social_buttons')->get(); + foreach ($results as $result) { + $db->table('socialbuttons')->insert( + ['user_id' => $result->id, 'buttons' => $result->social_buttons] + ); + } + }, +]; diff --git a/migrations/2016_10_22_000000_drop_socialbuttons_table.php b/migrations/2016_10_22_000000_drop_socialbuttons_table.php new file mode 100644 index 0000000..64ec34b --- /dev/null +++ b/migrations/2016_10_22_000000_drop_socialbuttons_table.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the MIT license + */ + +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Database\Schema\Builder; + +return [ + 'up' => function (Builder $schema) { + $schema->drop('socialbuttons'); + }, + 'down' => function (Builder $schema) { + $schema->create('socialbuttons', function (Blueprint $table) { + $table->increments('id'); + $table->integer('user_id')->unsigned(); + $table->longText('buttons'); + }); + }, +]; diff --git a/src/Api/Controllers/EditSocialButtonsController.php b/src/Api/Controllers/EditSocialButtonsController.php deleted file mode 100644 index a5e71af..0000000 --- a/src/Api/Controllers/EditSocialButtonsController.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the MIT license - */ - -namespace Davis\SocialProfile\Api\Controllers; - -use Davis\SocialProfile\Api\Serializers\SocialButtonsSerializer; -use Davis\SocialProfile\Commands\SaveSocialSettings; -use Flarum\Api\Controller\AbstractResourceController; -use Illuminate\Contracts\Bus\Dispatcher; -use Psr\Http\Message\ServerRequestInterface; -use Tobscure\JsonApi\Document; - -class EditSocialButtonsController extends AbstractResourceController -{ - public $serializer = SocialButtonsSerializer::class; - - protected $bus; - - public function __construct(Dispatcher $bus) - { - $this->bus = $bus; - } - - protected function data(ServerRequestInterface $request, Document $document) - { - $actor = $request->getAttribute('actor'); - $Buttons = array_get($request->getParsedBody(), 'buttons'); - - return $this->bus->dispatch( - new SaveSocialSettings($Buttons, $actor) - ); - } -} diff --git a/src/Api/Controllers/GetSocialButtonsController.php b/src/Api/Controllers/GetSocialButtonsController.php deleted file mode 100644 index 2c749e4..0000000 --- a/src/Api/Controllers/GetSocialButtonsController.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the MIT license - */ - -namespace Davis\SocialProfile\Api\Controllers; - -use Davis\SocialProfile\Repository\UserSocialRepository; -use Flarum\Api\Controller\AbstractResourceController; -use Psr\Http\Message\ServerRequestInterface; -use Tobscure\JsonApi\Document; - -class GetSocialButtonsController extends AbstractResourceController -{ - public $serializer = 'Davis\SocialProfile\Api\Serializers\GetSocialButtonsSerializer'; - - public function __construct(UserSocialRepository $users) - { - $this->users = $users; - } - - protected function data(ServerRequestInterface $request, Document $document) - { - $id = array_get($request->getQueryParams(), 'user'); - - $actor = $request->getAttribute('actor'); - - return $this->users->findOrFail($id, $actor); - } -} diff --git a/src/Api/Serializers/GetSocialButtonsSerializer.php b/src/Api/Serializers/GetSocialButtonsSerializer.php deleted file mode 100644 index 4d7aa05..0000000 --- a/src/Api/Serializers/GetSocialButtonsSerializer.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the MIT license - */ - -namespace Davis\SocialProfile\Api\Serializers; - -use Flarum\Api\Serializer\UserBasicSerializer; -use Flarum\Core\Access\Gate; - -class GetSocialButtonsSerializer extends UserBasicSerializer -{ - protected $gate; - - public function __construct(Gate $gate) - { - $this->gate = $gate; - } - - protected function getDefaultAttributes($user) - { - $gate = $this->gate->forUser($this->actor); - - $attributes = [ - 'buttons' => $user->buttons, - ]; - - return $attributes; - } -} diff --git a/src/Api/Serializers/SocialButtonsSerializer.php b/src/Api/Serializers/SocialButtonsSerializer.php deleted file mode 100644 index 4c2f8f5..0000000 --- a/src/Api/Serializers/SocialButtonsSerializer.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the MIT license - */ - -namespace Davis\SocialProfile\Api\Serializers; - -use Flarum\Api\Serializer\AbstractSerializer; - -class SocialButtonsSerializer extends AbstractSerializer -{ - //protected $type = 'images'; - - protected function getDefaultAttributes($model) - { - return [ - // - ]; - } -} diff --git a/src/Commands/SaveSocialSettings.php b/src/Commands/SaveSocialSettings.php deleted file mode 100644 index b74fc5d..0000000 --- a/src/Commands/SaveSocialSettings.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the MIT license - */ - -namespace Davis\SocialProfile\Commands; - -use Flarum\Core\User; - -class SaveSocialSettings -{ - public $Buttons; - - public $actor; - - public function __construct($Buttons, User $actor) - { - $this->Buttons = $Buttons; - $this->actor = $actor; - } -} diff --git a/src/Commands/SaveSocialSettingsHandler.php b/src/Commands/SaveSocialSettingsHandler.php deleted file mode 100644 index a047369..0000000 --- a/src/Commands/SaveSocialSettingsHandler.php +++ /dev/null @@ -1,58 +0,0 @@ - - * - * For the full copyright and license information, please view the MIT license - */ - -namespace Davis\SocialProfile\Commands; - -use Davis\SocialProfile\Buttons; -use Davis\SocialProfile\Events\SocialProfileEditted; -use Flarum\Core\Access\AssertPermissionTrait; -use Flarum\Core\Repository\UserRepository; -use Flarum\Core\Support\DispatchEventsTrait; -use Flarum\Foundation\Application; -use Illuminate\Events\Dispatcher; - -class SaveSocialSettingsHandler -{ - use DispatchEventsTrait; - use AssertPermissionTrait; - - protected $users; - - protected $app; - - public function __construct( - Dispatcher $events, - UserRepository $users, - Application $app - ) { - $this->events = $events; - $this->users = $users; - $this->app = $app; - } - - public function handle(SaveSocialSettings $command) - { - if (Buttons::where('user_id', $command->actor->id)->exists()) { - $Buttons = Buttons::where('user_id', $command->actor->id)->first(); - } else { - $Buttons = new Buttons; - } - $Buttons->user_id = $command->actor->id; - $Buttons->Buttons = $command->Buttons; - - $this->events->fire( - new SocialProfileEditted($command->actor, $command->Buttons) - ); - - $Buttons->save(); - - return $Buttons; - } -} diff --git a/src/Events/SocialProfileEditted.php b/src/Events/UserButtonsWereChanged.php similarity index 51% rename from src/Events/SocialProfileEditted.php rename to src/Events/UserButtonsWereChanged.php index b0a85f8..04a882d 100644 --- a/src/Events/SocialProfileEditted.php +++ b/src/Events/UserButtonsWereChanged.php @@ -1,27 +1,36 @@ - - * - * For the full copyright and license information, please view the MIT license - */ - -namespace Davis\SocialProfile\Events; - -use Davis\SocialProfile\Buttons; -use Flarum\Core\User; - -class SocialProfileEditted -{ - public $actor; - - public $Buttons; - - public function __construct(User $actor, $Buttons) - { - $this->actor = $actor; - $this->Buttons = $Buttons; - } -} + + * + * For the full copyright and license information, please view the MIT license + */ + +namespace Davis\SocialProfile\Events; + +use Flarum\Core\User; + +class UserButtonsWereChanged +{ + /** + * @var User + */ + public $user; + + /** + * @var User + */ + public $actor; + + /** + * @param User $user + * @param User $actor + */ + public function __construct(User $user, User $actor = null) + { + $this->user = $user; + $this->actor = $actor; + } +} diff --git a/src/Listeners/AddApiAttributes.php b/src/Listeners/AddApiAttributes.php deleted file mode 100755 index 899bfe9..0000000 --- a/src/Listeners/AddApiAttributes.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the MIT license - */ - -namespace Davis\SocialProfile\Listeners; - -use Davis\SocialProfile\Api\Controllers\EditSocialButtonsController; -use Davis\SocialProfile\Api\Controllers\GetSocialButtonsController; -use Flarum\Event\ConfigureApiRoutes; -use Illuminate\Events\Dispatcher; - -class AddApiAttributes -{ - public function subscribe(Dispatcher $events) - { - $events->listen(ConfigureApiRoutes::class, [$this, 'configureApiRoutes']); - } - - public function configureApiRoutes(ConfigureApiRoutes $event) - { - $event->post('/profile/socialbuttons', 'davis.profile.buttons', EditSocialButtonsController::class); - $event->get('/profile/socialbutton/{user}', 'davis.profile.button.user', GetSocialButtonsController::class); - } -} diff --git a/src/Listeners/AddClientAssets.php b/src/Listeners/AddClientAssets.php index 1193f4c..30ec9b7 100644 --- a/src/Listeners/AddClientAssets.php +++ b/src/Listeners/AddClientAssets.php @@ -3,7 +3,7 @@ /* * This file is part of davis/flarum-ext-socialprofile * - * (c) Connor Davis + * © Connor Davis * * For the full copyright and license information, please view the MIT license */ @@ -27,15 +27,15 @@ public function addAssets(ConfigureClientView $event) { if ($event->isForum()) { $event->addAssets([ - __DIR__.'/../../js/forum/dist/extension.js', - __DIR__.'/../../less/forum/extension.less' + __DIR__ . '/../../js/forum/dist/extension.js', + __DIR__ . '/../../less/forum/extension.less', ]); $event->addBootstrapper('Davis/SocialProfile/main'); } if ($event->isAdmin()) { $event->addAssets([ - __DIR__.'/../../js/admin/dist/extension.js' + __DIR__ . '/../../js/admin/dist/extension.js', ]); $event->addBootstrapper('Davis/SocialProfile/main'); } @@ -43,9 +43,9 @@ public function addAssets(ConfigureClientView $event) public function addLocales(ConfigureLocales $event) { - foreach (new DirectoryIterator(__DIR__.'/../../locale') as $file) { + foreach (new DirectoryIterator(__DIR__ . '/../../locale') as $file) { if ($file->isFile() && in_array($file->getExtension(), ['yml', 'yaml'])) { - $event->locales->addTranslations($file->getBasename('.'.$file->getExtension()), $file->getPathname()); + $event->locales->addTranslations($file->getBasename('.' . $file->getExtension()), $file->getPathname()); } } } diff --git a/src/Listeners/AddUserProfileAttributes.php b/src/Listeners/AddUserProfileAttributes.php new file mode 100644 index 0000000..aea7b5a --- /dev/null +++ b/src/Listeners/AddUserProfileAttributes.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the MIT license + */ + +namespace Davis\SocialProfile\Listeners; + +use Flarum\Api\Serializer\UserSerializer; +use Flarum\Event\PrepareApiAttributes; +use Illuminate\Contracts\Events\Dispatcher; + +class AddUserProfileAttributes +{ + /** + * @param Dispatcher $events + */ + public function subscribe(Dispatcher $events) + { + $events->listen(PrepareApiAttributes::class, [$this, 'addApiAttributes']); + } + + /** + * @param PrepareApiAttributes $event + */ + public function addApiAttributes(PrepareApiAttributes $event) + { + if ($event->isSerializer(UserSerializer::class)) { + $event->attributes['socialButtons'] = $event->model->social_buttons; + } + } +} diff --git a/src/Listeners/LoadSettingsFromDatabase.php b/src/Listeners/LoadSettingsFromDatabase.php index 7e9e188..801f9ec 100644 --- a/src/Listeners/LoadSettingsFromDatabase.php +++ b/src/Listeners/LoadSettingsFromDatabase.php @@ -3,7 +3,7 @@ /* * This file is part of davis/flarum-ext-socialprofile * - * (c) Connor Davis + * © Connor Davis * * For the full copyright and license information, please view the MIT license */ @@ -20,7 +20,7 @@ class LoadSettingsFromDatabase protected $packagePrefix = 'davis.socialprofile.'; protected $fieldsToGet = [ - 'test', + 'test', ]; protected $settings; @@ -39,7 +39,7 @@ public function prepareApiAttributes(PrepareApiAttributes $event) { if ($event->isSerializer(ForumSerializer::class)) { foreach ($this->fieldsToGet as $field) { - $event->attributes[$this->packagePrefix.$field] = $this->settings->get($this->packagePrefix.$field); + $event->attributes[$this->packagePrefix . $field] = $this->settings->get($this->packagePrefix . $field); } } } diff --git a/src/Listeners/UpdateProfileInDatabase.php b/src/Listeners/UpdateProfileInDatabase.php new file mode 100644 index 0000000..2f17ea1 --- /dev/null +++ b/src/Listeners/UpdateProfileInDatabase.php @@ -0,0 +1,101 @@ + + * + * For the full copyright and license information, please view the MIT license + */ + +namespace Davis\SocialProfile\Listeners; + +use Davis\SocialProfile\Events\UserButtonsWereChanged; +use Davis\SocialProfile\ProfileValidator; +use Flarum\Core\Access\AssertPermissionTrait; +use Flarum\Event\UserWillBeSaved; +use Illuminate\Contracts\Events\Dispatcher; + +class UpdateProfileInDatabase +{ + use AssertPermissionTrait; + + /** + * Validator for limited suspension. + * + * @var SuspendValidator + */ + protected $validator; + + /** + * @param SuspendValidator $validator + */ + public function __construct(ProfileValidator $validator) + { + $this->validator = $validator; + } + + /** + * @param Dispatcher $events + */ + public function subscribe(Dispatcher $events) + { + $events->listen(UserWillBeSaved::class, [$this, 'whenUserWillBeSaved']); + } + + /** + * @param UserWillBeSaved $event + */ + public function whenUserWillBeSaved(UserWillBeSaved $event) + { + $attributes = array_get($event->data, 'attributes', []); + + if (array_key_exists('socialButtons', $attributes)) { + $this->validator->assertValid($attributes); + + $user = $event->user; + $actor = $event->actor; + + if ($actor->id !== $user->id) { + $this->assertPermission( + $this->elementsOnlyRemoved( + $user->social_buttons, + $attributes['socialButtons'] + ) + ); + $this->assertCan($actor, 'edit', $user); + } + + $user->social_buttons = $attributes['socialButtons']; + $user->raise(new UserButtonsWereChanged($user)); + } + } + + protected function elementsOnlyRemoved($current, $proposed) + { + $current = json_decode($current); + $proposed = json_decode($proposed); + + foreach ($proposed as $component) { + if (!$this->hasMatchingComponent($current, $component)) { + return false; + } + } + + return true; + } + + protected function hasMatchingComponent($array, $component) + { + $foundMatch = false; + + foreach ($array as $test) { + if ($component == $test) { + $foundMatch = true; + break; + } + } + + return $foundMatch; + } +} diff --git a/src/ProfileValidator.php b/src/ProfileValidator.php new file mode 100644 index 0000000..47f0ade --- /dev/null +++ b/src/ProfileValidator.php @@ -0,0 +1,88 @@ + + * + * For the full copyright and license information, please view the MIT license + */ + +namespace Davis\SocialProfile; + +use Flarum\Core\Validator\AbstractValidator; +use Flarum\Event\ConfigureValidator; + +class ProfileValidator extends AbstractValidator +{ + /** + * {@inheritdoc} + */ + protected $rules = [ + 'socialButtons' => ['json', 'socialbuttons'], + 'title' => ['string', 'max:55', 'required'], + 'url' => ['url', 'max:120', 'required'], + 'icon' => ['string', 'max:15', 'required'], + 'favicon' => ['string', 'max:120', 'required'], + ]; + + /** + * {@inheritdoc} + */ + protected function getMessages() + { + return [ + 'socialButtons.socialbuttons' => 'The data you sent is missing required variables.', + ]; + } + + /** + * {@inheritdoc} + */ + protected function makeValidator(array $attributes) + { + $rules = array_only($this->getRules(), array_keys($attributes)); + + $this->validator->extend('socialbuttons', function ($attribute, $value, $parameters, $validator) { + return $this->validateSocialButtons($attribute, $value, $parameters, $validator); + }); + $validator = $this->validator->make($attributes, $rules, $this->getMessages()); + + $this->events->fire( + new ConfigureValidator($this, $validator) + ); + + return $validator; + } + + protected function validateSocialButtons($attribute, $value, $parameters, $validator) + { + if ($value != '[]') { + $data = json_decode($value); + + foreach ($data as $button) { + if (!isset($button->title)) { + return false; + } else if (!isset($button->url)) { + return false; + } else if (!isset($button->icon)) { + return false; + } else if (!isset($button->favicon)) { + return false; + } else { + $attributes = [ + 'title' => $button->title, + 'url' => $button->url, + 'icon' => $button->icon, + 'favicon' => $button->favicon, + ]; + $this->assertValid($attributes); + + return true; + } + } + } else { + return true; + } + } +} diff --git a/src/Repository/UserSocialRepository.php b/src/Repository/UserSocialRepository.php deleted file mode 100644 index e6b03ed..0000000 --- a/src/Repository/UserSocialRepository.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the MIT license - */ - -namespace Davis\SocialProfile\Repository; - -use Davis\SocialProfile\Buttons; - -class UserSocialRepository -{ - public function query() - { - return Buttons::query(); - } - - public function findOrFail($id) - { - return Buttons::where('user_id', $id)->first(); - } -}