diff --git a/packages/jaeger-ui/package.json b/packages/jaeger-ui/package.json index f33a18099c..fddf564d57 100644 --- a/packages/jaeger-ui/package.json +++ b/packages/jaeger-ui/package.json @@ -23,6 +23,7 @@ "devDependencies": { "@types/match-sorter": "^2.3.0", "@types/react-window": "^1.8.0", + "@types/redux-form": "^8.3.5", "@wojtekmaj/enzyme-adapter-react-17": "^0.8.0", "babel-plugin-import": "1.13.5", "bluebird": "^3.5.0", diff --git a/packages/jaeger-ui/src/components/DeepDependencies/traces.tsx b/packages/jaeger-ui/src/components/DeepDependencies/traces.tsx index f751ca02c6..6c48517b3b 100644 --- a/packages/jaeger-ui/src/components/DeepDependencies/traces.tsx +++ b/packages/jaeger-ui/src/components/DeepDependencies/traces.tsx @@ -13,12 +13,13 @@ // limitations under the License. import * as React from 'react'; +import { History as RouterHistory, Location } from 'history'; import _get from 'lodash/get'; import memoizeOne from 'memoize-one'; import queryString from 'query-string'; import { connect } from 'react-redux'; -import { DeepDependencyGraphPageImpl, TOwnProps, TProps, TReduxProps } from '.'; +import { DeepDependencyGraphPageImpl, TReduxProps } from '.'; import { getUrlState, sanitizeUrlState } from './url'; import { ROUTE_PATH } from '../SearchTracePage/url'; import GraphModel, { makeGraph } from '../../model/ddg/GraphModel'; @@ -59,8 +60,13 @@ export function mapStateToProps(state: ReduxState, ownProps: TOwnProps): TReduxP }; } +type TOwnProps = { + history: RouterHistory; + location: Location; +}; + // export for tests -export class TracesDdgImpl extends React.PureComponent { +export class TracesDdgImpl extends React.PureComponent { render(): React.ReactNode { const { location } = this.props; const urlArgs = queryString.parse(location.search); diff --git a/packages/jaeger-ui/src/components/Monitor/ServicesView/index.tsx b/packages/jaeger-ui/src/components/Monitor/ServicesView/index.tsx index 870a8581b8..07b9e255c8 100644 --- a/packages/jaeger-ui/src/components/Monitor/ServicesView/index.tsx +++ b/packages/jaeger-ui/src/components/Monitor/ServicesView/index.tsx @@ -18,8 +18,7 @@ import { ActionFunction, Action } from 'redux-actions'; import _debounce from 'lodash/debounce'; import _isEqual from 'lodash/isEqual'; import _isEmpty from 'lodash/isEmpty'; -// @ts-ignore -import { Field, formValueSelector, reduxForm } from 'redux-form'; +import { Field, formValueSelector, InjectedFormProps, reduxForm } from 'redux-form'; // @ts-ignore import store from 'store'; import { connect } from 'react-redux'; @@ -137,8 +136,10 @@ const convertServiceErrorRateToPercentages = (serviceErrorRate: null | ServiceMe return { ...serviceErrorRate, metricPoints: convertedMetricsPoints }; }; +type TPropsWithInjectedFormProps = TProps & InjectedFormProps<{}, TProps>; + // export for tests -export class MonitorATMServicesViewImpl extends React.PureComponent { +export class MonitorATMServicesViewImpl extends React.PureComponent { docsLink: string; graphDivWrapper: React.RefObject; serviceSelectorValue: string = ''; @@ -150,7 +151,7 @@ export class MonitorATMServicesViewImpl extends React.PureComponent

Choose service

trackSelectService(newValue)} + onChange={(e, newValue: string) => trackSelectService(newValue)} name="service" component={AdaptedVirtualSelect} placeholder="Select A Service" @@ -310,7 +311,7 @@ export class MonitorATMServicesViewImpl extends React.PureComponent { + onChange={(e, value: number) => { const { label } = timeFrameOptions.find(option => option.value === value)!; trackSelectTimeframe(label); }} @@ -455,7 +456,7 @@ export default connect( mapStateToProps, mapDispatchToProps )( - reduxForm({ + reduxForm<{}, TProps>({ form: 'serviceForm', })(MonitorATMServicesViewImpl) ); diff --git a/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ResultItem.tsx b/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ResultItem.tsx index 8ed44bdb9d..a44b554175 100644 --- a/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ResultItem.tsx +++ b/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ResultItem.tsx @@ -14,6 +14,7 @@ import * as React from 'react'; import { Col, Divider, Row, Tag } from 'antd'; +import { LocationDescriptor } from 'history'; import { Link } from 'react-router-dom'; import { sortBy } from 'lodash'; @@ -34,7 +35,7 @@ import './ResultItem.css'; type Props = { durationPercent: number; isInDiffCohort: boolean; - linkTo: string; + linkTo: LocationDescriptor; toggleComparison: (traceID: string) => void; trace: Trace; disableComparision: boolean; diff --git a/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ResultItemTitle.tsx b/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ResultItemTitle.tsx index 163c8bd8f8..9ed127ab4a 100644 --- a/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ResultItemTitle.tsx +++ b/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/ResultItemTitle.tsx @@ -14,6 +14,7 @@ import * as React from 'react'; import { Checkbox } from 'antd'; +import { LocationDescriptor } from 'history'; import { Link } from 'react-router-dom'; import TraceName from '../../common/TraceName'; @@ -30,7 +31,7 @@ type Props = { durationPercent?: number; error?: ApiError; isInDiffCohort: boolean; - linkTo: string | TNil; + linkTo: LocationDescriptor | TNil; state?: FetchedState | TNil; targetBlank?: boolean; toggleComparison: (traceID: string, isInDiffCohort: boolean) => void; @@ -72,7 +73,9 @@ export default class ResultItemTitle extends React.PureComponent { } = this.props; // Use a div when the ResultItemTitle doesn't link to anything let WrapperComponent: string | typeof Link = 'div'; - const wrapperProps: Record = { className: 'ResultItemTitle--item ub-flex-auto' }; + const wrapperProps: Record = { + className: 'ResultItemTitle--item ub-flex-auto', + }; if (linkTo) { wrapperProps.to = linkTo; WrapperComponent = Link; diff --git a/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/index.js b/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/index.tsx similarity index 87% rename from packages/jaeger-ui/src/components/SearchTracePage/SearchResults/index.js rename to packages/jaeger-ui/src/components/SearchTracePage/SearchResults/index.tsx index 5c536c4f87..f68c484122 100644 --- a/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/index.js +++ b/packages/jaeger-ui/src/components/SearchTracePage/SearchResults/index.tsx @@ -17,14 +17,14 @@ import * as React from 'react'; import { Select } from 'antd'; import { History as RouterHistory, Location } from 'history'; -import { Link, withRouter } from 'react-router-dom'; +import { Link, RouteComponentProps, withRouter } from 'react-router-dom'; import { Field, formValueSelector, reduxForm } from 'redux-form'; import queryString from 'query-string'; import AltViewOptions from './AltViewOptions'; import DiffSelection from './DiffSelection'; import * as markers from './index.markers'; -import { trackAltView } from './index.track'; +import { EAltViewActions, trackAltView } from './index.track'; import ResultItem from './ResultItem'; import ScatterPlot from './ScatterPlot'; import { getUrl } from '../url'; @@ -37,28 +37,28 @@ import { getPercentageOfDuration } from '../../../utils/date'; import { stripEmbeddedState } from '../../../utils/embedded-url'; import reduxFormFieldAdapter from '../../../utils/redux-form-field-adapter'; -import type { FetchedTrace } from '../../../types'; -import type { SearchQuery } from '../../../types/search'; -import type { KeyValuePair } from '../../../types/trace'; +import { FetchedTrace } from '../../../types'; +import { SearchQuery } from '../../../types/search'; +import { KeyValuePair, Trace } from '../../../types/trace'; import './index.css'; type SearchResultsProps = { - cohortAddTrace: string => void, - cohortRemoveTrace: string => void, - diffCohort: FetchedTrace[], - disableComparisons: boolean, - goToTrace: string => void, - hideGraph: boolean, - history: RouterHistory, - loading: boolean, - location: Location, - maxTraceDuration: number, - queryOfResults?: SearchQuery, - showStandaloneLink: boolean, - skipMessage?: boolean, - spanLinks?: Record | undefined | null, - traces: TraceSummary[], + cohortAddTrace: (traceId: string) => void; + cohortRemoveTrace: (traceId: string) => void; + diffCohort: FetchedTrace[]; + disableComparisons: boolean; + goToTrace: (traceId: string) => void; + hideGraph: boolean; + history: RouterHistory; + loading: boolean; + location: Location; + maxTraceDuration: number; + queryOfResults?: SearchQuery; + showStandaloneLink: boolean; + skipMessage?: boolean; + spanLinks?: Record | undefined; + traces: Trace[]; }; const Option = Select.Option; @@ -90,12 +90,10 @@ const SelectSort = reduxForm({ export const sortFormSelector = formValueSelector('traceResultsSort'); -export class UnconnectedSearchResults extends React.PureComponent { - props: SearchResultsProps; - +export class UnconnectedSearchResults extends React.PureComponent { static defaultProps = { skipMessage: false, spanLinks: undefined, queryOfResults: undefined }; - toggleComparison = (traceID: string, remove: boolean) => { + toggleComparison = (traceID: string, remove?: boolean) => { const { cohortAddTrace, cohortRemoveTrace } = this.props; if (remove) { cohortRemoveTrace(traceID); @@ -107,7 +105,7 @@ export class UnconnectedSearchResults extends React.PureComponent { const { location, history } = this.props; const urlState = queryString.parse(location.search); - const view = urlState.view && urlState.view === 'ddg' ? 'traces' : 'ddg'; + const view = urlState.view && urlState.view === 'ddg' ? EAltViewActions.Traces : EAltViewActions.Ddg; trackAltView(view); history.push(getUrl({ ...urlState, view })); }; @@ -172,7 +170,7 @@ export class UnconnectedSearchResults extends React.PureComponent sp.tags.some(isErrorTag)) ? 'red' : '#12939A', }))} - onValueClick={t => { + onValueClick={(t: Trace) => { goToTrace(t.traceID); }} /> diff --git a/packages/jaeger-ui/src/index.js b/packages/jaeger-ui/src/index.tsx similarity index 92% rename from packages/jaeger-ui/src/index.js rename to packages/jaeger-ui/src/index.tsx index cbdde1cd71..4511e02979 100644 --- a/packages/jaeger-ui/src/index.js +++ b/packages/jaeger-ui/src/index.tsx @@ -20,7 +20,6 @@ import './site-prefix'; import React from 'react'; import { BrowserRouter } from 'react-router-dom'; import { createRoot } from 'react-dom/client'; -import { document } from 'global'; import JaegerUIApp from './components/App'; import { context as trackingContext } from './utils/tracking'; @@ -36,9 +35,9 @@ import 'u-basscss/css/typography.css'; const UI_ROOT_ID = 'jaeger-ui-root'; -const root = createRoot(document.getElementById(UI_ROOT_ID)); +const root = createRoot(document.getElementById(UI_ROOT_ID)!); -if (trackingContext) { +if (typeof trackingContext === 'object' && trackingContext !== null) { trackingContext.context(() => { root.render( diff --git a/packages/jaeger-ui/src/types/search.tsx b/packages/jaeger-ui/src/types/search.tsx index 5747876ee5..e90bdfc6cd 100644 --- a/packages/jaeger-ui/src/types/search.tsx +++ b/packages/jaeger-ui/src/types/search.tsx @@ -25,30 +25,3 @@ export type SearchQuery = { start: number | string; tags: string | TNil; }; - -/** - * Type used to summarize traces for the search page. - */ -export type TraceSummary = { - /** - * Duration of trace in milliseconds. - */ - duration: number; - /** - * Start time of trace in milliseconds. - */ - timestamp: number; - traceName: string; - traceID: string; - numberOfErredSpans: number; - numberOfSpans: number; - services: { name: string; numberOfSpans: number }[]; -}; - -export type TraceSummaries = { - /** - * Duration of longest trace in `traces` in milliseconds. - */ - maxDuration: number; - traces: TraceSummary[]; -}; diff --git a/packages/jaeger-ui/tsconfig.lint.json b/packages/jaeger-ui/tsconfig.lint.json index 562e1172d2..2a44b81358 100644 --- a/packages/jaeger-ui/tsconfig.lint.json +++ b/packages/jaeger-ui/tsconfig.lint.json @@ -28,11 +28,29 @@ "files": [ "src/actions/jaeger-api.js", "src/api/jaeger.js", + "src/components/App/index.jsx", + "src/components/DependencyGraph/DAG.jsx", + "src/components/DependencyGraph/DependencyForceGraph.jsx", + "src/components/DependencyGraph/index.jsx", + "src/components/SearchTracePage/index.jsx", + "src/components/SearchTracePage/SearchForm.jsx", + "src/components/SearchTracePage/SearchForm.markers.js", + "src/components/SearchTracePage/SearchResults/ScatterPlot.jsx", + "src/components/SearchTracePage/SearchResults/index.markers.js", "src/components/SearchTracePage/SearchResults/ResultItem.markers.js", + "src/middlewares/index.js", "src/model/order-by.js", + "src/propTypes/dependencies.js", + "src/reducers/config.js", + "src/reducers/dependencies.js", + "src/reducers/index.js", + "src/reducers/services.js", + "src/reducers/trace.js", + "src/selectors/dependencies.js", "src/selectors/process.js", "src/selectors/span.js", "src/selectors/trace.js", + "src/utils/configure-store.js", "src/utils/sort.js", "src/utils/TreeNode.js" ] diff --git a/yarn.lock b/yarn.lock index 58e5535dbd..17e429c35e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2718,6 +2718,14 @@ version "2.2.1" resolved "https://registry.yarnpkg.com/@types/redux-actions/-/redux-actions-2.2.1.tgz#c1f4a7283ecd3cd696291550361e441bf9389370" +"@types/redux-form@^8.3.5": + version "8.3.5" + resolved "https://registry.yarnpkg.com/@types/redux-form/-/redux-form-8.3.5.tgz#7c55f4182952a41eca67e9d26e2a41ad425859a5" + integrity sha512-SchB4i7nxgWNbJS4cXEZducztkvHzVrb5xlAXwfLpbrLPo6tMY06+kx1GqMv42+YnGy9TpCAkF51a21HatqWBA== + dependencies: + "@types/react" "*" + redux "^3.6.0 || ^4.0.0" + "@types/scheduler@*": version "0.16.2" resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" @@ -15311,6 +15319,13 @@ redux@^3.0.2, redux@^3.6.0, redux@^3.7.2: loose-envify "^1.1.0" symbol-observable "^1.0.3" +"redux@^3.6.0 || ^4.0.0": + version "4.2.1" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" + integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== + dependencies: + "@babel/runtime" "^7.9.2" + regenerate-unicode-properties@^10.1.0: version "10.1.0" resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c"