Skip to content

Commit

Permalink
replace route input with typeahead select menu
Browse files Browse the repository at this point in the history
  • Loading branch information
rottencandy committed Oct 1, 2020
1 parent a4ec191 commit 175816c
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 80 deletions.
@@ -1,26 +1,19 @@
import * as React from 'react';
import * as _ from 'lodash';
import { useFormikContext, FormikValues } from 'formik';
import { useFormikContext } from 'formik';
import { TextInputTypes } from '@patternfly/react-core';
import { InputField, DropdownField } from '@console/shared';
import { makePortName } from '../../../utils/imagestream-utils';
import { InputField } from '@console/shared';
import { DeployImageFormData, GitImportFormData } from '../import-types';
import PortInputField from './PortInputField';

const CreateRoute: React.FC = () => {
const {
values: {
image: { ports },
route: { defaultUnknownPort, targetPort },
route: { defaultUnknownPort },
},
} = useFormikContext<FormikValues>();
const portOptions = ports.reduce((acc, port) => {
const name = makePortName(port);
acc[name] = (
<>
{port.containerPort} &rarr; {port.containerPort} ({port.protocol})
</>
);
return acc;
}, {});
} = useFormikContext<DeployImageFormData | GitImportFormData>();
const portOptions = ports.map((port) => port.containerPort.toString());
const placeholderPort = ports[0]?.containerPort || defaultUnknownPort;

return (
<>
Expand All @@ -37,24 +30,13 @@ const CreateRoute: React.FC = () => {
placeholder="/"
helpText="Path that the router watches to route traffic to the service."
/>
{_.isEmpty(ports) ? (
<InputField
type={TextInputTypes.text}
name="route.unknownTargetPort"
label="Target Port"
placeholder={defaultUnknownPort}
helpText="Target port for traffic."
/>
) : (
<DropdownField
name="route.targetPort"
label="Target Port"
items={portOptions}
title={portOptions[targetPort] || 'Select target port'}
helpText="Target port for traffic."
fullWidth
/>
)}
<PortInputField
name="route.unknownTargetPort"
label="Target Port"
placeholderText={placeholderPort.toString()}
helpText="Target port for traffic."
options={portOptions}
/>
</>
);
};
Expand Down
@@ -0,0 +1,71 @@
import * as React from 'react';
import { useField, useFormikContext, FormikValues } from 'formik';
import { FormGroup, Select, SelectVariant, SelectOption } from '@patternfly/react-core';
import { useFormikValidationFix, getFieldId } from '@console/shared';

interface RouteInputFieldProps {
name: string;
label: string;
options: string[];
placeholderText: string;
helpText: string;
}

const PortInputField: React.FC<RouteInputFieldProps> = ({
name,
label,
options,
placeholderText,
helpText,
}) => {
const [field, { touched, error }] = useField<string>(name);
const { setFieldValue, setFieldTouched } = useFormikContext<FormikValues>();
const [isOpen, setIsOpen] = React.useState<boolean>(false);
const fieldId = getFieldId(name, 'select-input');
const isValid = !(touched && error);
const errorMessage = !isValid ? error : '';

useFormikValidationFix(field.value);

const onToggle = () => {
setIsOpen(!isOpen);
};

const onSelect = (_event, selection: string) => {
setFieldValue(name, selection);
setFieldTouched(name);
onToggle();
};

const onClearSelection = () => {
setFieldValue(name, '');
setFieldTouched(name);
};

return (
<FormGroup
fieldId={fieldId}
validated={isValid ? 'default' : 'error'}
label={label}
helperText={helpText}
helperTextInvalid={errorMessage}
>
<Select
variant={SelectVariant.typeahead}
onToggle={onToggle}
onSelect={onSelect}
onClear={onClearSelection}
isOpen={isOpen}
selections={field.value}
placeholderText={placeholderText}
isCreatable
>
{options.map((val) => (
<SelectOption value={val} key={val} />
))}
</Select>
</FormGroup>
);
};

export default PortInputField;
@@ -1,10 +1,8 @@
import * as React from 'react';
import * as _ from 'lodash';
import { TextInputTypes } from '@patternfly/react-core';
import { useFormikContext, FormikValues } from 'formik';
import { InputField, DropdownField } from '@console/shared';
import { useFormikContext } from 'formik';
import FormSection from '../section/FormSection';
import { RouteData } from '../import-types';
import { RouteData, GitImportFormData, DeployImageFormData } from '../import-types';
import PortInputField from '../route/PortInputField';

export interface ServerlessRouteSectionProps {
route: RouteData;
Expand All @@ -14,40 +12,21 @@ const ServerlessRouteSection: React.FC<ServerlessRouteSectionProps> = ({ route }
const {
values: {
image: { ports },
route: { defaultUnknownPort, targetPort: routeTargetPort },
route: { defaultUnknownPort },
},
} = useFormikContext<FormikValues>();
const targetPort = routeTargetPort.split('-')[0];
const portOptions = ports.reduce((acc, port) => {
const name = port?.containerPort;
if (name) {
acc[name] = <>{port.containerPort}</>;
}
return acc;
}, {});
} = useFormikContext<DeployImageFormData | GitImportFormData>();
const placeholderPort = ports[0]?.containerPort || defaultUnknownPort;
const portOptions = ports.map((port) => port?.containerPort.toString());
return (
<FormSection title="Routing">
{route.create && (
<>
{_.isEmpty(ports) ? (
<InputField
type={TextInputTypes.text}
name="route.unknownTargetPort"
label="Target Port"
placeholder={defaultUnknownPort}
helpText="Target port for traffic."
/>
) : (
<DropdownField
name="route.targetPort"
label="Target Port"
items={portOptions}
title={portOptions[targetPort] || 'Select target port'}
helpText="Target port for traffic."
fullWidth
/>
)}
</>
<PortInputField
name="route.unknownTargetPort"
label="Target Port"
placeholderText={placeholderPort.toString()}
helpText="Target port for traffic."
options={portOptions}
/>
)}
</FormSection>
);
Expand Down
Expand Up @@ -136,8 +136,11 @@ export const routeValidationSchema = yup.object().shape({
.string()
.matches(pathRegex, { message: 'Path must start with /.', excludeEmptyString: true }),
unknownTargetPort: yup
.string()
.matches(/^\d+$/, { message: 'Port must be an Integer.', excludeEmptyString: true }),
.number()
.typeError('Port must be an Integer.')
.integer('Port must be an Integer.')
.min(1, 'Port must be between 1 and 65535.')
.max(65535, 'Port must be between 1 and 65535.'),
});

export const limitsValidationSchema = yup.object().shape({
Expand Down
16 changes: 9 additions & 7 deletions frontend/packages/dev-console/src/utils/shared-submit-utils.ts
Expand Up @@ -120,20 +120,22 @@ export const createRoute = (
ports = isiPorts;
}

let targetPort;
let targetPort: string;
if (_.get(formData, 'build.strategy') === 'Docker') {
const port = _.get(formData, 'docker.containerPort');
targetPort = makePortName({
containerPort: _.toInteger(port),
protocol: 'TCP',
});
} else if (_.isEmpty(ports)) {
targetPort = makePortName({
containerPort: _.toInteger(unknownTargetPort) || defaultUnknownPort,
protocol: 'TCP',
});
} else if (unknownTargetPort) {
targetPort = makePortName({ containerPort: _.toInteger(unknownTargetPort), protocol: 'TCP' });
} else {
targetPort = routeTargetPort || makePortName(_.head(ports));
targetPort =
routeTargetPort ||
makePortName({
containerPort: ports[0]?.containerPort || defaultUnknownPort,
protocol: 'TCP',
});
}

const newRoute: any = {
Expand Down
Expand Up @@ -34,9 +34,7 @@ export const getKnativeServiceDepResource = (
healthChecks,
resources,
} = formData;
const contTargetPort = targetPort
? parseInt(targetPort.split('-')[0], 10)
: parseInt(unknownTargetPort, 10);
const contTargetPort = parseInt(unknownTargetPort, 10) || parseInt(targetPort.split('-')[0], 10);
const imgPullPolicy = imagePolicy ? ImagePullPolicy.Always : ImagePullPolicy.IfNotPresent;
const { concurrencylimit, concurrencytarget, minpods, maxpods } = scaling;
const {
Expand Down

0 comments on commit 175816c

Please sign in to comment.