fix formatting with prettier

This commit is contained in:
Eduard Heimbuch
2020-08-12 12:53:59 +02:00
parent f3d2c3d17b
commit e9edd5ad8f
9 changed files with 177 additions and 172 deletions

View File

@@ -29,14 +29,14 @@ import parser from "gitdiff-parser";
import simpleDiff from "../__resources__/Diff.simple"; import simpleDiff from "../__resources__/Diff.simple";
import hunksDiff from "../__resources__/Diff.hunks"; import hunksDiff from "../__resources__/Diff.hunks";
import binaryDiff from "../__resources__/Diff.binary"; import binaryDiff from "../__resources__/Diff.binary";
import {DiffEventContext, File, FileControlFactory} from "./DiffTypes"; import { DiffEventContext, File, FileControlFactory } from "./DiffTypes";
import Toast from "../toast/Toast"; import Toast from "../toast/Toast";
import { getPath } from "./diffs"; import { getPath } from "./diffs";
import DiffButton from "./DiffButton"; import DiffButton from "./DiffButton";
import styled from "styled-components"; import styled from "styled-components";
import { MemoryRouter } from "react-router-dom"; import { MemoryRouter } from "react-router-dom";
import {one, two} from "../__resources__/changesets"; import { one, two } from "../__resources__/changesets";
import {Changeset} from "@scm-manager/ui-types"; import { Changeset } from "@scm-manager/ui-types";
import JumpToFileButton from "./JumpToFileButton"; import JumpToFileButton from "./JumpToFileButton";
const diffFiles = parser.parse(simpleDiff); const diffFiles = parser.parse(simpleDiff);
@@ -47,7 +47,7 @@ const Container = styled.div`
const RoutingDecorator = (story: () => ReactNode) => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>; const RoutingDecorator = (story: () => ReactNode) => <MemoryRouter initialEntries={["/"]}>{story()}</MemoryRouter>;
const fileControlFactory: (changeset: Changeset) => FileControlFactory = (changeset) => (file) => { const fileControlFactory: (changeset: Changeset) => FileControlFactory = changeset => file => {
const baseUrl = "/repo/hitchhiker/heartOfGold/code/changeset"; const baseUrl = "/repo/hitchhiker/heartOfGold/code/changeset";
const sourceLink = { const sourceLink = {
url: `${baseUrl}/${changeset.id}/${file.newPath}/`, url: `${baseUrl}/${changeset.id}/${file.newPath}/`,
@@ -76,10 +76,7 @@ const fileControlFactory: (changeset: Changeset) => FileControlFactory = (change
} }
} }
return links.map(({url, label}) => <JumpToFileButton return links.map(({ url, label }) => <JumpToFileButton tooltip={label} link={url} />);
tooltip={label}
link={url}
/>);
}; };
storiesOf("Diff", module) storiesOf("Diff", module)
@@ -164,8 +161,4 @@ storiesOf("Diff", module)
}); });
return <Diff diff={filesWithLanguage} />; return <Diff diff={filesWithLanguage} />;
}) })
.add("WithLinkToFile", () => ( .add("WithLinkToFile", () => <Diff diff={diffFiles} />);
<Diff
diff={diffFiles}
/>
));

View File

@@ -23,15 +23,15 @@
*/ */
import React from "react"; import React from "react";
import DiffFile from "./DiffFile"; import DiffFile from "./DiffFile";
import {DiffObjectProps, File, FileControlFactory} from "./DiffTypes"; import { DiffObjectProps, File, FileControlFactory } from "./DiffTypes";
import Notification from "../Notification"; import Notification from "../Notification";
import {WithTranslation, withTranslation} from "react-i18next"; import { WithTranslation, withTranslation } from "react-i18next";
type Props = WithTranslation & type Props = WithTranslation &
DiffObjectProps & { DiffObjectProps & {
diff: File[]; diff: File[];
fileControlFactory?: FileControlFactory; fileControlFactory?: FileControlFactory;
}; };
class Diff extends React.Component<Props> { class Diff extends React.Component<Props> {
static defaultProps: Partial<Props> = { static defaultProps: Partial<Props> = {
@@ -39,7 +39,7 @@ class Diff extends React.Component<Props> {
}; };
render() { render() {
const {diff, t, ...fileProps} = this.props; const { diff, t, ...fileProps } = this.props;
return ( return (
<> <>
{diff.length === 0 ? ( {diff.length === 0 ? (

View File

@@ -22,21 +22,21 @@
* SOFTWARE. * SOFTWARE.
*/ */
import React from "react"; import React from "react";
import {withTranslation, WithTranslation} from "react-i18next"; import { withTranslation, WithTranslation } from "react-i18next";
import classNames from "classnames"; import classNames from "classnames";
import styled from "styled-components"; import styled from "styled-components";
// @ts-ignore // @ts-ignore
import {Decoration, getChangeKey, Hunk} from "react-diff-view"; import { Decoration, getChangeKey, Hunk } from "react-diff-view";
import {ButtonGroup} from "../buttons"; import { ButtonGroup } from "../buttons";
import Tag from "../Tag"; import Tag from "../Tag";
import Icon from "../Icon"; import Icon from "../Icon";
import {Change, ChangeEvent, DiffObjectProps, File, Hunk as HunkType} from "./DiffTypes"; import { Change, ChangeEvent, DiffObjectProps, File, Hunk as HunkType } from "./DiffTypes";
import TokenizedDiffView from "./TokenizedDiffView"; import TokenizedDiffView from "./TokenizedDiffView";
import DiffButton from "./DiffButton"; import DiffButton from "./DiffButton";
import {MenuContext} from "@scm-manager/ui-components"; import { MenuContext } from "@scm-manager/ui-components";
import DiffExpander, {ExpandableHunk} from "./DiffExpander"; import DiffExpander, { ExpandableHunk } from "./DiffExpander";
import HunkExpandLink from "./HunkExpandLink"; import HunkExpandLink from "./HunkExpandLink";
import {Modal} from "../modals"; import { Modal } from "../modals";
import ErrorNotification from "../ErrorNotification"; import ErrorNotification from "../ErrorNotification";
import HunkExpandDivider from "./HunkExpandDivider"; import HunkExpandDivider from "./HunkExpandDivider";
@@ -44,8 +44,8 @@ const EMPTY_ANNOTATION_FACTORY = {};
type Props = DiffObjectProps & type Props = DiffObjectProps &
WithTranslation & { WithTranslation & {
file: File; file: File;
}; };
type Collapsible = { type Collapsible = {
collapsed?: boolean; collapsed?: boolean;
@@ -115,7 +115,7 @@ class DiffFile extends React.Component<Props, State> {
} }
defaultCollapse: () => boolean = () => { defaultCollapse: () => boolean = () => {
const {defaultCollapse, file} = this.props; const { defaultCollapse, file } = this.props;
if (typeof defaultCollapse === "boolean") { if (typeof defaultCollapse === "boolean") {
return defaultCollapse; return defaultCollapse;
} else if (typeof defaultCollapse === "function") { } else if (typeof defaultCollapse === "function") {
@@ -126,7 +126,7 @@ class DiffFile extends React.Component<Props, State> {
}; };
toggleCollapse = () => { toggleCollapse = () => {
const {file} = this.state; const { file } = this.state;
if (this.hasContent(file)) { if (this.hasContent(file)) {
this.setState(state => ({ this.setState(state => ({
collapsed: !state.collapsed collapsed: !state.collapsed
@@ -157,7 +157,7 @@ class DiffFile extends React.Component<Props, State> {
<HunkExpandLink <HunkExpandLink
icon={"fa-angle-double-up"} icon={"fa-angle-double-up"}
onClick={this.expandHead(expandableHunk, expandableHunk.maxExpandHeadRange)} onClick={this.expandHead(expandableHunk, expandableHunk.maxExpandHeadRange)}
text={this.props.t("diff.expandComplete", {count: expandableHunk.maxExpandHeadRange})} text={this.props.t("diff.expandComplete", { count: expandableHunk.maxExpandHeadRange })}
/> />
</HunkExpandDivider> </HunkExpandDivider>
); );
@@ -167,19 +167,19 @@ class DiffFile extends React.Component<Props, State> {
<HunkExpandLink <HunkExpandLink
icon={"fa-angle-up"} icon={"fa-angle-up"}
onClick={this.expandHead(expandableHunk, 10)} onClick={this.expandHead(expandableHunk, 10)}
text={this.props.t("diff.expandByLines", {count: 10})} text={this.props.t("diff.expandByLines", { count: 10 })}
/>{" "} />{" "}
<HunkExpandLink <HunkExpandLink
icon={"fa-angle-double-up"} icon={"fa-angle-double-up"}
onClick={this.expandHead(expandableHunk, expandableHunk.maxExpandHeadRange)} onClick={this.expandHead(expandableHunk, expandableHunk.maxExpandHeadRange)}
text={this.props.t("diff.expandComplete", {count: expandableHunk.maxExpandHeadRange})} text={this.props.t("diff.expandComplete", { count: expandableHunk.maxExpandHeadRange })}
/> />
</HunkExpandDivider> </HunkExpandDivider>
); );
} }
} }
// hunk header must be defined // hunk header must be defined
return <span/>; return <span />;
}; };
createHunkFooter = (expandableHunk: ExpandableHunk) => { createHunkFooter = (expandableHunk: ExpandableHunk) => {
@@ -190,7 +190,7 @@ class DiffFile extends React.Component<Props, State> {
<HunkExpandLink <HunkExpandLink
icon={"fa-angle-double-down"} icon={"fa-angle-double-down"}
onClick={this.expandBottom(expandableHunk, expandableHunk.maxExpandBottomRange)} onClick={this.expandBottom(expandableHunk, expandableHunk.maxExpandBottomRange)}
text={this.props.t("diff.expandComplete", {count: expandableHunk.maxExpandBottomRange})} text={this.props.t("diff.expandComplete", { count: expandableHunk.maxExpandBottomRange })}
/> />
</HunkExpandDivider> </HunkExpandDivider>
); );
@@ -200,19 +200,19 @@ class DiffFile extends React.Component<Props, State> {
<HunkExpandLink <HunkExpandLink
icon={"fa-angle-down"} icon={"fa-angle-down"}
onClick={this.expandBottom(expandableHunk, 10)} onClick={this.expandBottom(expandableHunk, 10)}
text={this.props.t("diff.expandByLines", {count: 10})} text={this.props.t("diff.expandByLines", { count: 10 })}
/>{" "} />{" "}
<HunkExpandLink <HunkExpandLink
icon={"fa-angle-double-down"} icon={"fa-angle-double-down"}
onClick={this.expandBottom(expandableHunk, expandableHunk.maxExpandBottomRange)} onClick={this.expandBottom(expandableHunk, expandableHunk.maxExpandBottomRange)}
text={this.props.t("diff.expandComplete", {count: expandableHunk.maxExpandBottomRange})} text={this.props.t("diff.expandComplete", { count: expandableHunk.maxExpandBottomRange })}
/> />
</HunkExpandDivider> </HunkExpandDivider>
); );
} }
} }
// hunk footer must be defined // hunk footer must be defined
return <span/>; return <span />;
}; };
createLastHunkFooter = (expandableHunk: ExpandableHunk) => { createLastHunkFooter = (expandableHunk: ExpandableHunk) => {
@@ -222,7 +222,7 @@ class DiffFile extends React.Component<Props, State> {
<HunkExpandLink <HunkExpandLink
icon={"fa-angle-down"} icon={"fa-angle-down"}
onClick={this.expandBottom(expandableHunk, 10)} onClick={this.expandBottom(expandableHunk, 10)}
text={this.props.t("diff.expandLastBottomByLines", {count: 10})} text={this.props.t("diff.expandLastBottomByLines", { count: 10 })}
/>{" "} />{" "}
<HunkExpandLink <HunkExpandLink
icon={"fa-angle-double-down"} icon={"fa-angle-double-down"}
@@ -233,7 +233,7 @@ class DiffFile extends React.Component<Props, State> {
); );
} }
// hunk header must be defined // hunk header must be defined
return <span/>; return <span />;
}; };
expandHead = (expandableHunk: ExpandableHunk, count: number) => { expandHead = (expandableHunk: ExpandableHunk, count: number) => {
@@ -255,16 +255,16 @@ class DiffFile extends React.Component<Props, State> {
}; };
diffExpanded = (newFile: File) => { diffExpanded = (newFile: File) => {
this.setState({file: newFile, diffExpander: new DiffExpander(newFile)}); this.setState({ file: newFile, diffExpander: new DiffExpander(newFile) });
}; };
diffExpansionFailed = (err: any) => { diffExpansionFailed = (err: any) => {
this.setState({expansionError: err}); this.setState({ expansionError: err });
}; };
collectHunkAnnotations = (hunk: HunkType) => { collectHunkAnnotations = (hunk: HunkType) => {
const {annotationFactory} = this.props; const { annotationFactory } = this.props;
const {file} = this.state; const { file } = this.state;
if (annotationFactory) { if (annotationFactory) {
return annotationFactory({ return annotationFactory({
hunk, hunk,
@@ -276,8 +276,8 @@ class DiffFile extends React.Component<Props, State> {
}; };
handleClickEvent = (change: Change, hunk: HunkType) => { handleClickEvent = (change: Change, hunk: HunkType) => {
const {onClick} = this.props; const { onClick } = this.props;
const {file} = this.state; const { file } = this.state;
const context = { const context = {
changeId: getChangeKey(change), changeId: getChangeKey(change),
change, change,
@@ -290,7 +290,7 @@ class DiffFile extends React.Component<Props, State> {
}; };
createGutterEvents = (hunk: HunkType) => { createGutterEvents = (hunk: HunkType) => {
const {onClick} = this.props; const { onClick } = this.props;
if (onClick) { if (onClick) {
return { return {
onClick: (event: ChangeEvent) => { onClick: (event: ChangeEvent) => {
@@ -311,7 +311,7 @@ class DiffFile extends React.Component<Props, State> {
} else if (i > 0) { } else if (i > 0) {
items.push( items.push(
<Decoration> <Decoration>
<HunkDivider/> <HunkDivider />
</Decoration> </Decoration>
); );
} }
@@ -354,7 +354,7 @@ class DiffFile extends React.Component<Props, State> {
if (file.oldPath !== file.newPath && (file.type === "copy" || file.type === "rename")) { if (file.oldPath !== file.newPath && (file.type === "copy" || file.type === "rename")) {
return ( return (
<> <>
{file.oldPath} <Icon name="arrow-right" color="inherit"/> {file.newPath} {file.oldPath} <Icon name="arrow-right" color="inherit" /> {file.newPath}
</> </>
); );
} else if (file.type === "delete") { } else if (file.type === "delete") {
@@ -373,7 +373,7 @@ class DiffFile extends React.Component<Props, State> {
}; };
renderChangeTag = (file: File) => { renderChangeTag = (file: File) => {
const {t} = this.props; const { t } = this.props;
if (!file.type) { if (!file.type) {
return; return;
} }
@@ -385,14 +385,14 @@ class DiffFile extends React.Component<Props, State> {
const color = const color =
value === "added" ? "success is-outlined" : value === "deleted" ? "danger is-outlined" : "info is-outlined"; value === "added" ? "success is-outlined" : value === "deleted" ? "danger is-outlined" : "info is-outlined";
return <ChangeTypeTag className={classNames("is-rounded", "has-text-weight-normal")} color={color} label={value}/>; return <ChangeTypeTag className={classNames("is-rounded", "has-text-weight-normal")} color={color} label={value} />;
}; };
hasContent = (file: File) => file && !file.isBinary && file.hunks && file.hunks.length > 0; hasContent = (file: File) => file && !file.isBinary && file.hunks && file.hunks.length > 0;
render() { render() {
const {fileControlFactory, fileAnnotationFactory, t} = this.props; const { fileControlFactory, fileAnnotationFactory, t } = this.props;
const {file, collapsed, sideBySide, diffExpander, expansionError} = this.state; const { file, collapsed, sideBySide, diffExpander, expansionError } = this.state;
const viewType = sideBySide ? "split" : "unified"; const viewType = sideBySide ? "split" : "unified";
let body = null; let body = null;
@@ -413,39 +413,41 @@ class DiffFile extends React.Component<Props, State> {
</div> </div>
); );
} }
const collapseIcon = this.hasContent(file) ? <Icon name={icon} color="inherit"/> : null; const collapseIcon = this.hasContent(file) ? <Icon name={icon} color="inherit" /> : null;
const fileControls = fileControlFactory ? fileControlFactory(file, this.setCollapse) : null; const fileControls = fileControlFactory ? fileControlFactory(file, this.setCollapse) : null;
const sideBySideToggle = file.hunks && file.hunks.length && <MenuContext.Consumer> const sideBySideToggle = file.hunks && file.hunks.length && (
{({setCollapsed}) => ( <MenuContext.Consumer>
<DiffButton {({ setCollapsed }) => (
icon={sideBySide ? "align-left" : "columns"} <DiffButton
tooltip={t(sideBySide ? "diff.combined" : "diff.sideBySide")} icon={sideBySide ? "align-left" : "columns"}
onClick={() => tooltip={t(sideBySide ? "diff.combined" : "diff.sideBySide")}
this.toggleSideBySide(() => { onClick={() =>
if (this.state.sideBySide) { this.toggleSideBySide(() => {
setCollapsed(true); if (this.state.sideBySide) {
} setCollapsed(true);
}) }
} })
/> }
)} />
</MenuContext.Consumer>; )}
</MenuContext.Consumer>
);
const headerButtons = ( const headerButtons = (
<ButtonWrapper className={classNames("level-right", "is-flex")}> <ButtonWrapper className={classNames("level-right", "is-flex")}>
<ButtonGroup> <ButtonGroup>
{sideBySideToggle} {sideBySideToggle}
{fileControls} {fileControls}
</ButtonGroup> </ButtonGroup>
</ButtonWrapper> </ButtonWrapper>
); );
let errorModal; let errorModal;
if (expansionError) { if (expansionError) {
errorModal = ( errorModal = (
<Modal <Modal
title={t("diff.expansionFailed")} title={t("diff.expansionFailed")}
closeFunction={() => this.setState({expansionError: undefined})} closeFunction={() => this.setState({ expansionError: undefined })}
body={<ErrorNotification error={expansionError}/>} body={<ErrorNotification error={expansionError} />}
active={true} active={true}
/> />
); );

View File

@@ -22,22 +22,22 @@
* SOFTWARE. * SOFTWARE.
*/ */
import React from "react"; import React from "react";
import {apiClient} from "../apiclient"; import { apiClient } from "../apiclient";
import ErrorNotification from "../ErrorNotification"; import ErrorNotification from "../ErrorNotification";
// @ts-ignore // @ts-ignore
import parser from "gitdiff-parser"; import parser from "gitdiff-parser";
import Loading from "../Loading"; import Loading from "../Loading";
import Diff from "./Diff"; import Diff from "./Diff";
import {DiffObjectProps, File} from "./DiffTypes"; import { DiffObjectProps, File } from "./DiffTypes";
import {NotFoundError} from "../errors"; import { NotFoundError } from "../errors";
import {Notification} from "../index"; import { Notification } from "../index";
import {withTranslation, WithTranslation} from "react-i18next"; import { withTranslation, WithTranslation } from "react-i18next";
type Props = WithTranslation & type Props = WithTranslation &
DiffObjectProps & { DiffObjectProps & {
url: string; url: string;
}; };
type State = { type State = {
diff?: File[]; diff?: File[];
@@ -68,8 +68,8 @@ class LoadingDiff extends React.Component<Props, State> {
} }
fetchDiff = () => { fetchDiff = () => {
const {url} = this.props; const { url } = this.props;
this.setState({loading: true}); this.setState({ loading: true });
apiClient apiClient
.get(url) .get(url)
.then(response => { .then(response => {
@@ -95,14 +95,14 @@ class LoadingDiff extends React.Component<Props, State> {
}; };
render() { render() {
const {diff, loading, error} = this.state; const { diff, loading, error } = this.state;
if (error) { if (error) {
if (error instanceof NotFoundError) { if (error instanceof NotFoundError) {
return <Notification type="info">{this.props.t("changesets.noChangesets")}</Notification>; return <Notification type="info">{this.props.t("changesets.noChangesets")}</Notification>;
} }
return <ErrorNotification error={error}/>; return <ErrorNotification error={error} />;
} else if (loading) { } else if (loading) {
return <Loading/>; return <Loading />;
} else if (!diff) { } else if (!diff) {
return null; return null;
} else { } else {

View File

@@ -22,11 +22,11 @@
* SOFTWARE. * SOFTWARE.
*/ */
import React from "react"; import React from "react";
import {Changeset, Collection, Link} from "@scm-manager/ui-types"; import { Changeset, Collection, Link } from "@scm-manager/ui-types";
import LoadingDiff from "../LoadingDiff"; import LoadingDiff from "../LoadingDiff";
import Notification from "../../Notification"; import Notification from "../../Notification";
import {WithTranslation, withTranslation} from "react-i18next"; import { WithTranslation, withTranslation } from "react-i18next";
import {FileControlFactory} from "../DiffTypes"; import { FileControlFactory } from "../DiffTypes";
type Props = WithTranslation & { type Props = WithTranslation & {
changeset: Changeset; changeset: Changeset;
@@ -49,12 +49,19 @@ export const createUrl = (changeset: Collection) => {
class ChangesetDiff extends React.Component<Props> { class ChangesetDiff extends React.Component<Props> {
render() { render() {
const {changeset, fileControlFactory, defaultCollapse, t} = this.props; const { changeset, fileControlFactory, defaultCollapse, t } = this.props;
if (!isDiffSupported(changeset)) { if (!isDiffSupported(changeset)) {
return <Notification type="danger">{t("changeset.diffNotSupported")}</Notification>; return <Notification type="danger">{t("changeset.diffNotSupported")}</Notification>;
} else { } else {
const url = createUrl(changeset); const url = createUrl(changeset);
return <LoadingDiff url={url} defaultCollapse={defaultCollapse} sideBySide={false} fileControlFactory={fileControlFactory}/>; return (
<LoadingDiff
url={url}
defaultCollapse={defaultCollapse}
sideBySide={false}
fileControlFactory={fileControlFactory}
/>
);
} }
} }
} }

View File

@@ -35,7 +35,7 @@ import ChangesetAuthor from "./ChangesetAuthor";
import ChangesetTags from "./ChangesetTags"; import ChangesetTags from "./ChangesetTags";
import ChangesetButtonGroup from "./ChangesetButtonGroup"; import ChangesetButtonGroup from "./ChangesetButtonGroup";
import ChangesetDescription from "./ChangesetDescription"; import ChangesetDescription from "./ChangesetDescription";
import {FileControlFactory} from "../DiffTypes"; import { FileControlFactory } from "../DiffTypes";
type Props = WithTranslation & { type Props = WithTranslation & {
repository: Repository; repository: Repository;
@@ -102,7 +102,7 @@ class ChangesetRow extends React.Component<Props> {
<AvatarWrapper> <AvatarWrapper>
<AvatarFigure className="media-left"> <AvatarFigure className="media-left">
<FixedSizedAvatar className="image"> <FixedSizedAvatar className="image">
<AvatarImage person={changeset.author}/> <AvatarImage person={changeset.author} />
</FixedSizedAvatar> </FixedSizedAvatar>
</AvatarFigure> </AvatarFigure>
</AvatarWrapper> </AvatarWrapper>
@@ -120,24 +120,24 @@ class ChangesetRow extends React.Component<Props> {
</ExtensionPoint> </ExtensionPoint>
</h4> </h4>
<p className="is-hidden-touch"> <p className="is-hidden-touch">
<Trans i18nKey="repos:changeset.summary" components={[changesetId, dateFromNow]}/> <Trans i18nKey="repos:changeset.summary" components={[changesetId, dateFromNow]} />
</p> </p>
<p className="is-hidden-desktop"> <p className="is-hidden-desktop">
<Trans i18nKey="repos:changeset.shortSummary" components={[changesetId, dateFromNow]}/> <Trans i18nKey="repos:changeset.shortSummary" components={[changesetId, dateFromNow]} />
</p> </p>
<AuthorWrapper className="is-size-7 is-ellipsis-overflow"> <AuthorWrapper className="is-size-7 is-ellipsis-overflow">
<ChangesetAuthor changeset={changeset}/> <ChangesetAuthor changeset={changeset} />
</AuthorWrapper> </AuthorWrapper>
</Metadata> </Metadata>
</div> </div>
</div> </div>
<VCenteredColumn className="column"> <VCenteredColumn className="column">
<ChangesetTags changeset={changeset}/> <ChangesetTags changeset={changeset} />
</VCenteredColumn> </VCenteredColumn>
</div> </div>
</div> </div>
<VCenteredChildColumn className={classNames("column", "is-flex")}> <VCenteredChildColumn className={classNames("column", "is-flex")}>
<ChangesetButtonGroup repository={repository} changeset={changeset}/> <ChangesetButtonGroup repository={repository} changeset={changeset} />
<ExtensionPoint <ExtensionPoint
name="changeset.right" name="changeset.right"
props={{ props={{

View File

@@ -43,7 +43,7 @@ import {
} from "@scm-manager/ui-components"; } from "@scm-manager/ui-components";
import ContributorTable from "./ContributorTable"; import ContributorTable from "./ContributorTable";
import { Link as ReactLink } from "react-router-dom"; import { Link as ReactLink } from "react-router-dom";
import {FileControlFactory} from "@scm-manager/ui-components"; import { FileControlFactory } from "@scm-manager/ui-components";
type Props = WithTranslation & { type Props = WithTranslation & {
changeset: Changeset; changeset: Changeset;

View File

@@ -22,12 +22,12 @@
* SOFTWARE. * SOFTWARE.
*/ */
import React from "react"; import React from "react";
import {connect} from "react-redux"; import { connect } from "react-redux";
import {compose} from "redux"; import { compose } from "redux";
import {withRouter} from "react-router-dom"; import { withRouter } from "react-router-dom";
import {WithTranslation, withTranslation} from "react-i18next"; import { WithTranslation, withTranslation } from "react-i18next";
import {Changeset, Repository} from "@scm-manager/ui-types"; import { Changeset, Repository } from "@scm-manager/ui-types";
import {ErrorPage, Loading} from "@scm-manager/ui-components"; import { ErrorPage, Loading } from "@scm-manager/ui-components";
import { import {
fetchChangesetIfNeeded, fetchChangesetIfNeeded,
getChangeset, getChangeset,
@@ -35,7 +35,7 @@ import {
isFetchChangesetPending isFetchChangesetPending
} from "../modules/changesets"; } from "../modules/changesets";
import ChangesetDetails from "../components/changesets/ChangesetDetails"; import ChangesetDetails from "../components/changesets/ChangesetDetails";
import {FileControlFactory} from "@scm-manager/ui-components"; import { FileControlFactory } from "@scm-manager/ui-components";
type Props = WithTranslation & { type Props = WithTranslation & {
id: string; id: string;
@@ -50,28 +50,33 @@ type Props = WithTranslation & {
class ChangesetView extends React.Component<Props> { class ChangesetView extends React.Component<Props> {
componentDidMount() { componentDidMount() {
const {fetchChangesetIfNeeded, repository, id} = this.props; const { fetchChangesetIfNeeded, repository, id } = this.props;
fetchChangesetIfNeeded(repository, id); fetchChangesetIfNeeded(repository, id);
} }
componentDidUpdate(prevProps: Props) { componentDidUpdate(prevProps: Props) {
const {fetchChangesetIfNeeded, repository, id} = this.props; const { fetchChangesetIfNeeded, repository, id } = this.props;
if (prevProps.id !== id) { if (prevProps.id !== id) {
fetchChangesetIfNeeded(repository, id); fetchChangesetIfNeeded(repository, id);
} }
} }
render() { render() {
const {changeset, loading, error, t, repository, fileControlFactoryFactory} = this.props; const { changeset, loading, error, t, repository, fileControlFactoryFactory } = this.props;
if (error) { if (error) {
return <ErrorPage title={t("changesets.errorTitle")} subtitle={t("changesets.errorSubtitle")} error={error}/>; return <ErrorPage title={t("changesets.errorTitle")} subtitle={t("changesets.errorSubtitle")} error={error} />;
} }
if (!changeset || loading) return <Loading/>; if (!changeset || loading) return <Loading />;
return <ChangesetDetails changeset={changeset} repository={repository} return (
fileControlFactory={fileControlFactoryFactory && fileControlFactoryFactory(changeset)}/>; <ChangesetDetails
changeset={changeset}
repository={repository}
fileControlFactory={fileControlFactoryFactory && fileControlFactoryFactory(changeset)}
/>
);
} }
} }

View File

@@ -22,11 +22,11 @@
* SOFTWARE. * SOFTWARE.
*/ */
import React from "react"; import React from "react";
import {connect} from "react-redux"; import { connect } from "react-redux";
import {Redirect, Route, RouteComponentProps, Switch} from "react-router-dom"; import { Redirect, Route, RouteComponentProps, Switch } from "react-router-dom";
import {WithTranslation, withTranslation} from "react-i18next"; import { WithTranslation, withTranslation } from "react-i18next";
import {binder, ExtensionPoint} from "@scm-manager/ui-extensions"; import { binder, ExtensionPoint } from "@scm-manager/ui-extensions";
import {Changeset, Repository} from "@scm-manager/ui-types"; import { Changeset, Repository } from "@scm-manager/ui-types";
import { import {
CustomQueryFlexWrappedColumns, CustomQueryFlexWrappedColumns,
ErrorPage, ErrorPage,
@@ -39,7 +39,7 @@ import {
StateMenuContextProvider, StateMenuContextProvider,
SubNavigation SubNavigation
} from "@scm-manager/ui-components"; } from "@scm-manager/ui-components";
import {fetchRepoByName, getFetchRepoFailure, getRepository, isFetchRepoPending} from "../modules/repos"; import { fetchRepoByName, getFetchRepoFailure, getRepository, isFetchRepoPending } from "../modules/repos";
import RepositoryDetails from "../components/RepositoryDetails"; import RepositoryDetails from "../components/RepositoryDetails";
import EditRepo from "./EditRepo"; import EditRepo from "./EditRepo";
import BranchesOverview from "../branches/containers/BranchesOverview"; import BranchesOverview from "../branches/containers/BranchesOverview";
@@ -49,34 +49,34 @@ import EditRepoNavLink from "../components/EditRepoNavLink";
import BranchRoot from "../branches/containers/BranchRoot"; import BranchRoot from "../branches/containers/BranchRoot";
import PermissionsNavLink from "../components/PermissionsNavLink"; import PermissionsNavLink from "../components/PermissionsNavLink";
import RepositoryNavLink from "../components/RepositoryNavLink"; import RepositoryNavLink from "../components/RepositoryNavLink";
import {getLinks, getRepositoriesLink} from "../../modules/indexResource"; import { getLinks, getRepositoriesLink } from "../../modules/indexResource";
import CodeOverview from "../codeSection/containers/CodeOverview"; import CodeOverview from "../codeSection/containers/CodeOverview";
import ChangesetView from "./ChangesetView"; import ChangesetView from "./ChangesetView";
import SourceExtensions from "../sources/containers/SourceExtensions"; import SourceExtensions from "../sources/containers/SourceExtensions";
import {FileControlFactory, JumpToFileButton} from "@scm-manager/ui-components"; import { FileControlFactory, JumpToFileButton } from "@scm-manager/ui-components";
type Props = RouteComponentProps & type Props = RouteComponentProps &
WithTranslation & { WithTranslation & {
namespace: string; namespace: string;
name: string; name: string;
repository: Repository; repository: Repository;
loading: boolean; loading: boolean;
error: Error; error: Error;
repoLink: string; repoLink: string;
indexLinks: object; indexLinks: object;
// dispatch functions // dispatch functions
fetchRepoByName: (link: string, namespace: string, name: string) => void; fetchRepoByName: (link: string, namespace: string, name: string) => void;
}; };
class RepositoryRoot extends React.Component<Props> { class RepositoryRoot extends React.Component<Props> {
componentDidMount() { componentDidMount() {
const {fetchRepoByName, namespace, name, repoLink} = this.props; const { fetchRepoByName, namespace, name, repoLink } = this.props;
fetchRepoByName(repoLink, namespace, name); fetchRepoByName(repoLink, namespace, name);
} }
componentDidUpdate(prevProps: Props) { componentDidUpdate(prevProps: Props) {
const {fetchRepoByName, namespace, name, repoLink} = this.props; const { fetchRepoByName, namespace, name, repoLink } = this.props;
if (namespace !== prevProps.namespace || name !== prevProps.name) { if (namespace !== prevProps.namespace || name !== prevProps.name) {
fetchRepoByName(repoLink, namespace, name); fetchRepoByName(repoLink, namespace, name);
} }
@@ -106,7 +106,7 @@ class RepositoryRoot extends React.Component<Props> {
}; };
getCodeLinkname = () => { getCodeLinkname = () => {
const {repository} = this.props; const { repository } = this.props;
if (repository?._links?.sources) { if (repository?._links?.sources) {
return "sources"; return "sources";
} }
@@ -117,7 +117,7 @@ class RepositoryRoot extends React.Component<Props> {
}; };
evaluateDestinationForCodeLink = () => { evaluateDestinationForCodeLink = () => {
const {repository} = this.props; const { repository } = this.props;
const url = `${this.matchedUrl()}/code`; const url = `${this.matchedUrl()}/code`;
if (repository?._links?.sources) { if (repository?._links?.sources) {
return `${url}/sources/`; return `${url}/sources/`;
@@ -126,16 +126,16 @@ class RepositoryRoot extends React.Component<Props> {
}; };
render() { render() {
const {loading, error, indexLinks, repository, t} = this.props; const { loading, error, indexLinks, repository, t } = this.props;
if (error) { if (error) {
return ( return (
<ErrorPage title={t("repositoryRoot.errorTitle")} subtitle={t("repositoryRoot.errorSubtitle")} error={error}/> <ErrorPage title={t("repositoryRoot.errorTitle")} subtitle={t("repositoryRoot.errorSubtitle")} error={error} />
); );
} }
if (!repository || loading) { if (!repository || loading) {
return <Loading/>; return <Loading />;
} }
const url = this.matchedUrl(); const url = this.matchedUrl();
@@ -154,7 +154,7 @@ class RepositoryRoot extends React.Component<Props> {
redirectedUrl = url + "/info"; redirectedUrl = url + "/info";
} }
const fileControlFactoryFactory: (changeset: Changeset) => FileControlFactory = (changeset) => (file) => { const fileControlFactoryFactory: (changeset: Changeset) => FileControlFactory = changeset => file => {
const baseUrl = `${url}/code/sources`; const baseUrl = `${url}/code/sources`;
const sourceLink = { const sourceLink = {
url: `${baseUrl}/${changeset.id}/${file.newPath}/`, url: `${baseUrl}/${changeset.id}/${file.newPath}/`,
@@ -183,73 +183,71 @@ class RepositoryRoot extends React.Component<Props> {
} }
} }
return links.map(({url, label}) => <JumpToFileButton return links.map(({ url, label }) => <JumpToFileButton tooltip={label} link={url} />);
tooltip={label}
link={url}
/>);
}; };
return ( return (
<StateMenuContextProvider> <StateMenuContextProvider>
<Page <Page
title={repository.namespace + "/" + repository.name} title={repository.namespace + "/" + repository.name}
afterTitle={<ExtensionPoint name={"repository.afterTitle"} props={{repository}}/>} afterTitle={<ExtensionPoint name={"repository.afterTitle"} props={{ repository }} />}
> >
<CustomQueryFlexWrappedColumns> <CustomQueryFlexWrappedColumns>
<PrimaryContentColumn> <PrimaryContentColumn>
<Switch> <Switch>
<Redirect exact from={this.props.match.url} to={redirectedUrl}/> <Redirect exact from={this.props.match.url} to={redirectedUrl} />
{/* redirect pre 2.0.0-rc2 links */} {/* redirect pre 2.0.0-rc2 links */}
<Redirect from={`${url}/changeset/:id`} to={`${url}/code/changeset/:id`}/> <Redirect from={`${url}/changeset/:id`} to={`${url}/code/changeset/:id`} />
<Redirect exact from={`${url}/sources`} to={`${url}/code/sources`}/> <Redirect exact from={`${url}/sources`} to={`${url}/code/sources`} />
<Redirect from={`${url}/sources/:revision/:path*`} to={`${url}/code/sources/:revision/:path*`}/> <Redirect from={`${url}/sources/:revision/:path*`} to={`${url}/code/sources/:revision/:path*`} />
<Redirect exact from={`${url}/changesets`} to={`${url}/code/changesets`}/> <Redirect exact from={`${url}/changesets`} to={`${url}/code/changesets`} />
<Redirect from={`${url}/branch/:branch/changesets`} to={`${url}/code/branch/:branch/changesets/`}/> <Redirect from={`${url}/branch/:branch/changesets`} to={`${url}/code/branch/:branch/changesets/`} />
<Route path={`${url}/info`} exact component={() => <RepositoryDetails repository={repository}/>}/> <Route path={`${url}/info`} exact component={() => <RepositoryDetails repository={repository} />} />
<Route path={`${url}/settings/general`} component={() => <EditRepo repository={repository}/>}/> <Route path={`${url}/settings/general`} component={() => <EditRepo repository={repository} />} />
<Route <Route
path={`${url}/settings/permissions`} path={`${url}/settings/permissions`}
render={() => ( render={() => (
<Permissions namespace={this.props.repository.namespace} repoName={this.props.repository.name}/> <Permissions namespace={this.props.repository.namespace} repoName={this.props.repository.name} />
)} )}
/> />
<Route <Route
exact exact
path={`${url}/code/changeset/:id`} path={`${url}/code/changeset/:id`}
render={() => <ChangesetView repository={repository} render={() => (
fileControlFactoryFactory={fileControlFactoryFactory}/>} <ChangesetView repository={repository} fileControlFactoryFactory={fileControlFactoryFactory} />
)}
/> />
<Route <Route
path={`${url}/code/sourceext/:extension`} path={`${url}/code/sourceext/:extension`}
exact={true} exact={true}
render={() => <SourceExtensions repository={repository}/>} render={() => <SourceExtensions repository={repository} />}
/> />
<Route <Route
path={`${url}/code/sourceext/:extension/:revision/:path*`} path={`${url}/code/sourceext/:extension/:revision/:path*`}
render={() => <SourceExtensions repository={repository} baseUrl={`${url}/code/sources`}/>} render={() => <SourceExtensions repository={repository} baseUrl={`${url}/code/sources`} />}
/> />
<Route <Route
path={`${url}/code`} path={`${url}/code`}
render={() => <CodeOverview baseUrl={`${url}/code`} repository={repository}/>} render={() => <CodeOverview baseUrl={`${url}/code`} repository={repository} />}
/> />
<Route <Route
path={`${url}/branch/:branch`} path={`${url}/branch/:branch`}
render={() => <BranchRoot repository={repository} baseUrl={`${url}/branch`}/>} render={() => <BranchRoot repository={repository} baseUrl={`${url}/branch`} />}
/> />
<Route <Route
path={`${url}/branches`} path={`${url}/branches`}
exact={true} exact={true}
render={() => <BranchesOverview repository={repository} baseUrl={`${url}/branch`}/>} render={() => <BranchesOverview repository={repository} baseUrl={`${url}/branch`} />}
/> />
<Route path={`${url}/branches/create`} render={() => <CreateBranch repository={repository}/>}/> <Route path={`${url}/branches/create`} render={() => <CreateBranch repository={repository} />} />
<ExtensionPoint name="repository.route" props={extensionProps} renderAll={true}/> <ExtensionPoint name="repository.route" props={extensionProps} renderAll={true} />
</Switch> </Switch>
</PrimaryContentColumn> </PrimaryContentColumn>
<SecondaryNavigationColumn> <SecondaryNavigationColumn>
<SecondaryNavigation label={t("repositoryRoot.menu.navigationLabel")}> <SecondaryNavigation label={t("repositoryRoot.menu.navigationLabel")}>
<ExtensionPoint name="repository.navigation.topLevel" props={extensionProps} renderAll={true}/> <ExtensionPoint name="repository.navigation.topLevel" props={extensionProps} renderAll={true} />
<NavLink <NavLink
to={`${url}/info`} to={`${url}/info`}
icon="fas fa-info-circle" icon="fas fa-info-circle"
@@ -276,15 +274,15 @@ class RepositoryRoot extends React.Component<Props> {
activeOnlyWhenExact={false} activeOnlyWhenExact={false}
title={t("repositoryRoot.menu.sourcesNavLink")} title={t("repositoryRoot.menu.sourcesNavLink")}
/> />
<ExtensionPoint name="repository.navigation" props={extensionProps} renderAll={true}/> <ExtensionPoint name="repository.navigation" props={extensionProps} renderAll={true} />
<SubNavigation <SubNavigation
to={`${url}/settings/general`} to={`${url}/settings/general`}
label={t("repositoryRoot.menu.settingsNavLink")} label={t("repositoryRoot.menu.settingsNavLink")}
title={t("repositoryRoot.menu.settingsNavLink")} title={t("repositoryRoot.menu.settingsNavLink")}
> >
<EditRepoNavLink repository={repository} editUrl={`${url}/settings/general`}/> <EditRepoNavLink repository={repository} editUrl={`${url}/settings/general`} />
<PermissionsNavLink permissionUrl={`${url}/settings/permissions`} repository={repository}/> <PermissionsNavLink permissionUrl={`${url}/settings/permissions`} repository={repository} />
<ExtensionPoint name="repository.setting" props={extensionProps} renderAll={true}/> <ExtensionPoint name="repository.setting" props={extensionProps} renderAll={true} />
</SubNavigation> </SubNavigation>
</SecondaryNavigation> </SecondaryNavigation>
</SecondaryNavigationColumn> </SecondaryNavigationColumn>
@@ -296,7 +294,7 @@ class RepositoryRoot extends React.Component<Props> {
} }
const mapStateToProps = (state: any, ownProps: Props) => { const mapStateToProps = (state: any, ownProps: Props) => {
const {namespace, name} = ownProps.match.params; const { namespace, name } = ownProps.match.params;
const repository = getRepository(state, namespace, name); const repository = getRepository(state, namespace, name);
const loading = isFetchRepoPending(state, namespace, name); const loading = isFetchRepoPending(state, namespace, name);
const error = getFetchRepoFailure(state, namespace, name); const error = getFetchRepoFailure(state, namespace, name);