Skip to content

Commit 535e8da

Browse files
authored
Connector builder test result display (#18533)
* [SPIKE] add Builder page with editor * add YamlEditor component * export colors from CSS * move template into dedicated file * fix initial load from local storage * move download button into separate component * fix stylelint * remove console log * add todo * make monaco background transparent and apply gradient to parent div background * clarify comment * remove unnecessary 180deg * lock the builder UI behind a feature * use rgb instead of hex to fix stylelint * use _colors.scss and disable hex length stylelint rule * disable rule in file * generify ConnectorDocumentationLayout into TwoPanelLayout * use TwoPanelLayout for BuilderPage * add darker gradient color to _colors.scss and use in gradient * move /builder to /connector-builder * rename TwoPanelLayout to ResizablePanels * put gradient on parent container instead * make lightOverlay actually overlay instead of un-rendering children * add testing panel component and stream selector * fix rotated text * fix more styling * remove unnecessary comment * add starting flex to right panel * replace react-select dropdown with headless-ui listbox * add test controls and fix button icon styling * add Configure Test Input button and modal * add connector builder client * move connector builder state into dedicated context * fix bold prop in Text component to not throw error * pass parsed yaml->json into query * store config in connector builder state context * add result display * fix styles of result display * move config menu into testing panel * capitalize stream names * undo changes to Text component, since that is being addressed in a separate PR * fix more merge issues and fix generated schema usage * capitalize header * remove console log * rename data to streamRead * fix stylelint and use variables * use another variable for spacing * use stream name in state data object * add paginator component * save progress on result display * generify stream selector and add slice selector * add page display with tabs * fix scrolling and add logic to make mocking results easier * make mocks more unique * wire up slice selector to content shown * improve placeholder text style * add gap in page display * make controlled component and fix mocks * move tab titles into intl * fix typo * move placeholder into intl * update listbox and paginator to be more generic * clean up paginator styles * undo change to App.tsx * cleanup * use intl for slice label fallback * remove manifest and config from react-query keys to prevent losing results when editing yaml * switch to functional style for generic components
1 parent 4e905ca commit 535e8da

23 files changed

+630
-160
lines changed

airbyte-webapp/package-lock.json

Lines changed: 39 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

airbyte-webapp/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"react-intl": "^6.1.1",
5555
"react-lazylog": "^4.5.3",
5656
"react-markdown": "^7.0.1",
57+
"react-paginate": "^8.1.3",
5758
"react-query": "^3.39.1",
5859
"react-reflex": "^4.0.9",
5960
"react-router-dom": "^6.3.0",
@@ -100,6 +101,7 @@
100101
"@types/react-dom": "^17.0.11",
101102
"@types/react-helmet": "^6.1.5",
102103
"@types/react-lazylog": "^4.5.1",
104+
"@types/react-paginate": "^7.1.1",
103105
"@types/react-slick": "^0.23.10",
104106
"@types/react-table": "^7.7.12",
105107
"@types/react-widgets": "^4.4.7",
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
@use "scss/variables";
2+
@use "scss/colors";
3+
4+
.tabList {
5+
flex: 0 0 auto;
6+
display: flex;
7+
}
8+
9+
.tab {
10+
flex: 1;
11+
background-color: transparent;
12+
border: 0;
13+
}
14+
15+
.tabTitle {
16+
border-bottom: variables.$border-thin solid colors.$grey-50;
17+
color: colors.$grey-300;
18+
font-weight: 500;
19+
font-size: 10px;
20+
cursor: pointer;
21+
padding: 3px;
22+
}
23+
24+
.selected {
25+
border-bottom-color: colors.$grey-300;
26+
color: colors.$dark-blue;
27+
}
28+
29+
.tabPanelContainer {
30+
flex: 1;
31+
min-height: 0;
32+
}
33+
34+
.tabPanel {
35+
max-height: 100%;
36+
overflow-y: auto;
37+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { Tab } from "@headlessui/react";
2+
import classNames from "classnames";
3+
import { useIntl } from "react-intl";
4+
5+
import { Text } from "components/ui/Text";
6+
7+
import {
8+
HttpRequest,
9+
HttpResponse,
10+
StreamReadSlicesItemPagesItem,
11+
StreamReadSlicesItemPagesItemRecordsItem,
12+
} from "core/request/ConnectorBuilderClient";
13+
14+
import styles from "./PageDisplay.module.scss";
15+
16+
interface PageDisplayProps {
17+
page: StreamReadSlicesItemPagesItem;
18+
className?: string;
19+
}
20+
21+
interface TabData {
22+
title: string;
23+
content: StreamReadSlicesItemPagesItemRecordsItem[] | HttpRequest | HttpResponse;
24+
}
25+
26+
export const PageDisplay: React.FC<PageDisplayProps> = ({ page, className }) => {
27+
const { formatMessage } = useIntl();
28+
const tabs: TabData[] = [{ title: formatMessage({ id: "connectorBuilder.recordsTab" }), content: page.records }];
29+
if (page.request) {
30+
tabs.push({ title: formatMessage({ id: "connectorBuilder.requestTab" }), content: page.request });
31+
}
32+
if (page.response) {
33+
tabs.push({ title: formatMessage({ id: "connectorBuilder.responseTab" }), content: page.response });
34+
}
35+
36+
return (
37+
<div className={classNames(className)}>
38+
<Tab.Group>
39+
<Tab.List className={styles.tabList}>
40+
{tabs.map((tab) => (
41+
<Tab className={styles.tab}>
42+
{({ selected }) => (
43+
<Text className={classNames(styles.tabTitle, { [styles.selected]: selected })}>{tab.title}</Text>
44+
)}
45+
</Tab>
46+
))}
47+
</Tab.List>
48+
<Tab.Panels className={styles.tabPanelContainer}>
49+
{tabs.map((tab) => (
50+
<Tab.Panel className={styles.tabPanel}>
51+
<pre>{JSON.stringify(tab.content, null, 2)}</pre>
52+
</Tab.Panel>
53+
))}
54+
</Tab.Panels>
55+
</Tab.Group>
56+
</div>
57+
);
58+
};
Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,37 @@
11
@use "scss/colors";
22
@use "scss/variables";
33

4-
.displayBox {
5-
padding: variables.$spacing-md;
6-
border-radius: variables.$border-radius-xs;
7-
overflow-x: auto;
8-
}
9-
104
.container {
115
display: flex;
126
flex-direction: column;
13-
gap: variables.$spacing-md;
7+
gap: variables.$spacing-lg;
148
}
159

16-
.slice {
17-
background-color: colors.$blue-200;
10+
.sliceSelector {
11+
flex: 0 0 auto;
1812
}
1913

20-
.page {
21-
background-color: colors.$blue-100;
22-
}
23-
24-
.pageData {
25-
background-color: colors.$blue-50;
14+
.pageDisplay {
15+
flex: 1;
16+
min-height: 0;
17+
display: flex;
18+
flex-direction: column;
19+
gap: variables.$spacing-sm;
2620
}
2721

28-
.state {
29-
background-color: colors.$orange-50;
22+
.paginator {
23+
display: flex;
24+
gap: variables.$spacing-sm;
25+
align-self: center;
26+
justify-self: flex-end;
27+
margin-top: auto;
28+
margin-bottom: 0;
29+
flex: 0 0 auto;
3030
}
3131

32-
.logs {
33-
background-color: colors.$grey-200;
32+
.pageLabel {
33+
display: flex;
34+
flex-direction: column;
35+
justify-content: center;
36+
font-size: 10px;
3437
}
Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,45 @@
11
import classNames from "classnames";
2+
import { useState } from "react";
23

4+
import { Paginator } from "components/ui/Paginator";
35
import { Text } from "components/ui/Text";
46

57
import { StreamRead } from "core/request/ConnectorBuilderClient";
68

9+
import { PageDisplay } from "./PageDisplay";
710
import styles from "./ResultDisplay.module.scss";
11+
import { SliceSelector } from "./SliceSelector";
812

913
interface ResultDisplayProps {
1014
streamRead: StreamRead;
15+
className?: string;
1116
}
1217

13-
export const ResultDisplay: React.FC<ResultDisplayProps> = ({ streamRead }) => {
18+
export const ResultDisplay: React.FC<ResultDisplayProps> = ({ streamRead, className }) => {
19+
const [selectedSliceIndex, setSelectedSliceIndex] = useState(0);
20+
const [selectedPage, setSelectedPage] = useState(0);
21+
22+
const handlePageChange = (selectedPageIndex: number) => {
23+
setSelectedPage(selectedPageIndex);
24+
};
25+
26+
const slice = streamRead.slices[selectedSliceIndex];
27+
const numPages = slice.pages.length;
28+
const page = slice.pages[selectedPage];
29+
1430
return (
15-
<div className={styles.container}>
16-
{streamRead.slices.map((slice) => (
17-
<div className={classNames(styles.displayBox, styles.container, styles.slice)}>
18-
<Text>Slice {JSON.stringify(slice.sliceDescriptor)}</Text>
19-
{slice.pages.map((page, pageNumber) => (
20-
<div className={classNames(styles.displayBox, styles.container, styles.page)}>
21-
<Text>Page {pageNumber}</Text>
22-
<div className={classNames(styles.displayBox, styles.pageData)}>
23-
Request:
24-
<pre>{JSON.stringify(page.request, null, 2)}</pre>
25-
</div>
26-
<div className={classNames(styles.displayBox, styles.pageData)}>
27-
Response:
28-
<pre>{JSON.stringify(page.response, null, 2)}</pre>
29-
</div>
30-
<div className={classNames(styles.displayBox, styles.pageData)}>
31-
Records:
32-
<pre>{JSON.stringify(page.records, null, 2)}</pre>
33-
</div>
34-
</div>
35-
))}
36-
{slice.state && (
37-
<div className={classNames(styles.displayBox, styles.state)}>
38-
State:
39-
<pre>{JSON.stringify(slice.state, null, 2)}</pre>
40-
</div>
41-
)}
42-
</div>
43-
))}
44-
{streamRead.logs.length > 0 && (
45-
<div className={classNames(styles.displayBox, styles.logs)}>
46-
Logs:
47-
<pre>{JSON.stringify(streamRead.logs, null, 2)}</pre>
48-
</div>
49-
)}
31+
<div className={classNames(className, styles.container)}>
32+
<SliceSelector
33+
className={styles.sliceSelector}
34+
slices={streamRead.slices}
35+
selectedSliceIndex={selectedSliceIndex}
36+
onSelect={setSelectedSliceIndex}
37+
/>
38+
<PageDisplay className={styles.pageDisplay} page={page} />
39+
<div className={styles.paginator}>
40+
<Text className={styles.pageLabel}>Page:</Text>
41+
<Paginator numPages={numPages} onPageChange={handlePageChange} selectedPage={selectedPage} />
42+
</div>
5043
</div>
5144
);
5245
};
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
@use "scss/variables";
2+
@use "scss/colors";
3+
4+
.button {
5+
padding: variables.$spacing-sm variables.$spacing-md;
6+
background-color: transparent;
7+
border: variables.$border-thin solid colors.$dark-blue;
8+
border-radius: variables.$border-radius-xs;
9+
display: flex;
10+
align-items: center;
11+
}
12+
13+
.arrow {
14+
margin-left: auto;
15+
font-size: 10px;
16+
}

0 commit comments

Comments
 (0)