Skip to content

Commit

Permalink
PRfD - Create PR page (#8206)
Browse files Browse the repository at this point in the history
* Create PR page

* Integrate List API

* Fix Creation function

* Extract BranchesSelection to a component

* Fix dates

* Improve error handling

* Update page width

* Fix error handling
  • Loading branch information
itaigilo authored Sep 24, 2024
1 parent e419027 commit 158d547
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 143 deletions.
115 changes: 43 additions & 72 deletions webui/src/lib/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -569,80 +569,51 @@ class Tags {

class Pulls {
async get(repoId, pullId) {
// const response = await apiRequest(`/repositories/${encodeURIComponent(repoId)}/pulls/${encodeURIComponent(pullId)}`);
// if (response.status === 404) {
// throw new NotFoundError(`could not find pull ${pullId}`);
// } else if (response.status !== 200) {
// throw new Error(`could not get pullId: ${await extractError(response)}`);
// }
// return response.json();

// TODO: this is for development purposes only
console.log("get pull", {repoId, pullId});
return {
"id": pullId,
"title": "Test PR 1",
"status": "open",
"creation_date": 1726575741,
"author": "test-user-1",
"description": "This is a test PR",
"source_branch": "test-1",
"destination_branch": "main"
}
}

async list(repoId, state = "open", prefix = "", after = "", amount = DEFAULT_LISTING_AMOUNT) {
// const query = qs({prefix, after, amount});
// const response = await apiRequest(`/repositories/${encodeURIComponent(repoId)}/pulls?` + query);
// if (response.status !== 200) {
// throw new Error(`could not list pulls: ${await extractError(response)}`);
// }
// return response.json();

// TODO: this is for development purposes only
console.log("list pulls", {repoId, state, prefix, after, amount});
let results = [
{
"id": "test-pull-1",
"title": "Test PR 1",
"status": "open",
"creation_date": 1726575741,
"author": "test-user-1",
"description": "This is a test PR",
"source_branch": "feature-branch-1",
"destination_branch": "main"
},
{
"id": "test-pull-2",
"title": "Next Test PR 2",
"status": "closed",
"creation_date": 1726402941,
"author": "test-user-2",
"description": "This is a another test PR",
"source_branch": "feature-branch-2",
"destination_branch": "main"
},
{
"id": "test-pull-3",
"title": "Another Test PR 3",
"status": "open",
"creation_date": 1718454141,
"author": "test-user-1",
"description": "This is also a test PR",
"source_branch": "feature-branch-3",
"destination_branch": "feature-branch-1"
const response = await apiRequest(`/repositories/${encodeURIComponent(repoId)}/pulls/${encodeURIComponent(pullId)}`);
if (response.status === 404) {
throw new NotFoundError(`Could not find pull request (id = ${pullId}).`);
} else if (response.status !== 200) {
throw new Error(`Could not get pull request (id = ${pullId}): ${await extractError(response)}`);
}
return response.json();
}

async list(repoId, status = "open", prefix = "", after = "", amount = DEFAULT_LISTING_AMOUNT) {
const query = qs({status, prefix, after, amount});
const response = await apiRequest(`/repositories/${encodeURIComponent(repoId)}/pulls?` + query);
if (response.status !== 200) {
const baseMessage = 'Could not list pull requests';
switch (response.status) {
case 400:
case 401:
case 404:
throw new Error(`${baseMessage}: ${(await response.json()).message}`);
default:
throw new Error(`${baseMessage} (status = ${response.status}).`);
}
}
return response.json();
}

async create(repoId, pullDetails) {
const response = await apiRequest(`/repositories/${encodeURIComponent(repoId)}/pulls`, {
method: 'POST',
body: JSON.stringify(pullDetails),
});
if (response.status !== 201) {
const baseMessage = 'Could not create pull request';
switch (response.status) {
case 400:
case 401:
case 403:
case 404:
case 409:
throw new Error(`${baseMessage}: ${(await response.json()).message}`);
default:
throw new Error(`${baseMessage} (status = ${response.status}).`);
}
];
results = results.filter(pull => pull.status === state);
return {
"pagination": {
"has_more": false,
"max_per_page": 1000,
"next_offset": "",
"results": results.length
},
"results": results
}
return await response.text();
}
}

Expand Down
5 changes: 2 additions & 3 deletions webui/src/lib/components/repository/compareBranches.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {URINavigator} from "./tree";
import CompareBranchesActionsBar from "./compareBranchesActionBar";

const CompareBranches = (
{repo, reference, compareReference, showActionsBar, prefix = "", onSelectRef, onSelectCompare}
{repo, reference, compareReference, showActionsBar, prefix = "", baseSelectURL}
) => {
const [internalRefresh, setInternalRefresh] = useState(true);

Expand Down Expand Up @@ -47,9 +47,8 @@ const CompareBranches = (
<CompareBranchesActionsBar
repo={repo}
reference={reference}
onSelectRef={onSelectRef}
compareReference={compareReference}
onSelectCompare={onSelectCompare}
baseSelectURL={baseSelectURL}
doRefresh={doRefresh}
isEmptyDiff={isEmptyDiff}
/>
Expand Down
50 changes: 8 additions & 42 deletions webui/src/lib/components/repository/compareBranchesActionBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,59 +3,25 @@ import {refs as refsAPI} from "../../../lib/api";
import {RefTypeBranch} from "../../../constants";
import {ActionGroup, ActionsBar, AlertError, RefreshButton} from "../controls";
import {MetadataFields} from "./changes";
import {useRouter} from "../../hooks/router";
import RefDropdown from "./refDropdown";
import {ArrowLeftIcon, ArrowSwitchIcon, GitMergeIcon} from "@primer/octicons-react";
import OverlayTrigger from "react-bootstrap/OverlayTrigger";
import Tooltip from "react-bootstrap/Tooltip";
import {GitMergeIcon} from "@primer/octicons-react";
import Button from "react-bootstrap/Button";
import Modal from "react-bootstrap/Modal";
import Form from "react-bootstrap/Form";
import {FormControl, FormHelperText, InputLabel, MenuItem, Select} from "@mui/material";
import CompareBranchesSelection from "./compareBranchesSelection";

const CompareBranchesActionsBar = (
{repo, reference, onSelectRef, compareReference, onSelectCompare, doRefresh, isEmptyDiff}
{repo, reference, compareReference, baseSelectURL, doRefresh, isEmptyDiff}
) => {
const router = useRouter();
const handleSwitchRefs = useCallback((e) => {
e.preventDefault();
router.push({
pathname: `/repositories/:repoId/compare`, params: {repoId: repo.id},
query: {ref: compareReference.id, compare: reference.id}
});
}, []);

return <ActionsBar>
<ActionGroup orientation="left">
<RefDropdown
prefix={'Base '}
repo={repo}
selected={(reference) ? reference : null}
withCommits={true}
withWorkspace={false}
selectRef={onSelectRef}/>

<ArrowLeftIcon className="me-2 mt-2" size="small" verticalAlign="middle"/>

<RefDropdown
prefix={'Compared to '}
emptyText={'Compare with...'}
<CompareBranchesSelection
repo={repo}
selected={(compareReference) ? compareReference : null}
reference={reference}
compareReference={compareReference}
baseSelectURL={baseSelectURL}
withCommits={true}
withWorkspace={false}
selectRef={onSelectCompare}/>

<OverlayTrigger placement="bottom" overlay={
<Tooltip>Switch directions</Tooltip>
}>
<span>
<Button variant={"link"}
onClick={handleSwitchRefs}>
<ArrowSwitchIcon className="me-2 mt-2" size="small" verticalAlign="middle"/>
</Button>
</span>
</OverlayTrigger>&#160;&#160;
/>
</ActionGroup>

<ActionGroup orientation="right">
Expand Down
74 changes: 74 additions & 0 deletions webui/src/lib/components/repository/compareBranchesSelection.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React, {useCallback} from "react";
import {useRouter} from "../../hooks/router";
import RefDropdown from "./refDropdown";
import {ArrowLeftIcon, ArrowSwitchIcon} from "@primer/octicons-react";
import OverlayTrigger from "react-bootstrap/OverlayTrigger";
import Tooltip from "react-bootstrap/Tooltip";
import Button from "react-bootstrap/Button";

const CompareBranchesSelection = (
{repo, reference, compareReference, baseSelectURL, withCommits, withWorkspace, withTags}
) => {
const router = useRouter();

const handleSwitchRefs = useCallback((e) => {
e.preventDefault();
router.push({
pathname: baseSelectURL,
params: {repoId: repo.id},
query: {ref: compareReference.id, compare: reference.id}
});
}, []);

const route = query => router.push({
pathname: baseSelectURL,
params: {repoId: repo.id},
query
});

const onSelectRef = reference => route(compareReference ?
{ref: reference.id, compare: compareReference.id} :
{ref: reference.id}
);
const onSelectCompare = compareReference => route(reference ?
{ref: reference.id, compare: compareReference.id} :
{compare: compareReference.id}
);


return <>
<RefDropdown
prefix={'Base '}
repo={repo}
selected={(reference) ? reference : null}
withCommits={withCommits}
withWorkspace={withWorkspace}
withTags={withTags}
selectRef={onSelectRef}/>

<ArrowLeftIcon className="me-2 mt-2" size="small" verticalAlign="middle"/>

<RefDropdown
prefix={'Compared to '}
emptyText={'Compare with...'}
repo={repo}
selected={(compareReference) ? compareReference : null}
withCommits={withCommits}
withWorkspace={withWorkspace}
withTags={withTags}
selectRef={onSelectCompare}/>

<OverlayTrigger placement="bottom" overlay={
<Tooltip>Switch directions</Tooltip>
}>
<span>
<Button variant={"link"}
onClick={handleSwitchRefs}>
<ArrowSwitchIcon className="me-2 mt-2" size="small" verticalAlign="middle"/>
</Button>
</span>
</OverlayTrigger>
</>;
};

export default CompareBranchesSelection;
18 changes: 1 addition & 17 deletions webui/src/pages/repositories/repository/compare.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,14 @@ const CompareContainer = () => {
if (loading) return <Loading/>;
if (error) return <RepoError error={error}/>;

const route = query => router.push({
pathname: `/repositories/:repoId/compare`,
params: {repoId: repo.id},
query
});

const onSelectRef = reference => route(compare ?
{ref: reference.id, compare: compare.id} :
{ref: reference.id}
);
const onSelectCompare = compare => route(reference ?
{ref: reference.id, compare: compare.id} :
{compare: compare.id}
);

return (
<CompareBranches
repo={repo}
reference={reference}
compareReference={compare}
showActionsBar={true}
prefix={prefix}
onSelectRef={onSelectRef}
onSelectCompare={onSelectCompare}
baseSelectURL={"/repositories/:repoId/compare"}
/>
);
};
Expand Down
Loading

0 comments on commit 158d547

Please sign in to comment.