Skip to content

Commit

Permalink
feat(bulk-import): use react query to fetch repositories
Browse files Browse the repository at this point in the history
  • Loading branch information
debsmita1 committed Nov 7, 2024
1 parent ae43642 commit 54e98c1
Show file tree
Hide file tree
Showing 24 changed files with 537 additions and 609 deletions.
5 changes: 5 additions & 0 deletions workspaces/bulk-import/.changeset/serious-lizards-bathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@red-hat-developer-hub/backstage-plugin-bulk-import': minor
---

use react query to fetch repositories
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,11 @@ const handlers = [
)
) {
return res(
ctx.status(400),
ctx.json({ message: 'Dry run for creating import jobs failed' }),
ctx.json({
message: 'Dry run for creating import jobs failed',
ok: false,
status: 404,
}),
);
}
return res(ctx.json(jobs));
Expand Down Expand Up @@ -368,6 +371,8 @@ describe('BulkImportBackendClient', () => {

expect(response).toEqual({
message: 'Dry run for creating import jobs failed',
ok: false,
status: 404,
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,11 @@ export class BulkImportBackendClient implements BulkImportAPI {
body: JSON.stringify(importRepositories),
},
);
return jsonResponse.json();
if (!jsonResponse.ok) {
const errorResponse = await jsonResponse.json();
throw errorResponse;
}
return jsonResponse.status === 204 ? null : await jsonResponse.json();
}

async deleteImportAction(repo: string, defaultBranch: string) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ import React from 'react';

import { useDrawer } from '@janus-idp/shared-react';
import { makeStyles } from '@material-ui/core';
import { Alert, AlertTitle } from '@material-ui/lab';
import FormControl from '@mui/material/FormControl';
import { useFormikContext } from 'formik';
import { get } from 'lodash';

import { AddRepositoriesFormValues, PullRequestPreviewData } from '../../types';
import { PreviewFileSidebar } from '../PreviewFile/PreviewFileSidebar';
// import HelpIcon from '@mui/icons-material/HelpOutline';
// import FormControlLabel from '@mui/material/FormControlLabel';
// import Radio from '@mui/material/Radio';
// import RadioGroup from '@mui/material/RadioGroup';
// import Tooltip from '@mui/material/Tooltip';
// import Typography from '@mui/material/Typography';
// import { useFormikContext } from 'formik';
// import { AddRepositoriesFormValues } from '../../types';
import { AddRepositoriesFormFooter } from './AddRepositoriesFormFooter';
import { AddRepositoriesTable } from './AddRepositoriesTable';

const useStyles = makeStyles(theme => ({
body: {
marginBottom: '50px',
padding: '24px',
},
approvalTool: {
display: 'flex',
flexDirection: 'row',
justifyContent: 'left',
alignItems: 'center',
paddingTop: '24px',
paddingBottom: '24px',
paddingLeft: '16px',
backgroundColor: theme.palette.background.paper,
borderBottomStyle: 'groove',
border: theme.palette.divider,
},

approvalToolTooltip: {
paddingTop: '4px',
paddingRight: '24px',
paddingLeft: '5px',
},
}));

export const AddRepositories = ({ error }: { error: any }) => {
const styles = useStyles();
const { openDrawer, setOpenDrawer, drawerData } = useDrawer();
const { setFieldValue, values } =
useFormikContext<AddRepositoriesFormValues>();

const closeDrawer = () => {
setOpenDrawer(false);
};

const handleSave = (pullRequest: PullRequestPreviewData, _event: any) => {
Object.keys(pullRequest).forEach(pr => {
setFieldValue(
`repositories.${pr}.catalogInfoYaml.prTemplate`,
pullRequest[pr],
);
});
setOpenDrawer(false);
};

return (
<>
<FormControl fullWidth>
<div className={styles.body}>
{error && (
<div style={{ paddingBottom: '10px' }}>
<Alert severity="error">
<AlertTitle>{get(error, 'name') || 'Error occured'}</AlertTitle>
{get(error, 'err') || 'Failed to create pull request'}
</Alert>
</div>
)}
{/*
// Enable this when ServiceNow approval tool is supported
<span className={styles.approvalTool}>
<Typography fontSize="16px" fontWeight="500">
Approval tool
</Typography>
<Tooltip
placement="top"
title="When adding a new repository, it requires approval. Once the PR is approved or the ServiceNow ticket is closed, the repositories will be added to the Catalog page."
>
<span className={styles.approvalToolTooltip}>
<HelpIcon fontSize="small" />
</span>
</Tooltip>
<RadioGroup
id="approval-tool"
data-testid="approval-tool"
row
name="approvalTool"
value={values.approvalTool}
onChange={(_event, value: string) => {
setFieldValue('approvalTool', value);
}}
>
<FormControlLabel value="git" control={<Radio />} label="Git" />
<FormControlLabel
value="servicenow"
control={<Radio />}
label="ServiceNow"
disabled
/>
</RadioGroup>
</span> */}
<AddRepositoriesTable title="Selected repositories" />
</div>
<br />
</FormControl>
<AddRepositoriesFormFooter />
{openDrawer && (
<PreviewFileSidebar
open={openDrawer}
onClose={closeDrawer}
data={drawerData}
repositoryType={values.repositoryType}
handleSave={handleSave}
/>
)}
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const AddRepositoriesDrawer = ({
}: {
open: boolean;
onClose: () => void;
onSelect: (repos: AddedRepositories, drawerOrgName: string) => void;
onSelect: (repos: AddedRepositories) => void;
title: string;
orgData: AddRepositoryData;
}) => {
Expand All @@ -89,7 +89,7 @@ export const AddRepositoriesDrawer = ({
};

const handleSelectRepoFromDrawer = (selected: AddedRepositories) => {
onSelect(selected, orgData?.orgName || '');
onSelect(selected);
const newStatus = { ...(status?.errors || {}) };
Object.keys(newStatus).forEach(s => {
if (!Object.keys(selected).find(sel => sel === s)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,18 @@ import { configApiRef, identityApiRef } from '@backstage/core-plugin-api';
import { MockConfigApi, TestApiProvider } from '@backstage/test-utils';

import { useDrawer } from '@janus-idp/shared-react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { render, screen } from '@testing-library/react';
import { useFormikContext } from 'formik';

import { bulkImportApiRef } from '../../api/BulkImportBackendClient';
import { mockGetImportJobs, mockGetRepositories } from '../../mocks/mockData';
import { ImportJobStatus, RepositorySelection } from '../../types';
import { AddRepositoriesForm } from './AddRepositoriesForm';
import {
ImportJobStatus,
OrgAndRepoResponse,
RepositorySelection,
} from '../../types';
import { AddRepositories } from './AddRepositories';

jest.mock('formik', () => ({
...jest.requireActual('formik'),
Expand Down Expand Up @@ -57,6 +62,16 @@ jest.mock('@material-ui/core', () => ({
},
}));

const createTestQueryClient = () =>
new QueryClient({
defaultOptions: {
queries: {
retry: false, // Disable retries for testing
},
},
});
let queryClient: QueryClient;

class MockBulkImportApi {
async getImportAction(
repo: string,
Expand All @@ -66,6 +81,13 @@ class MockBulkImportApi {
i => i.repository.url === repo,
) as ImportJobStatus;
}
async dataFetcher(
_pageNo: number,
_size: number,
_searchString: string,
): Promise<OrgAndRepoResponse> {
return mockGetRepositories;
}
}

const mockBulkImportApi = new MockBulkImportApi();
Expand All @@ -83,9 +105,10 @@ beforeEach(() => {
},
setFieldValue: jest.fn(),
});
queryClient = createTestQueryClient();
});

describe('AddRepsositoriesForm', () => {
describe('AddRepositoriesForm', () => {
it('should render the repositories list with the footer', async () => {
(useDrawer as jest.Mock).mockImplementation(initial => ({
initial,
Expand All @@ -110,7 +133,9 @@ describe('AddRepsositoriesForm', () => {
],
]}
>
<AddRepositoriesForm error={null} />
<QueryClientProvider client={queryClient}>
<AddRepositories error={null} />
</QueryClientProvider>
</TestApiProvider>
</Router>,
);
Expand Down Expand Up @@ -147,9 +172,9 @@ describe('AddRepsositoriesForm', () => {
],
]}
>
<AddRepositoriesForm
error={{ message: 'error', title: 'error occurred' }}
/>
<QueryClientProvider client={queryClient}>
<AddRepositories error={{ err: 'error occurred' }} />
</QueryClientProvider>
</TestApiProvider>
</Router>,
);
Expand Down
Loading

0 comments on commit 54e98c1

Please sign in to comment.