From 5a9cbbc0737a1479951ca78d8fc8e143cc62ca93 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Fri, 1 Nov 2019 09:29:57 +0100 Subject: [PATCH] use i18n for missing extension warning / fix encoding for branches containing slashes --- scm-ui/ui-webapp/public/locales/de/repos.json | 5 ++- scm-ui/ui-webapp/public/locales/en/repos.json | 5 ++- scm-ui/ui-webapp/public/locales/es/repos.json | 5 ++- .../src/repos/containers/RepositoryRoot.tsx | 7 ++++ .../sources/containers/SourceExtensions.tsx | 36 ++++++++----------- .../src/repos/sources/containers/Sources.tsx | 12 +++---- .../src/repos/sources/modules/sources.ts | 10 +++--- 7 files changed, 45 insertions(+), 35 deletions(-) diff --git a/scm-ui/ui-webapp/public/locales/de/repos.json b/scm-ui/ui-webapp/public/locales/de/repos.json index 8ae5c405af..e156cc903e 100644 --- a/scm-ui/ui-webapp/public/locales/de/repos.json +++ b/scm-ui/ui-webapp/public/locales/de/repos.json @@ -113,7 +113,10 @@ "description": "Beschreibung", "size": "Größe" }, - "noSources": "Keine Sources in diesem Branch gefunden." + "noSources": "Keine Sources in diesem Branch gefunden.", + "extension" : { + "notBound": "Keine Erweiterung angebunden." + } }, "permission": { "title": "Berechtigungen bearbeiten", diff --git a/scm-ui/ui-webapp/public/locales/en/repos.json b/scm-ui/ui-webapp/public/locales/en/repos.json index d621bad7bf..0466bab77f 100644 --- a/scm-ui/ui-webapp/public/locales/en/repos.json +++ b/scm-ui/ui-webapp/public/locales/en/repos.json @@ -113,7 +113,10 @@ "description": "Description", "size": "Size" }, - "noSources": "No sources found for this branch." + "noSources": "No sources found for this branch.", + "extension" : { + "notBound": "No extension bound." + } }, "permission": { "title": "Edit Permissions", diff --git a/scm-ui/ui-webapp/public/locales/es/repos.json b/scm-ui/ui-webapp/public/locales/es/repos.json index 8372c7e592..ef9bd2badc 100644 --- a/scm-ui/ui-webapp/public/locales/es/repos.json +++ b/scm-ui/ui-webapp/public/locales/es/repos.json @@ -113,7 +113,10 @@ "description": "Discripción", "size": "tamaño" }, - "noSources": "No se han encontrado fuentes para esta rama." + "noSources": "No se han encontrado fuentes para esta rama.", + "extension" : { + "notBound": "Sin extensión conectada." + } }, "permission": { "title": "Editar permisos", diff --git a/scm-ui/ui-webapp/src/repos/containers/RepositoryRoot.tsx b/scm-ui/ui-webapp/src/repos/containers/RepositoryRoot.tsx index 8e8c9867d5..1e2b94f828 100644 --- a/scm-ui/ui-webapp/src/repos/containers/RepositoryRoot.tsx +++ b/scm-ui/ui-webapp/src/repos/containers/RepositoryRoot.tsx @@ -68,6 +68,12 @@ class RepositoryRoot extends React.Component { return route.location.pathname.match(regex); }; + matchesSources = (route: any) => { + const url = this.matchedUrl(); + const regex = new RegExp(`${url}/(sources|sourceext)/.*`); + return route.location.pathname.match(regex); + }; + render() { const { loading, error, indexLinks, repository, t } = this.props; @@ -196,6 +202,7 @@ class RepositoryRoot extends React.Component { to={`${url}/sources`} icon="fas fa-code" label={t("repositoryRoot.menu.sourcesNavLink")} + activeWhenMatch={this.matchesSources} activeOnlyWhenExact={false} /> diff --git a/scm-ui/ui-webapp/src/repos/sources/containers/SourceExtensions.tsx b/scm-ui/ui-webapp/src/repos/sources/containers/SourceExtensions.tsx index a340d6ef26..c75b0106a9 100644 --- a/scm-ui/ui-webapp/src/repos/sources/containers/SourceExtensions.tsx +++ b/scm-ui/ui-webapp/src/repos/sources/containers/SourceExtensions.tsx @@ -3,17 +3,13 @@ import { Repository, File } from "@scm-manager/ui-types"; import { withRouter, RouteComponentProps } from "react-router-dom"; import { ExtensionPoint, binder } from "@scm-manager/ui-extensions"; -import { - fetchSources, - getFetchSourcesFailure, - getSources, - isFetchSourcesPending -} from "../modules/sources"; -import { connect} from "react-redux"; +import { fetchSources, getFetchSourcesFailure, getSources, isFetchSourcesPending } from "../modules/sources"; +import { connect } from "react-redux"; import { Loading, ErrorNotification } from "@scm-manager/ui-components"; import Notification from "@scm-manager/ui-components/src/Notification"; +import {WithTranslation, withTranslation} from "react-i18next"; -type Props = RouteComponentProps & { +type Props = WithTranslation & RouteComponentProps & { repository: Repository; // url params @@ -36,11 +32,11 @@ class SourceExtensions extends React.Component { componentDidMount() { const { fetchSources, repository, revision, path } = this.props; // TODO get typing right - fetchSources(repository, revision || "", path || ""); + fetchSources(repository,revision || "", path || ""); } render() { - const { loading, error, repository, extension, revision, path, sources } = this.props; + const { loading, error, repository, extension, revision, path, sources, t } = this.props; if (error) { return ; } @@ -50,8 +46,7 @@ class SourceExtensions extends React.Component { const extprops = { extension, repository, revision, path, sources }; if (!binder.hasExtension(extensionPointName, extprops)) { - // TODO i18n - return No extension bound; + return {t("sources.extension.notBound")}; } return ; @@ -60,15 +55,12 @@ class SourceExtensions extends React.Component { const mapStateToProps = (state: any, ownProps: Props): Partial => { const { repository, match } = ownProps; - // TODO add query-string v6 - // see : https://www.pluralsight.com/guides/react-router-typescript // @ts-ignore const revision: string = match.params.revision; // @ts-ignore const path: string = match.params.path; // @ts-ignore const extension: string = match.params.extension; - const decodedRevision = revision ? decodeURIComponent(revision) : undefined; const loading = isFetchSourcesPending(state, repository, revision, path); const error = getFetchSourcesFailure(state, repository, revision, path); const sources = getSources(state, repository, revision, path); @@ -76,7 +68,7 @@ const mapStateToProps = (state: any, ownProps: Props): Partial => { return { repository, extension, - revision: decodedRevision, + revision, path, loading, error, @@ -87,12 +79,14 @@ const mapStateToProps = (state: any, ownProps: Props): Partial => { const mapDispatchToProps = (dispatch: any) => { return { fetchSources: (repository: Repository, revision: string, path: string) => { - dispatch(fetchSources(repository, revision, path)); + dispatch(fetchSources(repository, decodeURIComponent(revision), path)); } }; }; -export default withRouter(connect( - mapStateToProps, - mapDispatchToProps -)(SourceExtensions)); +export default withRouter( + connect( + mapStateToProps, + mapDispatchToProps + )(withTranslation("repos")(SourceExtensions)) +); diff --git a/scm-ui/ui-webapp/src/repos/sources/containers/Sources.tsx b/scm-ui/ui-webapp/src/repos/sources/containers/Sources.tsx index 7a28178b51..b5c34b7a21 100644 --- a/scm-ui/ui-webapp/src/repos/sources/containers/Sources.tsx +++ b/scm-ui/ui-webapp/src/repos/sources/containers/Sources.tsx @@ -171,18 +171,18 @@ class Sources extends React.Component { const mapStateToProps = (state, ownProps) => { const { repository, match } = ownProps; const { revision, path } = match.params; - const decodedRevision = revision ? decodeURIComponent(revision) : undefined; + const decodedRevision = revision ? decodeURIComponent(revision) : revision; const loading = isFetchBranchesPending(state, repository); const error = getFetchBranchesFailure(state, repository); const branches = getBranches(state, repository); - const currentFileIsDirectory = decodedRevision + const currentFileIsDirectory = revision ? isDirectory(state, repository, decodedRevision, path) - : isDirectory(state, repository, revision, path); - const sources = getSources(state, repository, revision, path); + : isDirectory(state, repository, decodedRevision, path); + const sources = getSources(state, repository, decodedRevision, path); return { repository, - revision: decodedRevision, + revision, path, loading, error, @@ -198,7 +198,7 @@ const mapDispatchToProps = dispatch => { dispatch(fetchBranches(repository)); }, fetchSources: (repository: Repository, revision: string, path: string) => { - dispatch(fetchSources(repository, revision, path)); + dispatch(fetchSources(repository, decodeURIComponent(revision), path)); } }; }; diff --git a/scm-ui/ui-webapp/src/repos/sources/modules/sources.ts b/scm-ui/ui-webapp/src/repos/sources/modules/sources.ts index 8fbd45f864..d3d0380a69 100644 --- a/scm-ui/ui-webapp/src/repos/sources/modules/sources.ts +++ b/scm-ui/ui-webapp/src/repos/sources/modules/sources.ts @@ -1,5 +1,5 @@ import * as types from "../../../modules/types"; -import { Repository, File, Action } from "@scm-manager/ui-types"; +import { Repository, File, Action, Link } from "@scm-manager/ui-types"; import { apiClient } from "@scm-manager/ui-components"; import { isPending } from "../../../modules/pending"; import { getFailure } from "../../../modules/failure"; @@ -16,16 +16,16 @@ export function fetchSources(repository: Repository, revision: string, path: str .get(createUrl(repository, revision, path)) .then(response => response.json()) .then(sources => { - dispatch(fetchSourcesSuccess(repository, revision, path, sources)); + dispatch(fetchSourcesSuccess(repository, decodeURIComponent(revision), path, sources)); }) .catch(err => { - dispatch(fetchSourcesFailure(repository, revision, path, err)); + dispatch(fetchSourcesFailure(repository, decodeURIComponent(revision), path, err)); }); }; } function createUrl(repository: Repository, revision: string, path: string) { - const base = repository._links.sources.href; + const base = (repository._links.sources as Link).href; if (!revision && !path) { return base; } @@ -61,7 +61,7 @@ export function fetchSourcesFailure(repository: Repository, revision: string, pa function createItemId(repository: Repository, revision: string, path: string) { const revPart = revision ? revision : "_"; const pathPart = path ? path : ""; - return `${repository.namespace}/${repository.name}/${revPart}/${pathPart}`; + return `${repository.namespace}/${repository.name}/${decodeURIComponent(revPart)}/${pathPart}`; } // reducer