2019-07-03 09:35:15 +02:00
|
|
|
//@flow
|
|
|
|
|
import React from "react";
|
2019-07-31 15:40:35 +02:00
|
|
|
import injectSheet from "react-jss";
|
2019-08-20 15:50:11 +02:00
|
|
|
import type { Plugin } from "@scm-manager/ui-types";
|
|
|
|
|
import { CardColumn } from "@scm-manager/ui-components";
|
2019-07-04 17:31:15 +02:00
|
|
|
import PluginAvatar from "./PluginAvatar";
|
2019-08-21 14:54:01 +02:00
|
|
|
import classNames from "classnames";
|
2019-09-16 14:31:55 +02:00
|
|
|
import InstallPluginModal from "./InstallPluginModal";
|
|
|
|
|
import UpdatePluginModal from "./UpdatePluginModal";
|
2019-07-03 09:35:15 +02:00
|
|
|
|
|
|
|
|
type Props = {
|
2019-07-31 15:40:35 +02:00
|
|
|
plugin: Plugin,
|
2019-08-21 15:07:56 +02:00
|
|
|
refresh: () => void,
|
2019-07-31 15:40:35 +02:00
|
|
|
|
|
|
|
|
// context props
|
|
|
|
|
classes: any
|
|
|
|
|
};
|
|
|
|
|
|
2019-08-20 15:50:11 +02:00
|
|
|
type State = {
|
|
|
|
|
showModal: boolean
|
|
|
|
|
};
|
|
|
|
|
|
2019-07-31 15:40:35 +02:00
|
|
|
const styles = {
|
|
|
|
|
link: {
|
2019-08-20 17:19:57 +02:00
|
|
|
cursor: "pointer",
|
2019-09-16 14:31:55 +02:00
|
|
|
pointerEvents: "all",
|
|
|
|
|
padding: "0.5rem",
|
|
|
|
|
border: "solid 1px var(--dark-25)",
|
|
|
|
|
borderRadius: "4px",
|
|
|
|
|
"&:hover": {
|
|
|
|
|
borderColor: "var(--dark-50)"
|
|
|
|
|
}
|
2019-08-21 15:42:03 +02:00
|
|
|
},
|
2019-09-16 14:31:55 +02:00
|
|
|
topRight: {
|
2019-08-21 15:42:03 +02:00
|
|
|
position: "absolute",
|
|
|
|
|
right: 0,
|
|
|
|
|
top: 0
|
2019-07-31 15:40:35 +02:00
|
|
|
}
|
2019-07-03 09:35:15 +02:00
|
|
|
};
|
|
|
|
|
|
2019-08-20 15:50:11 +02:00
|
|
|
class PluginEntry extends React.Component<Props, State> {
|
|
|
|
|
constructor(props: Props) {
|
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
|
|
this.state = {
|
|
|
|
|
showModal: false
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-09 13:29:25 +02:00
|
|
|
createAvatar = (plugin: Plugin) => {
|
|
|
|
|
return <PluginAvatar plugin={plugin} />;
|
|
|
|
|
};
|
|
|
|
|
|
2019-08-20 15:50:11 +02:00
|
|
|
toggleModal = () => {
|
|
|
|
|
this.setState(prevState => ({
|
|
|
|
|
showModal: !prevState.showModal
|
|
|
|
|
}));
|
|
|
|
|
};
|
|
|
|
|
|
2019-08-21 14:54:01 +02:00
|
|
|
createFooterRight = (plugin: Plugin) => {
|
|
|
|
|
return <small className="level-item">{plugin.author}</small>;
|
|
|
|
|
};
|
|
|
|
|
|
2019-08-21 15:42:03 +02:00
|
|
|
isInstallable = () => {
|
|
|
|
|
const { plugin } = this.props;
|
|
|
|
|
return plugin._links && plugin._links.install && plugin._links.install.href;
|
|
|
|
|
};
|
|
|
|
|
|
2019-09-16 14:31:55 +02:00
|
|
|
isUpdatable = () => {
|
|
|
|
|
const { plugin } = this.props;
|
|
|
|
|
return plugin._links && plugin._links.update && plugin._links.update.href;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
createActionbar = () => {
|
2019-07-31 15:40:35 +02:00
|
|
|
const { classes } = this.props;
|
2019-08-21 15:42:03 +02:00
|
|
|
if (this.isInstallable()) {
|
2019-07-31 15:40:35 +02:00
|
|
|
return (
|
2019-08-21 14:54:01 +02:00
|
|
|
<span
|
2019-09-16 14:31:55 +02:00
|
|
|
className={classNames(classes.link, classes.topRight, "level-item")}
|
2019-08-21 14:54:01 +02:00
|
|
|
onClick={this.toggleModal}
|
|
|
|
|
>
|
|
|
|
|
<i className="fas fa-download has-text-info" />
|
|
|
|
|
</span>
|
2019-07-31 15:40:35 +02:00
|
|
|
);
|
2019-09-16 14:31:55 +02:00
|
|
|
} else if (this.isUpdatable()) {
|
|
|
|
|
return (
|
|
|
|
|
<span
|
|
|
|
|
className={classNames(classes.link, classes.topRight, "level-item")}
|
|
|
|
|
onClick={this.toggleModal}
|
|
|
|
|
>
|
|
|
|
|
<i className="fas fa-sync-alt has-text-info" />
|
|
|
|
|
</span>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
renderModal = () => {
|
|
|
|
|
const { plugin, refresh } = this.props;
|
|
|
|
|
if (this.isInstallable()) {
|
|
|
|
|
return (
|
|
|
|
|
<InstallPluginModal
|
|
|
|
|
plugin={plugin}
|
|
|
|
|
refresh={refresh}
|
|
|
|
|
onClose={this.toggleModal}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
} else if (this.isUpdatable()) {
|
|
|
|
|
return (
|
|
|
|
|
<UpdatePluginModal
|
|
|
|
|
plugin={plugin}
|
|
|
|
|
refresh={refresh}
|
|
|
|
|
onClose={this.toggleModal}
|
|
|
|
|
/>
|
|
|
|
|
);
|
2019-07-31 15:40:35 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2019-08-21 15:42:03 +02:00
|
|
|
createPendingSpinner = () => {
|
|
|
|
|
const { plugin, classes } = this.props;
|
|
|
|
|
if (plugin.pending) {
|
|
|
|
|
return (
|
2019-09-16 14:31:55 +02:00
|
|
|
<span className={classes.topRight}>
|
2019-08-21 15:42:03 +02:00
|
|
|
<i className="fas fa-spinner fa-spin has-text-info" />
|
|
|
|
|
</span>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
};
|
|
|
|
|
|
2019-07-03 09:35:15 +02:00
|
|
|
render() {
|
2019-09-16 14:31:55 +02:00
|
|
|
const { plugin } = this.props;
|
2019-08-20 15:50:11 +02:00
|
|
|
const { showModal } = this.state;
|
2019-07-09 13:29:25 +02:00
|
|
|
const avatar = this.createAvatar(plugin);
|
2019-09-16 14:31:55 +02:00
|
|
|
const actionbar = this.createActionbar();
|
2019-07-09 13:29:25 +02:00
|
|
|
const footerRight = this.createFooterRight(plugin);
|
|
|
|
|
|
2019-09-16 14:31:55 +02:00
|
|
|
const modal = showModal ? this.renderModal() : null;
|
2019-08-20 15:50:11 +02:00
|
|
|
|
2019-07-03 09:35:15 +02:00
|
|
|
return (
|
2019-08-20 15:50:11 +02:00
|
|
|
<>
|
|
|
|
|
<CardColumn
|
2019-08-21 15:42:03 +02:00
|
|
|
action={this.isInstallable() ? this.toggleModal : null}
|
2019-08-20 15:50:11 +02:00
|
|
|
avatar={avatar}
|
|
|
|
|
title={plugin.displayName ? plugin.displayName : plugin.name}
|
|
|
|
|
description={plugin.description}
|
2019-09-16 14:31:55 +02:00
|
|
|
contentRight={
|
|
|
|
|
plugin.pending ? this.createPendingSpinner() : actionbar
|
|
|
|
|
}
|
2019-08-20 15:50:11 +02:00
|
|
|
footerRight={footerRight}
|
|
|
|
|
/>
|
|
|
|
|
{modal}
|
|
|
|
|
</>
|
2019-07-03 09:35:15 +02:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-31 15:40:35 +02:00
|
|
|
export default injectSheet(styles)(PluginEntry);
|