Skip to content

Commit d9d3a4d

Browse files
authored
Merge pull request #48 from buildbarn/src_ctrl
Frontend improvements
2 parents 8160073 + d7523ba commit d9d3a4d

File tree

9 files changed

+95
-88
lines changed

9 files changed

+95
-88
lines changed

frontend/.env

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ NEXT_PUBLIC_BES_GRPC_BACKEND_URL=grpc://localhost:8082
33
NEXT_PUBLIC_BROWSER_URL=https://browser.example.com
44
NEXT_PUBLIC_COMPANY_NAME="Example Co"
55
NEXT_PUBLIC_COMPANY_SLACK_CHANNEL_NAME=ExampleCoBuild
6-
NEXT_PUBLIC_COMPANY_SLACK_CHANNEL_URL=https://exampleco.enterprise.slack.com/archives/CXXXXXXX
6+
NEXT_PUBLIC_COMPANY_SLACK_CHANNEL_URL=https://exampleco.enterprise.slack.com/archives/CXXXXXXX
7+
NEXT_PUBLIC_GITHUB_URL=https://github.com

frontend/src/app/tests/[slug]/page.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ interface PageParams {
1414
}
1515

1616
const Page: React.FC<PageParams> = ({ params }) => {
17-
const label = decodeURIComponent(params.slug)
17+
const label = decodeURIComponent(atob(decodeURIComponent(params.slug)))
1818
return (
1919
<Content
2020
content={

frontend/src/components/BazelInvocation/index.tsx

+38-38
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
TestCollection,
1212
TargetPair,
1313
BuildGraphMetrics,
14-
BazelCommand,
1514
} from "@/graphql/__generated__/graphql";
1615
import styles from "../AppBar/index.module.css"
1716
import React from "react";
@@ -68,19 +67,19 @@ const BazelInvocation: React.FC<{
6867
invocationID,
6968
build,
7069
state,
71-
stepLabel,
7270
bazelCommand,
7371
profile,
74-
relatedFiles,
7572
sourceControl,
7673
user,
7774
metrics,
7875
testCollection,
79-
targets
76+
targets,
77+
//stepLabel,
78+
//relatedFiles,
8079

8180
} = invocationOverview;
8281

83-
var buildLogs = "tmp"
82+
8483
//data for runner metrics
8584
var runnerMetrics: RunnerCount[] = [];
8685
metrics?.actionSummary?.runnerCount?.map((item: RunnerCount) => runnerMetrics.push(item));
@@ -91,9 +90,6 @@ const BazelInvocation: React.FC<{
9190
//artifact metrics
9291
var artifactMetrics: ArtifactMetrics | undefined = metrics?.artifactMetrics ?? undefined;
9392

94-
//data for target metrics
95-
var targetMetrics: TargetMetrics | undefined | null = metrics?.targetMetrics ?? undefined
96-
9793
//memory metrics
9894
var memoryMetrics: MemoryMetrics | undefined = metrics?.memoryMetrics ?? undefined
9995

@@ -107,21 +103,21 @@ const BazelInvocation: React.FC<{
107103
var networkMetrics: NetworkMetrics | undefined = metrics?.networkMetrics ?? undefined
108104
const bytesRecv = networkMetrics?.systemNetworkStats?.bytesRecv ?? 0
109105
const bytesSent = networkMetrics?.systemNetworkStats?.bytesSent ?? 0
110-
const hideNetworkMetricsTab: boolean = bytesRecv == 0 && bytesSent == 0
111106

112107
//test data
113108
var testCollections: TestCollection[] | undefined | null = testCollection
109+
110+
//data for target metrics
111+
var targetMetrics: TargetMetrics | undefined | null = metrics?.targetMetrics ?? undefined
114112
var targetData: TargetPair[] | undefined | null = targets
115113
var targetTimes: Map<string, number> = new Map<string, number>();
116-
117114
targetData?.map(x => { targetTimes.set(x.label ?? "", x.durationInMs ?? 0) })
118115

119-
//show/hide tabs
120-
const testCount = testCollection?.length ?? 0
121-
const hideTestsTab: boolean = testCount == 0
122-
const hideTargetsTab: boolean = (targetData?.length ?? 0) == 0 ? true : false
123-
const hideSourceControlTab: boolean = sourceControl == undefined || sourceControl == null ? true : false
116+
//logs
117+
var buildLogs = "tmp"
118+
const logs: string = buildLogs ?? "no build log data found..."
124119

120+
//build the title
125121
let { exitCode } = state;
126122
exitCode = exitCode ?? null;
127123
const titleBits: React.ReactNode[] = [<span key="label">User: {user?.LDAP}</span>];
@@ -133,9 +129,7 @@ const BazelInvocation: React.FC<{
133129
titleBits.push(<BuildStepResultTag key="result" result={exitCode?.name as BuildStepResultEnum} />);
134130
}
135131

136-
//logs
137-
const logs: string = buildLogs ?? "no build log data found..."
138-
132+
//tabs
139133
var items: TabsProps['items'] = [
140134
{
141135
key: 'BazelInvocationTabs-Problems',
@@ -146,14 +140,12 @@ const BazelInvocation: React.FC<{
146140
{exitCode === null || exitCode.code !== 0 ? (
147141
children
148142
) : (
149-
150143
<PortalAlert
151144
message="There is no debug information to display because there are no reported failures with the build step"
152145
type="success"
153146
showIcon
154147
/>
155148
)}
156-
157149
</Space>,
158150
},
159151
{
@@ -190,7 +182,6 @@ const BazelInvocation: React.FC<{
190182
<ActionDataMetrics acMetrics={acMetrics} />
191183
</Space>,
192184
},
193-
194185
{
195186
key: 'BazelInvocationTabs-Artifacts',
196187
label: 'Artifacts',
@@ -215,7 +206,6 @@ const BazelInvocation: React.FC<{
215206
<TimingMetricsDisplay timingMetrics={timingMetrics} buildGraphMetrics={buildGraphMetrics} />
216207
</Space>,
217208
},
218-
219209
{
220210
key: 'BazelInvocationTabs-Targets',
221211
label: 'Targets',
@@ -258,25 +248,35 @@ const BazelInvocation: React.FC<{
258248
},
259249
];
260250

261-
const hideLogs = true //hide the logs tab for now
262-
if (hideLogs == true) {
263-
var idx = items.findIndex((x, _) => x.key == "BazelInvocationTabs-Logs")
264-
if (idx > -1) {
265-
items.splice(idx, 1);
266-
}
251+
//show/hide tabs
252+
interface TabShowHideDisplay {
253+
hide: boolean,
254+
key: string
267255
}
268256

269-
if (hideTestsTab == true) {
270-
var idx = items.findIndex((x, _) => x.key == "BazelInvocationTabs-Tests")
271-
if (idx > -1) {
272-
items.splice(idx, 1);
273-
}
274-
}
257+
const hideTestsTab: boolean = (testCollection?.length ?? 0) == 0
258+
const hideTargetsTab: boolean = (targetData?.length ?? 0) == 0 ? true : false
259+
const hideNetworkTab: boolean = bytesRecv == 0 && bytesSent == 0
260+
const hideSourceControlTab: boolean = sourceControl?.runID == undefined || sourceControl.runID == null || sourceControl.runID == "" ? true : false
261+
const hideLogsTab: boolean = true
262+
const hideMemoryTab: boolean = (memoryMetrics?.peakPostGcHeapSize ?? 0) == 0 && (memoryMetrics?.peakPostGcHeapSize ?? 0) == 0 && (memoryMetrics?.usedHeapSizePostBuild ?? 0) == 0
263+
264+
const showHideTabs: TabShowHideDisplay[] = [
265+
{ key: "BazelInvocationTabs-Tests", hide: hideTestsTab },
266+
{ key: "BazelInvocationTabs-Targets", hide: hideTargetsTab },
267+
{ key: "BazelInvocationTabs-Network", hide: hideNetworkTab },
268+
{ key: "BazelInvocationTabs-SourceControl", hide: hideSourceControlTab },
269+
{ key: "BazelInvocationTabs-Logs", hide: hideLogsTab },
270+
{ key: "BazelInvocationTabs-Memory", hide: hideMemoryTab },
271+
]
275272

276-
if (hideNetworkMetricsTab == true) {
277-
var idx = items.findIndex((x, _) => x.key == "BazelInvocationTabs-Network")
278-
if (idx > -1) {
279-
items.splice(idx, 1);
273+
for (var i in showHideTabs) {
274+
var tab = showHideTabs[i]
275+
if (tab.hide == true) {
276+
var idx = items.findIndex((x, _) => x.key == tab.key)
277+
if (idx > -1) {
278+
items.splice(idx, 1);
279+
}
280280
}
281281
}
282282

frontend/src/components/Breadcrumbs/index.tsx

+15
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,21 @@ const Breadcrumbs: React.FC<Props> = ({ segmentTitles }) => {
4545
// For example, convert "/foo/bar/baz" to ["foo", "bar", "baz"]
4646
const segments = pathname.split(separator).filter(segment => segment.length > 0);
4747

48+
//special handling for the base64 encoded route params to get around nextjs being overly helpful and decoding urls automagically
49+
if (segments.includes("tests")) {
50+
var idx = segments.indexOf("tests")
51+
if (idx + 1 < segments.length) {
52+
segments[idx + 1] = atob(segments[idx + 1])
53+
}
54+
}
55+
//for future targets route
56+
if (segments.includes("targets")) {
57+
var idx = segments.indexOf("targets")
58+
if (idx + 1 < segments.length) {
59+
segments[idx + 1] = atob(segments[idx + 1])
60+
}
61+
}
62+
4863
// Iterate over the list of segments to build a breadcrumb object for each
4964
const breadcrumbs = segments.map((segment, index) => {
5065
// Compose the path by joining all preceding segments

frontend/src/components/CommandLine/index.tsx

+14-20
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,14 @@ const CommandLineDisplay: React.FC<{ commandLineData: BazelCommand | undefined |
1616
commandLineData: commandLineData
1717
}) => {
1818

19-
const createUnorderedList = (items: string[]): JSX.Element => {
20-
return (
21-
<ul>
22-
{items.map((item, index) => (
23-
<li key={index}>{item}</li>
24-
))}
25-
</ul>
26-
);
27-
};
28-
2919
var commandLineOptions: string[] = []
3020
commandLineData?.cmdLine?.forEach(x => commandLineOptions.push(x ?? ""))
21+
var cmdLine = [commandLineData?.executable, commandLineData?.command, commandLineData?.residual, commandLineData?.explicitCmdLine].join(" ")
3122

3223
return (
3324

3425
<Space direction="vertical" size="middle" style={{ display: 'flex' }} >
35-
<PortalCard type="inner" icon={<CodeOutlined />} titleBits={["Command Line"]}>
36-
<Row>
37-
<Space size="large">
38-
<strong>Explicit Command Line:</strong>
39-
<div>
40-
{commandLineData?.executable} {commandLineData?.command} {commandLineData?.residual} {commandLineData?.explicitCmdLine}
41-
</div>
42-
</Space>
43-
</Row>
26+
<PortalCard type="inner" icon={<CodeOutlined />} titleBits={["Explicit Command Line:", cmdLine]}>
4427
<Row>
4528
<Space size="large">
4629
<div>
@@ -50,13 +33,24 @@ const CommandLineDisplay: React.FC<{ commandLineData: BazelCommand | undefined |
5033
dataSource={commandLineData?.cmdLine?.filter(x => x !== undefined).toSorted() as string[]}
5134
renderItem={(item) => <List.Item>{item}</List.Item>}
5235
/>
53-
36+
</div>
37+
</Space>
38+
</Row>
39+
<Row>
40+
<Space size="large">
41+
<div>
5442
<List
5543
bordered
5644
header={<div><strong>Explicit Startup Options:</strong></div>}
5745
dataSource={commandLineData?.explicitStartupOptions?.filter(x => x !== undefined) as string[]}
5846
renderItem={(item) => <List.Item>{item}</List.Item>}
5947
/>
48+
</div>
49+
</Space>
50+
</Row>
51+
<Row>
52+
<Space size="large">
53+
<div>
6054
<List
6155
bordered
6256
header={<div><strong>Effective Startup Options:</strong></div>}

frontend/src/components/SourceControlDisplay/index.tsx

+13-15
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,26 @@
11
import React from "react";
2-
import { Space, Table, Row, Col, Statistic, List, Descriptions } from 'antd';
3-
import { BranchesOutlined, CodeOutlined, DeploymentUnitOutlined, SearchOutlined } from '@ant-design/icons';
4-
import type { StatisticProps, TableColumnsType } from "antd/lib";
5-
import CountUp from 'react-countup';
6-
import { BazelCommand, SourceControl, TargetMetrics, TargetPair } from "@/graphql/__generated__/graphql";
2+
import { Space, Row, Descriptions } from 'antd';
3+
import { BranchesOutlined } from '@ant-design/icons';
4+
import { SourceControl } from "@/graphql/__generated__/graphql";
75
import PortalCard from "../PortalCard";
8-
import { SearchFilterIcon, SearchWidget } from '@/components/SearchWidgets';
9-
import NullBooleanTag from "../NullableBooleanTag";
10-
import styles from "../../theme/theme.module.css"
11-
import { millisecondsToTime } from "../Utilities/time";
126
import Link from "next/link";
13-
7+
import { env } from 'next-runtime-env';
148

159

1610
const SourceControlDisplay: React.FC<{ sourceControlData: SourceControl | undefined | null }> = ({
1711
sourceControlData: sourceControlData
1812
}) => {
1913
//build urls
20-
const runURL = sourceControlData?.repoURL + "/actions/runs/" + "10976627244"
21-
const actorURL = "https://github.com/" + sourceControlData?.actor
22-
const branchURL = sourceControlData?.repoURL + "/tree/" + sourceControlData?.branch
23-
const commitURL = sourceControlData?.repoURL + "/commit/" + sourceControlData?.commitSha
14+
var ghUrl = env('NEXT_PUBLIC_GITHUB_URL') ?? "https://github.com/"
15+
if (!ghUrl.endsWith("/")) {
16+
ghUrl += "/"
17+
}
18+
const runURL = ghUrl + sourceControlData?.repoURL + "/actions/runs/" + "10976627244"
19+
const actorURL = ghUrl + sourceControlData?.actor
20+
const branchURL = ghUrl + sourceControlData?.repoURL + "/tree/" + sourceControlData?.branch
21+
const commitURL = ghUrl + sourceControlData?.repoURL + "/commit/" + sourceControlData?.commitSha
2422
const prParts = sourceControlData?.refs?.split("/") ?? ""
25-
const prURL = sourceControlData?.repoURL + "/" + prParts[1] + "/" + prParts[2]
23+
const prURL = ghUrl + sourceControlData?.repoURL + "/" + prParts[1] + "/" + prParts[2]
2624

2725
return (
2826
<Space direction="vertical" size="middle" style={{ display: 'flex' }} >

frontend/src/components/TestGrid/index.tsx

+3-4
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ const columns: TableColumnsType<TestGridRowDataType> = [
4646
title: "Label",
4747
dataIndex: "label",
4848
filterSearch: true,
49-
render: (_, record) => <Link href={"tests/" + encodeURIComponent(record.label)}>{record.label}</Link>,
49+
render: (_, record) =>
50+
51+
<Link href={"tests/" + btoa(encodeURIComponent(record.label))}>{record.label}</Link>,
5052
filterDropdown: filterProps => (
5153
<SearchWidget placeholder="Target Pattern..." {...filterProps} />
5254
),
@@ -123,14 +125,11 @@ const TestGrid: React.FC<Props> = () => {
123125
var vars: GetTestsWithOffsetQueryVariables = {}
124126
if (filters['label']?.length) {
125127
var label = filters['label']?.[0]?.toString() ?? ""
126-
console.log(label)
127128
vars.label = label
128129
} else {
129130
vars.label = ""
130131
}
131-
console.log("pagination.curreent", pagination.current)
132132
vars.offset = ((pagination.current ?? 1) - 1) * PAGE_SIZE;
133-
console.log(vars.offset)
134133
setVariables(vars)
135134
},
136135
[variables],

frontend/src/components/TestGridBtn/index.tsx

+8-8
Original file line numberDiff line numberDiff line change
@@ -39,35 +39,35 @@ const TestGridBtn: React.FC<Props> = ({ status, invocationId }) => {
3939

4040
),
4141
PASSED: (
42-
<Button href={"/bazel-invocations/" + invocationId} icon={<CheckCircleFilled />} color="success" className={themeStyles.colorSuccess} />
42+
<Button href={"/bazel-invocations/" + invocationId} icon={<CheckCircleFilled />} className={themeStyles.colorSuccess} />
4343

4444
),
4545
FLAKY: (
46-
<Button icon={<InfoCircleFilled />} color="warning" className={themeStyles.colorAborted} />
46+
<Button href={"/bazel-invocations/" + invocationId} icon={<InfoCircleFilled />} className={themeStyles.colorAborted} />
4747

4848
),
4949
FAILED: (
50-
<Button icon={<CloseCircleFilled />} color="danger" className={themeStyles.colorFailure} />
50+
<Button href={"/bazel-invocations/" + invocationId} icon={<CloseCircleFilled />} color="danger" className={themeStyles.colorFailure} />
5151

5252
),
5353
TIMEOUT: (
54-
<Button icon={<MinusCircleFilled />} color="danger" className={themeStyles.colorFailure} />
54+
<Button href={"/bazel-invocations/" + invocationId} icon={<MinusCircleFilled />} color="danger" className={themeStyles.colorFailure} />
5555

5656
),
5757
INCOMPLETE: (
58-
<Button icon={<StopOutlined />} color="secondary" className={themeStyles.colorAborted} />
58+
<Button href={"/bazel-invocations/" + invocationId} icon={<StopOutlined />} className={themeStyles.colorAborted} />
5959

6060
),
6161
REMOTE_FAILURE: (
62-
<Button icon={<CloseCircleFilled />} color="danger" className={themeStyles.colorFailure} />
62+
<Button href={"/bazel-invocations/" + invocationId} icon={<CloseCircleFilled />} color="danger" className={themeStyles.colorFailure} />
6363

6464
),
6565
FAILED_TO_BUILD: (
66-
<Button icon={<QuestionCircleFilled />} color="danger" className={themeStyles.colorFailure} />
66+
<Button href={"/bazel-invocations/" + invocationId} icon={<QuestionCircleFilled />} color="danger" className={themeStyles.colorFailure} />
6767

6868
),
6969
TOOL_HALTED_BEFORE_TESTING: (
70-
<Button icon={<QuestionCircleFilled />} color="secondary" className={themeStyles.colorDisabled} />
70+
<Button href={"/bazel-invocations/" + invocationId} icon={<QuestionCircleFilled />} className={themeStyles.colorDisabled} />
7171
),
7272
};
7373

frontend/src/components/TestsMetrics/index.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ const test_columns: TableColumnsType<TestDataType> = [
7575
{
7676
title: "Label",
7777
dataIndex: "name",
78-
render: (_, record) => <Link href={"/tests/" + encodeURIComponent(record.name)}>{record.name}</Link>,
78+
render: (_, record) => <Link href={"/tests/" + btoa(encodeURIComponent(record.name))}>{record.name}</Link>,
7979
filterSearch: true,
8080
filterDropdown: filterProps => (
8181
<SearchWidget placeholder="Target Pattern..." {...filterProps} />

0 commit comments

Comments
 (0)