Merge branch 'develop' into feature/import_git_from_url

This commit is contained in:
Eduard Heimbuch
2020-12-02 14:39:45 +01:00
71 changed files with 2240 additions and 588 deletions

View File

@@ -26,7 +26,7 @@ import { Trans, useTranslation, WithTranslation, withTranslation } from "react-i
import classNames from "classnames";
import styled from "styled-components";
import { ExtensionPoint } from "@scm-manager/ui-extensions";
import { Changeset, ParentChangeset, Repository } from "@scm-manager/ui-types";
import { Changeset, Link, ParentChangeset, Repository, Tag } from "@scm-manager/ui-types";
import {
AvatarImage,
AvatarWrapper,
@@ -41,7 +41,10 @@ import {
FileControlFactory,
Icon,
Level,
SignatureIcon
SignatureIcon,
Tooltip,
ErrorNotification,
CreateTagModal
} from "@scm-manager/ui-components";
import ContributorTable from "./ContributorTable";
import { Link as ReactLink } from "react-router-dom";
@@ -50,10 +53,7 @@ type Props = WithTranslation & {
changeset: Changeset;
repository: Repository;
fileControlFactory?: FileControlFactory;
};
type State = {
collapsed: boolean;
refetchChangeset?: () => void;
};
const RightMarginP = styled.p`
@@ -82,7 +82,7 @@ const ContributorLine = styled.div`
`;
const ContributorColumn = styled.p`
flex-grow: 1;
flex-grow: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@@ -108,7 +108,6 @@ const ContributorToggleLine = styled.p`
const ChangesetSummary = styled.div`
display: flex;
justify-content: space-between;
`;
const SeparatedParents = styled.div`
@@ -147,7 +146,7 @@ const Contributors: FC<{ changeset: Changeset }> = ({ changeset }) => {
<Icon name="angle-right" /> <ChangesetAuthor changeset={changeset} />
</ContributorColumn>
{signatureIcon}
<CountColumn className={"is-hidden-mobile"}>
<CountColumn className={"is-hidden-mobile is-hidden-tablet-only is-hidden-desktop-only"}>
(
<span className="has-text-link">
{t("changeset.contributors.count", { count: countContributors(changeset) })}
@@ -159,109 +158,131 @@ const Contributors: FC<{ changeset: Changeset }> = ({ changeset }) => {
);
};
class ChangesetDetails extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
collapsed: false
};
}
const ChangesetDetails: FC<Props> = ({ changeset, repository, fileControlFactory, t, refetchChangeset }) => {
const [collapsed, setCollapsed] = useState(false);
const [isTagCreationModalVisible, setTagCreationModalVisible] = useState(false);
const [error, setError] = useState<Error | undefined>();
render() {
const { changeset, repository, fileControlFactory, t } = this.props;
const { collapsed } = this.state;
const description = changesets.parseDescription(changeset.description);
const id = <ChangesetId repository={repository} changeset={changeset} link={false} />;
const date = <DateFromNow date={changeset.date} />;
const parents = changeset._embedded.parents.map((parent: ParentChangeset, index: number) => (
<ReactLink title={parent.id} to={parent.id} key={index}>
{parent.id.substring(0, 7)}
</ReactLink>
));
const showCreateButton = "tag" in changeset._links;
const description = changesets.parseDescription(changeset.description);
const id = <ChangesetId repository={repository} changeset={changeset} link={false} />;
const date = <DateFromNow date={changeset.date} />;
const parents = changeset._embedded.parents.map((parent: ParentChangeset, index: number) => (
<ReactLink title={parent.id} to={parent.id} key={index}>
{parent.id.substring(0, 7)}
</ReactLink>
));
return (
<>
<div className={classNames("content", "is-marginless")}>
<h4>
<ExtensionPoint
name="changeset.description"
props={{
changeset,
value: description.title
}}
renderAll={false}
>
<ChangesetDescription changeset={changeset} value={description.title} />
</ExtensionPoint>
</h4>
<article className="media">
<AvatarWrapper>
<RightMarginP className={classNames("image", "is-64x64")}>
<AvatarImage person={changeset.author} />
</RightMarginP>
</AvatarWrapper>
<div className="media-content">
<Contributors changeset={changeset} />
<ChangesetSummary className="is-ellipsis-overflow">
<p>
<Trans i18nKey="repos:changeset.summary" components={[id, date]} />
</p>
{parents?.length > 0 && (
<SeparatedParents>
{t("changeset.parents.label", { count: parents?.length }) + ": "}
{parents}
</SeparatedParents>
)}
</ChangesetSummary>
</div>
<div className="media-right">
<ChangesetTags changeset={changeset} />
</div>
</article>
<p>
{description.message.split("\n").map((item, key) => {
return (
<span key={key}>
<ExtensionPoint
name="changeset.description"
props={{
changeset,
value: item
}}
renderAll={false}
>
<ChangesetDescription changeset={changeset} value={item} />
</ExtensionPoint>
<br />
</span>
);
})}
</p>
</div>
<div>
<BottomMarginLevel
right={
<Button
action={this.collapseDiffs}
color="default"
icon={collapsed ? "eye" : "eye-slash"}
label={t("changesets.collapseDiffs")}
reducedMobile={true}
/>
}
/>
<ChangesetDiff changeset={changeset} fileControlFactory={fileControlFactory} defaultCollapse={collapsed} />
</div>
</>
);
}
collapseDiffs = () => {
this.setState(state => ({
collapsed: !state.collapsed
}));
const collapseDiffs = () => {
setCollapsed(!collapsed);
};
}
if (error) {
return <ErrorNotification error={error} />;
}
return (
<>
<div className={classNames("content", "is-marginless")}>
<h4>
<ExtensionPoint
name="changeset.description"
props={{
changeset,
value: description.title
}}
renderAll={false}
>
<ChangesetDescription changeset={changeset} value={description.title} />
</ExtensionPoint>
</h4>
<article className="media">
<AvatarWrapper>
<RightMarginP className={classNames("image", "is-64x64")}>
<AvatarImage person={changeset.author} />
</RightMarginP>
</AvatarWrapper>
<div className="media-content">
<Contributors changeset={changeset} />
<ChangesetSummary className="is-ellipsis-overflow">
<p>
<Trans i18nKey="repos:changeset.summary" components={[id, date]} />
</p>
{parents?.length > 0 && (
<SeparatedParents>
{t("changeset.parents.label", { count: parents?.length }) + ": "}
{parents}
</SeparatedParents>
)}
</ChangesetSummary>
</div>
<div className="media-right">
<ChangesetTags changeset={changeset} />
</div>
{showCreateButton && (
<div className="media-right">
<Tooltip message={t("changeset.tag.create")} location="top">
<Button
color="success"
className="tag"
label={(changeset._embedded["tags"]?.length === 0 && t("changeset.tag.create")) || ""}
icon="plus"
action={() => setTagCreationModalVisible(true)}
/>
</Tooltip>
</div>
)}
{isTagCreationModalVisible && (
<CreateTagModal
revision={changeset.id}
onClose={() => setTagCreationModalVisible(false)}
onCreated={() => {
refetchChangeset?.();
setTagCreationModalVisible(false);
}}
onError={setError}
tagCreationLink={(changeset._links["tag"] as Link).href}
existingTagsLink={(repository._links["tags"] as Link).href}
/>
)}
</article>
<p>
{description.message.split("\n").map((item, key) => {
return (
<span key={key}>
<ExtensionPoint
name="changeset.description"
props={{
changeset,
value: item
}}
renderAll={false}
>
<ChangesetDescription changeset={changeset} value={item} />
</ExtensionPoint>
<br />
</span>
);
})}
</p>
</div>
<div>
<BottomMarginLevel
right={
<Button
action={collapseDiffs}
color="default"
icon={collapsed ? "eye" : "eye-slash"}
label={t("changesets.collapseDiffs")}
reducedMobile={true}
/>
}
/>
<ChangesetDiff changeset={changeset} fileControlFactory={fileControlFactory} defaultCollapse={collapsed} />
</div>
</>
);
};
export default withTranslation("repos")(ChangesetDetails);