show restart checkbox only if restarting is supported

This commit is contained in:
Sebastian Sdorra
2020-03-24 15:01:39 +01:00
parent 651a9a561a
commit 2873c44b52
6 changed files with 93 additions and 16 deletions

View File

@@ -69,7 +69,8 @@
"restartNotification": "Der SCM-Manager Kontext sollte nur neu gestartet werden, wenn aktuell niemand damit arbeitet.",
"executePending": "Die folgenden Plugin-Änderungen werden ausgeführt. Anschließend wird der SCM-Manager Kontext neu gestartet.",
"cancelPending": "Die folgenden Plugin-Änderungen werden abgebrochen und zurückgesetzt.",
"updateAllInfo": "Die folgenden Plugins werden aktualisiert. Die Änderungen werden nach dem nächsten Neustart wirksam."
"updateAllInfo": "Die folgenden Plugins werden aktualisiert. Die Änderungen werden nach dem nächsten Neustart wirksam.",
"manualRestartRequired": "Nach dem die Plugin-Änderung durchgeführt wurde, muss SCM-Manager neu gestartet werden."
}
},
"repositoryRole": {

View File

@@ -69,7 +69,8 @@
"restartNotification": "You should only restart the scm-manager context if no one else is currently working with it.",
"executePending": "The following plugin changes will be executed and after that the scm-manager context will be restarted.",
"cancelPending": "The following plugin changes will be canceled.",
"updateAllInfo": "The following plugin changes will be executed. You need to restart the scm-manager to make these changes effective."
"updateAllInfo": "The following plugin changes will be executed. You need to restart the scm-manager to make these changes effective.",
"manualRestartRequired": "After the plugin change has been made, scm-manager must be restarted."
}
},
"repositoryRole": {

View File

@@ -214,8 +214,25 @@ class PluginModal extends React.Component<Props, State> {
});
};
render() {
createRestartSectionContent = () => {
const { restart } = this.state;
const { plugin, pluginAction, t } = this.props;
if (plugin._links[pluginAction + "WithRestart"]) {
return (
<Checkbox
checked={restart}
label={t("plugins.modal.restart")}
onChange={this.handleRestartChange}
disabled={false}
/>
);
} else {
return <Notification type="warning">{t("plugins.modal.manualRestartRequired")}</Notification>;
}
};
render() {
const { plugin, pluginAction, onClose, t } = this.props;
const body = (
@@ -262,12 +279,7 @@ class PluginModal extends React.Component<Props, State> {
</div>
<div className="media">
<div className="media-content">
<Checkbox
checked={restart}
label={t("plugins.modal.restart")}
onChange={this.handleRestartChange}
disabled={false}
/>
{this.createRestartSectionContent()}
</div>
</div>
{this.renderNotifications()}

View File

@@ -27,6 +27,7 @@ package sonia.scm.api.v2.resources;
import de.otto.edison.hal.Links;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import sonia.scm.lifecycle.Restarter;
import sonia.scm.plugin.AvailablePlugin;
import sonia.scm.plugin.InstalledPlugin;
import sonia.scm.plugin.Plugin;
@@ -47,6 +48,9 @@ public abstract class PluginDtoMapper {
@Inject
private ResourceLinks resourceLinks;
@Inject
private Restarter restarter;
public abstract void map(PluginInformation plugin, @MappingTarget PluginDto dto);
public PluginDto mapInstalled(InstalledPlugin plugin, List<AvailablePlugin> availablePlugins) {
@@ -78,12 +82,20 @@ public abstract class PluginDtoMapper {
.self(information.getName()));
if (!plugin.isPending() && PluginPermissions.manage().isPermitted()) {
links.single(link("install", resourceLinks.availablePlugin().install(information.getName())));
String href = resourceLinks.availablePlugin().install(information.getName());
appendLink(links, "install", href);
}
return new PluginDto(links.build());
}
private void appendLink(Links.Builder links, String name, String href) {
links.single(link(name, href));
if (restarter.isSupported()) {
links.single(link(name + "WithRestart", href + "?restart=true"));
}
}
private PluginDto createDtoForInstalled(InstalledPlugin plugin, List<AvailablePlugin> availablePlugins) {
PluginInformation information = plugin.getDescriptor().getInformation();
Optional<AvailablePlugin> availablePlugin = checkForUpdates(plugin, availablePlugins);
@@ -96,13 +108,16 @@ public abstract class PluginDtoMapper {
&& !availablePlugin.get().isPending()
&& PluginPermissions.manage().isPermitted()
) {
links.single(link("update", resourceLinks.availablePlugin().install(information.getName())));
String href = resourceLinks.availablePlugin().install(information.getName());
appendLink(links, "update", href);
}
if (plugin.isUninstallable()
&& (!availablePlugin.isPresent() || !availablePlugin.get().isPending())
&& PluginPermissions.manage().isPermitted()
) {
links.single(link("uninstall", resourceLinks.installedPlugin().uninstall(information.getName())));
String href = resourceLinks.installedPlugin().uninstall(information.getName());
appendLink(links, "uninstall", href);
}
PluginDto dto = new PluginDto(links.build());

View File

@@ -36,6 +36,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import sonia.scm.lifecycle.Restarter;
import sonia.scm.plugin.AvailablePlugin;
import sonia.scm.plugin.AvailablePluginDescriptor;
import sonia.scm.plugin.InstalledPlugin;
@@ -59,6 +60,9 @@ class PluginDtoCollectionMapperTest {
ResourceLinks resourceLinks = ResourceLinksMock.createMock(URI.create("/"));
@Mock
private Restarter restarter;
@InjectMocks
PluginDtoMapperImpl pluginDtoMapper;
@@ -142,7 +146,7 @@ class PluginDtoCollectionMapperTest {
}
@Test
void shouldAddInstallLinkForNewVersionWhenPermitted() {
void shouldAddUpdateLinkForNewVersionWhenPermitted() {
when(subject.isPermitted("plugin:manage")).thenReturn(true);
PluginDtoCollectionMapper mapper = new PluginDtoCollectionMapper(resourceLinks, pluginDtoMapper, manager);
@@ -154,6 +158,21 @@ class PluginDtoCollectionMapperTest {
assertThat(plugin.getLinks().getLinkBy("update")).isNotEmpty();
}
@Test
void shouldAddUpdateWithRestartLinkForNewVersionWhenPermitted() {
when(restarter.isSupported()).thenReturn(true);
when(subject.isPermitted("plugin:manage")).thenReturn(true);
PluginDtoCollectionMapper mapper = new PluginDtoCollectionMapper(resourceLinks, pluginDtoMapper, manager);
HalRepresentation result = mapper.mapInstalled(
singletonList(createInstalledPlugin("scm-some-plugin", "1")),
singletonList(createAvailablePlugin("scm-some-plugin", "2")));
PluginDto plugin = getPluginDtoFromResult(result);
assertThat(plugin.getLinks().getLinkBy("update")).isNotEmpty();
assertThat(plugin.getLinks().getLinkBy("updateWithRestart")).isNotEmpty();
}
@Test
void shouldSetInstalledPluginPendingWhenCorrespondingAvailablePluginIsPending() {
when(subject.isPermitted("plugin:manage")).thenReturn(true);

View File

@@ -35,6 +35,7 @@ import org.mockito.Answers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import sonia.scm.lifecycle.Restarter;
import sonia.scm.plugin.AvailablePlugin;
import sonia.scm.plugin.AvailablePluginDescriptor;
import sonia.scm.plugin.InstalledPlugin;
@@ -56,6 +57,9 @@ class PluginDtoMapperTest {
@SuppressWarnings("unused") // Is injected
private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(URI.create("https://hitchhiker.com/"));
@Mock
private Restarter restarter;
@InjectMocks
private PluginDtoMapperImpl mapper;
@@ -122,6 +126,7 @@ class PluginDtoMapperTest {
PluginDto dto = mapper.mapAvailable(plugin);
assertThat(dto.getLinks().getLinkBy("install")).isEmpty();
assertThat(dto.getLinks().getLinkBy("installWithRestart")).isEmpty();
}
@Test
@@ -134,6 +139,17 @@ class PluginDtoMapperTest {
.isEqualTo("https://hitchhiker.com/v2/plugins/available/scm-cas-plugin/install");
}
@Test
void shouldAppendInstallWithRestartLink() {
when(restarter.isSupported()).thenReturn(true);
when(subject.isPermitted("plugin:manage")).thenReturn(true);
AvailablePlugin plugin = createAvailable(createPluginInformation());
PluginDto dto = mapper.mapAvailable(plugin);
assertThat(dto.getLinks().getLinkBy("installWithRestart").get().getHref())
.isEqualTo("https://hitchhiker.com/v2/plugins/available/scm-cas-plugin/install?restart=true");
}
@Test
void shouldReturnMiscellaneousIfCategoryIsNull() {
PluginInformation information = createPluginInformation();
@@ -162,4 +178,17 @@ class PluginDtoMapperTest {
assertThat(dto.getLinks().getLinkBy("uninstall").get().getHref())
.isEqualTo("https://hitchhiker.com/v2/plugins/installed/scm-cas-plugin/uninstall");
}
@Test
void shouldAppendUninstallWithRestartLink() {
when(restarter.isSupported()).thenReturn(true);
when(subject.isPermitted("plugin:manage")).thenReturn(true);
InstalledPlugin plugin = createInstalled(createPluginInformation());
when(plugin.isUninstallable()).thenReturn(true);
PluginDto dto = mapper.mapInstalled(plugin, emptyList());
assertThat(dto.getLinks().getLinkBy("uninstallWithRestart").get().getHref())
.isEqualTo("https://hitchhiker.com/v2/plugins/installed/scm-cas-plugin/uninstall?restart=true");
}
}