feat: add readme card plugin on azure devops
Signed-off-by: Alisson Fabiano <afabiano@eshopworld.com>
This commit is contained in:
@@ -21,6 +21,8 @@ import {
|
||||
GitTag,
|
||||
PullRequest,
|
||||
PullRequestOptions,
|
||||
Readme,
|
||||
ReadmeConfig,
|
||||
RepoBuild,
|
||||
RepoBuildOptions,
|
||||
Team,
|
||||
@@ -64,4 +66,6 @@ export interface AzureDevOpsApi {
|
||||
definitionName?: string,
|
||||
options?: BuildRunOptions,
|
||||
): Promise<{ items: BuildRun[] }>;
|
||||
|
||||
getReadme(opts: ReadmeConfig): Promise<Readme | undefined>;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ import {
|
||||
GitTag,
|
||||
PullRequest,
|
||||
PullRequestOptions,
|
||||
Readme,
|
||||
ReadmeConfig,
|
||||
RepoBuild,
|
||||
RepoBuildOptions,
|
||||
Team,
|
||||
@@ -30,6 +32,10 @@ import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api';
|
||||
import { AzureDevOpsApi } from './AzureDevOpsApi';
|
||||
import { ResponseError } from '@backstage/errors';
|
||||
|
||||
function isNotFoundError(error: any): error is ResponseError {
|
||||
return error.response.status === 404;
|
||||
}
|
||||
|
||||
export class AzureDevOpsClient implements AzureDevOpsApi {
|
||||
private readonly discoveryApi: DiscoveryApi;
|
||||
private readonly identityApi: IdentityApi;
|
||||
@@ -130,6 +136,23 @@ export class AzureDevOpsClient implements AzureDevOpsApi {
|
||||
return { items };
|
||||
}
|
||||
|
||||
public getReadme = async (
|
||||
opts: ReadmeConfig,
|
||||
): Promise<Readme | undefined> => {
|
||||
try {
|
||||
return await this.get(
|
||||
`readme/${encodeURIComponent(opts.project)}/${encodeURIComponent(
|
||||
opts.repo,
|
||||
)}`,
|
||||
);
|
||||
} catch (e) {
|
||||
if (isNotFoundError(e)) {
|
||||
return undefined;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
};
|
||||
|
||||
private async get<T>(path: string): Promise<T> {
|
||||
const baseUrl = `${await this.discoveryApi.getBaseUrl('azure-devops')}/`;
|
||||
const url = new URL(path, baseUrl);
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2022 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 { Button, makeStyles } from '@material-ui/core';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import {
|
||||
InfoCard,
|
||||
Progress,
|
||||
MarkdownContent,
|
||||
EmptyState,
|
||||
} from '@backstage/core-components';
|
||||
import { useEntity } from '@backstage/plugin-catalog-react';
|
||||
import { useProjectRepoFromEntity } from '../../hooks';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
import React from 'react';
|
||||
import { azureDevOpsApiRef } from '../../api';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
infoCard: {
|
||||
marginBottom: theme.spacing(3),
|
||||
'& + .MuiAlert-root': {
|
||||
marginTop: theme.spacing(3),
|
||||
},
|
||||
'& .MuiCardContent-root': {
|
||||
padding: theme.spacing(2, 1, 2, 2),
|
||||
},
|
||||
},
|
||||
readMe: {
|
||||
overflowY: 'auto',
|
||||
paddingRight: theme.spacing(1),
|
||||
'&::-webkit-scrollbar-track': {
|
||||
backgroundColor: '#F5F5F5',
|
||||
borderRadius: '5px',
|
||||
},
|
||||
'&::-webkit-scrollbar': {
|
||||
width: '5px',
|
||||
backgroundColor: '#F5F5F5',
|
||||
borderRadius: '5px',
|
||||
},
|
||||
'&::-webkit-scrollbar-thumb': {
|
||||
border: '1px solid #555555',
|
||||
backgroundColor: '#555',
|
||||
borderRadius: '4px',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
type Props = {
|
||||
maxHeight?: number;
|
||||
};
|
||||
|
||||
export const ReadMeCard = (props: Props) => {
|
||||
const classes = useStyles();
|
||||
const api = useApi(azureDevOpsApiRef);
|
||||
const { entity } = useEntity();
|
||||
const { project, repo } = useProjectRepoFromEntity(entity);
|
||||
|
||||
const { loading, error, value } = useAsync(
|
||||
() =>
|
||||
api.getReadme({
|
||||
project,
|
||||
repo,
|
||||
}),
|
||||
[api, project, repo, entity],
|
||||
);
|
||||
|
||||
if (loading) {
|
||||
return <Progress />;
|
||||
} else if (error) {
|
||||
return (
|
||||
<Alert severity="error" className={classes.infoCard}>
|
||||
{error.message}
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
if (!value)
|
||||
return (
|
||||
<EmptyState
|
||||
title="No README available for this entity"
|
||||
missing="field"
|
||||
description="You can add a README to your entity by following the Azure DevOps documentation."
|
||||
action={
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
href="https://docs.microsoft.com/en-us/azure/devops/repos/git/create-a-readme?view=azure-devops"
|
||||
>
|
||||
Read more
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<InfoCard
|
||||
title="Readme"
|
||||
className={classes.infoCard}
|
||||
deepLink={{
|
||||
link: value!.url,
|
||||
title: 'Readme',
|
||||
onClick: e => {
|
||||
e.preventDefault();
|
||||
window.open(value?.url);
|
||||
},
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className={classes.readMe}
|
||||
style={{
|
||||
maxHeight: `${props.maxHeight}px`,
|
||||
}}
|
||||
>
|
||||
<MarkdownContent content={value?.content ?? ''} />
|
||||
</div>
|
||||
</InfoCard>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2022 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.
|
||||
*/
|
||||
|
||||
export { ReadMeCard } from './ReadMeCard';
|
||||
@@ -19,6 +19,7 @@ export {
|
||||
EntityAzurePipelinesContent,
|
||||
EntityAzureGitTagsContent,
|
||||
EntityAzurePullRequestsContent,
|
||||
EntityAzureReadMeContent,
|
||||
isAzureDevOpsAvailable,
|
||||
isAzurePipelinesAvailable,
|
||||
AzurePullRequestsPage,
|
||||
|
||||
Reference in New Issue
Block a user