2020-03-23 15:35:58 +01:00
|
|
|
/*
|
|
|
|
|
* MIT License
|
|
|
|
|
*
|
|
|
|
|
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
|
|
|
* copies or substantial portions of the Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
|
* SOFTWARE.
|
|
|
|
|
*/
|
2021-07-28 15:04:00 +02:00
|
|
|
import React, { FC, useState } from "react";
|
2019-10-20 18:02:52 +02:00
|
|
|
import { Repository } from "@scm-manager/ui-types";
|
2021-07-28 15:04:00 +02:00
|
|
|
import { DateFromNow, Modal } from "@scm-manager/ui-components";
|
2019-10-20 18:02:52 +02:00
|
|
|
import RepositoryAvatar from "./RepositoryAvatar";
|
2022-03-29 15:04:14 +02:00
|
|
|
import { binder, ExtensionPoint, extensionPoints } from "@scm-manager/ui-extensions";
|
2021-07-28 15:04:00 +02:00
|
|
|
import GroupEntry from "../layout/GroupEntry";
|
|
|
|
|
import RepositoryFlags from "./RepositoryFlags";
|
2020-12-16 10:58:29 +01:00
|
|
|
import styled from "styled-components";
|
2021-07-28 15:04:00 +02:00
|
|
|
import Icon from "../Icon";
|
|
|
|
|
import { useTranslation } from "react-i18next";
|
2021-09-15 17:40:08 +02:00
|
|
|
import classNames from "classnames";
|
2021-11-11 14:50:11 +01:00
|
|
|
import { EXTENSION_POINT } from "../avatar/Avatar";
|
2018-12-20 09:48:01 +01:00
|
|
|
|
2020-03-27 12:17:20 +01:00
|
|
|
type DateProp = Date | string;
|
|
|
|
|
|
2021-07-28 15:04:00 +02:00
|
|
|
type Props = {
|
2019-10-19 16:38:07 +02:00
|
|
|
repository: Repository;
|
2020-03-27 12:17:20 +01:00
|
|
|
// @VisibleForTesting
|
|
|
|
|
// the baseDate is only to avoid failing snapshot tests
|
|
|
|
|
baseDate?: DateProp;
|
2018-12-20 09:48:01 +01:00
|
|
|
};
|
|
|
|
|
|
2021-07-28 15:04:00 +02:00
|
|
|
const ContentRightContainer = styled.div`
|
|
|
|
|
height: calc(80px - 1.5rem);
|
|
|
|
|
`;
|
2020-11-24 17:34:21 +01:00
|
|
|
|
2021-07-28 15:04:00 +02:00
|
|
|
const QuickAction = styled(Icon)`
|
2021-11-11 14:50:11 +01:00
|
|
|
margin-top: 0.2rem;
|
2021-07-28 15:04:00 +02:00
|
|
|
`;
|
2018-12-20 09:48:01 +01:00
|
|
|
|
2021-11-11 14:50:11 +01:00
|
|
|
const ContactAvatar = styled.img`
|
|
|
|
|
max-width: 20px;
|
|
|
|
|
`;
|
|
|
|
|
|
|
|
|
|
const ContactActionWrapper = styled.a`
|
|
|
|
|
height: 20px;
|
|
|
|
|
width: 20px;
|
|
|
|
|
padding-right: 2rem;
|
|
|
|
|
`;
|
|
|
|
|
|
2021-07-28 15:04:00 +02:00
|
|
|
const Name = styled.strong`
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
overflow-x: hidden;
|
|
|
|
|
overflow-y: visible;
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
`;
|
2018-12-20 09:48:01 +01:00
|
|
|
|
2021-07-28 15:04:00 +02:00
|
|
|
const RepositoryEntry: FC<Props> = ({ repository, baseDate }) => {
|
|
|
|
|
const [t] = useTranslation("repos");
|
|
|
|
|
const [openCloneModal, setOpenCloneModal] = useState(false);
|
|
|
|
|
|
2021-11-11 14:50:11 +01:00
|
|
|
const avatarFactory = binder.getExtension(EXTENSION_POINT);
|
|
|
|
|
|
|
|
|
|
const renderContactIcon = () => {
|
|
|
|
|
if (avatarFactory) {
|
2021-12-16 17:54:39 +01:00
|
|
|
return (
|
|
|
|
|
<ContactAvatar
|
|
|
|
|
className="has-rounded-border"
|
|
|
|
|
src={avatarFactory({ mail: repository.contact })}
|
|
|
|
|
alt={repository.contact}
|
|
|
|
|
/>
|
|
|
|
|
);
|
2021-11-11 14:50:11 +01:00
|
|
|
}
|
2021-12-16 17:54:39 +01:00
|
|
|
return <QuickAction className={classNames("is-clickable", "has-hover-visible")} name="envelope" color="info" />;
|
2021-11-11 14:50:11 +01:00
|
|
|
};
|
|
|
|
|
|
2021-07-28 15:04:00 +02:00
|
|
|
const createContentRight = () => (
|
2021-09-15 17:40:08 +02:00
|
|
|
<ContentRightContainer
|
|
|
|
|
className={classNames(
|
|
|
|
|
"is-flex",
|
|
|
|
|
"is-flex-direction-column",
|
|
|
|
|
"is-justify-content-space-between",
|
|
|
|
|
"is-relative",
|
|
|
|
|
"mr-4"
|
|
|
|
|
)}
|
|
|
|
|
>
|
2021-08-31 07:39:02 +02:00
|
|
|
{openCloneModal && (
|
|
|
|
|
<Modal
|
|
|
|
|
size="L"
|
|
|
|
|
active={openCloneModal}
|
|
|
|
|
title={t("overview.clone")}
|
|
|
|
|
body={
|
2022-03-29 15:04:14 +02:00
|
|
|
<ExtensionPoint<extensionPoints.RepositoryDetailsInformation>
|
2021-08-31 07:39:02 +02:00
|
|
|
name="repos.repository-details.information"
|
|
|
|
|
renderAll={true}
|
|
|
|
|
props={{
|
2021-11-11 14:50:11 +01:00
|
|
|
repository
|
2021-08-31 07:39:02 +02:00
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
}
|
|
|
|
|
closeFunction={() => setOpenCloneModal(false)}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2021-11-11 14:50:11 +01:00
|
|
|
<span className={classNames("is-flex", "is-justify-content-flex-end", "is-align-items-center")}>
|
|
|
|
|
{repository.contact ? (
|
|
|
|
|
<ContactActionWrapper
|
|
|
|
|
href={`mailto:${repository.contact}`}
|
|
|
|
|
target="_blank"
|
|
|
|
|
className={"is-size-5"}
|
|
|
|
|
title={t("overview.contact", { contact: repository.contact })}
|
|
|
|
|
>
|
|
|
|
|
{renderContactIcon()}
|
|
|
|
|
</ContactActionWrapper>
|
|
|
|
|
) : null}
|
2021-07-28 15:04:00 +02:00
|
|
|
<QuickAction
|
2021-12-16 17:54:39 +01:00
|
|
|
className={classNames("is-clickable", "is-size-5", "has-hover-visible")}
|
2021-07-28 15:04:00 +02:00
|
|
|
name="download"
|
|
|
|
|
color="info"
|
|
|
|
|
onClick={() => setOpenCloneModal(true)}
|
|
|
|
|
title={t("overview.clone")}
|
2020-11-24 17:34:21 +01:00
|
|
|
/>
|
2021-09-15 17:40:08 +02:00
|
|
|
</span>
|
|
|
|
|
<small className="pb-1">
|
2021-06-30 08:40:49 +02:00
|
|
|
<DateFromNow baseDate={baseDate} date={repository.lastModified || repository.creationDate} />
|
2021-09-15 17:40:08 +02:00
|
|
|
</small>
|
2021-07-28 15:04:00 +02:00
|
|
|
</ContentRightContainer>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const repositoryLink = `/repo/${repository.namespace}/${repository.name}/`;
|
|
|
|
|
const actions = createContentRight();
|
|
|
|
|
const name = (
|
|
|
|
|
<div className="is-flex">
|
2022-03-29 15:04:14 +02:00
|
|
|
<ExtensionPoint<extensionPoints.RepositoryCardBeforeTitle>
|
|
|
|
|
name="repository.card.beforeTitle"
|
|
|
|
|
props={{ repository }}
|
|
|
|
|
/>
|
2021-07-28 15:04:00 +02:00
|
|
|
<Name>{repository.name}</Name> <RepositoryFlags repository={repository} className="is-hidden-mobile" />
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<GroupEntry
|
|
|
|
|
avatar={<RepositoryAvatar repository={repository} size={48} />}
|
|
|
|
|
name={name}
|
|
|
|
|
description={repository.description}
|
|
|
|
|
contentRight={actions}
|
|
|
|
|
link={repositoryLink}
|
2021-11-16 11:35:58 +01:00
|
|
|
ariaLabel={repository.name}
|
2019-07-09 13:29:25 +02:00
|
|
|
/>
|
2021-07-28 15:04:00 +02:00
|
|
|
</>
|
|
|
|
|
);
|
|
|
|
|
};
|
2018-12-20 09:48:01 +01:00
|
|
|
|
2021-07-28 15:04:00 +02:00
|
|
|
export default RepositoryEntry;
|