diff --git a/gradle/changelog/add-timestamp-first-push.yaml b/gradle/changelog/add-timestamp-first-push.yaml new file mode 100644 index 0000000000..a853a6c9d7 --- /dev/null +++ b/gradle/changelog/add-timestamp-first-push.yaml @@ -0,0 +1,2 @@ +- type: added + description: Extension point for contributor row in contributor table diff --git a/scm-ui/ui-components/src/repos/changesets/Contributor.tsx b/scm-ui/ui-components/src/repos/changesets/Contributor.tsx new file mode 100644 index 0000000000..0c4008e734 --- /dev/null +++ b/scm-ui/ui-components/src/repos/changesets/Contributor.tsx @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020 - present Cloudogu GmbH + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +import React, { FC } from "react"; +import { Person } from "@scm-manager/ui-types"; +import { useTranslation } from "react-i18next"; +import { extensionPoints, useBinder } from "@scm-manager/ui-extensions"; +import ContributorAvatar from "./ContributorAvatar"; + +const Contributor: FC<{ person: Person }> = ({ person }) => { + const [t] = useTranslation("repos"); + const binder = useBinder(); + const avatarFactory = binder.getExtension("avatar.factory"); + let prefix = null; + if (avatarFactory) { + const avatar = avatarFactory(person); + if (avatar) { + prefix = ( + <> + {" "} + + ); + } + } + if (person.mail) { + return ( + + {prefix} + {person.name} + + ); + } + return <>{person.name}; +}; + +export default Contributor; diff --git a/scm-ui/ui-components/src/repos/changesets/ContributorRow.tsx b/scm-ui/ui-components/src/repos/changesets/ContributorRow.tsx new file mode 100644 index 0000000000..98501bd3a1 --- /dev/null +++ b/scm-ui/ui-components/src/repos/changesets/ContributorRow.tsx @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020 - present Cloudogu GmbH + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +import React, { FC } from "react"; +import styled from "styled-components"; + +const SizedTd = styled.td` + width: 10rem; +`; + +const ContributorRow: FC<{ label: string }> = ({ label, children }) => { + return ( + + {label}: + {children} + + ); +}; + +export default ContributorRow; diff --git a/scm-ui/ui-components/src/repos/changesets/index.ts b/scm-ui/ui-components/src/repos/changesets/index.ts index a02545873c..dfc6f6b4e1 100644 --- a/scm-ui/ui-components/src/repos/changesets/index.ts +++ b/scm-ui/ui-components/src/repos/changesets/index.ts @@ -31,3 +31,5 @@ export { default as ChangesetTagsCollapsed } from "./ChangesetTagsCollapsed"; export { default as ContributorAvatar } from "./ContributorAvatar"; export { default as SignatureIcon } from "./SignatureIcon"; export { default as SingleChangeset } from "./SingleChangeset"; +export { default as Contributor } from "./Contributor"; +export { default as ContributorRow } from "./ContributorRow"; diff --git a/scm-ui/ui-extensions/src/extensionPoints.tsx b/scm-ui/ui-extensions/src/extensionPoints.tsx index d5d6afd7d7..0a7b47871a 100644 --- a/scm-ui/ui-extensions/src/extensionPoints.tsx +++ b/scm-ui/ui-extensions/src/extensionPoints.tsx @@ -14,7 +14,7 @@ * along with this program. If not, see https://www.gnu.org/licenses/. */ -import React, { ComponentProps, ComponentType, FC, ReactNode } from "react"; +import React, { ComponentProps, ComponentType, ReactNode } from "react"; import { Branch, BranchDetails, @@ -305,6 +305,11 @@ export type ChangesetsAuthorSuffix = RenderableExtensionPointDefinition< { changeset: Changeset } >; +export type ChangesetsContributorTableRow = RenderableExtensionPointDefinition< + "changesets.contributor.table.row", + { changeset: Changeset } +>; + export type GroupNavigation = RenderableExtensionPointDefinition<"group.navigation", { group: Group; url: string }>; export type GroupRoute = RenderableExtensionPointDefinition<"group.route", { group: Group; url: string }>; diff --git a/scm-ui/ui-webapp/src/repos/components/changesets/ContributorTable.tsx b/scm-ui/ui-webapp/src/repos/components/changesets/ContributorTable.tsx index 42ba9eb1a9..d6386b1bbd 100644 --- a/scm-ui/ui-webapp/src/repos/components/changesets/ContributorTable.tsx +++ b/scm-ui/ui-webapp/src/repos/components/changesets/ContributorTable.tsx @@ -15,46 +15,15 @@ */ import React, { FC } from "react"; -import { Changeset, Person } from "@scm-manager/ui-types"; -import styled from "styled-components"; +import { Changeset } from "@scm-manager/ui-types"; import { useTranslation } from "react-i18next"; -import { extensionPoints, useBinder } from "@scm-manager/ui-extensions"; -import { CommaSeparatedList, ContributorAvatar } from "@scm-manager/ui-components"; +import { ExtensionPoint } from "@scm-manager/ui-extensions"; +import { CommaSeparatedList, Contributor, ContributorRow } from "@scm-manager/ui-components"; type Props = { changeset: Changeset; }; -const SizedTd = styled.td` - width: 10rem; -`; - -const Contributor: FC<{ person: Person }> = ({ person }) => { - const [t] = useTranslation("repos"); - const binder = useBinder(); - const avatarFactory = binder.getExtension("avatar.factory"); - let prefix = null; - if (avatarFactory) { - const avatar = avatarFactory(person); - if (avatar) { - prefix = ( - <> - {" "} - - ); - } - } - if (person.mail) { - return ( - - {prefix} - {person.name} - - ); - } - return <>{person.name}; -}; - const getUnique = (items: string[]) => Object.keys( items.reduce((result, item) => { @@ -72,11 +41,11 @@ const ContributorTable: FC = ({ changeset }) => { if (!changeset.contributors) { return []; } - return getUnique(changeset.contributors.map(contributor => contributor.type)); + return getUnique(changeset.contributors.map((contributor) => contributor.type)); }; const getPersonsByContributorType = (type: string) => { - return changeset.contributors?.filter(contributor => contributor.type === type).map(t => t.person); + return changeset.contributors?.filter((contributor) => contributor.type === type).map((t) => t.person); }; const getContributorsByType = () => { @@ -84,31 +53,27 @@ const ContributorTable: FC = ({ changeset }) => { const personsByContributorType = []; for (const type of availableContributorTypes) { - personsByContributorType.push({ type, persons: getPersonsByContributorType(type) }); + personsByContributorType.push({ type, contributors: getPersonsByContributorType(type) }); } return personsByContributorType; }; return ( - - {t("changeset.contributor.type.author")}: - - - {getContributorsByType().map(contributor => ( - - {t("changeset.contributor.type." + contributor.type)}: - - + + + + + {getContributorsByType().map((contribution) => ( + + + {contribution.contributors?.map((contributor) => ( + + ))} + + ))} +
- -
- - {contributor.persons?.map(person => ( - - ))} - -
); };