Skip to content

Commit

Permalink
remove search button and search status/result for deploy image
Browse files Browse the repository at this point in the history
add validated text

show field required when searchTerm is empty

create scss file  for image search component,  use patternfly validatedOption enum

add data-test-id to ImageSearch component

add classes for success help text

s

remove styles

removed funtional test because Input search button is removed and no longer used

remove $

fix functional tests

show inline error for ImageStream

add error

refactor

reorder Imports
  • Loading branch information
sahil143 committed Feb 20, 2020
1 parent e169dd1 commit c7c4ce0
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 292 deletions.
19 changes: 10 additions & 9 deletions frontend/integration-tests/tests/deploy-image.scenario.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { browser, $, element, by, ExpectedConditions as until } from 'protractor';
import { browser, element, by, ExpectedConditions as until } from 'protractor';

import { appHost, checkLogs, checkErrors, testName } from '../protractor.conf';

Expand Down Expand Up @@ -35,15 +35,16 @@ describe('Deploy Image', () => {

it('can be used to search for an image', async () => {
// Put the search term in the search field
await element(by.css('[data-test-id="deploy-image-search-term"]')).sendKeys(imageName);
// Click the search button
await element(by.css('[data-test-id="input-search-field-btn"]')).click();
// Wait for the results section to appear
await browser.wait(until.presenceOf($('.co-image-name-results__details')));
await element(by.css('[data-test-id=deploy-image-search-term]')).sendKeys(imageName);

//remove focus form image search field
await element(by.css('[data-test-id=application-form-app-name]')).click();

const helperText = 'form-input-searchTerm-field-helper';
// Wait for the validation
await browser.wait(until.presenceOf(element(by.id(helperText))));
// Confirm the results appeared
expect(
element(by.cssContainingText('.co-image-name-results__heading', imageName)).isPresent(),
).toBe(true);
expect(element(by.id(helperText)).isPresent()).toBe(true);
});

it('should auto fill in the application', async () => {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ export { default as DropdownField } from './DropdownField';
export { default as DroppableFileInputField } from './DroppableFileInputField';
export { default as EnvironmentField } from './EnvironmentField';
export { default as InputField } from './InputField';
export { default as InputSearchField } from './InputSearchField';
export { default as MultiColumnField } from './multi-column-field/MultiColumnField';
export { default as NSDropdownField } from './NSDropdownField';
export { default as NumberSpinnerField } from './NumberSpinnerField';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe('Application Launcher Menu', () => {
expect(pageSidebar.getText()).toContain('Topology');
expect(pageSidebar.getText()).toContain('+Add');
expect(pageSidebar.getText()).toContain('Builds');
expect(pageSidebar.getText()).toContain('Advanced');
expect(pageSidebar.getText()).toContain('More');
expect(pageSidebar.getText()).toContain('Project Details');
expect(pageSidebar.getText()).toContain('Project Access');
expect(pageSidebar.getText()).toContain('Search');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,97 +3,124 @@ import * as _ from 'lodash';
import { k8sCreate } from '@console/internal/module/k8s';
import { ImageStreamImportsModel } from '@console/internal/models';
import { useFormikContext, FormikValues } from 'formik';
import { TextInputTypes, Alert, AlertActionCloseButton, Button } from '@patternfly/react-core';
import {
TextInputTypes,
Alert,
AlertActionCloseButton,
Button,
ValidatedOptions,
} from '@patternfly/react-core';
import { SecretTypeAbstraction } from '@console/internal/components/secrets/create-secret';
import { InputSearchField } from '@console/shared';
import { InputField } from '@console/shared';
import { getSuggestedName, getPorts, makePortName } from '../../../utils/imagestream-utils';
import { secretModalLauncher } from '../CreateSecretModal';

const ImageSearch: React.FC = () => {
const { values, setFieldValue, dirty } = useFormikContext<FormikValues>();
const [newImageSecret, setNewImageSecret] = React.useState('');
const [alertVisible, shouldHideAlert] = React.useState(true);
const [validated, setValidated] = React.useState<ValidatedOptions>(ValidatedOptions.default);
const namespace = values.project.name;

const handleSearch = React.useCallback(
(searchTerm: string) => {
const importImage = {
kind: 'ImageStreamImport',
apiVersion: 'image.openshift.io/v1',
metadata: {
name: 'newapp',
namespace: values.project.name,
},
spec: {
import: false,
images: [
{
from: {
kind: 'DockerImage',
name: _.trim(searchTerm),
},
const handleSearch = React.useCallback(() => {
const searchTermImage = values.searchTerm;
setFieldValue('isSearchingForImage', true);
setValidated(ValidatedOptions.default);
const importImage = {
kind: 'ImageStreamImport',
apiVersion: 'image.openshift.io/v1',
metadata: {
name: 'newapp',
namespace: values.project.name,
},
spec: {
import: false,
images: [
{
from: {
kind: 'DockerImage',
name: _.trim(searchTermImage),
},
],
},
status: {},
};
},
],
},
status: {},
};

k8sCreate(ImageStreamImportsModel, importImage)
.then((imageStreamImport) => {
const status = _.get(imageStreamImport, 'status.images[0].status');
if (status.status === 'Success') {
const name = _.get(imageStreamImport, 'spec.images[0].from.name');
const image = _.get(imageStreamImport, 'status.images[0].image');
const tag = _.get(imageStreamImport, 'status.images[0].tag');
const isi = { name, image, tag, status };
const ports = getPorts(isi);
setFieldValue('isSearchingForImage', false);
setFieldValue('isi.name', name);
setFieldValue('isi.image', image);
setFieldValue('isi.tag', tag);
setFieldValue('isi.status', status);
setFieldValue('isi.ports', ports);
setFieldValue('image.ports', ports);
setFieldValue('image.tag', tag);
!values.name && setFieldValue('name', getSuggestedName(name));
!values.application.name &&
setFieldValue('application.name', `${getSuggestedName(name)}-app`);
// set default port value
const targetPort = _.head(ports);
targetPort && setFieldValue('route.targetPort', makePortName(targetPort));
} else {
setFieldValue('isSearchingForImage', false);
setFieldValue('isi', {});
setFieldValue('isi.status', status.message);
setFieldValue('route.targetPort', null);
}
})
.catch((error) => {
setFieldValue('isi', {});
setFieldValue('isi.status', error.message);
k8sCreate(ImageStreamImportsModel, importImage)
.then((imageStreamImport) => {
const status = _.get(imageStreamImport, 'status.images[0].status');
if (status.status === 'Success') {
const name = _.get(imageStreamImport, 'spec.images[0].from.name');
const image = _.get(imageStreamImport, 'status.images[0].image');
const tag = _.get(imageStreamImport, 'status.images[0].tag');
const isi = { name, image, tag, status };
const ports = getPorts(isi);
setFieldValue('isSearchingForImage', false);
});
},
[setFieldValue, values.application.name, values.name, values.project.name],
);
setFieldValue('isi.name', name);
setFieldValue('isi.image', image);
setFieldValue('isi.tag', tag);
setFieldValue('isi.status', status);
setFieldValue('isi.ports', ports);
setFieldValue('image.ports', ports);
setFieldValue('image.tag', tag);
!values.name && setFieldValue('name', getSuggestedName(name));
!values.application.name &&
setFieldValue('application.name', `${getSuggestedName(name)}-app`);
// set default port value
const targetPort = _.head(ports);
targetPort && setFieldValue('route.targetPort', makePortName(targetPort));
setValidated(ValidatedOptions.success);
} else {
setFieldValue('isSearchingForImage', false);
setFieldValue('isi', {});
setFieldValue('isi.status', status.message);
setFieldValue('route.targetPort', null);
setValidated(ValidatedOptions.error);
}
})
.catch((error) => {
setFieldValue('isi', {});
setFieldValue('isi.status', error.message);
setFieldValue('isSearchingForImage', false);
setValidated(ValidatedOptions.error);
});
}, [setFieldValue, values.application.name, values.name, values.project.name, values.searchTerm]);

const handleSave = (name: string) => {
setNewImageSecret(name);
values.searchTerm && handleSearch(values.searchTerm);
values.searchTerm && handleSearch();
};

const getHelpText = () => {
if (values.isSearchingForImage) {
return 'Validating...';
}
if (!values.isSearchingForImage && validated === ValidatedOptions.success) {
return 'Validated';
}
return '';
};

const helpTextInvalid = validated === ValidatedOptions.error && (
<span>{values.searchTerm === '' ? 'Required' : values.isi.status}</span>
);

React.useEffect(() => {
!dirty && values.searchTerm && handleSearch(values.searchTerm);
!dirty && values.searchTerm && handleSearch();
}, [dirty, handleSearch, values.searchTerm]);

return (
<>
<InputSearchField
<InputField
type={TextInputTypes.text}
data-test-id="deploy-image-search-term"
name="searchTerm"
label="Image Name"
onSearch={handleSearch}
placeholder="Enter an image name"
helpText={getHelpText()}
helpTextInvalid={helpTextInvalid}
validated={validated}
onBlur={handleSearch}
data-test-id="deploy-image-search-term"
required
/>
<div className="help-block" id="image-name-help">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import FormSection from '../section/FormSection';
import { imageRegistryType } from '../../../utils/imagestream-utils';
import ImageStream from './ImageStream';
import ImageSearch from './ImageSearch';
import SearchStatus from './SearchStatus';
import SearchResults from './SearchResults';

const ImageSearchSection: React.FC = () => {
const { values, setFieldValue, initialValues } = useFormikContext<FormikValues>();
Expand Down Expand Up @@ -49,8 +47,6 @@ const ImageSearchSection: React.FC = () => {
},
]}
/>
<SearchStatus />
<SearchResults />
</FormSection>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import * as _ from 'lodash';
import { Alert } from '@patternfly/react-core';
import { Alert, FormGroup, ValidatedOptions } from '@patternfly/react-core';
import { ExclamationCircleIcon } from '@patternfly/react-icons';
import { useFormikContext, FormikValues } from 'formik';
import { CheckboxField } from '@console/shared';
import { K8sResourceKind } from '@console/internal/module/k8s';
Expand Down Expand Up @@ -45,9 +46,10 @@ export const ImageStreamReducer = (state: ImageStreamState, action: ImageStreamA

const ImageStream: React.FC = () => {
const {
values: { imageStream, project, registry },
values: { imageStream, project, registry, isi },
setFieldValue,
} = useFormikContext<FormikValues>();
const [validated, setValidated] = React.useState<ValidatedOptions>(ValidatedOptions.default);
const [state, dispatch] = React.useReducer(ImageStreamReducer, initialState);
const [hasImageStreams, setHasImageStreams] = React.useState(false);
const {
Expand Down Expand Up @@ -75,23 +77,37 @@ const ImageStream: React.FC = () => {
registry === RegistryType.Internal &&
imageStream.namespace !== BuilderImagesNamespace.Openshift &&
project.name !== imageStream.namespace;
const helperTextInvalid = validated === ValidatedOptions.error && (
<>
<ExclamationCircleIcon />
&nbsp;{isi.status}
</>
);

return (
<>
<ImageStreamContext.Provider value={{ state, dispatch, hasImageStreams, setHasImageStreams }}>
<div className="row">
<div className="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<ImageStreamNsDropdown />
</div>
<div className="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<ImageStreamDropdown />
<div className="odc-imagestream-separator">/</div>
</div>
<div className="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<ImageStreamTagDropdown />
<div className="odc-imagestream-separator">:</div>
<ImageStreamContext.Provider
value={{ state, dispatch, hasImageStreams, setHasImageStreams, setValidated }}
>
<FormGroup
fieldId="image-stream-dropdowns"
validated={validated}
helperTextInvalid={helperTextInvalid}
>
<div className="row">
<div className="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<ImageStreamNsDropdown />
</div>
<div className="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<ImageStreamDropdown />
<div className="odc-imagestream-separator">/</div>
</div>
<div className="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<ImageStreamTagDropdown />
<div className="odc-imagestream-separator">:</div>
</div>
</div>
</div>
</FormGroup>
{isNamespaceSelected && isImageStreamSelected && !isTagsAvailable && hasCreateAccess && (
<div className="odc-imagestream-alert">
<Alert variant="warning" title="No Image streams tags found" isInline>
Expand Down

0 comments on commit c7c4ce0

Please sign in to comment.