Skip to content

Commit 647ee88

Browse files
authored
Move Configure button to overflow dropdown (#777)
1 parent de37189 commit 647ee88

File tree

6 files changed

+121
-8
lines changed

6 files changed

+121
-8
lines changed

src/main/frontend/pipeline-console-view/pipeline-console/main/PipelineConsole.tsx

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import "./pipeline-console.scss";
22
import "../../../pipeline-graph-view/app.scss";
33
import "../../../pipeline-graph-view/pipeline-graph/styles/main.scss";
44

5+
import { useEffect, useState } from "react";
6+
57
import Dropdown from "../../../common/components/dropdown.tsx";
68
import DropdownPortal from "../../../common/components/dropdown-portal.tsx";
79
import Skeleton from "./components/skeleton.tsx";
@@ -14,13 +16,28 @@ import { useLayoutPreferences } from "./providers/user-preference-provider.tsx";
1416
import ScrollToTopBottom from "./scroll-to-top-bottom.tsx";
1517
import SplitView from "./split-view.tsx";
1618
import StageView from "./StageView.tsx";
17-
import { CONSOLE, DOCUMENT } from "./symbols.tsx";
19+
import { CONSOLE, DOCUMENT, SETTINGS } from "./symbols.tsx";
1820

1921
export default function PipelineConsole() {
2022
const rootElement = document.getElementById("console-pipeline-root");
2123
const currentRunPath = rootElement?.dataset.currentRunPath!;
2224
const previousRunPath = rootElement?.dataset.previousRunPath;
2325

26+
const [configurePermission, setConfigurePermission] = useState(false);
27+
28+
useEffect(() => {
29+
const configureDataProxyName = document.getElementById(
30+
"console-pipeline-overflow-root",
31+
)?.dataset.proxyName;
32+
if (configureDataProxyName) {
33+
(window as any)[configureDataProxyName]?.hasConfigurePermission(function (
34+
enabled: any,
35+
) {
36+
setConfigurePermission(enabled?.responseJSON);
37+
});
38+
}
39+
}, [configurePermission]);
40+
2441
const { stageViewPosition, mainViewVisibility } = useLayoutPreferences();
2542
const {
2643
openStage,
@@ -58,6 +75,15 @@ export default function PipelineConsole() {
5875
icon: CONSOLE,
5976
href: `../console`,
6077
},
78+
configurePermission ? (
79+
{
80+
text: "Configure",
81+
icon: SETTINGS,
82+
href: `../../configure`,
83+
}
84+
) : (
85+
<></>
86+
),
6187
]}
6288
/>
6389
</DropdownPortal>

src/main/frontend/pipeline-console-view/pipeline-console/main/symbols.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,16 @@ export const CONSOLE = (
4242
/>
4343
</svg>
4444
);
45+
46+
export const SETTINGS = (
47+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
48+
<path
49+
fill="none"
50+
stroke="currentColor"
51+
strokeLinecap="round"
52+
strokeLinejoin="round"
53+
strokeWidth="32"
54+
d="M262.29 192.31a64 64 0 1057.4 57.4 64.13 64.13 0 00-57.4-57.4zM416.39 256a154.34 154.34 0 01-1.53 20.79l45.21 35.46a10.81 10.81 0 012.45 13.75l-42.77 74a10.81 10.81 0 01-13.14 4.59l-44.9-18.08a16.11 16.11 0 00-15.17 1.75A164.48 164.48 0 01325 400.8a15.94 15.94 0 00-8.82 12.14l-6.73 47.89a11.08 11.08 0 01-10.68 9.17h-85.54a11.11 11.11 0 01-10.69-8.87l-6.72-47.82a16.07 16.07 0 00-9-12.22 155.3 155.3 0 01-21.46-12.57 16 16 0 00-15.11-1.71l-44.89 18.07a10.81 10.81 0 01-13.14-4.58l-42.77-74a10.8 10.8 0 012.45-13.75l38.21-30a16.05 16.05 0 006-14.08c-.36-4.17-.58-8.33-.58-12.5s.21-8.27.58-12.35a16 16 0 00-6.07-13.94l-38.19-30A10.81 10.81 0 0149.48 186l42.77-74a10.81 10.81 0 0113.14-4.59l44.9 18.08a16.11 16.11 0 0015.17-1.75A164.48 164.48 0 01187 111.2a15.94 15.94 0 008.82-12.14l6.73-47.89A11.08 11.08 0 01213.23 42h85.54a11.11 11.11 0 0110.69 8.87l6.72 47.82a16.07 16.07 0 009 12.22 155.3 155.3 0 0121.46 12.57 16 16 0 0015.11 1.71l44.89-18.07a10.81 10.81 0 0113.14 4.58l42.77 74a10.8 10.8 0 01-2.45 13.75l-38.21 30a16.05 16.05 0 00-6.05 14.08c.33 4.14.55 8.3.55 12.47z"
55+
/>
56+
</svg>
57+
);

src/main/java/io/jenkins/plugins/pipelinegraphview/utils/AbstractPipelineViewAction.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import com.fasterxml.jackson.core.JsonProcessingException;
66
import com.fasterxml.jackson.databind.ObjectMapper;
7+
import hudson.Functions;
78
import hudson.Plugin;
89
import hudson.model.Action;
910
import hudson.model.BallColor;
@@ -14,6 +15,7 @@
1415
import hudson.security.Permission;
1516
import hudson.util.HttpResponses;
1617
import io.jenkins.plugins.pipelinegraphview.Messages;
18+
import jakarta.servlet.ServletException;
1719
import java.io.IOException;
1820
import java.util.concurrent.ExecutionException;
1921
import java.util.concurrent.TimeoutException;
@@ -60,7 +62,15 @@ public Permission getCancelPermission() {
6062
}
6163

6264
public Permission getConfigurePermission() {
63-
return run.getParent().CONFIGURE;
65+
return Item.CONFIGURE;
66+
}
67+
68+
@JavaScriptMethod
69+
public boolean hasConfigurePermission() throws IOException, ServletException {
70+
if (run != null) {
71+
return Functions.hasPermission(run.getParent(), Item.CONFIGURE);
72+
}
73+
return false;
6474
}
6575

6676
public String getBuildDisplayName() {

src/main/resources/io/jenkins/plugins/pipelinegraphview/consoleview/PipelineConsoleViewAction/index.jelly

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,9 @@
7878
</div>
7979
</l:hasPermission>
8080
</j:if>
81-
<l:hasPermission permission="${it.configurePermission}">
82-
<a href="../../configure" class="jenkins-button">
83-
${%Configure}
84-
</a>
85-
</l:hasPermission>
86-
<div id="console-pipeline-overflow-root" />
81+
<j:set var="proxyId" value="${h.generateId()}" />
82+
<st:bind value="${it}" var="configureAction${proxyId}"/>
83+
<div id="console-pipeline-overflow-root" data-proxy-name="configureAction${proxyId}"/>
8784
</j:set>
8885

8986
<t:buildCaption controls="${controls}">
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package io.jenkins.plugins.pipelinegraphview;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertTrue;
5+
6+
import com.microsoft.playwright.Page;
7+
import com.microsoft.playwright.junit.UsePlaywright;
8+
import com.microsoft.playwright.options.AriaRole;
9+
import hudson.model.Result;
10+
import hudson.security.FullControlOnceLoggedInAuthorizationStrategy;
11+
import io.jenkins.plugins.casc.misc.ConfiguredWithCode;
12+
import io.jenkins.plugins.casc.misc.JenkinsConfiguredWithCodeRule;
13+
import io.jenkins.plugins.casc.misc.junit.jupiter.WithJenkinsConfiguredWithCode;
14+
import io.jenkins.plugins.pipelinegraphview.playwright.PipelineJobPage;
15+
import io.jenkins.plugins.pipelinegraphview.playwright.PlaywrightConfig;
16+
import io.jenkins.plugins.pipelinegraphview.utils.TestUtils;
17+
import org.jenkinsci.plugins.workflow.job.WorkflowRun;
18+
import org.junit.jupiter.api.Test;
19+
20+
@WithJenkinsConfiguredWithCode
21+
@UsePlaywright(PlaywrightConfig.class)
22+
class PipelineGraphViewConfigureTest {
23+
24+
@Test
25+
@ConfiguredWithCode("configure-appearance.yml")
26+
void configureButtonRedirects(Page p, JenkinsConfiguredWithCodeRule j) throws Exception {
27+
WorkflowRun run =
28+
TestUtils.createAndRunJob(j, "hello_world", "helloWorldScriptedPipeline.jenkinsfile", Result.SUCCESS);
29+
new PipelineJobPage(p, run.getParent())
30+
.goTo()
31+
.hasBuilds(1)
32+
.nthBuild(0)
33+
.goToBuild()
34+
.goToPipelineOverview()
35+
.configure();
36+
37+
String newUrl = p.url();
38+
String targetUrl = j.getURL() + run.getParent().getUrl() + "configure";
39+
assertEquals(targetUrl, newUrl);
40+
}
41+
42+
@Test
43+
@ConfiguredWithCode("configure-appearance.yml")
44+
void noConfigurePermissions(Page p, JenkinsConfiguredWithCodeRule j) throws Exception {
45+
// Set authorizations strategy to 'Logged-in users can do anything' so anonymous users only have read access
46+
j.jenkins.setAuthorizationStrategy(new FullControlOnceLoggedInAuthorizationStrategy());
47+
WorkflowRun run =
48+
TestUtils.createAndRunJob(j, "hello_world", "helloWorldScriptedPipeline.jenkinsfile", Result.SUCCESS);
49+
new PipelineJobPage(p, run.getParent())
50+
.goTo()
51+
.hasBuilds(1)
52+
.nthBuild(0)
53+
.goToBuild()
54+
.goToPipelineOverview();
55+
56+
p.click("#console-pipeline-overflow-root");
57+
assertTrue(p.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Configure"))
58+
.isHidden());
59+
}
60+
}

src/test/java/io/jenkins/plugins/pipelinegraphview/playwright/PipelineOverviewPage.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,13 @@ public PipelineOverviewPage stageIsVisibleInTree(String stage) {
133133
return this;
134134
}
135135

136+
public PipelineOverviewPage configure() {
137+
page.click("#console-pipeline-overflow-root");
138+
page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("Configure"))
139+
.click();
140+
return this;
141+
}
142+
136143
public PipelineOverviewPage cancel() {
137144
page.click("#pgv-cancel");
138145
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Yes"))

0 commit comments

Comments
 (0)