diff --git a/src/actions.ts b/src/actions.ts index 42fc125d2..915ed7032 100644 --- a/src/actions.ts +++ b/src/actions.ts @@ -34,5 +34,6 @@ export const actions = addPrefix(ACTION_PREFIX, { OPEN_DASHBOARD: "OPEN_DASHBOARD", OPEN_INSTALLATION_WIZARD: "OPEN_INSTALLATION_WIZARD", SET_SCOPE: "SET_SCOPE", + CHANGE_SCOPE: "CHANGE_SCOPE", SET_STATE: "SET_STATE" }); diff --git a/src/components/Assets/AssetsFilter/index.tsx b/src/components/Assets/AssetsFilter/index.tsx index b059da61c..fa0fe7e33 100644 --- a/src/components/Assets/AssetsFilter/index.tsx +++ b/src/components/Assets/AssetsFilter/index.tsx @@ -74,6 +74,7 @@ export const AssetsFilter = (props: AssetsFilterProps) => { const [selectedInsights, setSelectedInsights] = useState([]); const config = useContext(ConfigContext); const previousEnvironment = usePrevious(config.environment); + const previousScope = usePrevious(config.scope); const getData = ( services: string[], @@ -135,8 +136,10 @@ export const AssetsFilter = (props: AssetsFilterProps) => { useEffect(() => { if ( - isEnvironment(previousEnvironment) && - previousEnvironment.originalName !== config.environment?.originalName + (isEnvironment(previousEnvironment) && + previousEnvironment.originalName !== + config.environment?.originalName) || + (previousScope && previousScope !== config.scope) ) { const defaultFilters = { services: [], @@ -151,7 +154,9 @@ export const AssetsFilter = (props: AssetsFilterProps) => { previousEnvironment, config.environment, setPersistedFilters, - props.onApply + props.onApply, + previousScope, + config.scope ]); useEffect(() => { diff --git a/src/components/Assets/index.tsx b/src/components/Assets/index.tsx index f3bfcf684..c4ce11fee 100644 --- a/src/components/Assets/index.tsx +++ b/src/components/Assets/index.tsx @@ -1,5 +1,4 @@ import { - ChangeEvent, useContext, useEffect, useLayoutEffect, @@ -16,7 +15,7 @@ import { usePrevious } from "../../hooks/usePrevious"; import { FeatureFlag } from "../../types"; import { ConfigContext } from "../common/App/ConfigContext"; import { EmptyState } from "../common/EmptyState"; -import { MagnifierIcon } from "../common/icons/MagnifierIcon"; +import { SearchInput } from "../common/SearchInput"; import { AssetList } from "./AssetList"; import { AssetTypeList } from "./AssetTypeList"; import { AssetsFilter } from "./AssetsFilter"; @@ -79,8 +78,10 @@ export const Assets = () => { }, [config.scope]); useEffect(() => { - if (previousScope !== config.scope?.span) { + if (!previousScope || previousScope !== config.scope?.span) { setSelectedAssetTypeId(null); + setSearchInputValue(""); + setSelectedServices([]); } }, [config.scope, previousScope]); @@ -88,8 +89,8 @@ export const Assets = () => { setSelectedAssetTypeId(null); }; - const handleSearchInputChange = (e: ChangeEvent) => { - setSearchInputValue(e.target.value); + const handleSearchInputChange = (val: string | null) => { + setSearchInputValue(val || ""); }; const handleAssetTypeSelect = (assetTypeId: string) => { @@ -155,15 +156,10 @@ export const Assets = () => { Assets {window.assetsSearch === true && ( - - - - - - + )} {isComplexFilterEnabled ? ( { return ( diff --git a/src/components/Insights/DurationBreakdownInsight/index.tsx b/src/components/Insights/DurationBreakdownInsight/index.tsx index 8b1f96232..2aa086425 100644 --- a/src/components/Insights/DurationBreakdownInsight/index.tsx +++ b/src/components/Insights/DurationBreakdownInsight/index.tsx @@ -80,7 +80,7 @@ export const DurationBreakdownInsight = ( return ( {pageItems.map((entry) => { diff --git a/src/components/Insights/DurationInsight/index.tsx b/src/components/Insights/DurationInsight/index.tsx index af18e413e..3ac1ba9a3 100644 --- a/src/components/Insights/DurationInsight/index.tsx +++ b/src/components/Insights/DurationInsight/index.tsx @@ -283,7 +283,7 @@ export const DurationInsight = (props: DurationInsightProps) => { return ( diff --git a/src/components/Insights/DurationSlowdownSourceInsight/index.tsx b/src/components/Insights/DurationSlowdownSourceInsight/index.tsx index 18dc4a239..e9ba2b76e 100644 --- a/src/components/Insights/DurationSlowdownSourceInsight/index.tsx +++ b/src/components/Insights/DurationSlowdownSourceInsight/index.tsx @@ -53,7 +53,7 @@ export const DurationSlowdownSourceInsight = ( return ( Found spans slowing the endpoint diff --git a/src/components/Insights/EndpointNPlusOneInsight/index.tsx b/src/components/Insights/EndpointNPlusOneInsight/index.tsx index 9e243d458..4c4d1c8f7 100644 --- a/src/components/Insights/EndpointNPlusOneInsight/index.tsx +++ b/src/components/Insights/EndpointNPlusOneInsight/index.tsx @@ -58,7 +58,7 @@ export const EndpointNPlusOneInsight = ( return ( Check the following locations: diff --git a/src/components/Insights/EndpointQueryOptimizationInsight/index.tsx b/src/components/Insights/EndpointQueryOptimizationInsight/index.tsx index a168c4ca6..5861fbf02 100644 --- a/src/components/Insights/EndpointQueryOptimizationInsight/index.tsx +++ b/src/components/Insights/EndpointQueryOptimizationInsight/index.tsx @@ -56,7 +56,7 @@ export const EndpointQueryOptimizationInsight = ( return ( Check the following locations: diff --git a/src/components/Insights/ExcessiveAPICallsInsight/index.tsx b/src/components/Insights/ExcessiveAPICallsInsight/index.tsx index 6d285824d..e46a9d90e 100644 --- a/src/components/Insights/ExcessiveAPICallsInsight/index.tsx +++ b/src/components/Insights/ExcessiveAPICallsInsight/index.tsx @@ -40,7 +40,7 @@ export const ExcessiveAPICallsInsight = ( return ( diff --git a/src/components/Insights/HighNumberOfQueriesInsight/index.tsx b/src/components/Insights/HighNumberOfQueriesInsight/index.tsx index 6337e92b5..88b8e5b32 100644 --- a/src/components/Insights/HighNumberOfQueriesInsight/index.tsx +++ b/src/components/Insights/HighNumberOfQueriesInsight/index.tsx @@ -39,7 +39,7 @@ export const HighNumberOfQueriesInsight = ( return ( diff --git a/src/components/Insights/InsightCard/InsightCard.stories.tsx b/src/components/Insights/InsightCard/InsightCard.stories.tsx index b5c86fef6..bf4fdfe88 100644 --- a/src/components/Insights/InsightCard/InsightCard.stories.tsx +++ b/src/components/Insights/InsightCard/InsightCard.stories.tsx @@ -20,7 +20,6 @@ type Story = StoryObj; export const Default: Story = { args: { - title: "asdasdasd", data: { firstDetected: "2023-12-05T17:25:47.010Z", lastDetected: "2024-01-05T13:14:47.010Z", diff --git a/src/components/Insights/InsightCard/index.tsx b/src/components/Insights/InsightCard/index.tsx index 30fe2bdaa..5850ee628 100644 --- a/src/components/Insights/InsightCard/index.tsx +++ b/src/components/Insights/InsightCard/index.tsx @@ -1,5 +1,6 @@ import { useContext, useState } from "react"; import { useTheme } from "styled-components"; +import { actions } from "../../../actions"; import { PERCENTILES } from "../../../constants"; import { isString } from "../../../typeGuards/isString"; import { formatTimeDistance } from "../../../utils/formatTimeDistance"; @@ -123,16 +124,31 @@ export const InsightCard = (props: InsightCardProps) => { IS_NEW_TIME_LIMIT : false; + const handleLinkClick = (spanCodeObjectId?: string) => { + if (spanCodeObjectId) { + window.sendMessageToDigma({ + action: actions.CHANGE_SCOPE, + payload: { + span: spanCodeObjectId + } + }); + } + }; + return ( <> - {props.title} + handleLinkClick(props.spanInfo?.spanCodeObjectId)} + > + {props.spanInfo?.displayName} + } header={ diff --git a/src/components/Insights/InsightCard/styles.ts b/src/components/Insights/InsightCard/styles.ts index 33bfd3904..8157e207c 100644 --- a/src/components/Insights/InsightCard/styles.ts +++ b/src/components/Insights/InsightCard/styles.ts @@ -1,16 +1,18 @@ import styled from "styled-components"; -import { Link } from "../styles"; export const TitleIcon = styled.div` display: flex; `; -export const TitleText = styled.div` - fill: #a1b5ff; +export const Link = styled.a` + color: #7891d0; + text-decoration: none; + font-weight: 500; + font-size: 14px; + cursor: pointer; text-overflow: ellipsis; - overflow: hidden; white-space: nowrap; - display: block; + overflow: hidden; `; export const Title = styled.div` diff --git a/src/components/Insights/InsightCard/types.ts b/src/components/Insights/InsightCard/types.ts index 762c13f5f..560169af6 100644 --- a/src/components/Insights/InsightCard/types.ts +++ b/src/components/Insights/InsightCard/types.ts @@ -1,5 +1,5 @@ import { ReactNode } from "react"; -import { InsightType } from "../../../types"; +import { InsightType, SpanInfo } from "../../../types"; import { GenericCodeObjectInsight } from "../types"; export interface InsightCardProps { @@ -9,7 +9,6 @@ export interface InsightCardProps { menuItems?: string[]; stats?: string; buttons?: ReactNode[]; - title?: string; onRecalculate: ( prefixedCodeObjectId: string, insightType: InsightType @@ -18,6 +17,7 @@ export interface InsightCardProps { isRecent?: boolean; onRefresh: (insightType: InsightType) => void; isAsync?: boolean; + spanInfo?: SpanInfo | null; } export interface PercentileViewModeOptionProps { diff --git a/src/components/Insights/InsightsCatalog/index.tsx b/src/components/Insights/InsightsCatalog/index.tsx index ae9aa3760..766cb729b 100644 --- a/src/components/Insights/InsightsCatalog/index.tsx +++ b/src/components/Insights/InsightsCatalog/index.tsx @@ -1,6 +1,7 @@ import { useEffect, useState } from "react"; import { usePrevious } from "../../../hooks/usePrevious"; +import { useDebounce } from "../../../hooks/useDebounce"; import { isNumber } from "../../../typeGuards/isNumber"; import { Pagination } from "../../common/Pagination"; import { SearchInput } from "../../common/SearchInput"; @@ -15,23 +16,30 @@ export const InsightsCatalog = (props: InsightsCatalogProps) => { const { insights, onJiraTicketCreate, defaultQuery, totalCount } = props; const [page, setPage] = useState(0); const previousPage = usePrevious(page); - const [searchInputValue, setSearchInputValue] = useState( + const [searchInputValue, setSearchInputValue] = useState( defaultQuery.searchQuery ); + const debouncedSearchInputValue = useDebounce(searchInputValue, 1000); const [sorting, setSorting] = useState(defaultQuery.sorting); const previousSorting = usePrevious(sorting); - const previousSearchQuery = usePrevious(searchInputValue); + const previousSearchQuery = usePrevious(debouncedSearchInputValue); const pageStartItemNumber = page * PAGE_SIZE + 1; const pageEndItemNumber = Math.min( pageStartItemNumber + PAGE_SIZE - 1, totalCount ); + useEffect(() => { + if (previousPage !== page) { + window.scrollTo(0, 0); + } + }, [previousPage, page]); + useEffect(() => { props.onQueryChange({ page, sorting, - searchQuery: searchInputValue + searchQuery: debouncedSearchInputValue }); }, []); @@ -39,12 +47,12 @@ export const InsightsCatalog = (props: InsightsCatalogProps) => { if ( (isNumber(previousPage) && previousPage !== page) || (previousSorting && previousSorting !== sorting) || - previousSearchQuery !== searchInputValue + previousSearchQuery !== debouncedSearchInputValue ) { props.onQueryChange({ page, sorting, - searchQuery: searchInputValue + searchQuery: debouncedSearchInputValue }); } }, [ @@ -52,7 +60,7 @@ export const InsightsCatalog = (props: InsightsCatalogProps) => { sorting, previousPage, page, - searchInputValue, + debouncedSearchInputValue, previousSearchQuery ]); @@ -63,7 +71,7 @@ export const InsightsCatalog = (props: InsightsCatalogProps) => { onChange={(val: string | null) => { setSearchInputValue(val); }} - default={defaultQuery.searchQuery} + value={searchInputValue} /> { @@ -86,7 +94,7 @@ export const InsightsCatalog = (props: InsightsCatalogProps) => { diff --git a/src/components/Insights/InsightsPage/index.tsx b/src/components/Insights/InsightsPage/index.tsx index caa9dc46e..14fc3b9cb 100644 --- a/src/components/Insights/InsightsPage/index.tsx +++ b/src/components/Insights/InsightsPage/index.tsx @@ -1,7 +1,6 @@ import { useEffect } from "react"; import { v4 as uuidv4 } from "uuid"; import { usePersistence } from "../../../hooks/usePersistence"; -import { usePrevious } from "../../../hooks/usePrevious"; import { trackingEvents as globalTrackingEvents } from "../../../trackingEvents"; import { isUndefined } from "../../../typeGuards/isUndefined"; import { InsightType } from "../../../types"; @@ -473,7 +472,6 @@ const IS_INSIGHT_JIRA_TICKET_HINT_SHOWN_PERSISTENCE_KEY = "isInsightJiraTicketHintShown"; export const InsightsPage = (props: InsightPageProps) => { - const previousInsights = usePrevious(props.insights); const [isInsightJiraTicketHintShown, setIsInsightJiraTicketHintShown] = usePersistence( IS_INSIGHT_JIRA_TICKET_HINT_SHOWN_PERSISTENCE_KEY, @@ -482,12 +480,6 @@ export const InsightsPage = (props: InsightPageProps) => { const insightIndexWithJiraHint = getInsightToShowJiraHint(props.insights); - useEffect(() => { - if (props.insights !== previousInsights) { - window.scrollTo(0, 0); - } - }, [props.insights, previousInsights]); - useEffect(() => { window.sendMessageToDigma({ action: actions.MARK_INSIGHT_TYPES_AS_VIEWED, diff --git a/src/components/Insights/NPlusOneInsight/index.tsx b/src/components/Insights/NPlusOneInsight/index.tsx index 46c21bdf5..d85fe011b 100644 --- a/src/components/Insights/NPlusOneInsight/index.tsx +++ b/src/components/Insights/NPlusOneInsight/index.tsx @@ -47,7 +47,7 @@ export const NPlusOneInsight = (props: NPlusOneInsightProps) => { return ( Check the following SELECT statement: diff --git a/src/components/Insights/NoScalingIssueInsight/index.tsx b/src/components/Insights/NoScalingIssueInsight/index.tsx index a51e65def..3d1a35637 100644 --- a/src/components/Insights/NoScalingIssueInsight/index.tsx +++ b/src/components/Insights/NoScalingIssueInsight/index.tsx @@ -17,7 +17,7 @@ export const NoScalingIssueInsight = (props: NoScalingIssueInsightProps) => { return ( This code is scaling well at concurrent executions} buttons={[ diff --git a/src/components/Insights/PerformanceAtScaleInsight/index.tsx b/src/components/Insights/PerformanceAtScaleInsight/index.tsx index a48c11ece..d6f2493fb 100644 --- a/src/components/Insights/PerformanceAtScaleInsight/index.tsx +++ b/src/components/Insights/PerformanceAtScaleInsight/index.tsx @@ -67,7 +67,7 @@ export const PerformanceAtScaleInsight = ( Run at{" "} diff --git a/src/components/Insights/QueryOptimizationInsight/index.tsx b/src/components/Insights/QueryOptimizationInsight/index.tsx index b6f9d2b36..9b34c906b 100644 --- a/src/components/Insights/QueryOptimizationInsight/index.tsx +++ b/src/components/Insights/QueryOptimizationInsight/index.tsx @@ -53,7 +53,7 @@ export const QueryOptimizationInsight = ( return ( diff --git a/src/components/Insights/RequestBreakdownInsight/index.tsx b/src/components/Insights/RequestBreakdownInsight/index.tsx index 711c492f4..d1b3ee9a0 100644 --- a/src/components/Insights/RequestBreakdownInsight/index.tsx +++ b/src/components/Insights/RequestBreakdownInsight/index.tsx @@ -193,7 +193,7 @@ export const RequestBreakdownInsight = ( return ( { return ( diff --git a/src/components/Insights/SessionInViewInsight/index.tsx b/src/components/Insights/SessionInViewInsight/index.tsx index be1b6874d..38707844a 100644 --- a/src/components/Insights/SessionInViewInsight/index.tsx +++ b/src/components/Insights/SessionInViewInsight/index.tsx @@ -37,7 +37,7 @@ export const SessionInViewInsight = (props: SessionInViewInsightProps) => { return ( diff --git a/src/components/Insights/SlowEndpointInsight/index.tsx b/src/components/Insights/SlowEndpointInsight/index.tsx index fd5b4b854..d99a999b9 100644 --- a/src/components/Insights/SlowEndpointInsight/index.tsx +++ b/src/components/Insights/SlowEndpointInsight/index.tsx @@ -13,7 +13,7 @@ export const SlowEndpointInsight = (props: SlowEndpointInsightProps) => { return ( {`On average requests are slower than other endpoints by ${roundTo( diff --git a/src/components/Insights/SpanBottleneckInsight/index.tsx b/src/components/Insights/SpanBottleneckInsight/index.tsx index af55eddf3..ffadc06c8 100644 --- a/src/components/Insights/SpanBottleneckInsight/index.tsx +++ b/src/components/Insights/SpanBottleneckInsight/index.tsx @@ -29,7 +29,7 @@ export const SpanBottleneckInsight = (props: SpanBottleneckInsightProps) => { return ( diff --git a/src/components/Insights/SpanNexusInsight/index.tsx b/src/components/Insights/SpanNexusInsight/index.tsx index 5f90acce6..1f3a8dbe0 100644 --- a/src/components/Insights/SpanNexusInsight/index.tsx +++ b/src/components/Insights/SpanNexusInsight/index.tsx @@ -22,7 +22,7 @@ export const SpanNexusInsight = (props: SpanNexusInsightProps) => { return ( Multiple code flows depend on this location diff --git a/src/components/Insights/TopUsageInsight/index.tsx b/src/components/Insights/TopUsageInsight/index.tsx index 2c179130f..74627241f 100644 --- a/src/components/Insights/TopUsageInsight/index.tsx +++ b/src/components/Insights/TopUsageInsight/index.tsx @@ -38,7 +38,7 @@ export const TopUsageInsight = (props: TopUsageInsightProps) => { return ( {pageItems.map((flow, i) => { diff --git a/src/components/Insights/TrafficInsight/index.tsx b/src/components/Insights/TrafficInsight/index.tsx index 91346ed00..ba98a2338 100644 --- a/src/components/Insights/TrafficInsight/index.tsx +++ b/src/components/Insights/TrafficInsight/index.tsx @@ -44,7 +44,7 @@ export const TrafficInsight = (props: TrafficInsightProps) => { return ( {getDescription(props.insight.type)}} stats={`${valueString}/min`} diff --git a/src/components/Navigation/ScopeNavigation/index.tsx b/src/components/Navigation/ScopeNavigation/index.tsx index 7b7bd160d..e7eda8421 100644 --- a/src/components/Navigation/ScopeNavigation/index.tsx +++ b/src/components/Navigation/ScopeNavigation/index.tsx @@ -2,7 +2,7 @@ import { useContext, useEffect, useState } from "react"; import { actions } from "../../../actions"; import { dispatcher } from "../../../dispatcher"; import { usePrevious } from "../../../hooks/usePrevious"; -import { HistoryManager, HistoryStep } from "../../../utils/historyManager"; +import { HistoryManager, HistoryStep } from "../../../utils/HistoryManager"; import { ConfigContext } from "../../common/App/ConfigContext"; import { Scope } from "../../common/App/types"; import { HistoryNavigationPanel } from "../HistoryNavigationPanel"; diff --git a/src/components/Navigation/ScopeNavigation/styles.ts b/src/components/Navigation/ScopeNavigation/styles.ts deleted file mode 100644 index 549940deb..000000000 --- a/src/components/Navigation/ScopeNavigation/styles.ts +++ /dev/null @@ -1,14 +0,0 @@ -import styled from "styled-components"; - -export const NavigationButton = styled.button` - height: 28px; - width: 28px; - - &:not([disabled]) { - border: none; - } - - &:disabled { - color: ${({ theme }) => theme.colors.v3.icon.disabled}; - } -`; diff --git a/src/components/common/SearchInput/SearchInput.stories.tsx b/src/components/common/SearchInput/SearchInput.stories.tsx new file mode 100644 index 000000000..b956c919d --- /dev/null +++ b/src/components/common/SearchInput/SearchInput.stories.tsx @@ -0,0 +1,26 @@ +import { Meta, StoryObj } from "@storybook/react"; + +import { SearchInput } from "."; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction +const meta: Meta = { + title: "Common/SearchInput", + component: SearchInput, + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout + layout: "fullscreen" + } +}; + +export default meta; + +type Story = StoryObj; + +// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args +export const Default: Story = { + args: {} +}; + +export const Disabled: Story = { + args: {} +}; diff --git a/src/components/common/SearchInput/index.tsx b/src/components/common/SearchInput/index.tsx index 3b3fce996..8c2cfb083 100644 --- a/src/components/common/SearchInput/index.tsx +++ b/src/components/common/SearchInput/index.tsx @@ -1,17 +1,10 @@ -import { ChangeEvent, useEffect, useState } from "react"; -import { useDebounce } from "../../../hooks/useDebounce"; +import { ChangeEvent } from "react"; +import { CrossIcon } from "../icons/CrossIcon"; import { MagnifierIcon } from "../icons/MagnifierIcon"; import * as s from "./styles"; import { SearchInputProps } from "./types"; export const SearchInput = (props: SearchInputProps) => { - const [searchInputValue, setSearchInputValue] = useState(props.default); - const debouncedSearchInputValue = useDebounce(searchInputValue, 1000); - - useEffect(() => { - props.onChange(debouncedSearchInputValue); - }, [debouncedSearchInputValue]); - return ( @@ -20,9 +13,17 @@ export const SearchInput = (props: SearchInputProps) => { ) => - setSearchInputValue(e.target.value) + props.onChange(e.target.value) } + value={props.value || ""} /> + { + props.onChange(""); + }} + > + + ); }; diff --git a/src/components/common/SearchInput/styles.ts b/src/components/common/SearchInput/styles.ts index b84a54369..9daa67d81 100644 --- a/src/components/common/SearchInput/styles.ts +++ b/src/components/common/SearchInput/styles.ts @@ -76,3 +76,19 @@ export const SearchInput = styled.input` color: transparent; } `; + +export const DeleteTagButton = styled.button` + padding: 0; + cursor: pointer; + background: none; + border: none; + height: 14px; + right: 4px; + display: flex; + align-items: center; + margin: auto; + position: absolute; + top: 0; + bottom: 0; + color: ${({ theme }) => theme.colors.icon.disabledAlt}; +`; diff --git a/src/components/common/SearchInput/types.ts b/src/components/common/SearchInput/types.ts index f73e18955..7ebbf739d 100644 --- a/src/components/common/SearchInput/types.ts +++ b/src/components/common/SearchInput/types.ts @@ -1,4 +1,4 @@ export interface SearchInputProps { onChange: (value: string | null) => void; - default: string | null; + value?: string | null; }