Skip to content

Commit

Permalink
Merge pull request #111 from jaegertracing/issue-88-stored-search-set…
Browse files Browse the repository at this point in the history
…tings

Verify stored search settings
  • Loading branch information
tiffon authored Nov 6, 2017
2 parents cec107f + 21abefd commit df12ead
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 44 deletions.
16 changes: 14 additions & 2 deletions src/components/SearchTracePage/TraceSearchForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,19 @@ const mapStateToProps = state => {
let lastSearchOperation;

if (lastSearch) {
lastSearchService = lastSearch.service;
lastSearchOperation = lastSearch.operation;
// last search is only valid if the service is in the list of services
const { operation: lastOp, service: lastSvc } = lastSearch;
if (lastSvc && lastSvc !== '-') {
if (state.services.services.includes(lastSvc)) {
lastSearchService = lastSvc;
if (lastOp && lastOp !== '-') {
const ops = state.services.operationsForService[lastSvc];
if (lastOp === 'all' || (ops && ops.includes(lastOp))) {
lastSearchOperation = lastOp;
}
}
}
}
}

const {
Expand All @@ -242,6 +253,7 @@ const mapStateToProps = state => {
if (traceIDParams) {
traceIDs = traceIDParams instanceof Array ? traceIDParams.join(',') : traceIDParams;
}

return {
destroyOnUnmount: false,
initialValues: {
Expand Down
81 changes: 53 additions & 28 deletions src/components/SearchTracePage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import React, { Component } from 'react';
import _values from 'lodash/values';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import queryString from 'query-string';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Field, reduxForm, formValueSelector } from 'redux-form';
import { Link } from 'react-router-dom';
import { bindActionCreators } from 'redux';
import { Field, reduxForm, formValueSelector } from 'redux-form';
import store from 'store';

import JaegerLogo from '../../img/jaeger-logo.svg';

Expand Down Expand Up @@ -61,35 +62,45 @@ const traceResultsFiltersFormSelector = formValueSelector('traceResultsFilters')

export default class SearchTracePage extends Component {
componentDidMount() {
const { searchTraces, urlQueryParams, fetchServices } = this.props;
const { searchTraces, urlQueryParams, fetchServices, fetchServiceOperations } = this.props;
if (urlQueryParams.service || urlQueryParams.traceID) {
searchTraces(urlQueryParams);
}
fetchServices();
const { service } = store.get('lastSearch') || {};
if (service && service !== '-') {
fetchServiceOperations(service);
}
}

render() {
const {
traceResults,
services,
numberOfTraceResults,
maxTraceDuration,
loading,
errorMessage,
isHomepage,
loadingServices,
loadingTraces,
maxTraceDuration,
numberOfTraceResults,
services,
traceResults,
} = this.props;
const hasTraceResults = traceResults && traceResults.length > 0;
return (
<div className="trace-search ui grid padded">
<div className="four wide column">
<div className="ui tertiary segment" style={{ background: 'whitesmoke' }}>
<h3>Find Traces</h3>
<TraceSearchForm services={services} />
{!loadingServices && services
? <TraceSearchForm services={services} />
: <div className="m1">
<div className="ui active centered inline loader" />
</div>}
</div>
</div>
<div className="twelve wide column padded">
{loading && <div className="ui active centered inline loader" />}
{loadingTraces && <div className="ui active centered inline loader" />}
{errorMessage &&
!loading &&
!loadingTraces &&
<div className="ui message red trace-search--error">
There was an error querying for traces:<br />
{errorMessage}
Expand All @@ -103,11 +114,11 @@ export default class SearchTracePage extends Component {
</div>}
{!isHomepage &&
!hasTraceResults &&
!loading &&
!loadingTraces &&
!errorMessage &&
<div className="ui message trace-search--no-results">No trace results. Try another query.</div>}
{hasTraceResults &&
!loading &&
!loadingTraces &&
<div>
<div>
<div style={{ border: '1px solid #e6e6e6' }}>
Expand Down Expand Up @@ -165,7 +176,8 @@ SearchTracePage.propTypes = {
traceResults: PropTypes.array,
numberOfTraceResults: PropTypes.number,
maxTraceDuration: PropTypes.number,
loading: PropTypes.bool,
loadingServices: PropTypes.bool,
loadingTraces: PropTypes.bool,
urlQueryParams: PropTypes.shape({
service: PropTypes.string,
limit: PropTypes.string,
Expand All @@ -180,30 +192,38 @@ SearchTracePage.propTypes = {
history: PropTypes.shape({
push: PropTypes.func,
}),
fetchServiceOperations: PropTypes.func,
fetchServices: PropTypes.func,
errorMessage: PropTypes.string,
};

const stateTraceXformer = getLastXformCacher(stateTrace => {
const { traces: traceMap, loading, error: traceError } = stateTrace;
const { traces: traceMap, loading: loadingTraces, error: traceError } = stateTrace;
const { traces, maxDuration } = getTraceSummaries(_values(traceMap));
return { traces, maxDuration, loading, traceError };
return { traces, maxDuration, traceError, loadingTraces };
});

const stateServicesXformer = getLastXformCacher(stateServices => {
const { services: serviceList, operationsForService: opsBySvc, error: serviceError } = stateServices;
const services = serviceList.map(name => ({
name,
operations: opsBySvc[name] || [],
}));
return { services, serviceError };
const {
loading: loadingServices,
services: serviceList,
operationsForService: opsBySvc,
error: serviceError,
} = stateServices;
const services =
serviceList &&
serviceList.map(name => ({
name,
operations: opsBySvc[name] || [],
}));
return { loadingServices, services, serviceError };
});

function mapStateToProps(state) {
const query = queryString.parse(state.router.location.search);
const isHomepage = !Object.keys(query).length;
const { traces, maxDuration, loading, traceError } = stateTraceXformer(state.trace);
const { services, serviceError } = stateServicesXformer(state.services);
const { traces, maxDuration, traceError, loadingTraces } = stateTraceXformer(state.trace);
const { loadingServices, services, serviceError } = stateServicesXformer(state.services);
const errorMessage = serviceError || traceError ? `${serviceError || ''} ${traceError || ''}` : '';
const sortBy = traceResultsFiltersFormSelector(state, 'sortBy');
sortTraces(traces, sortBy);
Expand All @@ -216,16 +236,21 @@ function mapStateToProps(state) {
maxTraceDuration: maxDuration,
urlQueryParams: query,
services,
loading,
loadingTraces,
loadingServices,
errorMessage,
};
}

function mapDispatchToProps(dispatch) {
const { searchTraces, fetchServices } = bindActionCreators(jaegerApiActions, dispatch);
const { searchTraces, fetchServices, fetchServiceOperations } = bindActionCreators(
jaegerApiActions,
dispatch
);
return {
searchTraces,
fetchServiceOperations,
fetchServices,
searchTraces,
};
}
export const ConnectedSearchTracePage = connect(mapStateToProps, mapDispatchToProps)(SearchTracePage);
5 changes: 3 additions & 2 deletions src/reducers/services.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import { fetchServices, fetchServiceOperations as fetchOps } from '../actions/ja
import { baseStringComparator } from '../utils/sort';

const initialState = {
services: [],
// `services` initial value of `null` indicates they haven't yet been loaded
services: null,
operationsForService: {},
loading: false,
error: null,
Expand Down Expand Up @@ -48,7 +49,7 @@ function fetchOpsDone(state, { meta, payload }) {
if (Array.isArray(operations)) {
operations.sort(baseStringComparator);
}
const operationsForService = { ...state.operationsForService, [meta.serviceName]: operations };
const operationsForService = { ...state.operationsForService, [meta.serviceName]: operations || [] };
return { ...state, operationsForService };
}

Expand Down
19 changes: 7 additions & 12 deletions src/reducers/services.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const initialState = serviceReducer(undefined, {});

function verifyInitialState() {
expect(initialState).toEqual({
services: [],
services: null,
loading: false,
error: null,
operationsForService: {},
Expand Down Expand Up @@ -47,12 +47,8 @@ it('should handle a fetch services with loading state', () => {
const state = serviceReducer(initialState, {
type: `${fetchServices}_PENDING`,
});
expect(state).toEqual({
services: [],
operationsForService: {},
loading: true,
error: null,
});
const expected = { ...initialState, loading: true };
expect(state).toEqual(expected);
});

it('should handle successful services fetch', () => {
Expand Down Expand Up @@ -90,12 +86,11 @@ it('should handle a successful fetching operations for a service ', () => {
meta: { serviceName: 'serviceA' },
payload: { data: ops.slice() },
});
expect(state).toEqual({
services: [],
const expected = {
...initialState,
operationsForService: {
serviceA: ops,
},
loading: false,
error: null,
});
};
expect(state).toEqual(expected);
});

0 comments on commit df12ead

Please sign in to comment.