From 0704ab4bf332392f2ad44eec026f2ac20bd2a782 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Fri, 27 Jul 2018 16:12:50 -0700 Subject: [PATCH 1/5] Adding ability for plugin to hook the file upload button. --- components/file_upload/file_upload.jsx | 127 ++++++++++++++++++++++--- components/file_upload/index.js | 1 + plugins/registry.js | 27 +++++- sass/layout/_post.scss | 14 +++ 4 files changed, 156 insertions(+), 13 deletions(-) diff --git a/components/file_upload/file_upload.jsx b/components/file_upload/file_upload.jsx index eaaf90da9d20..ad0c6446d137 100644 --- a/components/file_upload/file_upload.jsx +++ b/components/file_upload/file_upload.jsx @@ -3,10 +3,11 @@ import $ from 'jquery'; import PropTypes from 'prop-types'; -import React, {PureComponent} from 'react'; +import React, {Component} from 'react'; import ReactDOM from 'react-dom'; import {defineMessages, intlShape} from 'react-intl'; import 'jquery-dragster/jquery.dragster.js'; +import {Dropdown} from 'react-bootstrap'; import Constants from 'utils/constants.jsx'; import DelayedAction from 'utils/delayed_action.jsx'; @@ -55,7 +56,7 @@ const holders = defineMessages({ const OVERLAY_TIMEOUT = 500; -export default class FileUpload extends PureComponent { +export default class FileUpload extends Component { static propTypes = { /** @@ -117,16 +118,26 @@ export default class FileUpload extends PureComponent { * Whether or not file upload is allowed. */ canUploadFiles: PropTypes.bool.isRequired, + + /** + * Plugin file upload methods to be added + */ + pluginFileUploadMethods: PropTypes.arrayOf(PropTypes.object), }; static contextTypes = { intl: intlShape, }; + static defaultProps = { + pluginFileUploadMethods: [], + }; + constructor(props) { super(props); this.state = { requests: {}, + menuOpen: false, }; } @@ -454,6 +465,26 @@ export default class FileUpload extends PureComponent { onUploadError(formatMessage(holders.limited, {count: Constants.MAX_UPLOAD_FILES})); } + toggleMenu = (open) => { + this.setState({menuOpen: open}); + } + + handleLocalFileUploaded = () => { + const uploadsRemaining = Constants.MAX_UPLOAD_FILES - this.props.fileCount; + if (uploadsRemaining > 0) { + if (this.props.onClick) { + this.props.onClick(); + } + } else { + this.handleMaxUploadReached(); + } + this.setState({menuOpen: false}); + } + + pluginUploadFiles = (files) => { + this.uploadFiles(files); + } + render() { let multiple = true; if (isMobileApp()) { @@ -468,14 +499,10 @@ export default class FileUpload extends PureComponent { } const uploadsRemaining = Constants.MAX_UPLOAD_FILES - this.props.fileCount; - const onClick = uploadsRemaining > 0 ? this.props.onClick : this.handleMaxUploadReached; - return ( - - {this.props.canUploadFiles && + let bodyAction; + if (this.props.pluginFileUploadMethods.length === 0) { + bodyAction = (
- } + ); + } else { + const pluginFileUploadMethods = this.props.pluginFileUploadMethods.map((item) => { + return ( +
  • { + if (item.action) { + item.action(this.pluginUploadFiles); + } + this.setState({menuOpen: false}); + }} + > + + {item.icon} + {item.text} + +
  • + ); + }); + const FileDropdownComponent = (props) => { + return ( + + ); + }; + bodyAction = ( + + + +
  • + + + {'Your Computer'} + + +
  • + {pluginFileUploadMethods} +
    +
    + ); + } + + if (!this.props.canUploadFiles) { + bodyAction = null; + } + + return ( + + {bodyAction} ); } diff --git a/components/file_upload/index.js b/components/file_upload/index.js index e22d91adf14b..63c08a26707d 100644 --- a/components/file_upload/index.js +++ b/components/file_upload/index.js @@ -20,6 +20,7 @@ function mapStateToProps(state) { uploadFile, maxFileSize, canUploadFiles: canUploadFiles(config), + pluginFileUploadMethods: state.plugins.components.FileUploadMethod, }; } diff --git a/plugins/registry.js b/plugins/registry.js index f087b620ef54..0d6f5bb04c96 100644 --- a/plugins/registry.js +++ b/plugins/registry.js @@ -145,7 +145,7 @@ export default class PluginRegistry { // - text - A string or JSX element to display in the menu // - action - A function to trigger when component is clicked on // Returns a unique identifier. - registerPostDropdownMenuAction = (text, action) => { + registerPostDropdownMenuAction(text, action) { const id = generateId(); store.dispatch({ @@ -164,10 +164,33 @@ export default class PluginRegistry { // Register a component at the bottom of the post dropdown menu. // Accepts a React component. Returns a unique identifier. - registerPostDropdownMenuComponent = (component) => { + registerPostDropdownMenuComponent(component) { return dispatchPluginComponentAction('PostDropdownMenuItem', this.id, component); } + // Register a post menu list item by providing some text and an action function. + // Accepts the following: + // - text - A string or JSX element to display in the menu + // - action - A function to trigger when component is clicked on + // Returns a unique identifier. + registerFileUploadMethod(icon, action, text) { + const id = generateId(); + + store.dispatch({ + type: ActionTypes.RECEIVED_PLUGIN_COMPONENT, + name: 'FileUploadMethod', + data: { + id, + pluginId: this.id, + text, + action, + icon, + }, + }); + + return id; + } + // Unregister a component using the unique identifier returned after registration. // Accepts a string id. // Returns undefined in all cases. diff --git a/sass/layout/_post.scss b/sass/layout/_post.scss index f7e794f1feb0..8eb0f0b9e051 100644 --- a/sass/layout/_post.scss +++ b/sass/layout/_post.scss @@ -1920,3 +1920,17 @@ height: 0; } } + +.file-attachment-menu-item-input { + cursor: pointer; + direction: ltr; + filter: alpha(opacity=0); + font-size: 23px; + height: 35px; + margin: 0; + opacity: 0; + position: absolute; + right: 0; + top: 0; + width: 100%; +} From f9ef3b019d39249d44592a985121c97f52d83d20 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Mon, 30 Jul 2018 10:51:25 -0700 Subject: [PATCH 2/5] Tweaks and localization. --- components/file_upload/file_upload.jsx | 12 ++++++------ i18n/en.json | 3 ++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/components/file_upload/file_upload.jsx b/components/file_upload/file_upload.jsx index ad0c6446d137..96d397023b6b 100644 --- a/components/file_upload/file_upload.jsx +++ b/components/file_upload/file_upload.jsx @@ -5,7 +5,7 @@ import $ from 'jquery'; import PropTypes from 'prop-types'; import React, {Component} from 'react'; import ReactDOM from 'react-dom'; -import {defineMessages, intlShape} from 'react-intl'; +import {defineMessages, intlShape, FormattedMessage} from 'react-intl'; import 'jquery-dragster/jquery.dragster.js'; import {Dropdown} from 'react-bootstrap'; @@ -540,10 +540,7 @@ export default class FileUpload extends Component { const FileDropdownComponent = (props) => { return (