show namespace input field if custom namespace strategy is selected

This commit is contained in:
Sebastian Sdorra
2019-03-11 16:39:48 +01:00
parent de157f4ef1
commit 257d1ebc27
4 changed files with 59 additions and 10 deletions

View File

@@ -1,5 +1,6 @@
{ {
"repository": { "repository": {
"namespace": "Namespace",
"name": "Name", "name": "Name",
"type": "Typ", "type": "Typ",
"contact": "Kontakt", "contact": "Kontakt",
@@ -8,10 +9,12 @@
"lastModified": "Zuletzt bearbeitet" "lastModified": "Zuletzt bearbeitet"
}, },
"validation": { "validation": {
"namespace-invalid": "Der Namespace des Repository ist ungültig",
"name-invalid": "Der Name des Repository ist ungültig", "name-invalid": "Der Name des Repository ist ungültig",
"contact-invalid": "Der Kontakt muss eine gültige E-Mail Adresse sein" "contact-invalid": "Der Kontakt muss eine gültige E-Mail Adresse sein"
}, },
"help": { "help": {
"namespaceHelpText": "Der Namespace des Repository. Dieser wird Teil der URL des Repository sein.",
"nameHelpText": "Der Name des Repository. Dieser wird Teil der URL des Repository sein.", "nameHelpText": "Der Name des Repository. Dieser wird Teil der URL des Repository sein.",
"typeHelpText": "Der Typ des Repository (Mercurial, Git oder Subversion).", "typeHelpText": "Der Typ des Repository (Mercurial, Git oder Subversion).",
"contactHelpText": "E-Mail Adresse der Person, die für das Repository verantwortlich ist.", "contactHelpText": "E-Mail Adresse der Person, die für das Repository verantwortlich ist.",

View File

@@ -1,5 +1,6 @@
{ {
"repository": { "repository": {
"namespace": "Namespace",
"name": "Name", "name": "Name",
"type": "Type", "type": "Type",
"contact": "Contact", "contact": "Contact",
@@ -8,10 +9,12 @@
"lastModified": "Last Modified" "lastModified": "Last Modified"
}, },
"validation": { "validation": {
"namespace-invalid": "The repository namespace is invalid",
"name-invalid": "The repository name is invalid", "name-invalid": "The repository name is invalid",
"contact-invalid": "Contact must be a valid mail address" "contact-invalid": "Contact must be a valid mail address"
}, },
"help": { "help": {
"namespaceHelpText": "The namespace of the repository. This name will be part of the repository url.",
"nameHelpText": "The name of the repository. This name will be part of the repository url.", "nameHelpText": "The name of the repository. This name will be part of the repository url.",
"typeHelpText": "The type of the repository (e.g. Mercurial, Git or Subversion).", "typeHelpText": "The type of the repository (e.g. Mercurial, Git or Subversion).",
"contactHelpText": "Email address of the person who is responsible for this repository.", "contactHelpText": "Email address of the person who is responsible for this repository.",

View File

@@ -15,12 +15,14 @@ type Props = {
submitForm: Repository => void, submitForm: Repository => void,
repository?: Repository, repository?: Repository,
repositoryTypes: RepositoryType[], repositoryTypes: RepositoryType[],
namespaceStrategy: string,
loading?: boolean, loading?: boolean,
t: string => string t: string => string
}; };
type State = { type State = {
repository: Repository, repository: Repository,
namespaceValidationError: boolean,
nameValidationError: boolean, nameValidationError: boolean,
contactValidationError: boolean contactValidationError: boolean
}; };
@@ -38,9 +40,9 @@ class RepositoryForm extends React.Component<Props, State> {
description: "", description: "",
_links: {} _links: {}
}, },
namespaceValidationError: false,
nameValidationError: false, nameValidationError: false,
contactValidationError: false, contactValidationError: false
descriptionValidationError: false
}; };
} }
@@ -61,6 +63,7 @@ class RepositoryForm extends React.Component<Props, State> {
isValid = () => { isValid = () => {
const repository = this.state.repository; const repository = this.state.repository;
return !( return !(
this.state.namespaceValidationError ||
this.state.nameValidationError || this.state.nameValidationError ||
this.state.contactValidationError || this.state.contactValidationError ||
this.isFalsy(repository.name) this.isFalsy(repository.name)
@@ -127,6 +130,22 @@ class RepositoryForm extends React.Component<Props, State> {
}); });
} }
renderNamespaceField = () => {
const { namespaceStrategy, t } = this.props;
if (namespaceStrategy === "CustomNamespaceStrategy") {
const repository = this.state.repository;
return <InputField
label={t("repository.namespace")}
onChange={this.handleNamespaceChange}
value={repository ? repository.namespace : ""}
validationError={this.state.namespaceValidationError}
errorMessage={t("validation.namespace-invalid")}
helpText={t("help.namespaceHelpText")}
/>;
}
return null;
};
renderCreateOnlyFields() { renderCreateOnlyFields() {
if (!this.isCreateMode()) { if (!this.isCreateMode()) {
return null; return null;
@@ -135,6 +154,7 @@ class RepositoryForm extends React.Component<Props, State> {
const repository = this.state.repository; const repository = this.state.repository;
return ( return (
<> <>
{this.renderNamespaceField()}
<InputField <InputField
label={t("repository.name")} label={t("repository.name")}
onChange={this.handleNameChange} onChange={this.handleNameChange}
@@ -154,6 +174,13 @@ class RepositoryForm extends React.Component<Props, State> {
); );
} }
handleNamespaceChange = (namespace: string) => {
this.setState({
namespaceValidationError: !validator.isNameValid(namespace),
repository: { ...this.state.repository, namespace }
});
};
handleNameChange = (name: string) => { handleNameChange = (name: string) => {
this.setState({ this.setState({
nameValidationError: !validator.isNameValid(name), nameValidationError: !validator.isNameValid(name),

View File

@@ -4,7 +4,7 @@ import { connect } from "react-redux";
import { translate } from "react-i18next"; import { translate } from "react-i18next";
import { Page } from "@scm-manager/ui-components"; import { Page } from "@scm-manager/ui-components";
import RepositoryForm from "../components/form"; import RepositoryForm from "../components/form";
import type { Repository, RepositoryType } from "@scm-manager/ui-types"; import type { Repository, RepositoryType, NamespaceStrategies } from "@scm-manager/ui-types";
import { import {
fetchRepositoryTypesIfNeeded, fetchRepositoryTypesIfNeeded,
getFetchRepositoryTypesFailure, getFetchRepositoryTypesFailure,
@@ -19,15 +19,21 @@ import {
} from "../modules/repos"; } from "../modules/repos";
import type { History } from "history"; import type { History } from "history";
import { getRepositoriesLink } from "../../modules/indexResource"; import { getRepositoriesLink } from "../../modules/indexResource";
import {
fetchNamespaceStrategiesIfNeeded,
getFetchNamespaceStrategiesFailure, getNamespaceStrategies, isFetchNamespaceStrategiesPending
} from "../../config/modules/namespaceStrategies";
type Props = { type Props = {
repositoryTypes: RepositoryType[], repositoryTypes: RepositoryType[],
typesLoading: boolean, namespaceStrategies: NamespaceStrategies,
pageLoading: boolean,
createLoading: boolean, createLoading: boolean,
error: Error, error: Error,
repoLink: string, repoLink: string,
// dispatch functions // dispatch functions
fetchNamespaceStrategiesIfNeeded: () => void,
fetchRepositoryTypesIfNeeded: () => void, fetchRepositoryTypesIfNeeded: () => void,
createRepo: ( createRepo: (
link: string, link: string,
@@ -45,6 +51,7 @@ class Create extends React.Component<Props> {
componentDidMount() { componentDidMount() {
this.props.resetForm(); this.props.resetForm();
this.props.fetchRepositoryTypesIfNeeded(); this.props.fetchRepositoryTypesIfNeeded();
this.props.fetchNamespaceStrategiesIfNeeded();
} }
repoCreated = (repo: Repository) => { repoCreated = (repo: Repository) => {
@@ -55,9 +62,10 @@ class Create extends React.Component<Props> {
render() { render() {
const { const {
typesLoading, pageLoading,
createLoading, createLoading,
repositoryTypes, repositoryTypes,
namespaceStrategies,
createRepo, createRepo,
error error
} = this.props; } = this.props;
@@ -67,13 +75,14 @@ class Create extends React.Component<Props> {
<Page <Page
title={t("create.title")} title={t("create.title")}
subtitle={t("create.subtitle")} subtitle={t("create.subtitle")}
loading={typesLoading} loading={pageLoading}
error={error} error={error}
showContentOnError={true} showContentOnError={true}
> >
<RepositoryForm <RepositoryForm
repositoryTypes={repositoryTypes} repositoryTypes={repositoryTypes}
loading={createLoading} loading={createLoading}
namespaceStrategy={namespaceStrategies.current}
submitForm={repo => { submitForm={repo => {
createRepo(repoLink, repo, (repo: Repository) => createRepo(repoLink, repo, (repo: Repository) =>
this.repoCreated(repo) this.repoCreated(repo)
@@ -87,14 +96,18 @@ class Create extends React.Component<Props> {
const mapStateToProps = state => { const mapStateToProps = state => {
const repositoryTypes = getRepositoryTypes(state); const repositoryTypes = getRepositoryTypes(state);
const typesLoading = isFetchRepositoryTypesPending(state); const namespaceStrategies = getNamespaceStrategies(state);
const pageLoading = isFetchRepositoryTypesPending(state)
|| isFetchNamespaceStrategiesPending(state);
const createLoading = isCreateRepoPending(state); const createLoading = isCreateRepoPending(state);
const error = const error = getFetchRepositoryTypesFailure(state)
getFetchRepositoryTypesFailure(state) || getCreateRepoFailure(state); || getCreateRepoFailure(state)
|| getFetchNamespaceStrategiesFailure(state);
const repoLink = getRepositoriesLink(state); const repoLink = getRepositoriesLink(state);
return { return {
repositoryTypes, repositoryTypes,
typesLoading, namespaceStrategies,
pageLoading,
createLoading, createLoading,
error, error,
repoLink repoLink
@@ -106,6 +119,9 @@ const mapDispatchToProps = dispatch => {
fetchRepositoryTypesIfNeeded: () => { fetchRepositoryTypesIfNeeded: () => {
dispatch(fetchRepositoryTypesIfNeeded()); dispatch(fetchRepositoryTypesIfNeeded());
}, },
fetchNamespaceStrategiesIfNeeded: () => {
dispatch(fetchNamespaceStrategiesIfNeeded());
},
createRepo: ( createRepo: (
link: string, link: string,
repository: Repository, repository: Repository,