Experimental implementation for webapp plugins (#7185)
* Start of experimental implementation for webapp plugins * Updates to webapp plugin architecture * Update pluggable test * Remove debug code
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
82a8bd99cc
Коммит
257edc9ea3
51
webapp/plugins/index.js
Обычный файл
51
webapp/plugins/index.js
Обычный файл
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
// EXPERIMENTAL - SUBJECT TO CHANGE
|
||||
|
||||
import store from 'stores/redux_store.jsx';
|
||||
import {ActionTypes} from 'utils/constants.jsx';
|
||||
import {getSiteURL} from 'utils/url.jsx';
|
||||
|
||||
window.plugins = {};
|
||||
|
||||
export function registerComponents(components) {
|
||||
store.dispatch({
|
||||
type: ActionTypes.RECEIVED_PLUGIN_COMPONENTS,
|
||||
data: components || {}
|
||||
});
|
||||
}
|
||||
|
||||
export function initializePlugins() {
|
||||
const pluginJson = window.mm_config.Plugins || '[]';
|
||||
|
||||
let pluginManifests;
|
||||
try {
|
||||
pluginManifests = JSON.parse(pluginJson);
|
||||
} catch (error) {
|
||||
console.error('Invalid plugins JSON: ' + error); //eslint-disable-line no-console
|
||||
return;
|
||||
}
|
||||
|
||||
pluginManifests.forEach((m) => {
|
||||
function onLoad() {
|
||||
// Add the plugin's js to the page
|
||||
const script = document.createElement('script');
|
||||
script.type = 'text/javascript';
|
||||
script.text = this.responseText;
|
||||
document.getElementsByTagName('head')[0].appendChild(script);
|
||||
|
||||
// Initialize the plugin
|
||||
console.log('Registering ' + m.id + ' plugin...'); //eslint-disable-line no-console
|
||||
const plugin = window.plugins[m.id];
|
||||
plugin.initialize(registerComponents, store);
|
||||
console.log('...done'); //eslint-disable-line no-console
|
||||
}
|
||||
|
||||
// Fetch the plugin's bundled js
|
||||
const xhrObj = new XMLHttpRequest();
|
||||
xhrObj.open('GET', getSiteURL() + m.bundle_path, true);
|
||||
xhrObj.addEventListener('load', onLoad);
|
||||
xhrObj.send('');
|
||||
});
|
||||
}
|
||||
17
webapp/plugins/pluggable/index.js
Обычный файл
17
webapp/plugins/pluggable/index.js
Обычный файл
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import {connect} from 'react-redux';
|
||||
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
|
||||
|
||||
import Pluggable from './pluggable.jsx';
|
||||
|
||||
function mapStateToProps(state, ownProps) {
|
||||
return {
|
||||
...ownProps,
|
||||
components: state.plugins.components,
|
||||
theme: getTheme(state)
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Pluggable);
|
||||
55
webapp/plugins/pluggable/pluggable.jsx
Обычный файл
55
webapp/plugins/pluggable/pluggable.jsx
Обычный файл
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
// EXPERIMENTAL - SUBJECT TO CHANGE
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export default class Pluggable extends React.PureComponent {
|
||||
static propTypes = {
|
||||
|
||||
/*
|
||||
* Should be a single overridable React component
|
||||
*/
|
||||
children: PropTypes.element.isRequired,
|
||||
|
||||
/*
|
||||
* Components for overriding provided by plugins
|
||||
*/
|
||||
components: PropTypes.object.isRequired,
|
||||
|
||||
/*
|
||||
* Logged in user's theme
|
||||
*/
|
||||
theme: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
render() {
|
||||
const child = React.Children.only(this.props.children).type;
|
||||
const components = this.props.components;
|
||||
|
||||
if (child == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Include any props passed to this component or to the child component
|
||||
let props = {...this.props};
|
||||
Reflect.deleteProperty(props, 'children');
|
||||
Reflect.deleteProperty(props, 'components');
|
||||
props = {...props, ...this.props.children.props};
|
||||
|
||||
// Override the default component with any registered plugin's component
|
||||
if (components.hasOwnProperty(child.name)) {
|
||||
const PluginComponent = components[child.name];
|
||||
return (
|
||||
<PluginComponent
|
||||
{...props}
|
||||
theme={this.props.theme}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return React.cloneElement(this.props.children, {...props});
|
||||
}
|
||||
}
|
||||
Ссылка в новой задаче
Block a user