From 37984ce003868d9a1f35103891e05a6ea1b9cc4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Szab=C3=B3?= Date: Mon, 27 Feb 2023 22:48:36 +0100 Subject: [PATCH] Convert SearchResults and index components to TS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As with https://github.com/jaegertracing/jaeger-ui/pull/1218, convert SearchResults and the root index component to use TS and the .tsx file extension rather than plain .js. TS was chosen here since SearchResults was already using Flow types, and index is trivially convertible. Adding `@types/react-form` as a new dev dependency to provide typings for `redux-form` in `SearchResults` in turn revealed type errors in the usage of `redux-form` in the `ServicesView` component, so update that component accordingly. Likewise, the conversion from Flow to TS revealed some typing errors in child components. Also update the list of JS files to be included in the TS linting process - since we now have two new TS files to be built and linted, the JS files that these import in turn need to be explicitly listed in tsconfig.lint.json, otherwise `tsc` complains that they are not included in the build. Signed-off-by: Máté Szabó --- packages/jaeger-ui/package.json | 1 + .../components/DeepDependencies/traces.tsx | 10 +++- .../components/Monitor/ServicesView/index.tsx | 15 +++--- .../SearchResults/ResultItem.tsx | 3 +- .../SearchResults/ResultItemTitle.tsx | 7 ++- .../SearchResults/{index.js => index.tsx} | 50 +++++++++---------- .../src/components/SearchTracePage/index.js | 2 +- .../jaeger-ui/src/{index.js => index.tsx} | 5 +- packages/jaeger-ui/src/types/search.tsx | 27 ---------- packages/jaeger-ui/tsconfig.lint.json | 18 +++++++ yarn.lock | 15 ++++++ 11 files changed, 84 insertions(+), 69 deletions(-) rename packages/jaeger-ui/src/components/SearchTracePage/SearchResults/{index.js => index.tsx} (87%) rename packages/jaeger-ui/src/{index.js => index.tsx} (92%) 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/components/SearchTracePage/index.js b/packages/jaeger-ui/src/components/SearchTracePage/index.js index c0955b8a52..aa3b0717bc 100644 --- a/packages/jaeger-ui/src/components/SearchTracePage/index.js +++ b/packages/jaeger-ui/src/components/SearchTracePage/index.js @@ -108,7 +108,7 @@ export class SearchTracePageImpl extends Component { { + loadJsonTraces={fileList => { loadJsonTraces(fileList); }} /> 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..9c1473a990 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.js", + "src/components/DependencyGraph/DAG.js", + "src/components/DependencyGraph/DependencyForceGraph.js", + "src/components/DependencyGraph/index.js", + "src/components/SearchTracePage/index.js", + "src/components/SearchTracePage/SearchForm.js", + "src/components/SearchTracePage/SearchForm.markers.js", + "src/components/SearchTracePage/SearchResults/ScatterPlot.js", + "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"