mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-12 00:15:44 +01:00
fix form validation after refactoring
This commit is contained in:
@@ -32,6 +32,7 @@ type Props = {
|
||||
repository: RepositoryUrlImport;
|
||||
onChange: (repository: RepositoryUrlImport) => void;
|
||||
setValid: (valid: boolean) => void;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
const Column = styled.div`
|
||||
@@ -42,7 +43,7 @@ const Columns = styled.div`
|
||||
padding: 0.75rem 0 0;
|
||||
`;
|
||||
|
||||
const ImportFromUrlForm: FC<Props> = ({ repository, onChange, setValid }) => {
|
||||
const ImportFromUrlForm: FC<Props> = ({ repository, onChange, setValid, disabled }) => {
|
||||
const [t] = useTranslation("repos");
|
||||
const [urlValidationError, setUrlValidationError] = useState(false);
|
||||
|
||||
@@ -72,6 +73,7 @@ const ImportFromUrlForm: FC<Props> = ({ repository, onChange, setValid }) => {
|
||||
helpText={t("help.importUrlHelpText")}
|
||||
validationError={urlValidationError}
|
||||
errorMessage={t("validation.url-invalid")}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</Column>
|
||||
<Column className="column is-half">
|
||||
@@ -80,6 +82,7 @@ const ImportFromUrlForm: FC<Props> = ({ repository, onChange, setValid }) => {
|
||||
onChange={username => onChange({ ...repository, username })}
|
||||
value={repository.username}
|
||||
helpText={t("help.usernameHelpText")}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</Column>
|
||||
<Column className="column is-half">
|
||||
@@ -89,6 +92,7 @@ const ImportFromUrlForm: FC<Props> = ({ repository, onChange, setValid }) => {
|
||||
value={repository.password}
|
||||
type="password"
|
||||
helpText={t("help.passwordHelpText")}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</Column>
|
||||
</Columns>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
import React, { FC, useState } from "react";
|
||||
import React, { FC, FormEvent, useState } from "react";
|
||||
import NamespaceAndNameFields from "./NamespaceAndNameFields";
|
||||
import { Repository, RepositoryUrlImport } from "@scm-manager/ui-types";
|
||||
import ImportFromUrlForm from "./ImportFromUrlForm";
|
||||
@@ -62,7 +62,9 @@ const ImportRepositoryFromUrl: FC<Props> = ({ url, setImportPending }) => {
|
||||
setImportPending(loading);
|
||||
};
|
||||
|
||||
const submit = () => {
|
||||
const submit = (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault();
|
||||
const currentPath = history.location.pathname;
|
||||
handleImportLoading(true);
|
||||
apiClient
|
||||
.post(url, repo, "application/vnd.scmm-repository+json;v=2")
|
||||
@@ -72,7 +74,11 @@ const ImportRepositoryFromUrl: FC<Props> = ({ url, setImportPending }) => {
|
||||
return apiClient.get(location);
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(repo => history.push(`/repo/${repo.namespace}/${repo.name}/code/sources`))
|
||||
.then(repo => {
|
||||
if (history.location.pathname === currentPath) {
|
||||
history.push(`/repo/${repo.namespace}/${repo.name}/code/sources`);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
setError(error);
|
||||
handleImportLoading(false);
|
||||
@@ -81,22 +87,24 @@ const ImportRepositoryFromUrl: FC<Props> = ({ url, setImportPending }) => {
|
||||
|
||||
return (
|
||||
<form onSubmit={submit}>
|
||||
<ErrorNotification error={error} />
|
||||
<ImportFromUrlForm
|
||||
repository={repo}
|
||||
onChange={setRepo}
|
||||
setValid={(importUrl: boolean) => setValid({ ...valid, importUrl })}
|
||||
disabled={loading}
|
||||
/>
|
||||
<ErrorNotification error={error} />
|
||||
<hr />
|
||||
<NamespaceAndNameFields
|
||||
repository={repo}
|
||||
onChange={setRepo as React.Dispatch<React.SetStateAction<Repository>>}
|
||||
setValid={(namespaceAndName: boolean) => setValid({ ...valid, namespaceAndName })}
|
||||
disabled={loading}
|
||||
/>
|
||||
<RepositoryInformationForm
|
||||
repository={repo}
|
||||
onChange={setRepo as React.Dispatch<React.SetStateAction<Repository>>}
|
||||
disabled={false}
|
||||
disabled={loading}
|
||||
setValid={(contact: boolean) => setValid({ ...valid, contact })}
|
||||
/>
|
||||
<Level
|
||||
|
||||
@@ -30,18 +30,21 @@ type Props = {
|
||||
repositoryTypes: RepositoryType[];
|
||||
repositoryType?: RepositoryType;
|
||||
setRepositoryType: (repositoryType: RepositoryType) => void;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
const ImportRepositoryTypeSelect: FC<Props> = ({ repositoryTypes, repositoryType, setRepositoryType }) => {
|
||||
const ImportRepositoryTypeSelect: FC<Props> = ({ repositoryTypes, repositoryType, setRepositoryType, disabled }) => {
|
||||
const [t] = useTranslation("repos");
|
||||
|
||||
const createSelectOptions = () => {
|
||||
const options = repositoryTypes.filter(repoType => !!repoType._links.import).map(repositoryType => {
|
||||
return {
|
||||
label: repositoryType.displayName,
|
||||
value: repositoryType.name
|
||||
};
|
||||
});
|
||||
const options = repositoryTypes
|
||||
.filter(repoType => !!repoType._links.import)
|
||||
.map(repositoryType => {
|
||||
return {
|
||||
label: repositoryType.displayName,
|
||||
value: repositoryType.name
|
||||
};
|
||||
});
|
||||
options.unshift({ label: "", value: "" });
|
||||
return options;
|
||||
};
|
||||
@@ -52,13 +55,14 @@ const ImportRepositoryTypeSelect: FC<Props> = ({ repositoryTypes, repositoryType
|
||||
};
|
||||
|
||||
return (
|
||||
<Select
|
||||
label={t("repository.type")}
|
||||
onChange={onChangeType}
|
||||
value={repositoryType ? repositoryType.name : ""}
|
||||
options={createSelectOptions()}
|
||||
helpText={t("help.typeHelpText")}
|
||||
/>
|
||||
<Select
|
||||
label={t("repository.type")}
|
||||
onChange={onChangeType}
|
||||
value={repositoryType ? repositoryType.name : ""}
|
||||
options={createSelectOptions()}
|
||||
helpText={t("help.typeHelpText")}
|
||||
disabled={disabled}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -22,17 +22,18 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
import React, { FC } from "react";
|
||||
import { RepositoryType, Link } from "@scm-manager/ui-types";
|
||||
import { Radio } from "@scm-manager/ui-components";
|
||||
import { Link, RepositoryType } from "@scm-manager/ui-types";
|
||||
import { LabelWithHelpIcon, Radio } from "@scm-manager/ui-components";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
type Props = {
|
||||
repositoryType: RepositoryType;
|
||||
importType: string;
|
||||
setImportType: (type: string) => void;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
const ImportTypeSelect: FC<Props> = ({ repositoryType, importType, setImportType }) => {
|
||||
const ImportTypeSelect: FC<Props> = ({ repositoryType, importType, setImportType, disabled }) => {
|
||||
const [t] = useTranslation("repos");
|
||||
|
||||
const changeImportType = (checked: boolean, name?: string) => {
|
||||
@@ -43,6 +44,7 @@ const ImportTypeSelect: FC<Props> = ({ repositoryType, importType, setImportType
|
||||
|
||||
return (
|
||||
<>
|
||||
<LabelWithHelpIcon label={t("import.importTypes.label")} key="import.importTypes.label" />
|
||||
{(repositoryType._links.import as Link[]).map((type, index) => (
|
||||
<Radio
|
||||
name={type.name}
|
||||
@@ -52,6 +54,7 @@ const ImportTypeSelect: FC<Props> = ({ repositoryType, importType, setImportType
|
||||
helpText={t(`import.importTypes.${type.name}.helpText`)}
|
||||
onChange={changeImportType}
|
||||
key={index}
|
||||
disabled={disabled}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
|
||||
@@ -36,45 +36,45 @@ type Props = {
|
||||
onChange: (repository: Repository) => void;
|
||||
namespaceStrategy: string;
|
||||
setValid: (valid: boolean) => void;
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
const NamespaceAndNameFields: FC<Props> = ({ repository, onChange, namespaceStrategy, setValid }) => {
|
||||
const NamespaceAndNameFields: FC<Props> = ({ repository, onChange, namespaceStrategy, setValid, disabled }) => {
|
||||
const [t] = useTranslation("repos");
|
||||
const [namespaceValidationError, setNamespaceValidationError] = useState(false);
|
||||
const [nameValidationError, setNameValidationError] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
//TODO fix validation
|
||||
if (repository.name) {
|
||||
const valid = validator.isNameValid(repository.name);
|
||||
setNameValidationError(!valid);
|
||||
onFieldChange();
|
||||
const nameValid = validator.isNameValid(repository.name);
|
||||
setNameValidationError(!nameValid);
|
||||
if (namespaceStrategy === CUSTOM_NAMESPACE_STRATEGY) {
|
||||
if (repository.namespace) {
|
||||
const namespaceValid = validator.isNamespaceValid(repository.namespace);
|
||||
setValid(!(!namespaceValid || !nameValid));
|
||||
} else {
|
||||
setValid(false);
|
||||
}
|
||||
} else {
|
||||
setValid(nameValid);
|
||||
}
|
||||
} else {
|
||||
setValid(false);
|
||||
}
|
||||
}, [repository.name]);
|
||||
}, [repository.name, repository.namespace]);
|
||||
|
||||
const handleNamespaceChange = (namespace: string) => {
|
||||
const valid = validator.isNamespaceValid(namespace);
|
||||
setNamespaceValidationError(!valid);
|
||||
onFieldChange(valid);
|
||||
onChange({ ...repository, namespace });
|
||||
};
|
||||
|
||||
const handleNameChange = (name: string) => {
|
||||
const valid = validator.isNameValid(name);
|
||||
setNameValidationError(!valid);
|
||||
onFieldChange();
|
||||
onChange({ ...repository, name });
|
||||
};
|
||||
|
||||
//TODO fix validation
|
||||
const onFieldChange = (namespaceValid?: boolean) => {
|
||||
if (namespaceStrategy === CUSTOM_NAMESPACE_STRATEGY && !validator.isNamespaceValid(repository.namespace)) {
|
||||
setValid(false);
|
||||
} else {
|
||||
setValid(!nameValidationError && !namespaceValidationError);
|
||||
}
|
||||
};
|
||||
|
||||
const renderNamespaceField = () => {
|
||||
const props = {
|
||||
label: t("repository.namespace"),
|
||||
@@ -82,7 +82,8 @@ const NamespaceAndNameFields: FC<Props> = ({ repository, onChange, namespaceStra
|
||||
value: repository ? repository.namespace : "",
|
||||
onChange: handleNamespaceChange,
|
||||
errorMessage: t("validation.namespace-invalid"),
|
||||
validationError: namespaceValidationError
|
||||
validationError: namespaceValidationError,
|
||||
disabled: disabled
|
||||
};
|
||||
|
||||
if (namespaceStrategy === CUSTOM_NAMESPACE_STRATEGY) {
|
||||
@@ -102,6 +103,7 @@ const NamespaceAndNameFields: FC<Props> = ({ repository, onChange, namespaceStra
|
||||
validationError={nameValidationError}
|
||||
errorMessage={t("validation.name-invalid")}
|
||||
helpText={t("help.nameHelpText")}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -78,7 +78,6 @@ const RepositoryForm: FC<Props> = ({
|
||||
});
|
||||
const [initRepository, setInitRepository] = useState(false);
|
||||
const [contextEntries, setContextEntries] = useState({});
|
||||
//TODO fix validation
|
||||
const [valid, setValid] = useState({ namespaceAndName: false, contact: true });
|
||||
const [t] = useTranslation("repos");
|
||||
|
||||
@@ -194,7 +193,7 @@ const RepositoryForm: FC<Props> = ({
|
||||
<RepositoryInformationForm
|
||||
repository={repo}
|
||||
onChange={setRepo}
|
||||
disabled={!createRepository}
|
||||
disabled={!(isModifiable() || createRepository)}
|
||||
setValid={contact => setValid({ ...valid, contact })}
|
||||
/>
|
||||
{submitButton()}
|
||||
|
||||
@@ -25,12 +25,16 @@
|
||||
import React, { FC } from "react";
|
||||
import styled from "styled-components";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button, ButtonAddons, Level } from "@scm-manager/ui-components";
|
||||
import { Button, ButtonAddons, Icon, Level } from "@scm-manager/ui-components";
|
||||
|
||||
type Props = {
|
||||
creationMode: "CREATE" | "IMPORT";
|
||||
};
|
||||
|
||||
const MarginIcon = styled(Icon)`
|
||||
padding-right: 0.5rem;
|
||||
`;
|
||||
|
||||
const SmallButton = styled(Button)`
|
||||
border-radius: 4px;
|
||||
font-size: 1rem;
|
||||
@@ -38,9 +42,14 @@ const SmallButton = styled(Button)`
|
||||
`;
|
||||
|
||||
const TopLevel = styled(Level)`
|
||||
margin-top: -2.75rem;
|
||||
margin-bottom: 2.75rem !important; //TODO Try to remove important
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: -1.5rem !important;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
@media (max-width: 785px) {
|
||||
margin-top: 4.5rem;
|
||||
}
|
||||
`;
|
||||
|
||||
const RepositoryFormSwitcher: FC<Props> = ({ creationMode }) => {
|
||||
@@ -59,17 +68,20 @@ const RepositoryFormSwitcher: FC<Props> = ({ creationMode }) => {
|
||||
right={
|
||||
<ButtonAddons>
|
||||
<SmallButton
|
||||
label={t("repositoryForm.createButton")}
|
||||
icon="fa fa-plus"
|
||||
color={isCreateMode() ? "link is-selected" : undefined}
|
||||
link={isImportMode() ? "/repos/create" : undefined}
|
||||
/>
|
||||
>
|
||||
<MarginIcon name="fa fa-plus" color={isCreateMode() ? "white" : "default"} />{" "}
|
||||
<p className="is-hidden-mobile is-hidden-tablet-only">{t("repositoryForm.createButton")}</p>
|
||||
</SmallButton>
|
||||
<SmallButton
|
||||
label={t("repositoryForm.importButton")}
|
||||
icon="fa fa-file-upload"
|
||||
color={isImportMode() ? "link is-selected" : undefined}
|
||||
link={isCreateMode() ? "/repos/import" : undefined}
|
||||
/>
|
||||
className="has-text-left-desktop"
|
||||
>
|
||||
<MarginIcon name="fa fa-file-upload" color={isImportMode() ? "white" : "default"} />
|
||||
<p className="is-hidden-mobile is-hidden-tablet-only">{t("repositoryForm.importButton")}</p>
|
||||
</SmallButton>
|
||||
</ButtonAddons>
|
||||
}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user