added modal with check for plugin installation

This commit is contained in:
Florian Scholdei
2019-08-20 15:50:11 +02:00
parent 3f183f9f6c
commit 02c295207c
5 changed files with 137 additions and 18 deletions

View File

@@ -1,7 +1,6 @@
//@flow //@flow
import type {Collection, Links} from "./hal"; import type {Collection, Links} from "./hal";
export type Plugin = { export type Plugin = {
name: string, name: string,
version: string, version: string,
@@ -10,6 +9,7 @@ export type Plugin = {
author: string, author: string,
category: string, category: string,
avatarUrl: string, avatarUrl: string,
dependencies: string[],
_links: Links _links: Links
}; };

View File

@@ -29,7 +29,15 @@
"installedNavLink": "Installiert", "installedNavLink": "Installiert",
"availableNavLink": "Verfügbar" "availableNavLink": "Verfügbar"
}, },
"noPlugins": "Keine Plugins gefunden." "noPlugins": "Keine Plugins gefunden.",
"modal": {
"title": "Plugin installieren",
"dependency": "Abhängigkeit:",
"dependency_plural": "Abhängigkeiten:",
"restart": "Neustarten um Plugin zu aktivieren",
"install": "Installieren",
"abort": "Abbrechen"
}
}, },
"repositoryRole": { "repositoryRole": {
"navLink": "Berechtigungsrollen", "navLink": "Berechtigungsrollen",

View File

@@ -29,7 +29,15 @@
"installedNavLink": "Installed", "installedNavLink": "Installed",
"availableNavLink": "Available" "availableNavLink": "Available"
}, },
"noPlugins": "No plugins found." "noPlugins": "No plugins found.",
"modal": {
"title": "Install Plugin",
"dependency": "Dependency:",
"dependency_plural": "Dependencies:",
"restart": "Restart to activate",
"install": "Install",
"abort": "Abort"
}
}, },
"repositoryRole": { "repositoryRole": {
"navLink": "Permission Roles", "navLink": "Permission Roles",

View File

@@ -4,6 +4,7 @@ import injectSheet from "react-jss";
import type { Plugin } from "@scm-manager/ui-types"; import type { Plugin } from "@scm-manager/ui-types";
import { CardColumn } from "@scm-manager/ui-components"; import { CardColumn } from "@scm-manager/ui-components";
import PluginAvatar from "./PluginAvatar"; import PluginAvatar from "./PluginAvatar";
import PluginModal from "./PluginModal";
type Props = { type Props = {
plugin: Plugin, plugin: Plugin,
@@ -12,23 +13,41 @@ type Props = {
classes: any classes: any
}; };
type State = {
showModal: boolean
};
const styles = { const styles = {
link: { link: {
pointerEvents: "cursor" pointerEvents: "all"
} }
}; };
class PluginEntry extends React.Component<Props> { class PluginEntry extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
showModal: false
};
}
createAvatar = (plugin: Plugin) => { createAvatar = (plugin: Plugin) => {
return <PluginAvatar plugin={plugin} />; return <PluginAvatar plugin={plugin} />;
}; };
toggleModal = () => {
this.setState(prevState => ({
showModal: !prevState.showModal
}));
};
createContentRight = (plugin: Plugin) => { createContentRight = (plugin: Plugin) => {
const { classes } = this.props; const { classes } = this.props;
if (plugin._links && plugin._links.install && plugin._links.install.href) { if (plugin._links && plugin._links.install && plugin._links.install.href) {
return ( return (
<div className={classes.link} onClick={() => console.log(plugin._links.install.href) /*TODO trigger plugin installation*/}> <div className={classes.link} onClick={this.toggleModal}>
<i className="fas fa-cloud-download-alt fa-2x has-text-info" /> <i className="fas fa-download fa-2x has-text-info" />
</div> </div>
); );
} }
@@ -44,13 +63,17 @@ class PluginEntry extends React.Component<Props> {
render() { render() {
const { plugin } = this.props; const { plugin } = this.props;
const { showModal } = this.state;
const avatar = this.createAvatar(plugin); const avatar = this.createAvatar(plugin);
const contentRight = this.createContentRight(plugin); const contentRight = this.createContentRight(plugin);
const footerLeft = this.createFooterLeft(plugin); const footerLeft = this.createFooterLeft(plugin);
const footerRight = this.createFooterRight(plugin); const footerRight = this.createFooterRight(plugin);
const modal = showModal ? <PluginModal plugin={plugin} onSubmit={this.toggleModal} onClose={this.toggleModal} /> : null;
// TODO: Add link to plugin page below // TODO: Add link to plugin page below
return ( return (
<>
<CardColumn <CardColumn
link="#" link="#"
avatar={avatar} avatar={avatar}
@@ -60,6 +83,8 @@ class PluginEntry extends React.Component<Props> {
footerLeft={footerLeft} footerLeft={footerLeft}
footerRight={footerRight} footerRight={footerRight}
/> />
{modal}
</>
); );
} }
} }

View File

@@ -0,0 +1,78 @@
//@flow
import React from "react";
import { translate } from "react-i18next";
import type { Plugin } from "@scm-manager/ui-types";
import {
Button,
ButtonGroup,
Checkbox,
Modal,
SubmitButton
} from "@scm-manager/ui-components";
type Props = {
plugin: Plugin,
onSubmit: () => void,
onClose: () => void,
// context props
t: string => string
};
class PluginModal extends React.Component<Props> {
renderDependencies() {
const { plugin, t } = this.props;
let dependencies = null;
if (plugin.dependencies && plugin.dependencies.length > 0) {
dependencies = (
<>
{t("plugins.modal.dependency", {count: plugin.dependencies.length})}
<ul>
{plugin.dependencies.map((dependency, index) => {
return <li key={index}>{dependency}</li>;
})}
</ul>
</>
);
}
return dependencies;
}
render() {
const { onSubmit, onClose, t } = this.props;
const body = (
<>
{this.renderDependencies()}
<Checkbox
checked={false}
label={t("plugins.modal.restart")}
onChange={null}
disabled={null}
/>
</>
);
const footer = (
<form onSubmit={onSubmit}>
<ButtonGroup>
<SubmitButton label={t("plugins.modal.install")} />
<Button label={t("plugins.modal.abort")} action={onClose} />
</ButtonGroup>
</form>
);
return (
<Modal
title={t("plugins.modal.title")}
closeFunction={() => onClose()}
body={body}
footer={footer}
active={true}
/>
);
}
}
export default translate("admin")(PluginModal);