Skip to content

Commit 43a64c2

Browse files
authored
[UI] Implemented support for branches (#4891)
* Implemented support for branches in the UI * Fix linting errors * Fix the UI integration test (URL pattern change)
1 parent 86fba52 commit 43a64c2

40 files changed

+1756
-86
lines changed

ui/tests/specs/e2e.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ test("End to End - Create new version", async ({ page }) => {
126126
await page.getByTestId("modal-btn-create").click();
127127

128128
// Make sure we redirected to the artifact detail page.
129-
await expect(page).toHaveURL(/.+\/explore\/e2e\/MyArtifact\/2/);
129+
await expect(page).toHaveURL(/.+\/explore\/e2e\/MyArtifact\/versions\/2/);
130130
});
131131

132132

ui/ui-app/src/app/App.tsx

+40-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { FunctionComponent } from "react";
66
import { Page } from "@patternfly/react-core";
77
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
88
import { AppHeader } from "@app/components";
9-
import { ExplorePage, GroupPage, NotFoundPage, RootRedirectPage, RulesPage, VersionPage } from "@app/pages";
9+
import { BranchPage, ExplorePage, GroupPage, NotFoundPage, RootRedirectPage, RulesPage, VersionPage } from "@app/pages";
1010
import { RolesPage, SettingsPage } from "./pages";
1111
import { ConfigService, useConfigService } from "@services/useConfigService.ts";
1212
import { LoggerService, useLoggerService } from "@services/useLoggerService.ts";
@@ -50,18 +50,56 @@ export const App: FunctionComponent<AppProps> = () => {
5050
<Route path="/roles" element={ <RolesPage /> } />
5151
<Route path="/settings" element={ <SettingsPage /> } />
5252
<Route path="/explore" element={ <ExplorePage /> } />
53+
5354
<Route
5455
path="/explore/:groupId"
5556
element={ <GroupPage /> }
5657
/>
58+
<Route
59+
path="/explore/:groupId/artifacts"
60+
element={ <GroupPage /> }
61+
/>
62+
5763
<Route
5864
path="/explore/:groupId/:artifactId"
5965
element={ <ArtifactPage /> }
6066
/>
6167
<Route
62-
path="/explore/:groupId/:artifactId/:version"
68+
path="/explore/:groupId/:artifactId/versions"
69+
element={ <ArtifactPage /> }
70+
/>
71+
<Route
72+
path="/explore/:groupId/:artifactId/branches"
73+
element={ <ArtifactPage /> }
74+
/>
75+
76+
<Route
77+
path="/explore/:groupId/:artifactId/versions/:version"
78+
element={ <VersionPage /> }
79+
/>
80+
<Route
81+
path="/explore/:groupId/:artifactId/versions/:version/content"
82+
element={ <VersionPage /> }
83+
/>
84+
<Route
85+
path="/explore/:groupId/:artifactId/versions/:version/documentation"
86+
element={ <VersionPage /> }
87+
/>
88+
<Route
89+
path="/explore/:groupId/:artifactId/versions/:version/references"
6390
element={ <VersionPage /> }
6491
/>
92+
93+
<Route
94+
path="/explore/:groupId/:artifactId/branches/:branchId"
95+
element={ <BranchPage /> }
96+
/>
97+
<Route
98+
path="/explore/:groupId/:artifactId/branches/:branchId/versions"
99+
element={ <BranchPage /> }
100+
/>
101+
102+
65103
<Route element={ <NotFoundPage /> } />
66104
</Routes>
67105
</Page>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { FunctionComponent, useEffect, useState } from "react";
2+
import { Button, Form, FormGroup, Modal } from "@patternfly/react-core";
3+
import { SearchedBranch, SearchedVersion } from "@sdk/lib/generated-client/models";
4+
import { IfNotLoading, ObjectSelect } from "@apicurio/common-ui-components";
5+
import { GroupsService, useGroupsService } from "@services/useGroupsService.ts";
6+
import { shash } from "@utils/string.utils.ts";
7+
8+
9+
/**
10+
* Props
11+
*/
12+
export type AddVersionToBranchModalProps = {
13+
isOpen: boolean;
14+
version: SearchedVersion;
15+
onClose: () => void;
16+
onAdd: (branch: SearchedBranch) => void;
17+
};
18+
19+
/**
20+
* Models the Add Version to Branch dialog.
21+
*/
22+
export const AddVersionToBranchModal: FunctionComponent<AddVersionToBranchModalProps> = (props: AddVersionToBranchModalProps) => {
23+
const [isLoading, setIsLoading] = useState(false);
24+
const [branches, setBranches] = useState<SearchedBranch[]>();
25+
const [selectedBranch, setSelectedBranch] = useState<SearchedBranch>();
26+
27+
const groups: GroupsService = useGroupsService();
28+
29+
const onAdd = (): void => {
30+
props.onAdd(selectedBranch as SearchedBranch);
31+
};
32+
33+
const search = (): void => {
34+
setIsLoading(true);
35+
groups.getArtifactBranches(props.version.groupId || "default", props.version.artifactId!, {
36+
page: 1,
37+
pageSize: 50
38+
}).then(results => {
39+
setIsLoading(false);
40+
setBranches(results.branches?.filter(branch => !branch.systemDefined));
41+
});
42+
};
43+
44+
useEffect(() => {
45+
if (props.isOpen) {
46+
search();
47+
}
48+
}, [props.isOpen]);
49+
50+
return (
51+
<Modal
52+
title="Add to Branch"
53+
variant="medium"
54+
isOpen={props.isOpen}
55+
onClose={props.onClose}
56+
className="add-to-branch pf-m-redhat-font"
57+
actions={[
58+
<Button
59+
key="add"
60+
variant="primary"
61+
data-testid="modal-btn-add"
62+
isDisabled={selectedBranch === undefined}
63+
onClick={onAdd}>Add</Button>,
64+
<Button
65+
key="cancel"
66+
variant="link"
67+
data-testid="modal-btn-cancel"
68+
onClick={props.onClose}>Cancel</Button>
69+
]}
70+
>
71+
<Form>
72+
<FormGroup label="Branch" isRequired={false} fieldId="form-branch">
73+
<IfNotLoading isLoading={isLoading}>
74+
<ObjectSelect
75+
noSelectionLabel="Select a branch"
76+
value={selectedBranch}
77+
items={branches || []}
78+
onSelect={setSelectedBranch}
79+
itemToString={item => item.branchId}
80+
itemToTestId={item => `branch-${shash(item.branchId)}`}
81+
toggleId="select-branch-toggle"
82+
appendTo="document"
83+
/>
84+
</IfNotLoading>
85+
</FormGroup>
86+
</Form>
87+
</Modal>
88+
);
89+
};

ui/ui-app/src/app/components/modals/CreateArtifactModal.tsx

-2
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,6 @@ export const CreateArtifactModal: FunctionComponent<CreateArtifactModalProps> =
225225
};
226226

227227
const fireCreateEvent = (): void => {
228-
console.debug("---");
229-
console.debug(data);
230228
props.onCreate(groupId, data);
231229
};
232230

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { FunctionComponent, useState } from "react";
2+
import { Button, Form, FormGroup, Modal, TextArea, TextInput } from "@patternfly/react-core";
3+
import { CreateBranch } from "@sdk/lib/generated-client/models";
4+
5+
6+
/**
7+
* Labels
8+
*/
9+
export type CreateBranchModalProps = {
10+
isOpen: boolean;
11+
onClose: () => void;
12+
onCreate: (data: CreateBranch) => void;
13+
};
14+
15+
/**
16+
* Models the create branch dialog.
17+
*/
18+
export const CreateBranchModal: FunctionComponent<CreateBranchModalProps> = (props: CreateBranchModalProps) => {
19+
const [branchId, setBranchId] = useState("");
20+
const [description, setDescription] = useState("");
21+
22+
const onBranchIdChange = (_event: any, value: any): void => {
23+
setBranchId(value);
24+
};
25+
26+
const onDescriptionChange = (_event: any, value: any): void => {
27+
setDescription(value);
28+
};
29+
30+
const onCreate = (): void => {
31+
const data: CreateBranch = {
32+
branchId,
33+
description
34+
};
35+
props.onCreate(data);
36+
};
37+
38+
return (
39+
<Modal
40+
title="Create Branch"
41+
variant="medium"
42+
isOpen={props.isOpen}
43+
onClose={props.onClose}
44+
className="create pf-m-redhat-font"
45+
actions={[
46+
<Button
47+
key="create"
48+
variant="primary"
49+
data-testid="modal-btn-create"
50+
onClick={onCreate}>Create</Button>,
51+
<Button
52+
key="cancel"
53+
variant="link"
54+
data-testid="modal-btn-cancel"
55+
onClick={props.onClose}>Cancel</Button>
56+
]}
57+
>
58+
<Form>
59+
<FormGroup
60+
label="Branch Id"
61+
isRequired={false}
62+
fieldId="form-branch-id"
63+
>
64+
<TextInput
65+
isRequired={false}
66+
type="text"
67+
id="form-branch-id"
68+
data-testid="create-version-branch-id"
69+
name="form-name"
70+
aria-describedby="form-branch-id-helper"
71+
value={branchId}
72+
placeholder="Unique Id of the new branch"
73+
onChange={onBranchIdChange}
74+
/>
75+
</FormGroup>
76+
<FormGroup
77+
label="Description"
78+
fieldId="form-description"
79+
>
80+
<TextArea
81+
isRequired={false}
82+
id="form-description"
83+
data-testid="create-branch-modal-description"
84+
name="form-description"
85+
aria-describedby="form-description-helper"
86+
value={description}
87+
placeholder="Description of the branch"
88+
onChange={onDescriptionChange}
89+
/>
90+
</FormGroup>
91+
</Form>
92+
</Modal>
93+
);
94+
};

0 commit comments

Comments
 (0)