Add settings icon to namespace group header

This commit is contained in:
René Pfeuffer
2020-09-17 08:21:31 +02:00
parent 0414da0f32
commit c679c064f3
7 changed files with 44 additions and 10 deletions

View File

@@ -27,7 +27,7 @@ import classNames from "classnames";
import styled from "styled-components"; import styled from "styled-components";
type Props = { type Props = {
name: string; name: ReactNode;
url?: string; url?: string;
elements: ReactNode[]; elements: ReactNode[];
}; };

View File

@@ -58,5 +58,6 @@ export type NamespaceCollection = {
export type RepositoryGroup = { export type RepositoryGroup = {
name: string; name: string;
namespace: Namespace;
repositories: Repository[]; repositories: Repository[];
}; };

View File

@@ -22,8 +22,10 @@
* SOFTWARE. * SOFTWARE.
*/ */
import React from "react"; import React from "react";
import { Link } from "react-router-dom";
import { CardColumnGroup, RepositoryEntry } from "@scm-manager/ui-components"; import { CardColumnGroup, RepositoryEntry } from "@scm-manager/ui-components";
import { RepositoryGroup } from "@scm-manager/ui-types"; import { RepositoryGroup } from "@scm-manager/ui-types";
import { Icon } from "@scm-manager/ui-components";
type Props = { type Props = {
group: RepositoryGroup; group: RepositoryGroup;
@@ -32,10 +34,23 @@ type Props = {
class RepositoryGroupEntry extends React.Component<Props> { class RepositoryGroupEntry extends React.Component<Props> {
render() { render() {
const { group } = this.props; const { group } = this.props;
const settingsLink = group.namespace?._links?.permissions && (
<Link to={`/namespace/${group.name}/settings`}>
<Icon color={"is-link"} name={"cog"} />
</Link>
);
const namespaceHeader = (
<>
<Link to={`/repos/${group.name}/`} className={"has-text-dark"}>
{group.name}
</Link>{" "}
{settingsLink}
</>
);
const entries = group.repositories.map((repository, index) => { const entries = group.repositories.map((repository, index) => {
return <RepositoryEntry repository={repository} key={index} />; return <RepositoryEntry repository={repository} key={index} />;
}); });
return <CardColumnGroup name={group.name} url={`/repos/${group.name}/`} elements={entries} />; return <CardColumnGroup name={namespaceHeader} elements={entries} />;
} }
} }

View File

@@ -23,20 +23,21 @@
*/ */
import React from "react"; import React from "react";
import { Repository } from "@scm-manager/ui-types"; import { NamespaceCollection, Repository } from "@scm-manager/ui-types";
import groupByNamespace from "./groupByNamespace"; import groupByNamespace from "./groupByNamespace";
import RepositoryGroupEntry from "./RepositoryGroupEntry"; import RepositoryGroupEntry from "./RepositoryGroupEntry";
type Props = { type Props = {
repositories: Repository[]; repositories: Repository[];
namespaces: NamespaceCollection;
}; };
class RepositoryList extends React.Component<Props> { class RepositoryList extends React.Component<Props> {
render() { render() {
const { repositories } = this.props; const { repositories, namespaces } = this.props;
const groups = groupByNamespace(repositories); const groups = groupByNamespace(repositories, namespaces);
return ( return (
<div className="content"> <div className="content">
{groups.map(group => { {groups.map(group => {

View File

@@ -73,21 +73,29 @@ it("should group the repositories by their namespace", () => {
hitchhikerHeartOfGold, hitchhikerHeartOfGold,
hitchhikerPuzzle42 hitchhikerPuzzle42
]; ];
const namespaces = {
_embedded: {
namespaces: [{ namespace: "hitchhiker" }, { namespace: "slarti" }, { namespace: "zaphod" }]
}
};
const expected = [ const expected = [
{ {
name: "hitchhiker", name: "hitchhiker",
namespace: { namespace: "hitchhiker" },
repositories: [hitchhikerHeartOfGold, hitchhikerPuzzle42, hitchhikerRestand] repositories: [hitchhikerHeartOfGold, hitchhikerPuzzle42, hitchhikerRestand]
}, },
{ {
name: "slarti", name: "slarti",
namespace: { namespace: "slarti" },
repositories: [slartiFjords, slartiBlueprintsFjords] repositories: [slartiFjords, slartiBlueprintsFjords]
}, },
{ {
name: "zaphod", name: "zaphod",
namespace: { namespace: "zaphod" },
repositories: [zaphodMarvinFirmware] repositories: [zaphodMarvinFirmware]
} }
]; ];
expect(groupByNamespace(repositories)).toEqual(expected); expect(groupByNamespace(repositories, namespaces)).toEqual(expected);
}); });

View File

@@ -22,17 +22,22 @@
* SOFTWARE. * SOFTWARE.
*/ */
import { Repository, RepositoryGroup } from "@scm-manager/ui-types"; import { NamespaceCollection, Repository, RepositoryGroup } from "@scm-manager/ui-types";
export default function groupByNamespace(repositories: Repository[]): RepositoryGroup[] { export default function groupByNamespace(
repositories: Repository[],
namespaces: NamespaceCollection
): RepositoryGroup[] {
const groups = {}; const groups = {};
for (const repository of repositories) { for (const repository of repositories) {
const groupName = repository.namespace; const groupName = repository.namespace;
let group = groups[groupName]; let group = groups[groupName];
if (!group) { if (!group) {
const namespace = findNamespace(namespaces, groupName);
group = { group = {
name: groupName, name: groupName,
namespace: namespace,
repositories: [] repositories: []
}; };
groups[groupName] = group; groups[groupName] = group;
@@ -58,3 +63,7 @@ function sortByName(a, b) {
} }
return 0; return 0;
} }
function findNamespace(namespaces: NamespaceCollection, namespaceToFind: string) {
return namespaces._embedded.namespaces.filter(namespace => namespace.namespace === namespaceToFind)[0];
}

View File

@@ -133,12 +133,12 @@ class Overview extends React.Component<Props> {
} }
renderRepositoryList() { renderRepositoryList() {
const { collection, page, location, t } = this.props; const { collection, page, location, namespaces, t } = this.props;
if (collection._embedded && collection._embedded.repositories.length > 0) { if (collection._embedded && collection._embedded.repositories.length > 0) {
return ( return (
<> <>
<RepositoryList repositories={collection._embedded.repositories} /> <RepositoryList repositories={collection._embedded.repositories} namespaces={namespaces} />
<LinkPaginator collection={collection} page={page} filter={urls.getQueryStringFromLocation(location)} /> <LinkPaginator collection={collection} page={page} filter={urls.getQueryStringFromLocation(location)} />
</> </>
); );