2018-08-24 12:43:10 +02:00
|
|
|
// @flow
|
|
|
|
|
import * as React from "react";
|
2018-09-05 14:32:49 +02:00
|
|
|
import { apiClient, Loading } from "@scm-manager/ui-components";
|
2018-10-15 13:46:42 +02:00
|
|
|
import { getUiPluginsLink } from "../modules/indexResource";
|
|
|
|
|
import { connect } from "react-redux";
|
2018-08-24 12:43:10 +02:00
|
|
|
|
|
|
|
|
type Props = {
|
2018-11-10 14:54:20 +01:00
|
|
|
loaded: boolean,
|
2018-10-15 13:46:42 +02:00
|
|
|
children: React.Node,
|
2018-11-10 14:54:20 +01:00
|
|
|
link: string,
|
|
|
|
|
callback: () => void
|
2018-08-24 12:43:10 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type State = {
|
|
|
|
|
message: string
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type Plugin = {
|
2018-08-30 11:40:53 +02:00
|
|
|
name: string,
|
2018-08-24 12:43:10 +02:00
|
|
|
bundles: string[]
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class PluginLoader extends React.Component<Props, State> {
|
|
|
|
|
constructor(props: Props) {
|
|
|
|
|
super(props);
|
|
|
|
|
this.state = {
|
|
|
|
|
message: "booting"
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
componentDidMount() {
|
2018-11-10 14:54:20 +01:00
|
|
|
const { loaded } = this.props;
|
|
|
|
|
if (!loaded) {
|
|
|
|
|
this.setState({
|
|
|
|
|
message: "loading plugin information"
|
|
|
|
|
});
|
2019-02-18 14:55:23 +01:00
|
|
|
|
2018-11-10 14:54:20 +01:00
|
|
|
this.getPlugins(this.props.link);
|
|
|
|
|
}
|
2018-10-11 11:28:32 +02:00
|
|
|
}
|
|
|
|
|
|
2018-10-11 11:40:04 +02:00
|
|
|
getPlugins = (link: string): Promise<any> => {
|
|
|
|
|
return apiClient
|
2018-10-11 11:28:32 +02:00
|
|
|
.get(link)
|
2018-08-24 12:43:10 +02:00
|
|
|
.then(response => response.text())
|
|
|
|
|
.then(JSON.parse)
|
2018-08-27 12:59:26 +02:00
|
|
|
.then(pluginCollection => pluginCollection._embedded.plugins)
|
2018-08-24 12:43:10 +02:00
|
|
|
.then(this.loadPlugins)
|
2018-11-10 14:54:20 +01:00
|
|
|
.then(this.props.callback);
|
2018-10-11 11:28:32 +02:00
|
|
|
};
|
2018-08-24 12:43:10 +02:00
|
|
|
|
|
|
|
|
loadPlugins = (plugins: Plugin[]) => {
|
|
|
|
|
this.setState({
|
|
|
|
|
message: "loading plugins"
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const promises = [];
|
2019-02-18 14:55:23 +01:00
|
|
|
const sortedPlugins = plugins.sort(comparePluginsByName);
|
|
|
|
|
for (let plugin of sortedPlugins) {
|
2018-08-24 12:43:10 +02:00
|
|
|
promises.push(this.loadPlugin(plugin));
|
|
|
|
|
}
|
2019-02-18 14:55:23 +01:00
|
|
|
return promises.reduce((chain, current) => {
|
|
|
|
|
return chain.then(chainResults => {
|
|
|
|
|
return current.then(currentResult => [...chainResults, currentResult])
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}, Promise.resolve([]));
|
2018-08-24 12:43:10 +02:00
|
|
|
};
|
|
|
|
|
|
2019-02-18 14:55:23 +01:00
|
|
|
|
2018-08-24 12:43:10 +02:00
|
|
|
loadPlugin = (plugin: Plugin) => {
|
|
|
|
|
this.setState({
|
|
|
|
|
message: `loading ${plugin.name}`
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const promises = [];
|
|
|
|
|
for (let bundle of plugin.bundles) {
|
2018-08-27 15:47:02 +02:00
|
|
|
promises.push(this.loadBundle(bundle));
|
2018-08-24 12:43:10 +02:00
|
|
|
}
|
|
|
|
|
return Promise.all(promises);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
loadBundle = (bundle: string) => {
|
2019-03-14 17:38:00 +01:00
|
|
|
return fetch(bundle, {
|
|
|
|
|
credentials: "same-origin",
|
|
|
|
|
headers: {
|
|
|
|
|
Cache: "no-cache",
|
|
|
|
|
// identify the request as ajax request
|
|
|
|
|
"X-Requested-With": "XMLHttpRequest"
|
|
|
|
|
}
|
|
|
|
|
})
|
2018-08-24 12:43:10 +02:00
|
|
|
.then(response => {
|
|
|
|
|
return response.text();
|
|
|
|
|
})
|
|
|
|
|
.then(script => {
|
|
|
|
|
// TODO is this safe???
|
2018-08-31 10:47:42 +02:00
|
|
|
// eslint-disable-next-line no-eval
|
2018-08-30 11:56:33 +02:00
|
|
|
eval(script); // NOSONAR
|
2018-08-24 12:43:10 +02:00
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
render() {
|
2018-11-10 14:54:20 +01:00
|
|
|
const { loaded } = this.props;
|
|
|
|
|
const { message } = this.state;
|
|
|
|
|
if (loaded) {
|
2018-08-24 12:43:10 +02:00
|
|
|
return <div>{this.props.children}</div>;
|
|
|
|
|
}
|
|
|
|
|
return <Loading message={message} />;
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-02-18 14:55:23 +01:00
|
|
|
const comparePluginsByName = (a: Plugin, b: Plugin) => {
|
|
|
|
|
if (a.name < b.name) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
if (a.name > b.name) {
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
};
|
2018-10-15 13:46:42 +02:00
|
|
|
const mapStateToProps = state => {
|
|
|
|
|
const link = getUiPluginsLink(state);
|
|
|
|
|
return {
|
|
|
|
|
link
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default connect(mapStateToProps)(PluginLoader);
|