mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-02 11:35:57 +01:00
Merge pull request #1331 from scm-manager/feature/tag_overview
Feature/tag overview
This commit is contained in:
@@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## Unreleased
|
||||
### Added
|
||||
- Tags overview for repository [#1331](https://github.com/scm-manager/scm-manager/pull/1331)
|
||||
|
||||
### Fixed
|
||||
- Missing synchronization during repository creation ([#1328](https://github.com/scm-manager/scm-manager/pull/1328))
|
||||
- Missing BranchCreatedEvent for mercurial ([#1334](https://github.com/scm-manager/scm-manager/pull/1334))
|
||||
|
||||
BIN
docs/de/user/repo/assets/repository-tag-detailView.png
Normal file
BIN
docs/de/user/repo/assets/repository-tag-detailView.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
BIN
docs/de/user/repo/assets/repository-tags-overview.png
Normal file
BIN
docs/de/user/repo/assets/repository-tags-overview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 47 KiB |
@@ -6,6 +6,7 @@ partiallyActive: true
|
||||
Der Bereich Repository umfasst alles auf Basis von Repositories in Namespaces. Dazu zählen alle Operationen auf Branches, der Code und Einstellungen.
|
||||
|
||||
* [Branches](branches/)
|
||||
* [Tags](tags/)
|
||||
* [Code](code/)
|
||||
* [Einstellungen](settings/)
|
||||
<!--- AppendLinkContentEnd -->
|
||||
|
||||
13
docs/de/user/repo/tags.md
Normal file
13
docs/de/user/repo/tags.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: Repository
|
||||
subtitle: Tags
|
||||
---
|
||||
### Übersicht
|
||||
Auf der Tags-Übersicht sind die existierenden Tags nach Erstelldatum absteigend aufgeführt. Bei einem Klick auf einen Tag wird der Benutzer zur Detailseite des Tags weitergeleitet.
|
||||
|
||||

|
||||
|
||||
### Tag Detailseite
|
||||
Hier wird ein Befehl zum Arbeiten mit dem Tag auf einer Kommandozeile aufgeführt.
|
||||
|
||||

|
||||
BIN
docs/en/user/repo/assets/repository-tag-detailView.png
Normal file
BIN
docs/en/user/repo/assets/repository-tag-detailView.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
BIN
docs/en/user/repo/assets/repository-tags-overview.png
Normal file
BIN
docs/en/user/repo/assets/repository-tags-overview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
@@ -5,6 +5,7 @@ partiallyActive: true
|
||||
The Repository area includes everything based on repositories in namespaces. This includes all operations on branches, the code and settings.
|
||||
|
||||
* [Branches](branches/)
|
||||
* [Tags](tags/)
|
||||
* [Code](code/)
|
||||
* [Settings](settings/)
|
||||
|
||||
|
||||
13
docs/en/user/repo/tags.md
Normal file
13
docs/en/user/repo/tags.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: Repository
|
||||
subtitle: Tags
|
||||
---
|
||||
### Overview
|
||||
The tag overview shows the tags that exist for this repository. By clicking on a tag, the details page of the tag is shown.
|
||||
|
||||

|
||||
|
||||
### Tag Details Page
|
||||
This page shows a command to work with the tag on the command line.
|
||||
|
||||

|
||||
48
scm-plugins/scm-git-plugin/src/main/js/GitTagInformation.tsx
Normal file
48
scm-plugins/scm-git-plugin/src/main/js/GitTagInformation.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import React, { FC } from "react";
|
||||
import { Tag } from "@scm-manager/ui-types";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
type Props = {
|
||||
tag: Tag;
|
||||
};
|
||||
|
||||
const GitTagInformation: FC<Props> = ({ tag }) => {
|
||||
const [t] = useTranslation("plugins");
|
||||
|
||||
return (
|
||||
<>
|
||||
<h4>{t("scm-git-plugin.information.checkoutTag")}</h4>
|
||||
<pre>
|
||||
<code>
|
||||
git checkout tags/{tag.name} -b branch/{tag.name}
|
||||
</code>
|
||||
</pre>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default GitTagInformation;
|
||||
@@ -32,6 +32,7 @@ import GitGlobalConfiguration from "./GitGlobalConfiguration";
|
||||
import GitBranchInformation from "./GitBranchInformation";
|
||||
import GitMergeInformation from "./GitMergeInformation";
|
||||
import RepositoryConfig from "./RepositoryConfig";
|
||||
import GitTagInformation from "./GitTagInformation";
|
||||
|
||||
// repository
|
||||
|
||||
@@ -42,6 +43,7 @@ export const gitPredicate = (props: any) => {
|
||||
|
||||
binder.bind("repos.repository-details.information", ProtocolInformation, gitPredicate);
|
||||
binder.bind("repos.branch-details.information", GitBranchInformation, gitPredicate);
|
||||
binder.bind("repos.tag-details.information", GitTagInformation, gitPredicate);
|
||||
binder.bind("repos.repository-merge.information", GitMergeInformation, gitPredicate);
|
||||
binder.bind("repos.repository-avatar", GitAvatar, gitPredicate);
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"replace": "Ein bestehendes Repository aktualisieren",
|
||||
"fetch": "Remote-Änderungen herunterladen",
|
||||
"checkout": "Branch wechseln",
|
||||
"checkoutTag": "Tag als neuen Branch auschecken",
|
||||
"merge": {
|
||||
"heading": "Merge des Source Branch in den Target Branch",
|
||||
"checkout": "1. Sicherstellen, dass der Workspace aufgeräumt ist und der Target Branch ausgecheckt wurde.",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"replace": "Push an existing repository",
|
||||
"fetch": "Get remote changes",
|
||||
"checkout": "Switch branch",
|
||||
"checkoutTag": "Checkout tag as new branch",
|
||||
"merge": {
|
||||
"heading": "How to merge source branch into target branch",
|
||||
"checkout": "1. Make sure your workspace is clean and checkout target branch",
|
||||
|
||||
46
scm-plugins/scm-hg-plugin/src/main/js/HgTagInformation.tsx
Normal file
46
scm-plugins/scm-hg-plugin/src/main/js/HgTagInformation.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import React, { FC } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Tag } from "@scm-manager/ui-types";
|
||||
|
||||
type Props = {
|
||||
tag: Tag;
|
||||
};
|
||||
|
||||
const HgTagInformation: FC<Props> = ({ tag }) => {
|
||||
const [t] = useTranslation("plugins");
|
||||
|
||||
return (
|
||||
<>
|
||||
<h4>{t("scm-hg-plugin.information.checkoutTag")}</h4>
|
||||
<pre>
|
||||
<code>hg update {tag.name}</code>
|
||||
</pre>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default HgTagInformation;
|
||||
@@ -28,6 +28,7 @@ import HgAvatar from "./HgAvatar";
|
||||
import { ConfigurationBinder as cfgBinder } from "@scm-manager/ui-components";
|
||||
import HgGlobalConfiguration from "./HgGlobalConfiguration";
|
||||
import HgBranchInformation from "./HgBranchInformation";
|
||||
import HgTagInformation from "./HgTagInformation";
|
||||
|
||||
const hgPredicate = (props: any) => {
|
||||
return props.repository && props.repository.type === "hg";
|
||||
@@ -35,6 +36,7 @@ const hgPredicate = (props: any) => {
|
||||
|
||||
binder.bind("repos.repository-details.information", ProtocolInformation, hgPredicate);
|
||||
binder.bind("repos.branch-details.information", HgBranchInformation, hgPredicate);
|
||||
binder.bind("repos.tag-details.information", HgTagInformation, hgPredicate);
|
||||
binder.bind("repos.repository-avatar", HgAvatar, hgPredicate);
|
||||
|
||||
// bind global configuration
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
"create" : "Neues Repository erstellen",
|
||||
"replace" : "Ein bestehendes Repository aktualisieren",
|
||||
"fetch": "Remote-Änderungen herunterladen",
|
||||
"checkout": "Branch wechseln"
|
||||
"checkout": "Branch wechseln",
|
||||
"checkoutTag": "Tag auschecken"
|
||||
},
|
||||
"config": {
|
||||
"link": "Mercurial",
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
"create" : "Create a new repository",
|
||||
"replace" : "Push an existing repository",
|
||||
"fetch": "Get remote changes",
|
||||
"checkout": "Switch branch"
|
||||
"checkout": "Switch branch",
|
||||
"checkoutTag": "Checkout tag"
|
||||
},
|
||||
"config": {
|
||||
"link": "Mercurial",
|
||||
|
||||
@@ -27,5 +27,6 @@ import { Links } from "./hal";
|
||||
export type Tag = {
|
||||
name: string;
|
||||
revision: string;
|
||||
date?: Date;
|
||||
_links: Links;
|
||||
};
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
"navigationLabel": "Repository",
|
||||
"informationNavLink": "Informationen",
|
||||
"branchesNavLink": "Branches",
|
||||
"tagsNavLink": "Tags",
|
||||
"sourcesNavLink": "Code",
|
||||
"settingsNavLink": "Einstellungen",
|
||||
"generalNavLink": "Generell",
|
||||
@@ -69,6 +70,21 @@
|
||||
"sources": "Sources",
|
||||
"defaultTag": "Default"
|
||||
},
|
||||
"tags": {
|
||||
"overview": {
|
||||
"title": "Übersicht aller verfügbaren Tags",
|
||||
"noTags": "Keine Tags gefunden.",
|
||||
"created": "Erstellt"
|
||||
},
|
||||
"table": {
|
||||
"tags": "Tags"
|
||||
}
|
||||
},
|
||||
"tag": {
|
||||
"name": "Name",
|
||||
"commit": "Commit",
|
||||
"sources": "Sources"
|
||||
},
|
||||
"code": {
|
||||
"sources": "Sources",
|
||||
"commits": "Commits",
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
"navigationLabel": "Repository",
|
||||
"informationNavLink": "Information",
|
||||
"branchesNavLink": "Branches",
|
||||
"tagsNavLink": "Tags",
|
||||
"sourcesNavLink": "Code",
|
||||
"settingsNavLink": "Settings",
|
||||
"generalNavLink": "General",
|
||||
@@ -69,6 +70,21 @@
|
||||
"sources": "Sources",
|
||||
"defaultTag": "Default"
|
||||
},
|
||||
"tags": {
|
||||
"overview": {
|
||||
"title": "Overview of all tags",
|
||||
"noTags": "No tags found.",
|
||||
"created": "Created"
|
||||
},
|
||||
"table": {
|
||||
"tags": "Tags"
|
||||
}
|
||||
},
|
||||
"tag": {
|
||||
"name": "Name",
|
||||
"commit": "Commit",
|
||||
"sources": "Sources"
|
||||
},
|
||||
"code": {
|
||||
"sources": "Sources",
|
||||
"commits": "Commits",
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
import React from "react";
|
||||
import React, { FC } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Branch } from "@scm-manager/ui-types";
|
||||
import DefaultBranchTag from "./DefaultBranchTag";
|
||||
@@ -31,24 +31,18 @@ type Props = {
|
||||
branch: Branch;
|
||||
};
|
||||
|
||||
class BranchRow extends React.Component<Props> {
|
||||
renderLink(to: string, label: string, defaultBranch?: boolean) {
|
||||
return (
|
||||
<Link to={to} title={label}>
|
||||
{label} <DefaultBranchTag defaultBranch={defaultBranch} />
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { baseUrl, branch } = this.props;
|
||||
const BranchRow: FC<Props> = ({ baseUrl, branch }) => {
|
||||
const to = `${baseUrl}/${encodeURIComponent(branch.name)}/info`;
|
||||
return (
|
||||
<tr>
|
||||
<td>{this.renderLink(to, branch.name, branch.defaultBranch)}</td>
|
||||
<td>
|
||||
<Link to={to} title={branch.name}>
|
||||
{branch.name}
|
||||
<DefaultBranchTag defaultBranch={branch.defaultBranch} />
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default BranchRow;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
import { FAILURE_SUFFIX, PENDING_SUFFIX, RESET_SUFFIX, SUCCESS_SUFFIX } from "../../../modules/types";
|
||||
import { apiClient } from "@scm-manager/ui-components";
|
||||
import { Action, Branch, BranchRequest, Repository } from "@scm-manager/ui-types";
|
||||
import { Action, Branch, BranchRequest, Repository, Link } from "@scm-manager/ui-types";
|
||||
import { isPending } from "../../../modules/pending";
|
||||
import { getFailure } from "../../../modules/failure";
|
||||
|
||||
@@ -65,7 +65,7 @@ export function fetchBranches(repository: Repository) {
|
||||
return function(dispatch: any) {
|
||||
dispatch(fetchBranchesPending(repository));
|
||||
return apiClient
|
||||
.get(repository._links.branches.href)
|
||||
.get((repository._links.branches as Link).href)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
dispatch(fetchBranchesSuccess(data, repository));
|
||||
@@ -77,7 +77,7 @@ export function fetchBranches(repository: Repository) {
|
||||
}
|
||||
|
||||
export function fetchBranch(repository: Repository, name: string) {
|
||||
let link = repository._links.branches.href;
|
||||
let link = (repository._links.branches as Link).href;
|
||||
if (!link.endsWith("/")) {
|
||||
link += "/";
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@ import CodeOverview from "../codeSection/containers/CodeOverview";
|
||||
import ChangesetView from "./ChangesetView";
|
||||
import SourceExtensions from "../sources/containers/SourceExtensions";
|
||||
import { FileControlFactory, JumpToFileButton } from "@scm-manager/ui-components";
|
||||
import TagsOverview from "../tags/container/TagsOverview";
|
||||
import TagRoot from "../tags/container/TagRoot";
|
||||
|
||||
type Props = RouteComponentProps &
|
||||
WithTranslation & {
|
||||
@@ -99,6 +101,12 @@ class RepositoryRoot extends React.Component<Props> {
|
||||
return route.location.pathname.match(regex);
|
||||
};
|
||||
|
||||
matchesTags = (route: any) => {
|
||||
const url = this.matchedUrl();
|
||||
const regex = new RegExp(`${url}/tag/.+/info`);
|
||||
return route.location.pathname.match(regex);
|
||||
};
|
||||
|
||||
matchesCode = (route: any) => {
|
||||
const url = this.matchedUrl();
|
||||
const regex = new RegExp(`${url}(/code)/.*`);
|
||||
@@ -245,6 +253,15 @@ class RepositoryRoot extends React.Component<Props> {
|
||||
render={() => <BranchesOverview repository={repository} baseUrl={`${url}/branch`} />}
|
||||
/>
|
||||
<Route path={`${url}/branches/create`} render={() => <CreateBranch repository={repository} />} />
|
||||
<Route
|
||||
path={`${url}/tag/:tag`}
|
||||
render={() => <TagRoot repository={repository} baseUrl={`${url}/tag`} />}
|
||||
/>
|
||||
<Route
|
||||
path={`${url}/tags`}
|
||||
exact={true}
|
||||
render={() => <TagsOverview repository={repository} baseUrl={`${url}/tag`} />}
|
||||
/>
|
||||
<ExtensionPoint name="repository.route" props={extensionProps} renderAll={true} />
|
||||
</Switch>
|
||||
</PrimaryContentColumn>
|
||||
@@ -267,6 +284,16 @@ class RepositoryRoot extends React.Component<Props> {
|
||||
activeOnlyWhenExact={false}
|
||||
title={t("repositoryRoot.menu.branchesNavLink")}
|
||||
/>
|
||||
<RepositoryNavLink
|
||||
repository={repository}
|
||||
linkName="tags"
|
||||
to={`${url}/tags/`}
|
||||
icon="fas fa-tags"
|
||||
label={t("repositoryRoot.menu.tagsNavLink")}
|
||||
activeWhenMatch={this.matchesTags}
|
||||
activeOnlyWhenExact={false}
|
||||
title={t("repositoryRoot.menu.tagsNavLink")}
|
||||
/>
|
||||
<RepositoryNavLink
|
||||
repository={repository}
|
||||
linkName={this.getCodeLinkname()}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import React, { FC } from "react";
|
||||
import { Tag, Repository } from "@scm-manager/ui-types";
|
||||
import { Button, ButtonAddons } from "@scm-manager/ui-components";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
type Props = {
|
||||
repository: Repository;
|
||||
tag: Tag;
|
||||
};
|
||||
|
||||
const TagButtonGroup: FC<Props> = ({ repository, tag }) => {
|
||||
const [t] = useTranslation("repos");
|
||||
|
||||
const changesetLink = `/repo/${repository.namespace}/${repository.name}/code/changeset/${encodeURIComponent(
|
||||
tag.revision
|
||||
)}`;
|
||||
const sourcesLink = `/repo/${repository.namespace}/${repository.name}/sources/${encodeURIComponent(tag.revision)}/`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<ButtonAddons>
|
||||
<Button link={changesetLink} icon="exchange-alt" label={t("tag.commit")} reducedMobile={true} />
|
||||
<Button link={sourcesLink} icon="code" label={t("tag.sources")} reducedMobile={true} />
|
||||
</ButtonAddons>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagButtonGroup;
|
||||
73
scm-ui/ui-webapp/src/repos/tags/components/TagDetail.tsx
Normal file
73
scm-ui/ui-webapp/src/repos/tags/components/TagDetail.tsx
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import React, { FC } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Repository, Tag } from "@scm-manager/ui-types";
|
||||
import { DateFromNow, Level } from "@scm-manager/ui-components";
|
||||
import styled from "styled-components";
|
||||
import TagButtonGroup from "./TagButtonGroup";
|
||||
|
||||
type Props = {
|
||||
repository: Repository;
|
||||
tag: Tag;
|
||||
};
|
||||
|
||||
const FlexRow = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const Created = styled.div`
|
||||
margin-left: 0.5rem;
|
||||
font-size: 0.8rem;
|
||||
`;
|
||||
|
||||
const Label = styled.strong`
|
||||
margin-right: 0.3rem;
|
||||
`;
|
||||
|
||||
const Date = styled(DateFromNow)`
|
||||
font-size: 0.8rem;
|
||||
`;
|
||||
|
||||
const TagDetail: FC<Props> = ({ tag, repository }) => {
|
||||
const [t] = useTranslation("repos");
|
||||
|
||||
return (
|
||||
<div className="media">
|
||||
<FlexRow className="media-content subtitle">
|
||||
<Label>{t("tag.name") + ": "} </Label> {tag.name}
|
||||
<Created className="is-ellipsis-overflow">
|
||||
{t("tags.overview.created")} <Date date={tag.date} className="has-text-grey" />
|
||||
</Created>
|
||||
</FlexRow>
|
||||
<div className="media-right">
|
||||
<TagButtonGroup repository={repository} tag={tag} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagDetail;
|
||||
60
scm-ui/ui-webapp/src/repos/tags/components/TagRow.tsx
Normal file
60
scm-ui/ui-webapp/src/repos/tags/components/TagRow.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import React, { FC } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Tag } from "@scm-manager/ui-types";
|
||||
import styled from "styled-components";
|
||||
import { DateFromNow } from "@scm-manager/ui-components";
|
||||
|
||||
type Props = {
|
||||
tag: Tag;
|
||||
baseUrl: string;
|
||||
};
|
||||
|
||||
const Created = styled.span`
|
||||
margin-left: 1rem;
|
||||
font-size: 0.8rem;
|
||||
`;
|
||||
|
||||
const TagRow: FC<Props> = ({ tag, baseUrl }) => {
|
||||
const [t] = useTranslation("repos");
|
||||
|
||||
const to = `${baseUrl}/${encodeURIComponent(tag.name)}/info`;
|
||||
return (
|
||||
<tr>
|
||||
<td>
|
||||
<Link to={to} title={tag.name}>
|
||||
{tag.name}
|
||||
<Created className="has-text-grey is-ellipsis-overflow">
|
||||
{t("tags.overview.created")} <DateFromNow date={tag.date} />
|
||||
</Created>
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagRow;
|
||||
60
scm-ui/ui-webapp/src/repos/tags/components/TagTable.tsx
Normal file
60
scm-ui/ui-webapp/src/repos/tags/components/TagTable.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import React, { FC } from "react";
|
||||
import { Tag } from "@scm-manager/ui-types";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import TagRow from "./TagRow";
|
||||
|
||||
type Props = {
|
||||
baseUrl: string;
|
||||
tags: Tag[];
|
||||
};
|
||||
|
||||
const TagTable: FC<Props> = ({ baseUrl, tags }) => {
|
||||
const [t] = useTranslation("repos");
|
||||
|
||||
const renderRow = () => {
|
||||
let rowContent = null;
|
||||
if (tags) {
|
||||
rowContent = tags.map((tag, index) => {
|
||||
return <TagRow key={index} baseUrl={baseUrl} tag={tag} />;
|
||||
});
|
||||
}
|
||||
return rowContent;
|
||||
};
|
||||
|
||||
return (
|
||||
<table className="card-table table is-hoverable is-fullwidth is-word-break">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{t("tags.table.tags")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>{renderRow()}</tbody>
|
||||
</table>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagTable;
|
||||
54
scm-ui/ui-webapp/src/repos/tags/components/TagView.tsx
Normal file
54
scm-ui/ui-webapp/src/repos/tags/components/TagView.tsx
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import React, { FC } from "react";
|
||||
import { Repository, Tag } from "@scm-manager/ui-types";
|
||||
import { ExtensionPoint } from "@scm-manager/ui-extensions";
|
||||
import TagDetail from "./TagDetail";
|
||||
|
||||
type Props = {
|
||||
repository: Repository;
|
||||
tag: Tag;
|
||||
};
|
||||
|
||||
const TagView: FC<Props> = ({ repository, tag }) => {
|
||||
return (
|
||||
<>
|
||||
<TagDetail tag={tag} repository={repository} />
|
||||
<hr />
|
||||
<div className="content">
|
||||
<ExtensionPoint
|
||||
name="repos.tag-details.information"
|
||||
renderAll={true}
|
||||
props={{
|
||||
repository,
|
||||
tag
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagView;
|
||||
97
scm-ui/ui-webapp/src/repos/tags/container/TagRoot.tsx
Normal file
97
scm-ui/ui-webapp/src/repos/tags/container/TagRoot.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import React, { FC, useEffect, useState } from "react";
|
||||
import { Link, Repository, Tag } from "@scm-manager/ui-types";
|
||||
import { Redirect, Switch, useLocation, useRouteMatch, Route } from "react-router-dom";
|
||||
import { apiClient, ErrorNotification, Loading } from "@scm-manager/ui-components";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import TagView from "../components/TagView";
|
||||
|
||||
type Props = {
|
||||
repository: Repository;
|
||||
baseUrl: string;
|
||||
};
|
||||
|
||||
const TagRoot: FC<Props> = ({ repository, baseUrl }) => {
|
||||
const match = useRouteMatch();
|
||||
const [tags, setTags] = useState<Tag[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | undefined>(undefined);
|
||||
const [tag, setTag] = useState<Tag>();
|
||||
|
||||
useEffect(() => {
|
||||
const link = (repository._links?.tags as Link)?.href;
|
||||
if (link) {
|
||||
apiClient
|
||||
.get(link)
|
||||
.then(r => r.json())
|
||||
.then(r => setTags(r._embedded.tags))
|
||||
.catch(setError);
|
||||
}
|
||||
}, [repository]);
|
||||
|
||||
useEffect(() => {
|
||||
const tagName = decodeURIComponent(match?.params?.tag);
|
||||
const link = tags?.length > 0 && (tags.find(tag => tag.name === tagName)?._links.self as Link).href;
|
||||
if (link) {
|
||||
apiClient
|
||||
.get(link)
|
||||
.then(r => r.json())
|
||||
.then(setTag)
|
||||
.then(() => setLoading(false))
|
||||
.catch(setError);
|
||||
}
|
||||
}, [tags]);
|
||||
|
||||
const stripEndingSlash = (url: string) => {
|
||||
if (url.endsWith("/")) {
|
||||
return url.substring(0, url.length - 1);
|
||||
}
|
||||
return url;
|
||||
};
|
||||
|
||||
const matchedUrl = () => {
|
||||
return stripEndingSlash(match.url);
|
||||
};
|
||||
|
||||
if (error) {
|
||||
return <ErrorNotification error={error} />;
|
||||
}
|
||||
|
||||
if (loading || !tags) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
const url = matchedUrl();
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Redirect exact from={url} to={`${url}/info`} />
|
||||
<Route path={`${url}/info`} component={() => <TagView repository={repository} tag={tag} />} />
|
||||
</Switch>
|
||||
);
|
||||
};
|
||||
|
||||
export default TagRoot;
|
||||
75
scm-ui/ui-webapp/src/repos/tags/container/TagsOverview.tsx
Normal file
75
scm-ui/ui-webapp/src/repos/tags/container/TagsOverview.tsx
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import React, { FC, useEffect, useState } from "react";
|
||||
import { Repository, Tag, Link } from "@scm-manager/ui-types";
|
||||
import { ErrorNotification, Loading, Notification, Subtitle, apiClient } from "@scm-manager/ui-components";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import orderTags from "../orderTags";
|
||||
import TagTable from "../components/TagTable";
|
||||
|
||||
type Props = {
|
||||
repository: Repository;
|
||||
baseUrl: string;
|
||||
};
|
||||
|
||||
const TagsOverview: FC<Props> = ({ repository, baseUrl }) => {
|
||||
const [t] = useTranslation("repos");
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | undefined>(undefined);
|
||||
const [tags, setTags] = useState<Tag[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const link = (repository._links?.tags as Link)?.href;
|
||||
if (link) {
|
||||
setLoading(true);
|
||||
apiClient
|
||||
.get(link)
|
||||
.then(r => r.json())
|
||||
.then(r => setTags(r._embedded.tags))
|
||||
.then(() => setLoading(false))
|
||||
.catch(setError);
|
||||
}
|
||||
}, [repository]);
|
||||
|
||||
const renderTagsTable = () => {
|
||||
if (!loading && tags?.length > 0) {
|
||||
orderTags(tags);
|
||||
return <TagTable baseUrl={baseUrl} tags={tags} />;
|
||||
}
|
||||
return <Notification type="info">{t("tags.overview.noTags")}</Notification>;
|
||||
};
|
||||
|
||||
if (error) {
|
||||
return <ErrorNotification error={error} />;
|
||||
}
|
||||
|
||||
if (loading) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
return <>{renderTagsTable()}</>;
|
||||
};
|
||||
|
||||
export default TagsOverview;
|
||||
52
scm-ui/ui-webapp/src/repos/tags/orderTags.test.ts
Normal file
52
scm-ui/ui-webapp/src/repos/tags/orderTags.test.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import orderTags from "./orderTags";
|
||||
|
||||
const tag1 = {
|
||||
name: "tag1",
|
||||
revision: "revision1",
|
||||
date: new Date(2020, 1, 1),
|
||||
_links: {}
|
||||
};
|
||||
const tag2 = {
|
||||
name: "tag2",
|
||||
revision: "revision2",
|
||||
date: new Date(2020, 1, 3),
|
||||
_links: {}
|
||||
};
|
||||
const tag3 = {
|
||||
name: "tag3",
|
||||
revision: "revision3",
|
||||
date: new Date(2020, 1, 2),
|
||||
_links: {}
|
||||
};
|
||||
|
||||
describe("order tags", () => {
|
||||
it("should order tags descending by date", () => {
|
||||
const tags = [tag1, tag2, tag3];
|
||||
orderTags(tags);
|
||||
expect(tags).toEqual([tag2, tag3, tag1]);
|
||||
});
|
||||
});
|
||||
32
scm-ui/ui-webapp/src/repos/tags/orderTags.ts
Normal file
32
scm-ui/ui-webapp/src/repos/tags/orderTags.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// sort tags by date beginning with latest first
|
||||
import { Tag } from "@scm-manager/ui-types";
|
||||
|
||||
export default (tags: Tag[]) => {
|
||||
tags.sort((a, b) => {
|
||||
return new Date(b.date) - new Date(a.date);
|
||||
});
|
||||
};
|
||||
@@ -31,17 +31,23 @@ import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
@Getter @Setter @NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@SuppressWarnings("java:S2160") // we do not need this for dto
|
||||
public class BranchDto extends HalRepresentation {
|
||||
|
||||
private static final String VALID_CHARACTERS_AT_START_AND_END = "\\w-,;\\]{}@&+=$#`|<>";
|
||||
private static final String VALID_CHARACTERS = VALID_CHARACTERS_AT_START_AND_END + "/.";
|
||||
static final String VALID_BRANCH_NAMES = "[" + VALID_CHARACTERS_AT_START_AND_END + "]([" + VALID_CHARACTERS + "]*[" + VALID_CHARACTERS_AT_START_AND_END + "])?";
|
||||
|
||||
@NotEmpty @Length(min = 1, max=100) @Pattern(regexp = VALID_BRANCH_NAMES)
|
||||
@NotEmpty
|
||||
@Length(min = 1, max = 100)
|
||||
@Pattern(regexp = VALID_BRANCH_NAMES)
|
||||
private String name;
|
||||
private String revision;
|
||||
private boolean defaultBranch;
|
||||
|
||||
@@ -120,7 +120,11 @@ public class BranchRootResource {
|
||||
schema = @Schema(implementation = ErrorDto.class)
|
||||
)
|
||||
)
|
||||
public Response get(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("branch") String branchName) throws IOException {
|
||||
public Response get(
|
||||
@PathParam("namespace") String namespace,
|
||||
@PathParam("name") String name,
|
||||
@PathParam("branch") String branchName
|
||||
) throws IOException {
|
||||
NamespaceAndName namespaceAndName = new NamespaceAndName(namespace, name);
|
||||
try (RepositoryService repositoryService = serviceFactory.create(namespaceAndName)) {
|
||||
Branches branches = repositoryService.getBranchesCommand().getBranches();
|
||||
@@ -293,7 +297,10 @@ public class BranchRootResource {
|
||||
mediaType = VndMediaType.ERROR_TYPE,
|
||||
schema = @Schema(implementation = ErrorDto.class)
|
||||
))
|
||||
public Response getAll(@PathParam("namespace") String namespace, @PathParam("name") String name) throws IOException {
|
||||
public Response getAll(
|
||||
@PathParam("namespace") String namespace,
|
||||
@PathParam("name") String name
|
||||
) throws IOException {
|
||||
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
|
||||
Branches branches = repositoryService.getBranchesCommand().getBranches();
|
||||
return Response.ok(branchCollectionToDtoMapper.map(repositoryService.getRepository(), branches.getBranches())).build();
|
||||
|
||||
@@ -62,5 +62,4 @@ class BranchToBranchDtoMapperTest {
|
||||
BranchDto dto = mapper.map(branch, new NamespaceAndName("hitchhiker", "heart-of-gold"));
|
||||
assertThat(dto.getLinks().getLinkBy("ka").get().getHref()).isEqualTo("http://hitchhiker/heart-of-gold/master");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user