Merge pull request #8868 from lykkeaxlin/minor-fixes
[Bazaar] Add to marketplace and some minor fixes
This commit is contained in:
@@ -69,21 +69,19 @@ export async function createRouter(
|
||||
}
|
||||
});
|
||||
|
||||
router.get('/projects/id/:id', async (request, response) => {
|
||||
const id = decodeURIComponent(request.params.id);
|
||||
router.get('/projects/:idOrRef', async (request, response) => {
|
||||
const idOrRef = decodeURIComponent(request.params.idOrRef);
|
||||
let data;
|
||||
|
||||
const data = await dbHandler.getMetadataById(parseInt(id, 10));
|
||||
if (/^-?\d+$/.test(idOrRef)) {
|
||||
data = await dbHandler.getMetadataById(parseInt(idOrRef, 10));
|
||||
} else {
|
||||
data = await dbHandler.getMetadataByRef(idOrRef);
|
||||
}
|
||||
|
||||
response.json({ status: 'ok', data: data });
|
||||
});
|
||||
|
||||
router.get('/projects/ref/:ref', async (request, response) => {
|
||||
const ref = decodeURIComponent(request.params.ref);
|
||||
|
||||
const data = await dbHandler.getMetadataByRef(ref);
|
||||
response.json({ status: 'ok', data: data });
|
||||
});
|
||||
|
||||
router.get('/projects', async (_, response) => {
|
||||
const data = await dbHandler.getProjects();
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"clean": "backstage-cli clean"
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/catalog-client": "^0.5.3",
|
||||
"@backstage/catalog-model": "^0.9.7",
|
||||
"@backstage/cli": "^0.10.5",
|
||||
"@backstage/core-components": "^0.8.3",
|
||||
|
||||
+36
-20
@@ -85,9 +85,12 @@ export class BazaarClient implements BazaarApi {
|
||||
async getProjectById(id: number): Promise<any> {
|
||||
const baseUrl = await this.discoveryApi.getBaseUrl('bazaar');
|
||||
|
||||
const response = await fetch(`${baseUrl}/projects/id/${id}`, {
|
||||
method: 'GET',
|
||||
});
|
||||
const response = await fetch(
|
||||
`${baseUrl}/projects/${encodeURIComponent(id)}`,
|
||||
{
|
||||
method: 'GET',
|
||||
},
|
||||
);
|
||||
|
||||
return response.ok ? response : null;
|
||||
}
|
||||
@@ -96,7 +99,7 @@ export class BazaarClient implements BazaarApi {
|
||||
const baseUrl = await this.discoveryApi.getBaseUrl('bazaar');
|
||||
|
||||
const response = await fetch(
|
||||
`${baseUrl}/projects/ref/${encodeURIComponent(entityRef)}`,
|
||||
`${baseUrl}/projects/${encodeURIComponent(entityRef)}`,
|
||||
{
|
||||
method: 'GET',
|
||||
},
|
||||
@@ -108,32 +111,45 @@ export class BazaarClient implements BazaarApi {
|
||||
async getMembers(id: number): Promise<any> {
|
||||
const baseUrl = await this.discoveryApi.getBaseUrl('bazaar');
|
||||
|
||||
return await fetch(`${baseUrl}/projects/${id}/members`, {
|
||||
method: 'GET',
|
||||
}).then(resp => resp.json());
|
||||
return await fetch(
|
||||
`${baseUrl}/projects/${encodeURIComponent(id)}/members`,
|
||||
{
|
||||
method: 'GET',
|
||||
},
|
||||
).then(resp => resp.json());
|
||||
}
|
||||
|
||||
async addMember(id: number, userId: string): Promise<void> {
|
||||
const baseUrl = await this.discoveryApi.getBaseUrl('bazaar');
|
||||
|
||||
await fetch(`${baseUrl}/projects/${id}/member/${userId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
await fetch(
|
||||
`${baseUrl}/projects/${encodeURIComponent(
|
||||
id,
|
||||
)}/member/${encodeURIComponent(userId)}`,
|
||||
{
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
picture: (await this.identityApi.getProfileInfo()).picture,
|
||||
}),
|
||||
},
|
||||
body: JSON.stringify({
|
||||
picture: this.identityApi.getProfile()?.picture,
|
||||
}),
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
async deleteMember(id: number, userId: string): Promise<void> {
|
||||
const baseUrl = await this.discoveryApi.getBaseUrl('bazaar');
|
||||
|
||||
await fetch(`${baseUrl}/projects/${id}/member/${userId}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
await fetch(
|
||||
`${baseUrl}/projects/${encodeURIComponent(
|
||||
id,
|
||||
)}/member/${encodeURIComponent(userId)}`,
|
||||
{
|
||||
method: 'DELETE',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
async getProjects(): Promise<any> {
|
||||
@@ -147,7 +163,7 @@ export class BazaarClient implements BazaarApi {
|
||||
async deleteProject(id: number): Promise<void> {
|
||||
const baseUrl = await this.discoveryApi.getBaseUrl('bazaar');
|
||||
|
||||
await fetch(`${baseUrl}/projects/${id}`, {
|
||||
await fetch(`${baseUrl}/projects/${encodeURIComponent(id)}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Grid, Typography, Link, makeStyles } from '@material-ui/core';
|
||||
import { InfoCard } from '@backstage/core-components';
|
||||
import { Grid, Typography, makeStyles } from '@material-ui/core';
|
||||
import { InfoCard, Link } from '@backstage/core-components';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
subheader: {
|
||||
@@ -39,7 +39,7 @@ export const About = () => {
|
||||
internal projects suitable for{' '}
|
||||
<Link
|
||||
target="_blank"
|
||||
href="https://en.wikipedia.org/wiki/Inner_source"
|
||||
to="https://en.wikipedia.org/wiki/Inner_source"
|
||||
>
|
||||
Inner Sourcing
|
||||
</Link>
|
||||
|
||||
@@ -57,7 +57,10 @@ export const AddProjectDialog = ({
|
||||
setSelectedEntity(entity);
|
||||
};
|
||||
|
||||
const handleSubmit: any = async (
|
||||
const handleSubmit: (
|
||||
getValues: UseFormGetValues<FormValues>,
|
||||
reset: UseFormReset<FormValues>,
|
||||
) => Promise<void> = async (
|
||||
getValues: UseFormGetValues<FormValues>,
|
||||
reset: UseFormReset<FormValues>,
|
||||
) => {
|
||||
|
||||
@@ -21,10 +21,9 @@ import {
|
||||
Card,
|
||||
CardContent,
|
||||
Typography,
|
||||
Link,
|
||||
GridSize,
|
||||
} from '@material-ui/core';
|
||||
import { Avatar } from '@backstage/core-components';
|
||||
import { Avatar, Link } from '@backstage/core-components';
|
||||
import { AboutField } from '@backstage/plugin-catalog';
|
||||
import { StatusTag } from '../StatusTag';
|
||||
import { Member, BazaarProject } from '../../types';
|
||||
@@ -32,6 +31,7 @@ import { Member, BazaarProject } from '../../types';
|
||||
const useStyles = makeStyles({
|
||||
break: {
|
||||
wordBreak: 'break-word',
|
||||
textAlign: 'justify',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -111,7 +111,7 @@ export const CardContentFields = ({
|
||||
/>
|
||||
<Link
|
||||
className={classes.break}
|
||||
href={`http://github.com/${member.userId}`}
|
||||
to={`http://github.com/${member.userId}`}
|
||||
target="_blank"
|
||||
>
|
||||
{member?.userId}
|
||||
|
||||
@@ -36,6 +36,11 @@ const useStyles = makeStyles({
|
||||
marginLeft: '0',
|
||||
marginRight: 'auto',
|
||||
},
|
||||
wordBreak: {
|
||||
wordBreak: 'break-all',
|
||||
whiteSpace: 'normal',
|
||||
margin: '-0.25rem 0',
|
||||
},
|
||||
});
|
||||
|
||||
export const EditProjectDialog = ({
|
||||
@@ -76,9 +81,9 @@ export const EditProjectDialog = ({
|
||||
});
|
||||
}, [bazaarProject]);
|
||||
|
||||
const handleEditSubmit: any = async (
|
||||
const handleEditSubmit: (
|
||||
getValues: UseFormGetValues<FormValues>,
|
||||
) => {
|
||||
) => Promise<void> = async (getValues: UseFormGetValues<FormValues>) => {
|
||||
const formValues = getValues();
|
||||
|
||||
const updateResponse = await bazaarApi.updateProject({
|
||||
@@ -101,7 +106,9 @@ export const EditProjectDialog = ({
|
||||
handleClose={handleDeleteClose}
|
||||
message={[
|
||||
'Are you sure you want to delete ',
|
||||
<b>{bazaarProject.name}</b>,
|
||||
<b key={bazaarProject.name} className={classes.wordBreak}>
|
||||
{bazaarProject.name}
|
||||
</b>,
|
||||
' from the Bazaar?',
|
||||
]}
|
||||
type="delete"
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { CardHeader, Divider, IconButton } from '@material-ui/core';
|
||||
import { CardHeader, Divider, IconButton, makeStyles } from '@material-ui/core';
|
||||
import {
|
||||
HeaderIconLinkRow,
|
||||
IconLinkVerticalProps,
|
||||
@@ -37,6 +37,14 @@ import { ConfirmationDialog } from '../ConfirmationDialog';
|
||||
import { CardContentFields } from '../CardContentFields';
|
||||
import { fetchProjectMembers } from '../../util/fetchMethods';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
wordBreak: {
|
||||
wordBreak: 'break-all',
|
||||
whiteSpace: 'normal',
|
||||
margin: '-0.25rem 0',
|
||||
},
|
||||
});
|
||||
|
||||
type Props = {
|
||||
bazaarProject: BazaarProject | null | undefined;
|
||||
fetchBazaarProject: () => Promise<BazaarProject | null>;
|
||||
@@ -46,6 +54,7 @@ export const EntityBazaarInfoContent = ({
|
||||
bazaarProject,
|
||||
fetchBazaarProject,
|
||||
}: Props) => {
|
||||
const classes = useStyles();
|
||||
const bazaarApi = useApi(bazaarApiRef);
|
||||
const identity = useApi(identityApiRef);
|
||||
const [openEdit, setOpenEdit] = useState(false);
|
||||
@@ -160,9 +169,11 @@ export const EntityBazaarInfoContent = ({
|
||||
handleClose={handleUnlinkClose}
|
||||
message={[
|
||||
'Are you sure you want to unlink ',
|
||||
<b>{parseEntityRef(bazaarProject.entityRef!).name}</b>,
|
||||
<b className={classes.wordBreak}>
|
||||
{parseEntityRef(bazaarProject.entityRef!).name}
|
||||
</b>,
|
||||
' from ',
|
||||
<b>{bazaarProject.name}</b>,
|
||||
<b className={classes.wordBreak}>{bazaarProject.name}</b>,
|
||||
' ?',
|
||||
]}
|
||||
type="unlink"
|
||||
@@ -171,7 +182,7 @@ export const EntityBazaarInfoContent = ({
|
||||
)}
|
||||
|
||||
<CardHeader
|
||||
title={bazaarProject?.name!}
|
||||
title={<p className={classes.wordBreak}>{bazaarProject?.name!}</p>}
|
||||
action={
|
||||
<div>
|
||||
<IconButton
|
||||
|
||||
@@ -15,7 +15,13 @@
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Card, CardHeader, Divider, IconButton } from '@material-ui/core';
|
||||
import {
|
||||
Card,
|
||||
CardHeader,
|
||||
Divider,
|
||||
IconButton,
|
||||
makeStyles,
|
||||
} from '@material-ui/core';
|
||||
import {
|
||||
HeaderIconLinkRow,
|
||||
IconLinkVerticalProps,
|
||||
@@ -37,7 +43,7 @@ import {
|
||||
import { Member, BazaarProject } from '../../types';
|
||||
import { bazaarApiRef } from '../../api';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import useAsyncFn from 'react-use/lib/useAsyncFn';
|
||||
import { useAsyncFn } from 'react-use';
|
||||
import {
|
||||
catalogApiRef,
|
||||
catalogRouteRef,
|
||||
@@ -59,6 +65,14 @@ import {
|
||||
} from '../../util/fetchMethods';
|
||||
import { parseBazaarResponse } from '../../util/parseMethods';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
wordBreak: {
|
||||
wordBreak: 'break-all',
|
||||
whiteSpace: 'normal',
|
||||
margin: '-0.25rem 0',
|
||||
},
|
||||
});
|
||||
|
||||
type Props = {
|
||||
initProject: BazaarProject;
|
||||
handleClose: () => void;
|
||||
@@ -70,6 +84,7 @@ export const HomePageBazaarInfoCard = ({
|
||||
handleClose,
|
||||
initEntity,
|
||||
}: Props) => {
|
||||
const classes = useStyles();
|
||||
const catalogLink = useRouteRef(catalogRouteRef);
|
||||
const bazaarApi = useApi(bazaarApiRef);
|
||||
const identity = useApi(identityApiRef);
|
||||
@@ -222,9 +237,11 @@ export const HomePageBazaarInfoCard = ({
|
||||
handleClose={() => setOpenUnlink(false)}
|
||||
message={[
|
||||
'Are you sure you want to unlink ',
|
||||
<b>{parseEntityRef(bazaarProject.value?.entityRef!).name}</b>,
|
||||
<b className={classes.wordBreak}>
|
||||
{parseEntityRef(bazaarProject.value?.entityRef!).name}
|
||||
</b>,
|
||||
' from ',
|
||||
<b>{bazaarProject.value?.name}</b>,
|
||||
<b className={classes.wordBreak}>{bazaarProject.value?.name}</b>,
|
||||
' ?',
|
||||
]}
|
||||
type="unlink"
|
||||
@@ -242,7 +259,11 @@ export const HomePageBazaarInfoCard = ({
|
||||
/>
|
||||
|
||||
<CardHeader
|
||||
title={bazaarProject.value?.name || initProject.name}
|
||||
title={
|
||||
<p className={classes.wordBreak}>
|
||||
{bazaarProject.value?.name || initProject.name}
|
||||
</p>
|
||||
}
|
||||
action={
|
||||
<div>
|
||||
<IconButton onClick={() => setOpenEdit(true)}>
|
||||
|
||||
@@ -15,13 +15,18 @@
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Controller, Control, FieldError } from 'react-hook-form';
|
||||
import {
|
||||
Controller,
|
||||
Control,
|
||||
FieldError,
|
||||
ValidationRule,
|
||||
} from 'react-hook-form';
|
||||
import { TextField } from '@material-ui/core';
|
||||
import { FormValues } from '../../types';
|
||||
|
||||
type Rules = {
|
||||
required: boolean;
|
||||
pattern?: any;
|
||||
pattern?: ValidationRule<RegExp> | undefined;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
|
||||
@@ -41,12 +41,19 @@ const useStyles = makeStyles({
|
||||
WebkitLineClamp: 7,
|
||||
WebkitBoxOrient: 'vertical',
|
||||
overflow: 'hidden',
|
||||
backgroundColor: '',
|
||||
textAlign: 'justify',
|
||||
},
|
||||
memberCount: {
|
||||
float: 'right',
|
||||
},
|
||||
content: { height: '13rem', marginBottom: '-0.5rem' },
|
||||
content: {
|
||||
height: '13rem',
|
||||
},
|
||||
header: {
|
||||
whiteSpace: 'nowrap',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
},
|
||||
});
|
||||
|
||||
type Props = {
|
||||
@@ -82,7 +89,12 @@ export const ProjectCard = ({
|
||||
<Card key={id}>
|
||||
<CardActionArea onClick={() => setOpenCard(true)}>
|
||||
<ItemCardHeader
|
||||
title={name}
|
||||
classes={{ root: classes.header }}
|
||||
title={
|
||||
<Typography noWrap variant="h6" component="h4">
|
||||
{name}
|
||||
</Typography>
|
||||
}
|
||||
subtitle={`updated ${DateTime.fromISO(
|
||||
new Date(updatedAt!).toISOString(),
|
||||
).toRelative({
|
||||
|
||||
@@ -16,12 +16,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import { Button, Dialog } from '@material-ui/core';
|
||||
import {
|
||||
useForm,
|
||||
SubmitHandler,
|
||||
UseFormReset,
|
||||
UseFormGetValues,
|
||||
} from 'react-hook-form';
|
||||
import { useForm, UseFormReset, UseFormGetValues } from 'react-hook-form';
|
||||
import { InputField } from '../InputField/InputField';
|
||||
import { InputSelector } from '../InputSelector/InputSelector';
|
||||
import { FormValues } from '../../types';
|
||||
@@ -36,7 +31,7 @@ type Props = {
|
||||
handleSave: (
|
||||
getValues: UseFormGetValues<FormValues>,
|
||||
reset: UseFormReset<FormValues>,
|
||||
) => SubmitHandler<FormValues>;
|
||||
) => Promise<void>;
|
||||
isAddForm: boolean;
|
||||
title: string;
|
||||
defaultValues: FormValues;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import React, { ChangeEvent, ReactNode } from 'react';
|
||||
import { FormControl, MenuItem, Select, makeStyles } from '@material-ui/core';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
@@ -27,7 +27,12 @@ const useStyles = makeStyles({
|
||||
|
||||
type Props = {
|
||||
sortMethodNbr: number;
|
||||
handleSortMethodChange: any;
|
||||
handleSortMethodChange:
|
||||
| ((
|
||||
event: ChangeEvent<{ name?: string | undefined; value: unknown }>,
|
||||
child: ReactNode,
|
||||
) => void)
|
||||
| undefined;
|
||||
};
|
||||
|
||||
export const SortMethodSelector = ({
|
||||
|
||||
@@ -33,7 +33,7 @@ import { fetchCatalogItems } from '../../util/fetchMethods';
|
||||
import { parseBazaarProject } from '../../util/parseMethods';
|
||||
|
||||
const useStyles = makeStyles({
|
||||
button: { width: '12rem' },
|
||||
button: { minWidth: '11rem' },
|
||||
container: {
|
||||
marginTop: '2rem',
|
||||
},
|
||||
@@ -141,7 +141,9 @@ export const SortView = () => {
|
||||
}
|
||||
}, [bazaarProjects, catalogEntities]);
|
||||
|
||||
const handleSortMethodChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
const handleSortMethodChange = (
|
||||
event: ChangeEvent<{ name?: string | undefined; value: unknown }>,
|
||||
) => {
|
||||
setSortMethodNbr(
|
||||
typeof event.target.value === 'number' ? event.target.value : 0,
|
||||
);
|
||||
|
||||
@@ -19,6 +19,7 @@ import { parseMember } from './parseMethods';
|
||||
import { BazaarProject, Member } from '../types';
|
||||
import { BazaarApi } from '../api';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { CatalogApi } from '@backstage/plugin-catalog-react';
|
||||
|
||||
export const fetchProjectMembers = async (
|
||||
bazaarApi: BazaarApi,
|
||||
@@ -37,7 +38,9 @@ export const fetchProjectMembers = async (
|
||||
return [];
|
||||
};
|
||||
|
||||
export const fetchCatalogItems = async (catalogApi: any): Promise<Entity[]> => {
|
||||
export const fetchCatalogItems = async (
|
||||
catalogApi: CatalogApi,
|
||||
): Promise<Entity[]> => {
|
||||
const entities = await catalogApi.getEntities({
|
||||
filter: {
|
||||
kind: ['Component', 'Resource'],
|
||||
|
||||
Reference in New Issue
Block a user