Merge with 2.0.0-m3

This commit is contained in:
Florian Scholdei
2019-10-10 10:59:04 +02:00
94 changed files with 2176 additions and 481 deletions

View File

@@ -0,0 +1,42 @@
// @flow
import React from "react";
import PluginActionModal from "./PluginActionModal";
import type { PendingPlugins } from "@scm-manager/ui-types";
import { apiClient } from "@scm-manager/ui-components";
import { translate } from "react-i18next";
type Props = {
onClose: () => void,
refresh: () => void,
pendingPlugins: PendingPlugins,
// context props
t: string => string
};
class CancelPendingActionModal extends React.Component<Props> {
render() {
const { onClose, pendingPlugins, t } = this.props;
return (
<PluginActionModal
description={t("plugins.modal.cancelPending")}
label={t("plugins.cancelPending")}
onClose={onClose}
pendingPlugins={pendingPlugins}
execute={this.cancelPending}
/>
);
}
cancelPending = () => {
const { pendingPlugins, refresh, onClose } = this.props;
return apiClient
.post(pendingPlugins._links.cancel.href)
.then(refresh)
.then(onClose);
};
}
export default translate("admin")(CancelPendingActionModal);

View File

@@ -0,0 +1,45 @@
// @flow
import React from "react";
import PluginActionModal from "./PluginActionModal";
import type { PendingPlugins } from "@scm-manager/ui-types";
import waitForRestart from "./waitForRestart";
import { apiClient, Notification } from "@scm-manager/ui-components";
import { translate } from "react-i18next";
type Props = {
onClose: () => void,
pendingPlugins: PendingPlugins,
// context props
t: string => string
};
class ExecutePendingActionModal extends React.Component<Props> {
render() {
const { onClose, pendingPlugins, t } = this.props;
return (
<PluginActionModal
description={t("plugins.modal.executePending")}
label={t("plugins.modal.executeAndRestart")}
onClose={onClose}
pendingPlugins={pendingPlugins}
execute={this.executeAndRestart}
>
<Notification type="warning">
{t("plugins.modal.restartNotification")}
</Notification>
</PluginActionModal>
);
}
executeAndRestart = () => {
const { pendingPlugins } = this.props;
return apiClient
.post(pendingPlugins._links.execute.href)
.then(waitForRestart);
};
}
export default translate("admin")(ExecutePendingActionModal);

View File

@@ -114,6 +114,7 @@ class PluginModal extends React.Component<Props, State> {
.catch(error => {
this.setState({
loading: false,
success: false,
error: error
});
});

View File

@@ -0,0 +1,42 @@
// @flow
import React from "react";
import PluginActionModal from "./PluginActionModal";
import type { PluginCollection } from "@scm-manager/ui-types";
import { apiClient } from "@scm-manager/ui-components";
import { translate } from "react-i18next";
type Props = {
onClose: () => void,
refresh: () => void,
installedPlugins: PluginCollection,
// context props
t: string => string
};
class UpdateAllActionModal extends React.Component<Props> {
render() {
const { onClose, installedPlugins, t } = this.props;
return (
<PluginActionModal
description={t("plugins.modal.updateAll")}
label={t("plugins.updateAll")}
onClose={onClose}
installedPlugins={installedPlugins}
execute={this.updateAll}
/>
);
}
updateAll = () => {
const { installedPlugins, refresh, onClose } = this.props;
return apiClient
.post(installedPlugins._links.update.href)
.then(refresh)
.then(onClose);
};
}
export default translate("admin")(UpdateAllActionModal);

View File

@@ -5,11 +5,13 @@ import { translate } from "react-i18next";
import { compose } from "redux";
import type { PendingPlugins, PluginCollection } from "@scm-manager/ui-types";
import {
ButtonGroup,
ErrorNotification,
Loading,
Notification,
Subtitle,
Title
Title,
Button
} from "@scm-manager/ui-components";
import {
fetchPendingPlugins,
@@ -27,7 +29,9 @@ import {
} from "../../../modules/indexResource";
import PluginTopActions from "../components/PluginTopActions";
import PluginBottomActions from "../components/PluginBottomActions";
import ExecutePendingAction from "../components/ExecutePendingAction";
import ExecutePendingActionModal from "../components/ExecutePendingActionModal";
import CancelPendingActionModal from "../components/CancelPendingActionModal";
import UpdateAllActionModal from "../components/UpdateAllActionModal";
type Props = {
loading: boolean,
@@ -41,14 +45,29 @@ type Props = {
pendingPlugins: PendingPlugins,
// context objects
t: string => string,
t: (key: string, params?: Object) => string,
// dispatched functions
fetchPluginsByLink: (link: string) => void,
fetchPendingPlugins: (link: string) => void
};
class PluginsOverview extends React.Component<Props> {
type State = {
showPendingModal: boolean,
showUpdateAllModal: boolean,
showCancelModal: boolean
};
class PluginsOverview extends React.Component<Props, State> {
constructor(props: Props, context: *) {
super(props, context);
this.state = {
showPendingModal: false,
showUpdateAllModal: false,
showCancelModal: false
};
}
componentDidMount() {
this.fetchPlugins();
}
@@ -102,17 +121,72 @@ class PluginsOverview extends React.Component<Props> {
};
createActions = () => {
const { pendingPlugins } = this.props;
const { pendingPlugins, collection, t } = this.props;
const buttons = [];
if (
pendingPlugins &&
pendingPlugins._links &&
pendingPlugins._links.execute
) {
return <ExecutePendingAction pendingPlugins={pendingPlugins} />;
buttons.push(
<Button
color="primary"
reducedMobile={true}
key={"executePending"}
icon={"arrow-circle-right"}
label={t("plugins.executePending")}
action={() => this.setState({ showPendingModal: true })}
/>
);
}
if (
pendingPlugins &&
pendingPlugins._links &&
pendingPlugins._links.cancel
) {
buttons.push(
<Button
color="primary"
reducedMobile={true}
key={"cancelPending"}
icon={"times"}
label={t("plugins.cancelPending")}
action={() => this.setState({ showCancelModal: true })}
/>
);
}
if (collection && collection._links && collection._links.update) {
buttons.push(
<Button
color="primary"
reducedMobile={true}
key={"updateAll"}
icon={"sync-alt"}
label={this.computeUpdateAllSize()}
action={() => this.setState({ showUpdateAllModal: true })}
/>
);
}
if (buttons.length > 0) {
return <ButtonGroup>{buttons}</ButtonGroup>;
}
return null;
};
computeUpdateAllSize = () => {
const { collection, t } = this.props;
const outdatedPlugins = collection._embedded.plugins.filter(
p => p._links.update
).length;
return t("plugins.outdatedPlugins", {
count: outdatedPlugins
});
};
render() {
const { loading, error, collection } = this.props;
@@ -131,10 +205,47 @@ class PluginsOverview extends React.Component<Props> {
<hr className="header-with-actions" />
{this.renderPluginsList()}
{this.renderFooter(actions)}
{this.renderModals()}
</>
);
}
renderModals = () => {
const { collection, pendingPlugins } = this.props;
const {
showPendingModal,
showCancelModal,
showUpdateAllModal
} = this.state;
if (showPendingModal) {
return (
<ExecutePendingActionModal
onClose={() => this.setState({ showPendingModal: false })}
pendingPlugins={pendingPlugins}
/>
);
}
if (showCancelModal) {
return (
<CancelPendingActionModal
onClose={() => this.setState({ showCancelModal: false })}
refresh={this.fetchPlugins}
pendingPlugins={pendingPlugins}
/>
);
}
if (showUpdateAllModal) {
return (
<UpdateAllActionModal
onClose={() => this.setState({ showUpdateAllModal: false })}
refresh={this.fetchPlugins}
installedPlugins={collection}
/>
);
}
};
renderPluginsList() {
const { collection, t } = this.props;

View File

@@ -71,5 +71,5 @@ export default withRouter(
connect(
mapStateToProps,
mapDispatchToProps
)(translate("changesets")(ChangesetView))
)(translate("repos")(ChangesetView))
);