Fix validation in "Add Entry" components (#1625)

This commit is contained in:
Florian Scholdei
2021-04-21 14:36:52 +02:00
committed by GitHub
parent b6018280ed
commit 05ef203038
4 changed files with 115 additions and 146 deletions

View File

@@ -0,0 +1,2 @@
- type: fixed
description: Validation in "Add Entry" components for configuration table ([#1625](https://github.com/scm-manager/scm-manager/pull/1625))

View File

@@ -29,6 +29,7 @@ import { createAttributesForTesting } from "../devBuild";
export type ButtonProps = {
label?: string;
title?: string;
loading?: boolean;
disabled?: boolean;
action?: (event: MouseEvent) => void;
@@ -43,7 +44,6 @@ export type ButtonProps = {
type Props = ButtonProps &
RouteComponentProps & {
title?: string;
type?: "button" | "submit" | "reset";
color?: string;
};

View File

@@ -21,24 +21,20 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import React, { MouseEvent } from "react";
import React, { FC, useState, MouseEvent } from "react";
import styled from "styled-components";
import Level from "../layout/Level";
import InputField from "./InputField";
import AddButton from "../buttons/AddButton";
import InputField from "./InputField";
type Props = {
addEntry: (p: string) => void;
disabled: boolean;
disabled?: boolean;
buttonLabel: string;
fieldLabel: string;
errorMessage: string;
helpText?: string;
validateEntry?: (p: string) => boolean;
};
type State = {
entryToAdd: string;
errorMessage: string;
};
const StyledLevel = styled(Level)`
@@ -46,46 +42,62 @@ const StyledLevel = styled(Level)`
margin-bottom: 1rem !important; // same margin as field
`;
const StyledInputField = styled(InputField)`
const FullWidthInputField = styled(InputField)`
width: 100%;
margin-right: 1.5rem;
`;
const StyledField = styled.div.attrs(props => ({
const StyledField = styled.div.attrs(() => ({
className: "field"
}))`
align-self: flex-end;
`;
class AddEntryToTableField extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
entryToAdd: ""
};
}
const AddEntryToTableField: FC<Props> = ({
addEntry,
disabled,
buttonLabel,
fieldLabel,
helpText,
validateEntry,
errorMessage
}) => {
const [entryToAdd, setEntryToAdd] = useState("");
isValid = () => {
const { validateEntry } = this.props;
if (!this.state.entryToAdd || this.state.entryToAdd === "" || !validateEntry) {
const handleAddEntryChange = (entryName: string) => {
setEntryToAdd(entryName);
};
const addButtonClicked = (event: MouseEvent) => {
event.preventDefault();
appendEntry();
};
const appendEntry = () => {
if (!disabled && entryToAdd !== "" && isValid()) {
addEntry(entryToAdd);
setEntryToAdd("");
}
};
const isValid = () => {
if (entryToAdd === "" || !validateEntry) {
return true;
} else {
return validateEntry(this.state.entryToAdd);
return validateEntry(entryToAdd);
}
};
render() {
const { disabled, buttonLabel, fieldLabel, errorMessage, helpText } = this.props;
return (
<StyledLevel
children={
<StyledInputField
<FullWidthInputField
label={fieldLabel}
errorMessage={errorMessage}
onChange={this.handleAddEntryChange}
validationError={!this.isValid()}
value={this.state.entryToAdd}
onReturnPressed={this.appendEntry}
onChange={handleAddEntryChange}
validationError={!isValid()}
value={entryToAdd}
onReturnPressed={appendEntry}
disabled={disabled}
helpText={helpText}
/>
@@ -94,35 +106,13 @@ class AddEntryToTableField extends React.Component<Props, State> {
<StyledField>
<AddButton
label={buttonLabel}
action={this.addButtonClicked}
disabled={disabled || this.state.entryToAdd === "" || !this.isValid()}
action={addButtonClicked}
disabled={disabled || entryToAdd === "" || !isValid()}
/>
</StyledField>
}
/>
);
}
addButtonClicked = (event: MouseEvent) => {
event.preventDefault();
this.appendEntry();
};
appendEntry = () => {
const { entryToAdd } = this.state;
this.props.addEntry(entryToAdd);
this.setState({
...this.state,
entryToAdd: ""
});
};
handleAddEntryChange = (entryname: string) => {
this.setState({
...this.state,
entryToAdd: entryname
});
};
}
export default AddEntryToTableField;

View File

@@ -21,16 +21,16 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import React, { MouseEvent } from "react";
import React, { FC, useState, MouseEvent } from "react";
import styled from "styled-components";
import { SelectValue } from "@scm-manager/ui-types";
import Level from "../layout/Level";
import Autocomplete from "../Autocomplete";
import AddButton from "../buttons/AddButton";
import Autocomplete from "../Autocomplete";
type Props = {
addEntry: (p: SelectValue) => void;
disabled: boolean;
disabled?: boolean;
buttonLabel: string;
fieldLabel: string;
helpText?: string;
@@ -40,24 +40,13 @@ type Props = {
noOptionsMessage?: string;
};
type State = {
selectedValue?: SelectValue;
};
const StyledAutocomplete = styled(Autocomplete)`
const FullWidthAutocomplete = styled(Autocomplete)`
width: 100%;
margin-right: 1.5rem;
`;
class AutocompleteAddEntryToTableField extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
selectedValue: undefined
};
}
render() {
const {
const AutocompleteAddEntryToTableField: FC<Props> = ({
addEntry,
disabled,
buttonLabel,
fieldLabel,
@@ -66,16 +55,33 @@ class AutocompleteAddEntryToTableField extends React.Component<Props, State> {
placeholder,
loadingMessage,
noOptionsMessage
} = this.props;
}) => {
const [selectedValue, setSelectedValue] = useState<SelectValue | undefined>(undefined);
const handleAddEntryChange = (selection: SelectValue) => {
setSelectedValue(selection);
};
const addButtonClicked = (event: MouseEvent) => {
event.preventDefault();
appendEntry();
};
const appendEntry = () => {
if (disabled || !selectedValue) {
return;
}
addEntry(selectedValue);
setSelectedValue(undefined);
};
const { selectedValue } = this.state;
return (
<Level
children={
<StyledAutocomplete
<FullWidthAutocomplete
label={fieldLabel}
loadSuggestions={loadSuggestions}
valueSelected={this.handleAddEntryChange}
valueSelected={handleAddEntryChange}
helpText={helpText}
value={selectedValue}
placeholder={placeholder}
@@ -86,40 +92,11 @@ class AutocompleteAddEntryToTableField extends React.Component<Props, State> {
}
right={
<div className="field">
<AddButton label={buttonLabel} action={this.addButtonClicked} disabled={disabled} />
<AddButton label={buttonLabel} action={addButtonClicked} disabled={disabled} />
</div>
}
/>
);
}
addButtonClicked = (event: MouseEvent) => {
event.preventDefault();
this.appendEntry();
};
appendEntry = () => {
const { selectedValue } = this.state;
if (!selectedValue) {
return;
}
this.setState(
// @ts-ignore
{
...this.state,
// @ts-ignore null is needed to clear the selection; undefined does not work
selectedValue: null
},
() => this.props.addEntry(selectedValue)
);
};
handleAddEntryChange = (selection: SelectValue) => {
this.setState({
...this.state,
selectedValue: selection
});
};
}
export default AutocompleteAddEntryToTableField;