mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-08 22:45:45 +01:00
Add files to empty repository (#1717)
It should also be possible to create new files in empty non-initiated repositories with the help of scm-manager/scm-editor-plugin/pull/39. So that the plugin can mount itself, a new endpoint was provided hereby. Co-authored-by: Eduard Heimbuch <eduard.heimbuch@cloudogu.com>
This commit is contained in:
2
gradle/changelog/add_files_to_empty_repo.yaml
Normal file
2
gradle/changelog/add_files_to_empty_repo.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
- type: Added
|
||||||
|
description: Create files in empty non-initiated repositories ([#1717](https://github.com/scm-manager/scm-manager/pull/1717))
|
||||||
@@ -26,12 +26,12 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { useHistory, useLocation, Link } from "react-router-dom";
|
import { useHistory, useLocation, Link } from "react-router-dom";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { binder, ExtensionPoint } from "@scm-manager/ui-extensions";
|
import { urls } from "@scm-manager/ui-api";
|
||||||
import { Branch, Repository, File } from "@scm-manager/ui-types";
|
import { Branch, Repository, File } from "@scm-manager/ui-types";
|
||||||
|
import { binder, ExtensionPoint, extensionPoints } from "@scm-manager/ui-extensions";
|
||||||
import Icon from "./Icon";
|
import Icon from "./Icon";
|
||||||
import Tooltip from "./Tooltip";
|
import Tooltip from "./Tooltip";
|
||||||
import copyToClipboard from "./CopyToClipboard";
|
import copyToClipboard from "./CopyToClipboard";
|
||||||
import { urls } from "@scm-manager/ui-api";
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
repository: Repository;
|
repository: Repository;
|
||||||
@@ -65,8 +65,6 @@ const BreadcrumbNav = styled.nav`
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 1rem 1rem !important;
|
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
/* move slash to end */
|
/* move slash to end */
|
||||||
@@ -127,7 +125,7 @@ const Breadcrumb: FC<Props> = ({
|
|||||||
baseUrl,
|
baseUrl,
|
||||||
sources,
|
sources,
|
||||||
permalink,
|
permalink,
|
||||||
preButtons
|
preButtons,
|
||||||
}) => {
|
}) => {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
@@ -138,7 +136,10 @@ const Breadcrumb: FC<Props> = ({
|
|||||||
if (path) {
|
if (path) {
|
||||||
const paths = path.split("/");
|
const paths = path.split("/");
|
||||||
return paths.map((pathFragment, index) => {
|
return paths.map((pathFragment, index) => {
|
||||||
const currPath = paths.slice(0, index + 1).join("/");
|
let currPath = paths.slice(0, index + 1).join("/");
|
||||||
|
if (!currPath.endsWith("/")) {
|
||||||
|
currPath = currPath + "/";
|
||||||
|
}
|
||||||
if (paths.length - 1 === index) {
|
if (paths.length - 1 === index) {
|
||||||
return (
|
return (
|
||||||
<li className="is-active" key={index}>
|
<li className="is-active" key={index}>
|
||||||
@@ -172,15 +173,45 @@ const Breadcrumb: FC<Props> = ({
|
|||||||
).finally(() => setCopying(false));
|
).finally(() => setCopying(false));
|
||||||
};
|
};
|
||||||
|
|
||||||
let homeUrl = baseUrl + "/";
|
const renderBreadcrumbNav = () => {
|
||||||
if (revision) {
|
let prefixButtons = null;
|
||||||
homeUrl += encodeURIComponent(revision) + "/";
|
if (preButtons) {
|
||||||
}
|
prefixButtons = <PrefixButton>{preButtons}</PrefixButton>;
|
||||||
|
}
|
||||||
|
|
||||||
let prefixButtons = null;
|
let homeUrl = baseUrl + "/";
|
||||||
if (preButtons) {
|
if (revision) {
|
||||||
prefixButtons = <PrefixButton>{preButtons}</PrefixButton>;
|
homeUrl += encodeURIComponent(revision) + "/";
|
||||||
}
|
} else {
|
||||||
|
homeUrl = `/repo/${repository.namespace}/${repository.name}/code/sources/`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BreadcrumbNav
|
||||||
|
className={classNames("breadcrumb", "sources-breadcrumb", "mx-2", "my-4")}
|
||||||
|
aria-label="breadcrumbs"
|
||||||
|
>
|
||||||
|
{prefixButtons}
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<Link to={homeUrl}>
|
||||||
|
<HomeIcon title={t("breadcrumb.home")} name="home" color="inherit" />
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
{pathSection()}
|
||||||
|
</ul>
|
||||||
|
<PermaLinkWrapper className="ml-1">
|
||||||
|
{copying ? (
|
||||||
|
<Icon name="spinner fa-spin" />
|
||||||
|
) : (
|
||||||
|
<Tooltip message={t("breadcrumb.copyPermalink")}>
|
||||||
|
<Icon name="link" color="inherit" onClick={() => copySource()} />
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</PermaLinkWrapper>
|
||||||
|
</BreadcrumbNav>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const extProps = {
|
const extProps = {
|
||||||
baseUrl,
|
baseUrl,
|
||||||
@@ -188,40 +219,33 @@ const Breadcrumb: FC<Props> = ({
|
|||||||
branch: branch ? branch : defaultBranch,
|
branch: branch ? branch : defaultBranch,
|
||||||
path,
|
path,
|
||||||
sources,
|
sources,
|
||||||
repository
|
repository,
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderExtensionPoints = () => {
|
||||||
|
if (
|
||||||
|
binder.hasExtension<extensionPoints.ReposSourcesEmptyActionbar>("repos.sources.empty.actionbar") &&
|
||||||
|
sources?._embedded?.children?.length === 0
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<ExtensionPoint
|
||||||
|
name="repos.sources.empty.actionbar"
|
||||||
|
props={{ repository, sources }}
|
||||||
|
renderAll={true}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (binder.hasExtension<extensionPoints.ReposSourcesActionbar>("repos.sources.actionbar")) {
|
||||||
|
return <ExtensionPoint name="repos.sources.actionbar" props={extProps} renderAll={true} />;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="is-flex is-align-items-center">
|
<div className="is-flex is-align-items-center is-justify-content-flex-end">
|
||||||
<BreadcrumbNav
|
{renderBreadcrumbNav()}
|
||||||
className={classNames("breadcrumb", "sources-breadcrumb", "ml-1", "mb-0")}
|
{<ActionBar className="my-2">{renderExtensionPoints()}</ActionBar>}
|
||||||
aria-label="breadcrumbs"
|
|
||||||
>
|
|
||||||
{prefixButtons}
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<Link to={homeUrl}>
|
|
||||||
<HomeIcon title={t("breadcrumb.home")} name="home" color="inherit" />
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
{pathSection()}
|
|
||||||
</ul>
|
|
||||||
<PermaLinkWrapper className="ml-1">
|
|
||||||
{copying ? (
|
|
||||||
<Icon name="spinner fa-spin" />
|
|
||||||
) : (
|
|
||||||
<Tooltip message={t("breadcrumb.copyPermalink")}>
|
|
||||||
<Icon name="link" color="inherit" onClick={() => copySource()} />
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</PermaLinkWrapper>
|
|
||||||
</BreadcrumbNav>
|
|
||||||
{binder.hasExtension("repos.sources.actionbar") && (
|
|
||||||
<ActionBar>
|
|
||||||
<ExtensionPoint name="repos.sources.actionbar" props={extProps} renderAll={true} />
|
|
||||||
</ActionBar>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<hr className="is-marginless" />
|
<hr className="is-marginless" />
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -1663,11 +1663,11 @@ exports[`Storyshots BreadCrumb Default 1`] = `
|
|||||||
className="Breadcrumbstories__Wrapper-sc-1eq8sgz-0 exRctT"
|
className="Breadcrumbstories__Wrapper-sc-1eq8sgz-0 exRctT"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="is-flex is-align-items-center"
|
className="is-flex is-align-items-center is-justify-content-flex-end"
|
||||||
>
|
>
|
||||||
<nav
|
<nav
|
||||||
aria-label="breadcrumbs"
|
aria-label="breadcrumbs"
|
||||||
className="Breadcrumb__BreadcrumbNav-zvtb4t-1 ieUHOq breadcrumb sources-breadcrumb ml-1 mb-0"
|
className="Breadcrumb__BreadcrumbNav-zvtb4t-1 eupowG breadcrumb sources-breadcrumb mx-2 my-4"
|
||||||
>
|
>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@@ -1684,7 +1684,7 @@ exports[`Storyshots BreadCrumb Default 1`] = `
|
|||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
className="is-ellipsis-overflow"
|
className="is-ellipsis-overflow"
|
||||||
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/src"
|
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/src/"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
title="src"
|
title="src"
|
||||||
>
|
>
|
||||||
@@ -1694,7 +1694,7 @@ exports[`Storyshots BreadCrumb Default 1`] = `
|
|||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
className="is-ellipsis-overflow"
|
className="is-ellipsis-overflow"
|
||||||
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/src/main"
|
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/src/main/"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
title="main"
|
title="main"
|
||||||
>
|
>
|
||||||
@@ -1704,7 +1704,7 @@ exports[`Storyshots BreadCrumb Default 1`] = `
|
|||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
className="is-ellipsis-overflow"
|
className="is-ellipsis-overflow"
|
||||||
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/src/main/java"
|
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/src/main/java/"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
title="java"
|
title="java"
|
||||||
>
|
>
|
||||||
@@ -1714,7 +1714,7 @@ exports[`Storyshots BreadCrumb Default 1`] = `
|
|||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
className="is-ellipsis-overflow"
|
className="is-ellipsis-overflow"
|
||||||
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/src/main/java/com"
|
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/src/main/java/com/"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
title="com"
|
title="com"
|
||||||
>
|
>
|
||||||
@@ -1748,6 +1748,9 @@ exports[`Storyshots BreadCrumb Default 1`] = `
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</nav>
|
</nav>
|
||||||
|
<div
|
||||||
|
className="Breadcrumb__ActionBar-zvtb4t-3 izqSnl my-2"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<hr
|
<hr
|
||||||
className="is-marginless"
|
className="is-marginless"
|
||||||
@@ -1760,11 +1763,11 @@ exports[`Storyshots BreadCrumb Long path 1`] = `
|
|||||||
className="Breadcrumbstories__Wrapper-sc-1eq8sgz-0 exRctT"
|
className="Breadcrumbstories__Wrapper-sc-1eq8sgz-0 exRctT"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="is-flex is-align-items-center"
|
className="is-flex is-align-items-center is-justify-content-flex-end"
|
||||||
>
|
>
|
||||||
<nav
|
<nav
|
||||||
aria-label="breadcrumbs"
|
aria-label="breadcrumbs"
|
||||||
className="Breadcrumb__BreadcrumbNav-zvtb4t-1 ieUHOq breadcrumb sources-breadcrumb ml-1 mb-0"
|
className="Breadcrumb__BreadcrumbNav-zvtb4t-1 eupowG breadcrumb sources-breadcrumb mx-2 my-4"
|
||||||
>
|
>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
@@ -1781,7 +1784,7 @@ exports[`Storyshots BreadCrumb Long path 1`] = `
|
|||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
className="is-ellipsis-overflow"
|
className="is-ellipsis-overflow"
|
||||||
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path"
|
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
title="dream-path"
|
title="dream-path"
|
||||||
>
|
>
|
||||||
@@ -1791,7 +1794,7 @@ exports[`Storyshots BreadCrumb Long path 1`] = `
|
|||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
className="is-ellipsis-overflow"
|
className="is-ellipsis-overflow"
|
||||||
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/src"
|
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/src/"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
title="src"
|
title="src"
|
||||||
>
|
>
|
||||||
@@ -1801,7 +1804,7 @@ exports[`Storyshots BreadCrumb Long path 1`] = `
|
|||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
className="is-ellipsis-overflow"
|
className="is-ellipsis-overflow"
|
||||||
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/src/main"
|
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/src/main/"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
title="main"
|
title="main"
|
||||||
>
|
>
|
||||||
@@ -1811,7 +1814,7 @@ exports[`Storyshots BreadCrumb Long path 1`] = `
|
|||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
className="is-ellipsis-overflow"
|
className="is-ellipsis-overflow"
|
||||||
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/src/main/scm-plugins"
|
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/src/main/scm-plugins/"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
title="scm-plugins"
|
title="scm-plugins"
|
||||||
>
|
>
|
||||||
@@ -1821,7 +1824,7 @@ exports[`Storyshots BreadCrumb Long path 1`] = `
|
|||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
className="is-ellipsis-overflow"
|
className="is-ellipsis-overflow"
|
||||||
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/src/main/scm-plugins/javaUtilityHomeHousingLinkReferrer"
|
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/src/main/scm-plugins/javaUtilityHomeHousingLinkReferrer/"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
title="javaUtilityHomeHousingLinkReferrer"
|
title="javaUtilityHomeHousingLinkReferrer"
|
||||||
>
|
>
|
||||||
@@ -1831,7 +1834,7 @@ exports[`Storyshots BreadCrumb Long path 1`] = `
|
|||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
className="is-ellipsis-overflow"
|
className="is-ellipsis-overflow"
|
||||||
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/src/main/scm-plugins/javaUtilityHomeHousingLinkReferrer/sonia"
|
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/src/main/scm-plugins/javaUtilityHomeHousingLinkReferrer/sonia/"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
title="sonia"
|
title="sonia"
|
||||||
>
|
>
|
||||||
@@ -1841,7 +1844,7 @@ exports[`Storyshots BreadCrumb Long path 1`] = `
|
|||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
className="is-ellipsis-overflow"
|
className="is-ellipsis-overflow"
|
||||||
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/src/main/scm-plugins/javaUtilityHomeHousingLinkReferrer/sonia/scm"
|
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/src/main/scm-plugins/javaUtilityHomeHousingLinkReferrer/sonia/scm/"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
title="scm"
|
title="scm"
|
||||||
>
|
>
|
||||||
@@ -1851,7 +1854,7 @@ exports[`Storyshots BreadCrumb Long path 1`] = `
|
|||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
className="is-ellipsis-overflow"
|
className="is-ellipsis-overflow"
|
||||||
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/src/main/scm-plugins/javaUtilityHomeHousingLinkReferrer/sonia/scm/repositoryUndergroundSupportManager"
|
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/src/main/scm-plugins/javaUtilityHomeHousingLinkReferrer/sonia/scm/repositoryUndergroundSupportManager/"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
title="repositoryUndergroundSupportManager"
|
title="repositoryUndergroundSupportManager"
|
||||||
>
|
>
|
||||||
@@ -1861,7 +1864,7 @@ exports[`Storyshots BreadCrumb Long path 1`] = `
|
|||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
className="is-ellipsis-overflow"
|
className="is-ellipsis-overflow"
|
||||||
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/src/main/scm-plugins/javaUtilityHomeHousingLinkReferrer/sonia/scm/repositoryUndergroundSupportManager/spi"
|
href="/scm-manager.org/scm/repo/hitchhiker/heartOfGold/sources/1/dream-path/src/main/scm-plugins/javaUtilityHomeHousingLinkReferrer/sonia/scm/repositoryUndergroundSupportManager/spi/"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
title="spi"
|
title="spi"
|
||||||
>
|
>
|
||||||
@@ -1895,6 +1898,9 @@ exports[`Storyshots BreadCrumb Long path 1`] = `
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</nav>
|
</nav>
|
||||||
|
<div
|
||||||
|
className="Breadcrumb__ActionBar-zvtb4t-3 izqSnl my-2"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<hr
|
<hr
|
||||||
className="is-marginless"
|
className="is-marginless"
|
||||||
|
|||||||
@@ -22,14 +22,16 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ExtensionPointDefinition } from "./binder";
|
import React from "react";
|
||||||
import {
|
import {
|
||||||
|
Branch,
|
||||||
IndexResources,
|
IndexResources,
|
||||||
NamespaceStrategies,
|
NamespaceStrategies,
|
||||||
Repository,
|
Repository,
|
||||||
RepositoryCreation,
|
RepositoryCreation,
|
||||||
RepositoryTypeCollection,
|
RepositoryTypeCollection,
|
||||||
} from "@scm-manager/ui-types";
|
} from "@scm-manager/ui-types";
|
||||||
|
import { ExtensionPointDefinition } from "./binder";
|
||||||
|
|
||||||
type RepositoryCreatorSubFormProps = {
|
type RepositoryCreatorSubFormProps = {
|
||||||
repository: RepositoryCreation;
|
repository: RepositoryCreation;
|
||||||
@@ -58,3 +60,24 @@ export type RepositoryCreatorExtension = {
|
|||||||
export type RepositoryCreator = ExtensionPointDefinition<"repos.creator", RepositoryCreatorExtension>;
|
export type RepositoryCreator = ExtensionPointDefinition<"repos.creator", RepositoryCreatorExtension>;
|
||||||
|
|
||||||
export type RepositoryFlags = ExtensionPointDefinition<"repository.flags", { repository: Repository }>;
|
export type RepositoryFlags = ExtensionPointDefinition<"repository.flags", { repository: Repository }>;
|
||||||
|
|
||||||
|
export type ReposSourcesActionbarExtensionProps = {
|
||||||
|
baseUrl: string;
|
||||||
|
revision: string;
|
||||||
|
branch: Branch | undefined;
|
||||||
|
path: string;
|
||||||
|
sources: File;
|
||||||
|
repository: Repository;
|
||||||
|
};
|
||||||
|
export type ReposSourcesActionbarExtension = React.ComponentType<ReposSourcesActionbarExtensionProps>;
|
||||||
|
export type ReposSourcesActionbar = ExtensionPointDefinition<"repos.sources.actionbar", ReposSourcesActionbarExtension>;
|
||||||
|
|
||||||
|
export type ReposSourcesEmptyActionbarExtensionProps = {
|
||||||
|
sources: File;
|
||||||
|
repository: Repository;
|
||||||
|
};
|
||||||
|
export type ReposSourcesEmptyActionbarExtension = ReposSourcesActionbarExtension;
|
||||||
|
export type ReposSourcesEmptyActionbar = ExtensionPointDefinition<
|
||||||
|
"repos.sources.empty.actionbar",
|
||||||
|
ReposSourcesEmptyActionbarExtension
|
||||||
|
>;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import { Route, useLocation } from "react-router-dom";
|
|||||||
import Sources from "../../sources/containers/Sources";
|
import Sources from "../../sources/containers/Sources";
|
||||||
import ChangesetsRoot from "../../containers/ChangesetsRoot";
|
import ChangesetsRoot from "../../containers/ChangesetsRoot";
|
||||||
import { Branch, Repository } from "@scm-manager/ui-types";
|
import { Branch, Repository } from "@scm-manager/ui-types";
|
||||||
import { ErrorPage, Loading, Notification } from "@scm-manager/ui-components";
|
import { ErrorPage, Loading } from "@scm-manager/ui-components";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useBranches } from "@scm-manager/ui-api";
|
import { useBranches } from "@scm-manager/ui-api";
|
||||||
import FileSearch from "./FileSearch";
|
import FileSearch from "./FileSearch";
|
||||||
@@ -71,7 +71,7 @@ const CodeOverviewWithBranches: FC<Props> = ({ repository, baseUrl }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (branches.length === 0) {
|
if (branches.length === 0) {
|
||||||
return <Notification type="info">{t("code.noBranches")}</Notification>;
|
return <Sources repository={repository} baseUrl={baseUrl} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <CodeRouting repository={repository} baseUrl={baseUrl} branches={branches} selectedBranch={selectedBranch} />;
|
return <CodeRouting repository={repository} baseUrl={baseUrl} branches={branches} selectedBranch={selectedBranch} />;
|
||||||
|
|||||||
@@ -22,17 +22,17 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
import React, { FC, useEffect } from "react";
|
import React, { FC, useEffect } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useHistory, useLocation, useParams } from "react-router-dom";
|
||||||
|
import { useSources } from "@scm-manager/ui-api";
|
||||||
import { Branch, Repository } from "@scm-manager/ui-types";
|
import { Branch, Repository } from "@scm-manager/ui-types";
|
||||||
import { Breadcrumb, Loading, Notification } from "@scm-manager/ui-components";
|
import { Breadcrumb, Loading, Notification } from "@scm-manager/ui-components";
|
||||||
import FileTree from "../components/FileTree";
|
import FileTree from "../components/FileTree";
|
||||||
import Content from "./Content";
|
import Content from "./Content";
|
||||||
import CodeActionBar from "../../codeSection/components/CodeActionBar";
|
import CodeActionBar from "../../codeSection/components/CodeActionBar";
|
||||||
import replaceBranchWithRevision from "../ReplaceBranchWithRevision";
|
import replaceBranchWithRevision from "../ReplaceBranchWithRevision";
|
||||||
import { useSources } from "@scm-manager/ui-api";
|
|
||||||
import { useHistory, useLocation, useParams } from "react-router-dom";
|
|
||||||
import FileSearchButton from "../../codeSection/components/FileSearchButton";
|
import FileSearchButton from "../../codeSection/components/FileSearchButton";
|
||||||
import { isEmptyDirectory, isRootFile } from "../utils/files";
|
import { isEmptyDirectory, isRootFile } from "../utils/files";
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
repository: Repository;
|
repository: Repository;
|
||||||
@@ -84,6 +84,10 @@ const Sources: FC<Props> = ({ repository, branches, selectedBranch, baseUrl }) =
|
|||||||
return <Loading />;
|
return <Loading />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!file) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
const onSelectBranch = (branch?: Branch) => {
|
const onSelectBranch = (branch?: Branch) => {
|
||||||
let url;
|
let url;
|
||||||
if (branch) {
|
if (branch) {
|
||||||
@@ -129,18 +133,17 @@ const Sources: FC<Props> = ({ repository, branches, selectedBranch, baseUrl }) =
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (file && file.directory) {
|
const renderPanelContent = () => {
|
||||||
let body;
|
if (file.directory) {
|
||||||
if (isRootFile(file) && isEmptyDirectory(file)) {
|
let body;
|
||||||
body = (
|
if (isRootFile(file) && isEmptyDirectory(file)) {
|
||||||
<div className="panel-block">
|
body = (
|
||||||
<Notification type="info">{t("sources.noSources")}</Notification>
|
<div className="panel-block">
|
||||||
</div>
|
<Notification type="info">{t("sources.noSources")}</Notification>
|
||||||
);
|
</div>
|
||||||
} else {
|
);
|
||||||
body = (
|
} else {
|
||||||
<>
|
body = (
|
||||||
{renderBreadcrumb()}
|
|
||||||
<FileTree
|
<FileTree
|
||||||
directory={file}
|
directory={file}
|
||||||
revision={revision || file.revision}
|
revision={revision || file.revision}
|
||||||
@@ -148,40 +151,45 @@ const Sources: FC<Props> = ({ repository, branches, selectedBranch, baseUrl }) =
|
|||||||
isFetchingNextPage={isFetchingNextPage}
|
isFetchingNextPage={isFetchingNextPage}
|
||||||
fetchNextPage={fetchNextPage}
|
fetchNextPage={fetchNextPage}
|
||||||
/>
|
/>
|
||||||
</>
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="panel">
|
||||||
|
{renderBreadcrumb()}
|
||||||
|
{body}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Content
|
||||||
|
file={file}
|
||||||
|
repository={repository}
|
||||||
|
revision={revision || file.revision}
|
||||||
|
breadcrumb={renderBreadcrumb()}
|
||||||
|
error={error || undefined}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const hasBranchesWhenSupporting = (repository: Repository) => {
|
||||||
|
return !repository._links.branches || (branches && branches.length !== 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{hasBranchesWhenSupporting(repository) && (
|
||||||
<CodeActionBar
|
<CodeActionBar
|
||||||
selectedBranch={selectedBranch}
|
selectedBranch={selectedBranch}
|
||||||
branches={branches}
|
branches={branches}
|
||||||
onSelectBranch={onSelectBranch}
|
onSelectBranch={onSelectBranch}
|
||||||
switchViewLink={evaluateSwitchViewLink()}
|
switchViewLink={evaluateSwitchViewLink()}
|
||||||
/>
|
/>
|
||||||
<div className="panel">{body}</div>
|
)}
|
||||||
</>
|
{renderPanelContent()}
|
||||||
);
|
</>
|
||||||
} else {
|
);
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<CodeActionBar
|
|
||||||
selectedBranch={selectedBranch}
|
|
||||||
branches={branches}
|
|
||||||
onSelectBranch={onSelectBranch}
|
|
||||||
switchViewLink={evaluateSwitchViewLink()}
|
|
||||||
/>
|
|
||||||
<Content
|
|
||||||
file={file}
|
|
||||||
repository={repository}
|
|
||||||
revision={revision || file.revision}
|
|
||||||
breadcrumb={renderBreadcrumb()}
|
|
||||||
error={error}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Sources;
|
export default Sources;
|
||||||
|
|||||||
@@ -28,14 +28,14 @@ export const isRootPath = (path: string) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const isRootFile = (file: File) => {
|
export const isRootFile = (file: File) => {
|
||||||
if (!file.directory) {
|
if (!file?.directory) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return isRootPath(file.path);
|
return isRootPath(file.path);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isEmptyDirectory = (file: File) => {
|
export const isEmptyDirectory = (file: File) => {
|
||||||
if (!file.directory) {
|
if (!file?.directory) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (file._embedded?.children?.length || 0) === 0;
|
return (file._embedded?.children?.length || 0) === 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user