Skip to content

Commit

Permalink
[fix]: Disable submit button on invalid minDuration or maxDuration (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
hari45678 authored Jan 20, 2025
1 parent 657cd00 commit 14837c3
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 22 deletions.
32 changes: 17 additions & 15 deletions packages/jaeger-ui/src/components/SearchTracePage/SearchForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
DEFAULT_OPERATION,
DEFAULT_LIMIT,
DEFAULT_LOOKBACK,
SEARCH_SIDEBAR_CHANGE_SERVICE_ACTION_TYPE,
CHANGE_SERVICE_ACTION_TYPE,
} from '../../constants/search-form';
import { getConfigValue } from '../../utils/config/get-config';
import SearchableSelect from '../common/SearchableSelect';
Expand Down Expand Up @@ -302,13 +302,15 @@ export class SearchFormImpl extends React.PureComponent {
};

render() {
const { invalid, searchMaxLookback, services, submitting: disabled } = this.props;
const { invalid, searchMaxLookback, services, submitting } = this.props;
const { formData } = this.state;
const { service: selectedService, lookback: selectedLookback } = formData;
const selectedServicePayload = services.find(s => s.name === selectedService);
const opsForSvc = (selectedServicePayload && selectedServicePayload.operations) || [];
const noSelectedService = selectedService === '-' || !selectedService;
const tz = selectedLookback === 'custom' ? new Date().toTimeString().replace(/^.*?GMT/, 'UTC') : null;
const invalidDuration =
validateDurationFields(formData.minDuration) || validateDurationFields(formData.maxDuration);

return (
<Form layout="vertical" onSubmitCapture={this.handleSubmit}>
Expand All @@ -323,7 +325,7 @@ export class SearchFormImpl extends React.PureComponent {
name="service"
value={this.state.formData.service}
placeholder="Select A Service"
disabled={disabled}
disabled={submitting}
onChange={value => this.handleChange({ service: value })}
>
{services.map(service => (
Expand All @@ -343,7 +345,7 @@ export class SearchFormImpl extends React.PureComponent {
<SearchableSelect
name="operation"
value={this.state.formData.operation}
disabled={disabled || noSelectedService}
disabled={submitting || noSelectedService}
placeholder="Select An Operation"
onChange={value => this.handleChange({ operation: value })}
>
Expand Down Expand Up @@ -429,7 +431,7 @@ export class SearchFormImpl extends React.PureComponent {
<Input
name="tags"
value={this.state.formData.tags}
disabled={disabled}
disabled={submitting}
placeholder="http.status_code=200 error=true"
onChange={e => this.handleChange({ tags: e.target.value })}
/>
Expand All @@ -439,7 +441,7 @@ export class SearchFormImpl extends React.PureComponent {
<SearchableSelect
name="lookback"
value={this.state.formData.lookback}
disabled={disabled}
disabled={submitting}
defaultValue={DEFAULT_LOOKBACK}
onChange={value => this.handleChange({ lookback: value })}
>
Expand Down Expand Up @@ -473,7 +475,7 @@ export class SearchFormImpl extends React.PureComponent {
<Input
name="startDate"
value={this.state.formData.startDate}
disabled={disabled}
disabled={submitting}
type="date"
placeholder="Start Date"
onChange={e => this.handleChange({ startDate: e.target.value })}
Expand All @@ -484,7 +486,7 @@ export class SearchFormImpl extends React.PureComponent {
<Input
name="startDateTime"
value={this.state.formData.startDateTime}
disabled={disabled}
disabled={submitting}
type="time"
onChange={e => this.handleChange({ startDateTime: e.target.value })}
/>
Expand Down Expand Up @@ -516,7 +518,7 @@ export class SearchFormImpl extends React.PureComponent {
<Input
name="endDate"
value={this.state.formData.endDate}
disabled={disabled}
disabled={submitting}
type="date"
placeholder="End Date"
onChange={e => this.handleChange({ endDate: e.target.value })}
Expand All @@ -527,7 +529,7 @@ export class SearchFormImpl extends React.PureComponent {
<Input
name="endDateTime"
value={this.state.formData.endDateTime}
disabled={disabled}
disabled={submitting}
type="time"
onChange={e => this.handleChange({ endDateTime: e.target.value })}
/>
Expand All @@ -542,7 +544,7 @@ export class SearchFormImpl extends React.PureComponent {
<ValidatedFormField
name="maxDuration"
value={this.state.formData.maxDuration}
disabled={disabled}
disabled={submitting}
validate={validateDurationFields}
placeholder={placeholderDurationFields}
onChange={e => this.handleChange({ maxDuration: e.target.value })}
Expand All @@ -555,7 +557,7 @@ export class SearchFormImpl extends React.PureComponent {
<ValidatedFormField
name="minDuration"
value={this.state.formData.minDuration}
disabled={disabled}
disabled={submitting}
validate={validateDurationFields}
placeholder={placeholderDurationFields}
onChange={e => this.handleChange({ minDuration: e.target.value })}
Expand All @@ -568,7 +570,7 @@ export class SearchFormImpl extends React.PureComponent {
<Input
name="resultsLimit"
value={this.state.formData.resultsLimit}
disabled={disabled}
disabled={submitting}
type="number"
placeholder="Limit Results"
min={1}
Expand All @@ -580,7 +582,7 @@ export class SearchFormImpl extends React.PureComponent {
<Button
htmlType="submit"
className="SearchForm--submit"
disabled={disabled || noSelectedService || invalid}
disabled={submitting || noSelectedService || invalid || invalidDuration}
data-test={markers.SUBMIT_BTN}
>
Find Traces
Expand Down Expand Up @@ -727,7 +729,7 @@ export function mapDispatchToProps(dispatch) {
return {
changeServiceHandler: service =>
dispatch({
type: SEARCH_SIDEBAR_CHANGE_SERVICE_ACTION_TYPE,
type: CHANGE_SERVICE_ACTION_TYPE,
payload: service,
}),
submitFormHandler: fields => submitForm(fields, searchTraces),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import {
} from './SearchForm';
import * as markers from './SearchForm.markers';
import getConfig from '../../utils/config/get-config';
import { SEARCH_SIDEBAR_CHANGE_SERVICE_ACTION_TYPE } from '../../constants/search-form';
import { CHANGE_SERVICE_ACTION_TYPE } from '../../constants/search-form';

function makeDateParams(dateOffset = 0) {
const date = new Date();
Expand Down Expand Up @@ -450,6 +450,26 @@ describe('<SearchForm>', () => {
expect(btn.prop('disabled')).toBeTruthy();
});

it('disables the submit button when duration is invalid', () => {
wrapper = shallow(<SearchForm {...defaultProps} />);
wrapper.instance().handleChange({ service: 'svcA' });
wrapper.instance().handleChange({ minDuration: '1ms' });
let btn = wrapper.find(`[data-test="${markers.SUBMIT_BTN}"]`);
let invalidDuration =
validateDurationFields(wrapper.state().formData.minDuration) ||
validateDurationFields(wrapper.state().formData.maxDuration);
expect(invalidDuration).not.toBeDefined();
expect(btn.prop('disabled')).toBeFalsy();

wrapper.instance().handleChange({ minDuration: '1kg' });
btn = wrapper.find(`[data-test="${markers.SUBMIT_BTN}"]`);
invalidDuration =
validateDurationFields(wrapper.state().formData.minDuration) ||
validateDurationFields(wrapper.state().formData.maxDuration);
expect(invalidDuration).toBeDefined();
expect(btn.prop('disabled')).toBeTruthy();
});

it('uses config.search.maxLimit', () => {
const maxLimit = 6789;
getConfig.apply({}, []);
Expand Down Expand Up @@ -702,7 +722,7 @@ describe('mapDispatchToProps()', () => {
changeServiceHandler(service);

expect(dispatch).toHaveBeenCalledWith({
type: SEARCH_SIDEBAR_CHANGE_SERVICE_ACTION_TYPE,
type: CHANGE_SERVICE_ACTION_TYPE,
payload: service,
});
});
Expand Down
2 changes: 1 addition & 1 deletion packages/jaeger-ui/src/constants/search-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ export const DEFAULT_OPERATION = 'all';
export const DEFAULT_LOOKBACK = '1h';
export const DEFAULT_LIMIT = 20;

export const SEARCH_SIDEBAR_CHANGE_SERVICE_ACTION_TYPE = '@@redux/searchSideBar/CHANGE_SERVICE';
export const CHANGE_SERVICE_ACTION_TYPE = '@@redux/searchSideBar/CHANGE_SERVICE';
4 changes: 2 additions & 2 deletions packages/jaeger-ui/src/middlewares/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ import { replace } from 'redux-first-history';

import { searchTraces, fetchServiceOperations } from '../actions/jaeger-api';
import { getUrl as getSearchUrl } from '../components/SearchTracePage/url';
import { SEARCH_SIDEBAR_CHANGE_SERVICE_ACTION_TYPE } from '../constants/search-form';
import { CHANGE_SERVICE_ACTION_TYPE } from '../constants/search-form';

export { default as trackMiddleware } from './track';

/**
* Middleware to load "operations" for a particular service.
*/
export const loadOperationsForServiceMiddleware = store => next => action => {
if (action.type === SEARCH_SIDEBAR_CHANGE_SERVICE_ACTION_TYPE && action.payload !== '-') {
if (action.type === CHANGE_SERVICE_ACTION_TYPE && action.payload !== '-') {
store.dispatch(fetchServiceOperations(action.payload));
}
return next(action);
Expand Down
4 changes: 2 additions & 2 deletions packages/jaeger-ui/src/middlewares/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jest.mock(

import * as jaegerMiddlewares from './index';
import { fetchServiceOperations } from '../actions/jaeger-api';
import { SEARCH_SIDEBAR_CHANGE_SERVICE_ACTION_TYPE } from '../constants/search-form';
import { CHANGE_SERVICE_ACTION_TYPE } from '../constants/search-form';

it('jaegerMiddlewares should contain the promise middleware', () => {
expect(typeof jaegerMiddlewares.promise).toBe('function');
Expand All @@ -36,7 +36,7 @@ it('loadOperationsForServiceMiddleware fetches operations for services', () => {
const dispatch = jest.fn();
const next = jest.fn();
const action = {
type: SEARCH_SIDEBAR_CHANGE_SERVICE_ACTION_TYPE,
type: CHANGE_SERVICE_ACTION_TYPE,
payload: 'yo',
};
loadOperationsForServiceMiddleware({ dispatch })(next)(action);
Expand Down

0 comments on commit 14837c3

Please sign in to comment.