mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-01-07 16:12:10 +01:00
Merge pull request #1080 from scm-manager/feature/favourite_repository
Feature/favourite repository
This commit is contained in:
@@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Libc based restart strategy for posix operating systems ([#1079](https://github.com/scm-manager/scm-manager/pull/1079))
|
||||
- Simple restart strategy with System.exit ([#1079](https://github.com/scm-manager/scm-manager/pull/1079))
|
||||
- Notification if restart is not supported on the underlying platform ([#1079](https://github.com/scm-manager/scm-manager/pull/1079))
|
||||
- Extension point before title in repository cards ([#1080](https://github.com/scm-manager/scm-manager/pull/1080))
|
||||
- Extension point after title on repository detail page ([#1080](https://github.com/scm-manager/scm-manager/pull/1080))
|
||||
|
||||
### Changed
|
||||
- Update resteasy to version 4.5.2.Final
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package sonia.scm.web.api;
|
||||
|
||||
import de.otto.edison.hal.HalRepresentation;
|
||||
import sonia.scm.repository.Repository;
|
||||
|
||||
/**
|
||||
* Maps a repository to a hal representation.
|
||||
* This is especially useful if a plugin would deliver a repository to the frontend.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public interface RepositoryToHalMapper {
|
||||
|
||||
/**
|
||||
* Returns the hal representation of the repository.
|
||||
*
|
||||
* @param repository repository to map
|
||||
* @return hal representation
|
||||
*/
|
||||
HalRepresentation map(Repository repository);
|
||||
}
|
||||
@@ -27,7 +27,7 @@ import styled from "styled-components";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
type Props = {
|
||||
title: string;
|
||||
title: ReactNode;
|
||||
description?: string;
|
||||
avatar: ReactNode;
|
||||
contentRight?: ReactNode;
|
||||
@@ -100,7 +100,7 @@ export default class CardColumn extends React.Component<Props> {
|
||||
<div className="is-flex">
|
||||
<ContentLeft className="content">
|
||||
<p className="shorten-text is-marginless">
|
||||
<strong>{title}</strong>
|
||||
{title}
|
||||
</p>
|
||||
<p className="shorten-text">{description}</p>
|
||||
</ContentLeft>
|
||||
|
||||
BIN
scm-ui/ui-components/src/__resources__/git-logo.png
Normal file
BIN
scm-ui/ui-components/src/__resources__/git-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
67
scm-ui/ui-components/src/__resources__/repository.ts
Normal file
67
scm-ui/ui-components/src/__resources__/repository.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
export default {
|
||||
contact: "heart-of-gold@hitchhiher.com",
|
||||
creationDate: "2020-03-23T08:26:01.164Z",
|
||||
description: "The starship Heart of Gold was the first spacecraft to make use of the Infinite Improbability Drive",
|
||||
healthCheckFailures: [],
|
||||
lastModified: "2020-03-23T08:26:01.876Z",
|
||||
namespace: "hitchhiher",
|
||||
name: "heartOfGold",
|
||||
type: "git",
|
||||
_links: {
|
||||
self: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git" },
|
||||
delete: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git" },
|
||||
update: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git" },
|
||||
permissions: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/permissions/" },
|
||||
protocol: [
|
||||
{ href: "ssh://scmadmin@localhost:4567/repo/scmadmin/Git", name: "ssh" },
|
||||
{ href: "http://localhost:8081/scm/repo/scmadmin/Git", name: "http" }
|
||||
],
|
||||
tags: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/tags/" },
|
||||
branches: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/branches/" },
|
||||
incomingChangesets: {
|
||||
href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/incoming/{source}/{target}/changesets",
|
||||
templated: true
|
||||
},
|
||||
incomingDiff: {
|
||||
href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/incoming/{source}/{target}/diff",
|
||||
templated: true
|
||||
},
|
||||
incomingDiffParsed: {
|
||||
href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/incoming/{source}/{target}/diff/parsed",
|
||||
templated: true
|
||||
},
|
||||
changesets: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/changesets/" },
|
||||
sources: { href: "http://localhost:8081/scm/api/v2/repositories/scmadmin/Git/sources/" },
|
||||
authorMappingConfig: {
|
||||
href: "http://localhost:8081/scm/api/v2/authormapping/configuration/scmadmin/Git"
|
||||
},
|
||||
unfavorize: { href: "http://localhost:8081/scm/api/v2/unfavorize/scmadmin/Git" },
|
||||
favorites: [
|
||||
{ href: "http://localhost:8081/scm/api/v2/unfavorize/scmadmin/Git", name: "unfavorize" },
|
||||
{ href: "http://localhost:8081/scm/api/v2/favorize/scmadmin/Git", name: "favorize" }
|
||||
]
|
||||
}
|
||||
};
|
||||
@@ -34188,6 +34188,472 @@ exports[`Storyshots MarkdownView Xml Code Block 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Storyshots RepositoryEntry Avatar EP 1`] = `
|
||||
<div
|
||||
className="RepositoryEntrystories__Spacing-toppdg-0 khfzcK box box-link-shadow"
|
||||
>
|
||||
<a
|
||||
className="overlay-column"
|
||||
href="/repo/hitchhiher/heartOfGold"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
<article
|
||||
className="CardColumn__NoEventWrapper-sc-1w6lsih-0 kZKqpc media"
|
||||
>
|
||||
<figure
|
||||
className="CardColumn__AvatarWrapper-sc-1w6lsih-1 bZyfne media-left"
|
||||
>
|
||||
<p
|
||||
className="image is-64x64"
|
||||
>
|
||||
<img
|
||||
alt="Logo"
|
||||
src="test-file-stub"
|
||||
/>
|
||||
</p>
|
||||
</figure>
|
||||
<div
|
||||
className="CardColumn__FlexFullHeight-sc-1w6lsih-2 cAdfGj media-content text-box is-flex"
|
||||
>
|
||||
<div
|
||||
className="is-flex"
|
||||
>
|
||||
<div
|
||||
className="CardColumn__ContentLeft-sc-1w6lsih-4 dumWkw content"
|
||||
>
|
||||
<p
|
||||
className="shorten-text is-marginless"
|
||||
>
|
||||
|
||||
<strong>
|
||||
heartOfGold
|
||||
</strong>
|
||||
</p>
|
||||
<p
|
||||
className="shorten-text"
|
||||
>
|
||||
The starship Heart of Gold was the first spacecraft to make use of the Infinite Improbability Drive
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className="CardColumn__ContentRight-sc-1w6lsih-5 kyEPRa"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="CardColumn__FooterWrapper-sc-1w6lsih-3 jlTqlS level is-flex"
|
||||
>
|
||||
<div
|
||||
className="level-left is-hidden-mobile"
|
||||
>
|
||||
<a
|
||||
className="RepositoryEntryLink__PointerEventsLink-sc-1hpqj0w-0 gtboNN level-item"
|
||||
href="/repo/hitchhiher/heartOfGold/branches"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-code-branch has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
className="RepositoryEntryLink__PointerEventsLink-sc-1hpqj0w-0 gtboNN level-item"
|
||||
href="/repo/hitchhiher/heartOfGold/code/changesets/"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-exchange-alt has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
className="RepositoryEntryLink__PointerEventsLink-sc-1hpqj0w-0 gtboNN level-item"
|
||||
href="/repo/hitchhiher/heartOfGold/code/sources/"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-code has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
className="RepositoryEntryLink__PointerEventsLink-sc-1hpqj0w-0 gtboNN level-item"
|
||||
href="/repo/hitchhiher/heartOfGold/settings/general"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-cog has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
className="level-right is-mobile is-marginless"
|
||||
>
|
||||
<small
|
||||
className="level-item"
|
||||
>
|
||||
<time
|
||||
className="DateFromNow__DateElement-sc-16hnz72-0 ehlCzi"
|
||||
title="2020-03-23 09:26:01"
|
||||
>
|
||||
3 days ago
|
||||
</time>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Storyshots RepositoryEntry Before Title EP 1`] = `
|
||||
<div
|
||||
className="RepositoryEntrystories__Spacing-toppdg-0 khfzcK box box-link-shadow"
|
||||
>
|
||||
<a
|
||||
className="overlay-column"
|
||||
href="/repo/hitchhiher/heartOfGold"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
<article
|
||||
className="CardColumn__NoEventWrapper-sc-1w6lsih-0 kZKqpc media"
|
||||
>
|
||||
<figure
|
||||
className="CardColumn__AvatarWrapper-sc-1w6lsih-1 bZyfne media-left"
|
||||
>
|
||||
<p
|
||||
className="image is-64x64"
|
||||
>
|
||||
<img
|
||||
alt="Logo"
|
||||
src="/images/blib.jpg"
|
||||
/>
|
||||
</p>
|
||||
</figure>
|
||||
<div
|
||||
className="CardColumn__FlexFullHeight-sc-1w6lsih-2 cAdfGj media-content text-box is-flex"
|
||||
>
|
||||
<div
|
||||
className="is-flex"
|
||||
>
|
||||
<div
|
||||
className="CardColumn__ContentLeft-sc-1w6lsih-4 dumWkw content"
|
||||
>
|
||||
<p
|
||||
className="shorten-text is-marginless"
|
||||
>
|
||||
<i
|
||||
className="fas fa-star"
|
||||
/>
|
||||
|
||||
<strong>
|
||||
heartOfGold
|
||||
</strong>
|
||||
</p>
|
||||
<p
|
||||
className="shorten-text"
|
||||
>
|
||||
The starship Heart of Gold was the first spacecraft to make use of the Infinite Improbability Drive
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className="CardColumn__ContentRight-sc-1w6lsih-5 kyEPRa"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="CardColumn__FooterWrapper-sc-1w6lsih-3 jlTqlS level is-flex"
|
||||
>
|
||||
<div
|
||||
className="level-left is-hidden-mobile"
|
||||
>
|
||||
<a
|
||||
className="RepositoryEntryLink__PointerEventsLink-sc-1hpqj0w-0 gtboNN level-item"
|
||||
href="/repo/hitchhiher/heartOfGold/branches"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-code-branch has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
className="RepositoryEntryLink__PointerEventsLink-sc-1hpqj0w-0 gtboNN level-item"
|
||||
href="/repo/hitchhiher/heartOfGold/code/changesets/"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-exchange-alt has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
className="RepositoryEntryLink__PointerEventsLink-sc-1hpqj0w-0 gtboNN level-item"
|
||||
href="/repo/hitchhiher/heartOfGold/code/sources/"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-code has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
className="RepositoryEntryLink__PointerEventsLink-sc-1hpqj0w-0 gtboNN level-item"
|
||||
href="/repo/hitchhiher/heartOfGold/settings/general"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-cog has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
className="level-right is-mobile is-marginless"
|
||||
>
|
||||
<small
|
||||
className="level-item"
|
||||
>
|
||||
<time
|
||||
className="DateFromNow__DateElement-sc-16hnz72-0 ehlCzi"
|
||||
title="2020-03-23 09:26:01"
|
||||
>
|
||||
3 days ago
|
||||
</time>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Storyshots RepositoryEntry Default 1`] = `
|
||||
<div
|
||||
className="RepositoryEntrystories__Spacing-toppdg-0 khfzcK box box-link-shadow"
|
||||
>
|
||||
<a
|
||||
className="overlay-column"
|
||||
href="/repo/hitchhiher/heartOfGold"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
<article
|
||||
className="CardColumn__NoEventWrapper-sc-1w6lsih-0 kZKqpc media"
|
||||
>
|
||||
<figure
|
||||
className="CardColumn__AvatarWrapper-sc-1w6lsih-1 bZyfne media-left"
|
||||
>
|
||||
<p
|
||||
className="image is-64x64"
|
||||
>
|
||||
<img
|
||||
alt="Logo"
|
||||
src="/images/blib.jpg"
|
||||
/>
|
||||
</p>
|
||||
</figure>
|
||||
<div
|
||||
className="CardColumn__FlexFullHeight-sc-1w6lsih-2 cAdfGj media-content text-box is-flex"
|
||||
>
|
||||
<div
|
||||
className="is-flex"
|
||||
>
|
||||
<div
|
||||
className="CardColumn__ContentLeft-sc-1w6lsih-4 dumWkw content"
|
||||
>
|
||||
<p
|
||||
className="shorten-text is-marginless"
|
||||
>
|
||||
|
||||
<strong>
|
||||
heartOfGold
|
||||
</strong>
|
||||
</p>
|
||||
<p
|
||||
className="shorten-text"
|
||||
>
|
||||
The starship Heart of Gold was the first spacecraft to make use of the Infinite Improbability Drive
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className="CardColumn__ContentRight-sc-1w6lsih-5 kyEPRa"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="CardColumn__FooterWrapper-sc-1w6lsih-3 jlTqlS level is-flex"
|
||||
>
|
||||
<div
|
||||
className="level-left is-hidden-mobile"
|
||||
>
|
||||
<a
|
||||
className="RepositoryEntryLink__PointerEventsLink-sc-1hpqj0w-0 gtboNN level-item"
|
||||
href="/repo/hitchhiher/heartOfGold/branches"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-code-branch has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
className="RepositoryEntryLink__PointerEventsLink-sc-1hpqj0w-0 gtboNN level-item"
|
||||
href="/repo/hitchhiher/heartOfGold/code/changesets/"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-exchange-alt has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
className="RepositoryEntryLink__PointerEventsLink-sc-1hpqj0w-0 gtboNN level-item"
|
||||
href="/repo/hitchhiher/heartOfGold/code/sources/"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-code has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
className="RepositoryEntryLink__PointerEventsLink-sc-1hpqj0w-0 gtboNN level-item"
|
||||
href="/repo/hitchhiher/heartOfGold/settings/general"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-cog has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
className="level-right is-mobile is-marginless"
|
||||
>
|
||||
<small
|
||||
className="level-item"
|
||||
>
|
||||
<time
|
||||
className="DateFromNow__DateElement-sc-16hnz72-0 ehlCzi"
|
||||
title="2020-03-23 09:26:01"
|
||||
>
|
||||
3 days ago
|
||||
</time>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Storyshots RepositoryEntry Quick Link EP 1`] = `
|
||||
<div
|
||||
className="RepositoryEntrystories__Spacing-toppdg-0 khfzcK box box-link-shadow"
|
||||
>
|
||||
<a
|
||||
className="overlay-column"
|
||||
href="/repo/hitchhiher/heartOfGold"
|
||||
onClick={[Function]}
|
||||
/>
|
||||
<article
|
||||
className="CardColumn__NoEventWrapper-sc-1w6lsih-0 kZKqpc media"
|
||||
>
|
||||
<figure
|
||||
className="CardColumn__AvatarWrapper-sc-1w6lsih-1 bZyfne media-left"
|
||||
>
|
||||
<p
|
||||
className="image is-64x64"
|
||||
>
|
||||
<img
|
||||
alt="Logo"
|
||||
src="/images/blib.jpg"
|
||||
/>
|
||||
</p>
|
||||
</figure>
|
||||
<div
|
||||
className="CardColumn__FlexFullHeight-sc-1w6lsih-2 cAdfGj media-content text-box is-flex"
|
||||
>
|
||||
<div
|
||||
className="is-flex"
|
||||
>
|
||||
<div
|
||||
className="CardColumn__ContentLeft-sc-1w6lsih-4 dumWkw content"
|
||||
>
|
||||
<p
|
||||
className="shorten-text is-marginless"
|
||||
>
|
||||
|
||||
<strong>
|
||||
heartOfGold
|
||||
</strong>
|
||||
</p>
|
||||
<p
|
||||
className="shorten-text"
|
||||
>
|
||||
The starship Heart of Gold was the first spacecraft to make use of the Infinite Improbability Drive
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
className="CardColumn__ContentRight-sc-1w6lsih-5 kyEPRa"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="CardColumn__FooterWrapper-sc-1w6lsih-3 jlTqlS level is-flex"
|
||||
>
|
||||
<div
|
||||
className="level-left is-hidden-mobile"
|
||||
>
|
||||
<a
|
||||
className="RepositoryEntryLink__PointerEventsLink-sc-1hpqj0w-0 gtboNN level-item"
|
||||
href="/repo/hitchhiher/heartOfGold/branches"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-code-branch has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
className="RepositoryEntryLink__PointerEventsLink-sc-1hpqj0w-0 gtboNN level-item"
|
||||
href="/repo/hitchhiher/heartOfGold/code/changesets/"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-exchange-alt has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
className="RepositoryEntryLink__PointerEventsLink-sc-1hpqj0w-0 gtboNN level-item"
|
||||
href="/repo/hitchhiher/heartOfGold/code/sources/"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-code has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
className="level-item"
|
||||
>
|
||||
<i
|
||||
className="fas fa-fas fa-code-branch fa-rotate-180 fa-fw has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
<a
|
||||
className="RepositoryEntryLink__PointerEventsLink-sc-1hpqj0w-0 gtboNN level-item"
|
||||
href="/repo/hitchhiher/heartOfGold/settings/general"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<i
|
||||
className="fas fa-cog has-text-inherit fa-lg"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
<div
|
||||
className="level-right is-mobile is-marginless"
|
||||
>
|
||||
<small
|
||||
className="level-item"
|
||||
>
|
||||
<time
|
||||
className="DateFromNow__DateElement-sc-16hnz72-0 ehlCzi"
|
||||
title="2020-03-23 09:26:01"
|
||||
>
|
||||
3 days ago
|
||||
</time>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Storyshots SyntaxHighlighter Go 1`] = `
|
||||
<div
|
||||
className="SyntaxHighlighterstories__Spacing-sc-1dcldp5-0 eofOgh"
|
||||
|
||||
@@ -33,6 +33,7 @@ import ErrorBoundary from "../ErrorBoundary";
|
||||
|
||||
type Props = {
|
||||
title?: string;
|
||||
afterTitle?: ReactNode;
|
||||
subtitle?: string;
|
||||
loading?: boolean;
|
||||
error?: Error;
|
||||
@@ -50,6 +51,15 @@ const PageActionContainer = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
const MarginLeft = styled.div`
|
||||
margin-left: 0.5rem;
|
||||
`;
|
||||
|
||||
const FlexContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
`;
|
||||
|
||||
export default class Page extends React.Component<Props> {
|
||||
componentDidUpdate() {
|
||||
const { title } = this.props;
|
||||
@@ -80,7 +90,7 @@ export default class Page extends React.Component<Props> {
|
||||
}
|
||||
|
||||
renderPageHeader() {
|
||||
const { error, title, subtitle, children } = this.props;
|
||||
const { error, title, afterTitle, subtitle, children } = this.props;
|
||||
|
||||
let pageActions = null;
|
||||
let pageActionsExists = false;
|
||||
@@ -104,7 +114,9 @@ export default class Page extends React.Component<Props> {
|
||||
<>
|
||||
<div className="columns">
|
||||
<div className="column">
|
||||
<Title title={title} />
|
||||
<FlexContainer>
|
||||
<Title title={title} /> {afterTitle && <MarginLeft>{afterTitle}</MarginLeft>}
|
||||
</FlexContainer>
|
||||
<Subtitle subtitle={subtitle} />
|
||||
</div>
|
||||
{pageActions}
|
||||
|
||||
93
scm-ui/ui-components/src/repos/RepositoryEntry.stories.tsx
Normal file
93
scm-ui/ui-components/src/repos/RepositoryEntry.stories.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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 {storiesOf} from "@storybook/react";
|
||||
import React, {FC, ReactNode} from "react";
|
||||
import styled from "styled-components";
|
||||
import repository from "../__resources__/repository";
|
||||
// @ts-ignore ignore unknown png
|
||||
import Git from "../__resources__/git-logo.png";
|
||||
import RepositoryEntry from "./RepositoryEntry";
|
||||
import {Binder, BinderContext} from "@scm-manager/ui-extensions";
|
||||
import {Repository} from "@scm-manager/ui-types";
|
||||
import Image from "../Image";
|
||||
import classNames from "classnames";
|
||||
import Icon from "../Icon";
|
||||
|
||||
const Spacing = styled.div`
|
||||
margin: 2rem;
|
||||
`;
|
||||
|
||||
const Container: FC = ({children}) => (
|
||||
<Spacing className="box box-link-shadow">{children}</Spacing>
|
||||
);
|
||||
|
||||
const bindAvatar = (binder: Binder, avatar: string) => {
|
||||
binder.bind("repos.repository-avatar", () => {
|
||||
return <Image src={avatar} alt="Logo"/>;
|
||||
});
|
||||
};
|
||||
|
||||
const bindBeforeTitle = (binder: Binder, extension: ReactNode) => {
|
||||
binder.bind("repository.card.beforeTitle", () => {
|
||||
return extension;
|
||||
});
|
||||
};
|
||||
|
||||
const bindQuickLink = (binder: Binder, extension: ReactNode) => {
|
||||
binder.bind("repository.card.quickLink", () => {
|
||||
return extension;
|
||||
});
|
||||
};
|
||||
|
||||
const withBinder = (binder: Binder, repository: Repository) => {
|
||||
return (
|
||||
<BinderContext.Provider value={binder}>
|
||||
<RepositoryEntry repository={repository}/>
|
||||
</BinderContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
const QuickLink = <a className="level-item"><Icon className="fa-lg" name="fas fa-code-branch fa-rotate-180 fa-fw"
|
||||
color="inherit"/></a>;
|
||||
|
||||
storiesOf("RepositoryEntry", module)
|
||||
.addDecorator(storyFn => <Container>{storyFn()}</Container>)
|
||||
.add("Default", () => {
|
||||
return <RepositoryEntry repository={repository}/>;
|
||||
})
|
||||
.add("Avatar EP", () => {
|
||||
const binder = new Binder("avatar");
|
||||
bindAvatar(binder, Git);
|
||||
return withBinder(binder, repository);
|
||||
})
|
||||
.add("Before Title EP", () => {
|
||||
const binder = new Binder("title");
|
||||
bindBeforeTitle(binder, <i className="fas fa-star"/>);
|
||||
return withBinder(binder, repository);
|
||||
})
|
||||
.add("Quick Link EP", () => {
|
||||
const binder = new Binder("title");
|
||||
bindQuickLink(binder, QuickLink);
|
||||
return withBinder(binder, repository);
|
||||
});
|
||||
@@ -85,15 +85,25 @@ class RepositoryEntry extends React.Component<Props> {
|
||||
);
|
||||
};
|
||||
|
||||
createTitle = () => {
|
||||
const { repository } = this.props;
|
||||
return (
|
||||
<>
|
||||
<ExtensionPoint name="repository.card.beforeTitle" props={{ repository }} /> <strong>{repository.name}</strong>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { repository } = this.props;
|
||||
const repositoryLink = this.createLink(repository);
|
||||
const footerLeft = this.createFooterLeft(repository, repositoryLink);
|
||||
const footerRight = this.createFooterRight(repository);
|
||||
const title = this.createTitle();
|
||||
return (
|
||||
<CardColumn
|
||||
avatar={<RepositoryAvatar repository={repository} />}
|
||||
title={repository.name}
|
||||
title={title}
|
||||
description={repository.description}
|
||||
link={repositoryLink}
|
||||
footerLeft={footerLeft}
|
||||
@@ -46,6 +46,9 @@ export { default as DiffFile } from "./DiffFile";
|
||||
export { default as DiffButton } from "./DiffButton";
|
||||
export { default as LoadingDiff } from "./LoadingDiff";
|
||||
export { DefaultCollapsed, DefaultCollapsedFunction } from "./defaultCollapsed";
|
||||
export { default as RepositoryAvatar } from "./RepositoryAvatar";
|
||||
export { default as RepositoryEntry } from "./RepositoryEntry";
|
||||
export { default as RepositoryEntryLink } from "./RepositoryEntryLink";
|
||||
|
||||
export {
|
||||
File,
|
||||
|
||||
@@ -433,6 +433,7 @@ $danger-25: scale-color($danger, $lightness: 75%);
|
||||
@import "~@fortawesome/fontawesome-free/scss/fontawesome";
|
||||
$fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
|
||||
@import "~@fortawesome/fontawesome-free/scss/solid";
|
||||
@import "~@fortawesome/fontawesome-free/scss/regular";
|
||||
@import "~@fortawesome/fontawesome-free/scss/brands";
|
||||
|
||||
@import "~react-diff-view/style/index";
|
||||
|
||||
@@ -181,7 +181,7 @@ class PluginEntry extends React.Component<Props, State> {
|
||||
<CardColumn
|
||||
action={this.isInstallable() ? () => this.toggleModal("showInstallModal") : null}
|
||||
avatar={avatar}
|
||||
title={plugin.displayName ? plugin.displayName : plugin.name}
|
||||
title={plugin.displayName ? <strong>{plugin.displayName}</strong> : <strong>{plugin.name}</strong>}
|
||||
description={plugin.description}
|
||||
contentRight={plugin.pending || plugin.markedForUninstall ? this.createPendingSpinner() : actionbar}
|
||||
footerRight={footerRight}
|
||||
|
||||
@@ -25,6 +25,7 @@ import React from "react";
|
||||
import { WithTranslation, withTranslation } from "react-i18next";
|
||||
import { Repository } from "@scm-manager/ui-types";
|
||||
import { DateFromNow, MailLink } from "@scm-manager/ui-components";
|
||||
import { ExtensionPoint } from "@scm-manager/ui-extensions";
|
||||
|
||||
type Props = WithTranslation & {
|
||||
repository: Repository;
|
||||
|
||||
@@ -22,9 +22,8 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
import React from "react";
|
||||
import { CardColumnGroup } from "@scm-manager/ui-components";
|
||||
import { CardColumnGroup, RepositoryEntry } from "@scm-manager/ui-components";
|
||||
import { RepositoryGroup } from "@scm-manager/ui-types";
|
||||
import RepositoryEntry from "./RepositoryEntry";
|
||||
|
||||
type Props = {
|
||||
group: RepositoryGroup;
|
||||
|
||||
@@ -172,7 +172,10 @@ class RepositoryRoot extends React.Component<Props, State> {
|
||||
setMenuCollapsed: (collapsed: boolean) => this.setState({ menuCollapsed: collapsed })
|
||||
}}
|
||||
>
|
||||
<Page title={repository.namespace + "/" + repository.name}>
|
||||
<Page
|
||||
title={repository.namespace + "/" + repository.name}
|
||||
afterTitle={<ExtensionPoint name={"repository.afterTitle"} props={{ repository }} />}
|
||||
>
|
||||
<CustomQueryFlexWrappedColumns>
|
||||
<PrimaryContentColumn collapsed={menuCollapsed}>
|
||||
<Switch>
|
||||
|
||||
@@ -27,6 +27,7 @@ package sonia.scm.api.v2.resources;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.servlet.ServletScopes;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
import sonia.scm.web.api.RepositoryToHalMapper;
|
||||
|
||||
public class MapperModule extends AbstractModule {
|
||||
@Override
|
||||
@@ -70,6 +71,8 @@ public class MapperModule extends AbstractModule {
|
||||
bind(ScmViolationExceptionToErrorDtoMapper.class).to(Mappers.getMapper(ScmViolationExceptionToErrorDtoMapper.class).getClass());
|
||||
bind(ExceptionWithContextToErrorDtoMapper.class).to(Mappers.getMapper(ExceptionWithContextToErrorDtoMapper.class).getClass());
|
||||
|
||||
bind(RepositoryToHalMapper.class).to(Mappers.getMapper(RepositoryToRepositoryDtoMapper.class).getClass());
|
||||
|
||||
// no mapstruct required
|
||||
bind(MeDtoFactory.class);
|
||||
bind(UIPluginDtoMapper.class);
|
||||
|
||||
@@ -38,6 +38,7 @@ import sonia.scm.repository.api.Command;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
import sonia.scm.repository.api.ScmProtocol;
|
||||
import sonia.scm.web.api.RepositoryToHalMapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -49,7 +50,7 @@ import static java.util.stream.Collectors.toList;
|
||||
// Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
|
||||
@SuppressWarnings("squid:S3306")
|
||||
@Mapper
|
||||
public abstract class RepositoryToRepositoryDtoMapper extends BaseMapper<Repository, RepositoryDto> {
|
||||
public abstract class RepositoryToRepositoryDtoMapper extends BaseMapper<Repository, RepositoryDto> implements RepositoryToHalMapper {
|
||||
|
||||
@Inject
|
||||
private ResourceLinks resourceLinks;
|
||||
@@ -58,6 +59,9 @@ public abstract class RepositoryToRepositoryDtoMapper extends BaseMapper<Reposit
|
||||
|
||||
abstract HealthCheckFailureDto toDto(HealthCheckFailure failure);
|
||||
|
||||
@Override
|
||||
public abstract RepositoryDto map(Repository modelObject);
|
||||
|
||||
@ObjectFactory
|
||||
RepositoryDto createDto(Repository repository) {
|
||||
Links.Builder linksBuilder = linkingTo().self(resourceLinks.repository().self(repository.getNamespace(), repository.getName()));
|
||||
|
||||
Reference in New Issue
Block a user