+
+
-
- -
-
-
diff --git a/plugins/bazaar/src/components/EditProjectDialog/EditProjectDialog.tsx b/plugins/bazaar/src/components/EditProjectDialog/EditProjectDialog.tsx
index 41c9e474d4..31865db767 100644
--- a/plugins/bazaar/src/components/EditProjectDialog/EditProjectDialog.tsx
+++ b/plugins/bazaar/src/components/EditProjectDialog/EditProjectDialog.tsx
@@ -15,81 +15,121 @@
*/
import React, { useState, useEffect } from 'react';
-import { Entity, stringifyEntityRef } from '@backstage/catalog-model';
import { useApi } from '@backstage/core-plugin-api';
import { ProjectDialog } from '../ProjectDialog';
-import { BazaarProject, FormValues, Size, Status } from '../../types';
+import { BazaarProject, FormValues } from '../../types';
import { bazaarApiRef } from '../../api';
import { UseFormGetValues } from 'react-hook-form';
+import { ConfirmationDialog } from '../ConfirmationDialog';
+import { Button, makeStyles } from '@material-ui/core';
type Props = {
- entity: Entity;
bazaarProject: BazaarProject;
+ openEdit: boolean;
+ handleEditClose: () => void;
+ handleCardClose?: () => void;
fetchBazaarProject: () => Promise
;
- open: boolean;
- handleClose: () => void;
- isAddForm: boolean;
+ fetchBazaarProjects?: () => void;
};
+const useStyles = makeStyles({
+ button: {
+ marginLeft: '0',
+ marginRight: 'auto',
+ },
+});
+
export const EditProjectDialog = ({
- entity,
bazaarProject,
+ openEdit,
+ handleEditClose,
+ handleCardClose,
fetchBazaarProject,
- open,
- handleClose,
+ fetchBazaarProjects,
}: Props) => {
+ const classes = useStyles();
+ const bazaarApi = useApi(bazaarApiRef);
+ const [openDelete, setOpenDelete] = useState(false);
const [defaultValues, setDefaultValues] = useState({
- announcement: bazaarProject.announcement,
- community: bazaarProject.community,
- status: bazaarProject.status,
- size: bazaarProject.size,
- startDate: bazaarProject?.startDate ?? null,
- endDate: bazaarProject?.endDate ?? null,
- responsible: bazaarProject.responsible,
+ ...bazaarProject,
+ startDate: bazaarProject.startDate ?? null,
+ endDate: bazaarProject.endDate ?? null,
});
- const bazaarApi = useApi(bazaarApiRef);
+ const handleDeleteClose = () => {
+ setOpenDelete(false);
+ handleEditClose();
+
+ if (handleCardClose) handleCardClose();
+ };
+
+ const handleDeleteSubmit = async () => {
+ await bazaarApi.deleteProject(bazaarProject.id);
+
+ handleDeleteClose();
+ if (fetchBazaarProjects) fetchBazaarProjects();
+ };
useEffect(() => {
setDefaultValues({
- announcement: bazaarProject.announcement,
- community: bazaarProject.community,
- status: bazaarProject.status,
- size: bazaarProject.size,
- startDate: bazaarProject?.startDate ?? null,
- endDate: bazaarProject?.endDate ?? null,
- responsible: bazaarProject.responsible,
+ ...bazaarProject,
+ startDate: bazaarProject.startDate ?? null,
+ endDate: bazaarProject.endDate ?? null,
});
}, [bazaarProject]);
- const handleSave: any = async (getValues: UseFormGetValues) => {
+ const handleEditSubmit: any = async (
+ getValues: UseFormGetValues,
+ ) => {
const formValues = getValues();
- const updateResponse = await bazaarApi.updateMetadata({
- name: entity.metadata.name,
- entityRef: stringifyEntityRef(entity),
- announcement: formValues.announcement,
- status: formValues.status as Status,
- community: formValues.community,
+ const updateResponse = await bazaarApi.updateProject({
+ ...formValues,
+ id: bazaarProject.id,
+ entityRef: bazaarProject.entityRef,
membersCount: bazaarProject.membersCount,
- size: formValues.size as Size,
startDate: formValues?.startDate ?? null,
endDate: formValues?.endDate ?? null,
- responsible: formValues.responsible,
});
if (updateResponse.status === 'ok') fetchBazaarProject();
- handleClose();
+ handleEditClose();
};
return (
-
+
+
{bazaarProject.name},
+ ' from the Bazaar?',
+ ]}
+ type="delete"
+ handleSubmit={handleDeleteSubmit}
+ />
+
+ {
+ setOpenDelete(true);
+ }}
+ >
+ Delete project
+
+ }
+ />
+
);
};
diff --git a/plugins/bazaar/src/components/EntityBazaarInfoCard/EntityBazaarInfoCard.tsx b/plugins/bazaar/src/components/EntityBazaarInfoCard/EntityBazaarInfoCard.tsx
index acae8f5342..685d400d3e 100644
--- a/plugins/bazaar/src/components/EntityBazaarInfoCard/EntityBazaarInfoCard.tsx
+++ b/plugins/bazaar/src/components/EntityBazaarInfoCard/EntityBazaarInfoCard.tsx
@@ -15,347 +15,48 @@
*/
import React, { useState, useEffect } from 'react';
-import {
- Grid,
- makeStyles,
- Card,
- CardContent,
- CardHeader,
- Typography,
- Divider,
- IconButton,
- Popover,
- MenuList,
- MenuItem,
- ListItemText,
- Link,
-} from '@material-ui/core';
-import {
- Progress,
- HeaderIconLinkRow,
- IconLinkVerticalProps,
- Avatar,
-} from '@backstage/core-components';
-import { useEntity } from '@backstage/plugin-catalog-react';
-import { AboutField } from '@backstage/plugin-catalog';
-import { StatusTag } from '../StatusTag';
-import EditIcon from '@material-ui/icons/Edit';
-import ChatIcon from '@material-ui/icons/Chat';
-import PersonAddIcon from '@material-ui/icons/PersonAdd';
-import MoreVertIcon from '@material-ui/icons/MoreVert';
-import DeleteIcon from '@material-ui/icons/Delete';
-import { EditProjectDialog } from '../EditProjectDialog';
-import { DeleteProjectDialog } from '../DeleteProjectDialog';
-import ExitToAppIcon from '@material-ui/icons/ExitToApp';
-import { useApi, identityApiRef } from '@backstage/core-plugin-api';
-import { Member, BazaarProject } from '../../types';
-import { bazaarApiRef } from '../../api';
-import { Alert } from '@material-ui/lab';
import { useAsyncFn } from 'react-use';
-
-const useStyles = makeStyles({
- description: {
- wordBreak: 'break-word',
- },
- icon: {
- marginRight: '1.75rem',
- },
- link: {
- color: '#9cc9ff',
- '&:hover': {
- textDecoration: 'underline',
- },
- },
- memberLink: {
- display: 'block',
- marginBottom: '0.3rem',
- },
-});
-
-const sortMembers = (m1: Member, m2: Member) => {
- return new Date(m2.joinDate!).getTime() - new Date(m1.joinDate!).getTime();
-};
+import { useApi } from '@backstage/core-plugin-api';
+import { stringifyEntityRef } from '@backstage/catalog-model';
+import { useEntity } from '@backstage/plugin-catalog-react';
+import { bazaarApiRef } from '../../api';
+import { EntityBazaarInfoContent } from '../EntityBazaarInfoContent';
+import { Card } from '@material-ui/core';
+import { parseBazaarResponse } from '../../util/parseMethods';
export const EntityBazaarInfoCard = () => {
const { entity } = useEntity();
- const classes = useStyles();
const bazaarApi = useApi(bazaarApiRef);
- const identity = useApi(identityApiRef);
- const [anchorEl, setAnchorEl] = useState();
- const [open, setOpen] = useState(false);
- const [popoverOpen, setPopoverOpen] = useState(false);
- const [openDelete, setOpenDelete] = useState(false);
- const [isMember, setIsMember] = useState(false);
- const [isBazaar, setIsBazaar] = useState(false);
- const [members, fetchMembers] = useAsyncFn(async () => {
- const response = await bazaarApi.getMembers(entity);
-
- const dbMembers = response.data.map((obj: any) => {
- const member: Member = {
- userId: obj.user_id,
- entityRef: obj.entity_ref,
- joinDate: obj.join_date,
- picture: obj.picture,
- };
-
- return member;
- });
-
- dbMembers.sort(sortMembers);
-
- return dbMembers;
- });
const [bazaarProject, fetchBazaarProject] = useAsyncFn(async () => {
- const response = await bazaarApi.getMetadata(entity);
+ const response = await bazaarApi.getProjectByRef(
+ stringifyEntityRef(entity),
+ );
- if (response) {
- const metadata = await response.json().then((resp: any) => resp.data[0]);
-
- if (metadata) {
- return {
- entityRef: metadata.entity_ref,
- name: metadata.name,
- community: metadata.community,
- announcement: metadata.announcement,
- status: metadata.status,
- updatedAt: metadata.updated_at,
- membersCount: metadata.members_count,
- size: metadata.size,
- startDate: metadata.start_date,
- endDate: metadata.end_date,
- responsible: metadata.responsible,
- } as BazaarProject;
- }
- }
- return null;
+ return await parseBazaarResponse(response);
});
+ const [isBazaar, setIsBazaar] = useState(bazaarProject.value ?? false);
+
useEffect(() => {
- fetchMembers();
fetchBazaarProject();
- }, [fetchMembers, fetchBazaarProject]);
+ }, [fetchBazaarProject]);
useEffect(() => {
- const isBazaarMember =
- members?.value
- ?.map((member: Member) => member.userId)
- .indexOf(identity.getUserId()) >= 0;
- const isBazaarProject = bazaarProject.value !== null;
+ const isBazaarProject = bazaarProject.value !== undefined;
- setIsMember(isBazaarMember);
setIsBazaar(isBazaarProject);
- }, [bazaarProject, members, identity]);
+ }, [bazaarProject.value]);
- const onOpen = (event: React.SyntheticEvent) => {
- setAnchorEl(event.currentTarget);
- setPopoverOpen(true);
- };
-
- const closeEdit = () => {
- setOpen(false);
- };
-
- const closeDelete = () => {
- setOpenDelete(false);
- };
-
- const popoverCloseHandler = () => {
- setPopoverOpen(false);
- };
-
- const handleMembersClick = async () => {
- if (!isMember) {
- await bazaarApi.addMember(entity);
- } else {
- await bazaarApi.deleteMember(entity);
- }
-
- fetchMembers();
- fetchBazaarProject();
- };
-
- const links: IconLinkVerticalProps[] = [
- {
- label: isMember ? 'Leave' : 'Join',
- icon: isMember ? : ,
- href: '',
- onClick: async () => {
- handleMembersClick();
- },
- },
- {
- label: 'Community',
- icon: ,
- href: bazaarProject?.value?.community,
- disabled: !bazaarProject?.value?.community || !isMember,
- },
- ];
-
- if (!isBazaar) {
- return null;
- } else if (bazaarProject.loading || members.loading) {
- return ;
- } else if (bazaarProject.error) {
- return {bazaarProject?.error?.message} ;
- } else if (members.error) {
- return {members?.error?.message} ;
- }
- return (
-
- {bazaarProject?.value && (
-
+
- )}
-
- {bazaarProject?.value && (
-
- )}
-
-
-
- }
- subheader={ }
- />
-
-
-
-
- {
- setOpen(true);
- setPopoverOpen(false);
- }}
- >
-
-
-
-
- {
- setOpenDelete(true);
- setPopoverOpen(false);
- }}
- >
-
-
-
-
-
-
-
-
- {bazaarProject?.value?.announcement
- ? bazaarProject?.value?.announcement
- .split('\n')
- .map((str: string, i: number) => (
-
- {str}
-
- ))
- : 'No announcement'}
-
-
-
-
- {' '}
-
- {members?.value?.length ? (
- members.value.slice(0, 7).map((member: Member) => {
- return (
-
-
-
- {member?.userId}
-
-
- );
- })
- ) : (
-
- )}
-
-
-
-
-
-
-
-
-
-
-
-
- {bazaarProject?.value?.size}
-
-
-
-
-
-
-
- {bazaarProject?.value?.startDate?.substring(0, 10) || ''}
-
-
-
-
-
-
-
- {bazaarProject?.value?.endDate?.substring(0, 10) || ''}
-
-
-
-
-
-
-
- {bazaarProject?.value?.responsible || ''}
-
-
-
-
-
-
- );
+
+ );
+ }
+ return null;
};
diff --git a/plugins/bazaar/src/components/EntityBazaarInfoContent/EntityBazaarInfoContent.tsx b/plugins/bazaar/src/components/EntityBazaarInfoContent/EntityBazaarInfoContent.tsx
new file mode 100644
index 0000000000..1a4754ea70
--- /dev/null
+++ b/plugins/bazaar/src/components/EntityBazaarInfoContent/EntityBazaarInfoContent.tsx
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2021 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, { useState, useEffect } from 'react';
+import { CardHeader, Divider, IconButton } from '@material-ui/core';
+import {
+ HeaderIconLinkRow,
+ IconLinkVerticalProps,
+} from '@backstage/core-components';
+import EditIcon from '@material-ui/icons/Edit';
+import ChatIcon from '@material-ui/icons/Chat';
+import PersonAddIcon from '@material-ui/icons/PersonAdd';
+import DashboardIcon from '@material-ui/icons/Dashboard';
+import LinkOffIcon from '@material-ui/icons/LinkOff';
+import { EditProjectDialog } from '../EditProjectDialog';
+import { useApi, identityApiRef } from '@backstage/core-plugin-api';
+import { BazaarProject, Member } from '../../types';
+import { bazaarApiRef } from '../../api';
+import { Alert } from '@material-ui/lab';
+import { useAsyncFn } from 'react-use';
+import ExitToAppIcon from '@material-ui/icons/ExitToApp';
+import { parseEntityRef } from '@backstage/catalog-model';
+import { ConfirmationDialog } from '../ConfirmationDialog';
+import { CardContentFields } from '../CardContentFields';
+import { fetchProjectMembers } from '../../util/fetchMethods';
+
+type Props = {
+ bazaarProject: BazaarProject | null | undefined;
+ fetchBazaarProject: () => Promise;
+};
+
+export const EntityBazaarInfoContent = ({
+ bazaarProject,
+ fetchBazaarProject,
+}: Props) => {
+ const bazaarApi = useApi(bazaarApiRef);
+ const identity = useApi(identityApiRef);
+ const [openEdit, setOpenEdit] = useState(false);
+ const [isMember, setIsMember] = useState(false);
+ const [openUnlink, setOpenUnlink] = useState(false);
+ const [members, fetchMembers] = useAsyncFn(async () => {
+ return bazaarProject
+ ? await fetchProjectMembers(bazaarApi, bazaarProject)
+ : [];
+ });
+
+ useEffect(() => {
+ fetchMembers();
+ }, [fetchMembers]);
+
+ useEffect(() => {
+ if (members.value) {
+ const isBazaarMember =
+ members.value
+ ?.map((member: Member) => member.userId)
+ .indexOf(identity.getUserId()) >= 0;
+
+ setIsMember(isBazaarMember);
+ }
+ }, [bazaarProject, members, identity]);
+
+ const handleMembersClick = async () => {
+ if (!isMember) {
+ await bazaarApi.addMember(bazaarProject?.id!, identity.getUserId());
+ } else {
+ await bazaarApi.deleteMember(bazaarProject!.id, identity.getUserId());
+ }
+ setIsMember(!isMember);
+ fetchMembers();
+ };
+
+ const links: IconLinkVerticalProps[] = [
+ {
+ label: 'Entity page',
+ icon: ,
+ disabled: true,
+ },
+ {
+ label: 'Unlink project',
+ icon: ,
+ disabled: false,
+ onClick: () => {
+ setOpenUnlink(true);
+ },
+ },
+ {
+ label: isMember ? 'Leave' : 'Join',
+ icon: isMember ? : ,
+ href: '',
+ onClick: async () => {
+ handleMembersClick();
+ },
+ },
+ {
+ label: 'Community',
+ icon: ,
+ href: bazaarProject?.community,
+ disabled: bazaarProject?.community === '' || !isMember,
+ },
+ ];
+
+ const handleEditClose = () => {
+ setOpenEdit(false);
+ };
+
+ const handleUnlinkClose = () => {
+ setOpenUnlink(false);
+ };
+
+ const handleUnlinkSubmit = async () => {
+ const updateResponse = await bazaarApi.updateProject({
+ ...bazaarProject,
+ entityRef: null,
+ });
+
+ if (updateResponse.status === 'ok') {
+ handleUnlinkClose();
+ fetchBazaarProject();
+ }
+ };
+
+ if (members.error) {
+ return {members?.error?.message} ;
+ }
+
+ if (bazaarProject) {
+ return (
+
+
+
+ {openUnlink && (
+ {parseEntityRef(bazaarProject.entityRef!).name},
+ ' from ',
+ {bazaarProject.name} ,
+ ' ?',
+ ]}
+ type="unlink"
+ handleSubmit={handleUnlinkSubmit}
+ />
+ )}
+
+
+ {
+ setOpenEdit(true);
+ }}
+ >
+
+
+
+ }
+ subheader={ }
+ />
+
+
+
+
+ );
+ }
+ return null;
+};
diff --git a/plugins/bazaar/src/components/EntityBazaarInfoContent/index.ts b/plugins/bazaar/src/components/EntityBazaarInfoContent/index.ts
new file mode 100644
index 0000000000..6be5ad7dbf
--- /dev/null
+++ b/plugins/bazaar/src/components/EntityBazaarInfoContent/index.ts
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2021 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 { EntityBazaarInfoContent } from './EntityBazaarInfoContent';
diff --git a/plugins/bazaar/src/components/HomePage/HomePage.tsx b/plugins/bazaar/src/components/HomePage/HomePage.tsx
index 32a16291fc..b34b7ac949 100644
--- a/plugins/bazaar/src/components/HomePage/HomePage.tsx
+++ b/plugins/bazaar/src/components/HomePage/HomePage.tsx
@@ -36,11 +36,7 @@ export const HomePage = () => {
return (
-
+
);
diff --git a/plugins/bazaar/src/components/HomePageBazaarInfoCard/HomePageBazaarInfoCard.tsx b/plugins/bazaar/src/components/HomePageBazaarInfoCard/HomePageBazaarInfoCard.tsx
new file mode 100644
index 0000000000..2d2a37f217
--- /dev/null
+++ b/plugins/bazaar/src/components/HomePageBazaarInfoCard/HomePageBazaarInfoCard.tsx
@@ -0,0 +1,267 @@
+/*
+ * Copyright 2021 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, { useState, useEffect } from 'react';
+import { Card, CardHeader, Divider, IconButton } from '@material-ui/core';
+import {
+ HeaderIconLinkRow,
+ IconLinkVerticalProps,
+} from '@backstage/core-components';
+import EditIcon from '@material-ui/icons/Edit';
+import ChatIcon from '@material-ui/icons/Chat';
+import PersonAddIcon from '@material-ui/icons/PersonAdd';
+import InsertLinkIcon from '@material-ui/icons/InsertLink';
+import DashboardIcon from '@material-ui/icons/Dashboard';
+import CloseIcon from '@material-ui/icons/Close';
+import LinkOffIcon from '@material-ui/icons/LinkOff';
+import { EditProjectDialog } from '../EditProjectDialog';
+import ExitToAppIcon from '@material-ui/icons/ExitToApp';
+import {
+ useApi,
+ identityApiRef,
+ useRouteRef,
+} from '@backstage/core-plugin-api';
+import { Member, BazaarProject } from '../../types';
+import { bazaarApiRef } from '../../api';
+import { Alert } from '@material-ui/lab';
+import { useAsyncFn } from 'react-use';
+import {
+ catalogApiRef,
+ catalogRouteRef,
+} from '@backstage/plugin-catalog-react';
+
+import {
+ parseEntityName,
+ stringifyEntityRef,
+ Entity,
+ parseEntityRef,
+} from '@backstage/catalog-model';
+
+import { ConfirmationDialog } from '../ConfirmationDialog/ConfirmationDialog';
+import { CardContentFields } from '../CardContentFields/CardContentFields';
+
+import { LinkProjectDialog } from '../LinkProjectDialog';
+import {
+ fetchCatalogItems,
+ fetchProjectMembers,
+} from '../../util/fetchMethods';
+import { parseBazaarResponse } from '../../util/parseMethods';
+
+type Props = {
+ initProject: BazaarProject;
+ fetchBazaarProjects: () => Promise
;
+ handleClose: () => void;
+ initEntity: Entity;
+};
+
+export const HomePageBazaarInfoCard = ({
+ initProject,
+ fetchBazaarProjects,
+ handleClose,
+ initEntity,
+}: Props) => {
+ const catalogLink = useRouteRef(catalogRouteRef);
+ const bazaarApi = useApi(bazaarApiRef);
+ const identity = useApi(identityApiRef);
+ const catalogApi = useApi(catalogApiRef);
+ const [openEdit, setOpenEdit] = useState(false);
+ const [openProjectSelector, setOpenProjectSelector] = useState(false);
+ const [openUnlink, setOpenUnlink] = useState(false);
+ const [isMember, setIsMember] = useState(false);
+
+ const [catalogEntities, fetchCatalogEntities] = useAsyncFn(async () => {
+ const entities = await fetchCatalogItems(catalogApi);
+ const bazaarProjects = await bazaarApi.getProjects();
+ const bazaarLinkedRefs: string[] = bazaarProjects.data
+ .filter((entity: any) => entity.entity_ref !== null)
+ .map((entity: any) => entity.entity_ref);
+
+ return entities.filter(
+ (entity: Entity) =>
+ !bazaarLinkedRefs.includes(stringifyEntityRef(entity)),
+ );
+ });
+
+ const [bazaarProject, fetchBazaarProject] = useAsyncFn(async () => {
+ const response = await bazaarApi.getProjectById(initProject.id);
+ return await parseBazaarResponse(response);
+ });
+
+ const [members, fetchMembers] = useAsyncFn(async () => {
+ return fetchProjectMembers(bazaarApi, bazaarProject.value ?? initProject);
+ });
+
+ useEffect(() => {
+ fetchMembers();
+ fetchBazaarProject();
+ fetchCatalogEntities();
+ }, [fetchMembers, fetchBazaarProject, fetchCatalogEntities]);
+
+ useEffect(() => {
+ if (members.value) {
+ const isBazaarMember =
+ members?.value
+ ?.map((member: Member) => member.userId)
+ .indexOf(identity.getUserId()) >= 0;
+ setIsMember(isBazaarMember);
+ }
+ }, [bazaarProject.value, members, identity]);
+
+ const handleMembersClick = async () => {
+ if (!isMember) {
+ await bazaarApi.addMember(bazaarProject.value!.id, identity.getUserId());
+ } else {
+ await bazaarApi.deleteMember(
+ bazaarProject.value!.id,
+ identity.getUserId(),
+ );
+ }
+ setIsMember(!isMember);
+ fetchMembers();
+ };
+
+ const getEntityPageLink = () => {
+ if (bazaarProject?.value?.entityRef) {
+ const { name, kind, namespace } = parseEntityName(
+ bazaarProject.value.entityRef,
+ );
+ return `${catalogLink()}/${namespace}/${kind}/${name}`;
+ }
+ return '';
+ };
+
+ const handleLink = () => {
+ if (bazaarProject.value?.entityRef) {
+ setOpenUnlink(true);
+ } else {
+ fetchCatalogEntities();
+ setOpenProjectSelector(true);
+ }
+ };
+
+ const links: IconLinkVerticalProps[] = [
+ {
+ label: 'Entity page',
+ icon: ,
+ href: bazaarProject.value?.entityRef ? getEntityPageLink() : '',
+ disabled: bazaarProject.value?.entityRef === null,
+ },
+ {
+ label: bazaarProject.value?.entityRef ? 'Unlink project' : 'Link project',
+ icon: bazaarProject.value?.entityRef ? (
+
+ ) : (
+
+ ),
+ onClick: handleLink,
+ },
+ {
+ label: isMember ? 'Leave' : 'Join',
+ icon: isMember ? : ,
+ href: '',
+ onClick: async () => {
+ handleMembersClick();
+ },
+ },
+ {
+ label: 'Community',
+ icon: ,
+ href: bazaarProject.value?.community,
+ disabled: !bazaarProject.value?.community || !isMember,
+ },
+ ];
+
+ const handleUnlinkSubmit = async () => {
+ const updateResponse = await bazaarApi.updateProject({
+ ...bazaarProject.value,
+ entityRef: null,
+ });
+
+ if (updateResponse.status === 'ok') {
+ setOpenUnlink(false);
+ fetchBazaarProject();
+ }
+ };
+
+ if (bazaarProject.error) {
+ return {bazaarProject?.error?.message} ;
+ } else if (members.error) {
+ return {members?.error?.message} ;
+ }
+
+ return (
+
+ setOpenProjectSelector(false)}
+ catalogEntities={catalogEntities.value || []}
+ bazaarProject={bazaarProject.value || initProject}
+ fetchBazaarProject={fetchBazaarProject}
+ initEntity={initEntity}
+ />
+
+ {openUnlink && (
+ setOpenUnlink(false)}
+ message={[
+ 'Are you sure you want to unlink ',
+ {parseEntityRef(bazaarProject.value?.entityRef!).name} ,
+ ' from ',
+ {bazaarProject.value?.name} ,
+ ' ?',
+ ]}
+ type="unlink"
+ handleSubmit={handleUnlinkSubmit}
+ />
+ )}
+
+
+ setOpenEdit(false)}
+ handleCardClose={handleClose}
+ fetchBazaarProject={fetchBazaarProject}
+ fetchBazaarProjects={fetchBazaarProjects}
+ />
+
+
+ setOpenEdit(true)}>
+
+
+
+
+
+
+ }
+ subheader={ }
+ />
+
+
+
+
+
+ );
+};
diff --git a/plugins/bazaar/src/components/HomePageBazaarInfoCard/index.ts b/plugins/bazaar/src/components/HomePageBazaarInfoCard/index.ts
new file mode 100644
index 0000000000..0edfba0652
--- /dev/null
+++ b/plugins/bazaar/src/components/HomePageBazaarInfoCard/index.ts
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2021 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 { HomePageBazaarInfoCard } from './HomePageBazaarInfoCard';
diff --git a/plugins/bazaar/src/components/InputField/InputField.tsx b/plugins/bazaar/src/components/InputField/InputField.tsx
index 9932e5b1fc..76eb28da6c 100644
--- a/plugins/bazaar/src/components/InputField/InputField.tsx
+++ b/plugins/bazaar/src/components/InputField/InputField.tsx
@@ -25,7 +25,7 @@ type Rules = {
};
type Props = {
- inputType: 'announcement' | 'community' | 'responsible';
+ inputType: 'description' | 'community' | 'responsible' | 'name';
error?: FieldError | undefined;
control: Control