diff --git a/package-lock.json b/package-lock.json index 3933beac1..3f31130a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,8 @@ "semver": "^7.5.4", "styled-components": "^6.1.0", "uuid": "^9.0.1", - "zustand": "^4.5.4" + "zustand": "^4.5.5", + "zustand-slices": "^0.3.0" }, "devDependencies": { "@babel/core": "^7.23.2", @@ -17567,9 +17568,9 @@ } }, "node_modules/use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } @@ -18216,11 +18217,11 @@ } }, "node_modules/zustand": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.4.tgz", - "integrity": "sha512-/BPMyLKJPtFEvVL0E9E9BTUM63MNyhPGlvxk1XjrfWTUlV+BR8jufjsovHzrtR6YNcBEcL7cMHovL1n9xHawEg==", + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.5.tgz", + "integrity": "sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==", "dependencies": { - "use-sync-external-store": "1.2.0" + "use-sync-external-store": "1.2.2" }, "engines": { "node": ">=12.7.0" @@ -18241,6 +18242,21 @@ "optional": true } } + }, + "node_modules/zustand-slices": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/zustand-slices/-/zustand-slices-0.3.0.tgz", + "integrity": "sha512-deJuuBXvHx/wJvx+3bsCnkZf6AaCfagUggz2H8WQ9Z0bLXvVLFp4TD+QFBPtilOsbaIvJIRgW+maLJxgHAzFRw==", + "peerDependencies": { + "immer": ">=9.0.6", + "react": ">=18.0.0", + "zustand": ">=4.0.0" + }, + "peerDependenciesMeta": { + "immer": { + "optional": true + } + } } }, "dependencies": { @@ -30651,9 +30667,9 @@ } }, "use-sync-external-store": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", - "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz", + "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==", "requires": {} }, "util": { @@ -31120,12 +31136,18 @@ "dev": true }, "zustand": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.4.tgz", - "integrity": "sha512-/BPMyLKJPtFEvVL0E9E9BTUM63MNyhPGlvxk1XjrfWTUlV+BR8jufjsovHzrtR6YNcBEcL7cMHovL1n9xHawEg==", + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.5.tgz", + "integrity": "sha512-+0PALYNJNgK6hldkgDq2vLrw5f6g/jCInz52n9RTpropGgeAf/ioFUCdtsjCqu4gNhW9D01rUQBROoRjdzyn2Q==", "requires": { - "use-sync-external-store": "1.2.0" + "use-sync-external-store": "1.2.2" } + }, + "zustand-slices": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/zustand-slices/-/zustand-slices-0.3.0.tgz", + "integrity": "sha512-deJuuBXvHx/wJvx+3bsCnkZf6AaCfagUggz2H8WQ9Z0bLXvVLFp4TD+QFBPtilOsbaIvJIRgW+maLJxgHAzFRw==", + "requires": {} } } } diff --git a/package.json b/package.json index 4f42e97c6..144061a22 100644 --- a/package.json +++ b/package.json @@ -122,6 +122,7 @@ "semver": "^7.5.4", "styled-components": "^6.1.0", "uuid": "^9.0.1", - "zustand": "^4.5.4" + "zustand": "^4.5.5", + "zustand-slices": "^0.3.0" } } diff --git a/src/components/Assets/AssetList/AssetEntry/index.tsx b/src/components/Assets/AssetList/AssetEntry/index.tsx index dae0ba702..ade2ee55a 100644 --- a/src/components/Assets/AssetList/AssetEntry/index.tsx +++ b/src/components/Assets/AssetList/AssetEntry/index.tsx @@ -1,5 +1,5 @@ -import { useGlobalStore } from "../../../../containers/Main/stores/useGlobalStore"; import { getFeatureFlagValue } from "../../../../featureFlags"; +import { useConfigSelector } from "../../../../store/config/useConfigSelector"; import { isNumber } from "../../../../typeGuards/isNumber"; import { isString } from "../../../../typeGuards/isString"; import { FeatureFlag, InsightType } from "../../../../types"; @@ -24,7 +24,7 @@ export const AssetEntry = ({ isImpactHidden, sortingCriterion }: AssetEntryProps) => { - const backendInfo = useGlobalStore.use.backendInfo(); + const { backendInfo } = useConfigSelector(); const isNewImpactScoreCalculationEnabled = getFeatureFlagValue( backendInfo, FeatureFlag.IS_NEW_IMPACT_SCORE_CALCULATION_ENABLED diff --git a/src/components/Assets/AssetList/index.tsx b/src/components/Assets/AssetList/index.tsx index 9ca6f6343..985c4c0b3 100644 --- a/src/components/Assets/AssetList/index.tsx +++ b/src/components/Assets/AssetList/index.tsx @@ -1,9 +1,9 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { DefaultTheme, useTheme } from "styled-components"; import { DigmaMessageError } from "../../../api/types"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; import { dispatcher } from "../../../dispatcher"; import { usePrevious } from "../../../hooks/usePrevious"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; import { isEnvironment } from "../../../typeGuards/isEnvironment"; import { changeScope } from "../../../utils/actions/changeScope"; import { SCOPE_CHANGE_EVENTS } from "../../Main/types"; @@ -140,12 +140,10 @@ export const AssetList = ({ filteredCount ); const listRef = useRef(null); - const environment = useGlobalStore.use.environment(); - const backendInfo = useGlobalStore.use.backendInfo(); + const { environment, backendInfo, scope } = useConfigSelector(); const refreshTimerId = useRef(); const previousEnvironment = usePrevious(environment); const previousViewScope = usePrevious(scopeViewOptions); - const scope = useGlobalStore.use.scope(); const isServicesFilterEnabled = !scope?.span?.spanCodeObjectId; const refreshData = useCallback(() => { diff --git a/src/components/Assets/AssetTypeList/index.tsx b/src/components/Assets/AssetTypeList/index.tsx index 45d13e29b..902153e21 100644 --- a/src/components/Assets/AssetTypeList/index.tsx +++ b/src/components/Assets/AssetTypeList/index.tsx @@ -1,8 +1,8 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { DigmaMessageError } from "../../../api/types"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; import { dispatcher } from "../../../dispatcher"; import { usePrevious } from "../../../hooks/usePrevious"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; import { isEnvironment } from "../../../typeGuards/isEnvironment"; import { isNull } from "../../../typeGuards/isNull"; import { isString } from "../../../typeGuards/isString"; @@ -69,8 +69,7 @@ export const AssetTypeList = ({ const previousData = usePrevious(data); const [lastSetDataTimeStamp, setLastSetDataTimeStamp] = useState(); const previousLastSetDataTimeStamp = usePrevious(lastSetDataTimeStamp); - const scope = useGlobalStore.use.scope(); - const environment = useGlobalStore.use.environment(); + const { scope, environment } = useConfigSelector(); const previousEnvironment = usePrevious(environment); const refreshTimerId = useRef(); const previousSearchQuery = usePrevious(searchQuery); diff --git a/src/components/Assets/AssetsFilter/index.tsx b/src/components/Assets/AssetsFilter/index.tsx index 5f4f658a8..c234267d3 100644 --- a/src/components/Assets/AssetsFilter/index.tsx +++ b/src/components/Assets/AssetsFilter/index.tsx @@ -1,8 +1,9 @@ import { ComponentType, useEffect, useState } from "react"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; import { dispatcher } from "../../../dispatcher"; import { usePersistence } from "../../../hooks/usePersistence"; import { usePrevious } from "../../../hooks/usePrevious"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; +import { useStore } from "../../../store/useStore"; import { isEnvironment } from "../../../typeGuards/isEnvironment"; import { isNull } from "../../../typeGuards/isNull"; import { isUndefined } from "../../../typeGuards/isUndefined"; @@ -18,6 +19,7 @@ import { IconProps } from "../../common/icons/types"; import { AssetScopeOption } from "../AssetsViewScopeConfiguration/types"; import { actions } from "../actions"; import { trackingEvents } from "../tracking"; +import * as s from "./styles"; import { AssetFilterCategory, AssetFilterQuery, @@ -26,8 +28,6 @@ import { GetAssetFiltersDataPayload } from "./types"; -import * as s from "./styles"; - const PERSISTENCE_KEY = "assetsFilters"; const getData = ({ @@ -98,12 +98,16 @@ export const AssetsFilter = ({ const previousData = usePrevious(data); const [isOpen, setIsOpen] = useState(false); const previousIsOpen = usePrevious(isOpen); - const globallySelectedServices = useGlobalStore.use.selectedServices(); - const setGloballySelectedServices = useGlobalStore.use.setSelectedServices(); + const { + selectedServices: globallySelectedServices, + environment, + scope + } = useConfigSelector(); + const { setSelectedServices: setGloballySelectedServices } = + useStore.getState(); const [persistedFilters, setPersistedFilters] = usePersistence(PERSISTENCE_KEY, "project"); const previousPersistedFilters = usePrevious(persistedFilters); - const scope = useGlobalStore.use.scope(); const isServicesFilterEnabled = !scope?.span?.spanCodeObjectId; const [selectedServices, setSelectedServices] = useState( isServicesFilterEnabled ? globallySelectedServices ?? [] : [] @@ -112,7 +116,6 @@ export const AssetsFilter = ({ const [selectedConsumers, setSelectedConsumers] = useState([]); const [selectedInternals, setSelectedInternals] = useState([]); const [selectedInsights, setSelectedInsights] = useState([]); - const environment = useGlobalStore.use.environment(); const previousEnvironment = usePrevious(environment); const previousScope = usePrevious(scope); diff --git a/src/components/Assets/index.tsx b/src/components/Assets/index.tsx index 102fc37f8..55fcebef6 100644 --- a/src/components/Assets/index.tsx +++ b/src/components/Assets/index.tsx @@ -1,9 +1,9 @@ import { useCallback, useEffect, useMemo, useState } from "react"; import { useParams } from "react-router-dom"; -import { useGlobalStore } from "../../containers/Main/stores/useGlobalStore"; import { getFeatureFlagValue } from "../../featureFlags"; import { useDebounce } from "../../hooks/useDebounce"; import { usePrevious } from "../../hooks/usePrevious"; +import { useConfigSelector } from "../../store/config/useConfigSelector"; import { FeatureFlag } from "../../types"; import { sendUserActionTrackingEvent } from "../../utils/actions/sendUserActionTrackingEvent"; import { useHistory } from "../Main/useHistory"; @@ -31,8 +31,7 @@ export const Assets = () => { const [assetScopeOption, setAssetScopeOption] = useState(null); const [selectedFilters, setSelectedFilters] = useState(); - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments, backendInfo } = useConfigSelector(); const previousScopeSpanCodeObjectId = usePrevious( scope?.span?.spanCodeObjectId ); @@ -42,7 +41,6 @@ export const Assets = () => { useState(null); const { goTo } = useHistory(); const isBackendUpgradeMessageVisible = false; - const backendInfo = useGlobalStore.use.backendInfo(); const areExtendedAssetsFiltersEnabled = getFeatureFlagValue( backendInfo, FeatureFlag.ARE_EXTENDED_ASSETS_FILTERS_ENABLED diff --git a/src/components/Dashboard/Report/ReportHeader/index.tsx b/src/components/Dashboard/Report/ReportHeader/index.tsx index d43dd8faf..dc53f70d6 100644 --- a/src/components/Dashboard/Report/ReportHeader/index.tsx +++ b/src/components/Dashboard/Report/ReportHeader/index.tsx @@ -1,10 +1,10 @@ import { useEffect, useMemo, useState } from "react"; import { actions as globalActions } from "../../../../actions"; -import { useGlobalStore } from "../../../../containers/Main/stores/useGlobalStore"; import { DataFetcherConfiguration, useFetchData } from "../../../../hooks/useFetchData"; +import { useConfigSelector } from "../../../../store/config/useConfigSelector"; import { sendUserActionTrackingEvent } from "../../../../utils/actions/sendUserActionTrackingEvent"; import { GlobeIcon } from "../../../common/icons/12px/GlobeIcon"; import { WrenchIcon } from "../../../common/icons/12px/WrenchIcon"; @@ -40,7 +40,7 @@ export const ReportHeader = ({ const [selectedEnvironment, setSelectedEnvironment] = useState( null ); - const environments = useGlobalStore.use.environments(); + const { environments } = useConfigSelector(); const handleSelectedEnvironmentChanged = (option: string | string[]) => { const newItem = option === selectedEnvironment diff --git a/src/components/Errors/index.tsx b/src/components/Errors/index.tsx index 7256c7467..1b5f44443 100644 --- a/src/components/Errors/index.tsx +++ b/src/components/Errors/index.tsx @@ -1,12 +1,12 @@ import { useParams } from "react-router-dom"; -import { useGlobalStore } from "../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../store/config/useConfigSelector"; import { useHistory } from "../Main/useHistory"; import { ErrorDetails } from "./ErrorDetails"; import { ErrorsList } from "./ErrorsList"; import * as s from "./styles"; export const Errors = () => { - const scope = useGlobalStore.use.scope(); + const { scope } = useConfigSelector(); const spanCodeObjectId = scope?.span?.spanCodeObjectId; const methodId = scope?.span?.methodId ?? undefined; const { goTo } = useHistory(); diff --git a/src/components/Highlights/Impact/index.tsx b/src/components/Highlights/Impact/index.tsx index 6b6cbb629..62a49f0cf 100644 --- a/src/components/Highlights/Impact/index.tsx +++ b/src/components/Highlights/Impact/index.tsx @@ -1,7 +1,7 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; import { useEffect } from "react"; import { PERFORMANCE_IMPACT_DOCUMENTATION_URL } from "../../../constants"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; import { openURLInDefaultBrowser } from "../../../utils/actions/openURLInDefaultBrowser"; import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActionTrackingEvent"; import { SCOPE_CHANGE_EVENTS } from "../../Main/types"; @@ -76,9 +76,7 @@ const getRankTagType = (normalizedRank: number) => { export const Impact = () => { const { data, getData } = useImpactData(); - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); - const backendInfo = useGlobalStore.use.backendInfo(); + const { scope, environments, backendInfo } = useConfigSelector(); useEffect(() => { getData(); diff --git a/src/components/Highlights/Impact/useImpactData.ts b/src/components/Highlights/Impact/useImpactData.ts index 61d554ff7..2e14a0805 100644 --- a/src/components/Highlights/Impact/useImpactData.ts +++ b/src/components/Highlights/Impact/useImpactData.ts @@ -1,7 +1,7 @@ import { useCallback, useEffect, useRef, useState } from "react"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; import { dispatcher } from "../../../dispatcher"; import { usePrevious } from "../../../hooks/usePrevious"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; import { actions as mainActions } from "../../Main/actions"; import { GetHighlightsImpactDataPayload, ImpactData } from "./types"; @@ -9,8 +9,7 @@ const REFRESH_INTERVAL = 10 * 1000; // in milliseconds export const useImpactData = () => { const [data, setData] = useState(); - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const [lastSetDataTimeStamp, setLastSetDataTimeStamp] = useState(); const previousLastSetDataTimeStamp = usePrevious(lastSetDataTimeStamp); const refreshTimerId = useRef(); diff --git a/src/components/Highlights/Performance/index.tsx b/src/components/Highlights/Performance/index.tsx index c035c942d..82efe5d99 100644 --- a/src/components/Highlights/Performance/index.tsx +++ b/src/components/Highlights/Performance/index.tsx @@ -1,7 +1,7 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; import { useEffect, useState } from "react"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; import { usePrevious } from "../../../hooks/usePrevious"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; import { isBoolean } from "../../../typeGuards/isBoolean"; import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActionTrackingEvent"; import { formatTimeDistance } from "../../../utils/formatTimeDistance"; @@ -26,8 +26,7 @@ export const Performance = () => { const [isInitialLoading, setIsInitialLoading] = useState(true); const { data, getData } = usePerformanceData(); const previousData = usePrevious(data); - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); useEffect(() => { getData(); diff --git a/src/components/Highlights/Performance/usePerformanceData.ts b/src/components/Highlights/Performance/usePerformanceData.ts index c8f03d0f9..def692fb0 100644 --- a/src/components/Highlights/Performance/usePerformanceData.ts +++ b/src/components/Highlights/Performance/usePerformanceData.ts @@ -1,7 +1,7 @@ import { useCallback, useEffect, useRef, useState } from "react"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; import { dispatcher } from "../../../dispatcher"; import { usePrevious } from "../../../hooks/usePrevious"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; import { actions as mainActions } from "../../Main/actions"; import { GetHighlightsPerformanceDataPayload, PerformanceData } from "./types"; @@ -9,8 +9,7 @@ const REFRESH_INTERVAL = 10 * 1000; // in milliseconds export const usePerformanceData = () => { const [data, setData] = useState(); - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const [lastSetDataTimeStamp, setLastSetDataTimeStamp] = useState(); const previousLastSetDataTimeStamp = usePrevious(lastSetDataTimeStamp); const refreshTimerId = useRef(); diff --git a/src/components/Highlights/Scaling/index.tsx b/src/components/Highlights/Scaling/index.tsx index 106994361..2fba83575 100644 --- a/src/components/Highlights/Scaling/index.tsx +++ b/src/components/Highlights/Scaling/index.tsx @@ -1,7 +1,7 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; import { useEffect } from "react"; import { SCALING_ISSUE_DOCUMENTATION_URL } from "../../../constants"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; import { openURLInDefaultBrowser } from "../../../utils/actions/openURLInDefaultBrowser"; import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActionTrackingEvent"; import { getDurationString } from "../../../utils/getDurationString"; @@ -75,8 +75,7 @@ const demoData: EnvironmentScalingData[] = [ export const Scaling = () => { const { data, getData } = useScalingData(); - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const { goTo } = useHistory(); useEffect(() => { diff --git a/src/components/Highlights/Scaling/useScalingData.ts b/src/components/Highlights/Scaling/useScalingData.ts index 1b8b6a8c6..b2e25ee57 100644 --- a/src/components/Highlights/Scaling/useScalingData.ts +++ b/src/components/Highlights/Scaling/useScalingData.ts @@ -1,7 +1,7 @@ import { useCallback, useEffect, useRef, useState } from "react"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; import { dispatcher } from "../../../dispatcher"; import { usePrevious } from "../../../hooks/usePrevious"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; import { actions as mainActions } from "../../Main/actions"; import { GetHighlightsScalingDataPayload, ScalingData } from "./types"; @@ -9,8 +9,7 @@ const REFRESH_INTERVAL = 10 * 1000; // in milliseconds export const useScalingData = () => { const [data, setData] = useState(); - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const [lastSetDataTimeStamp, setLastSetDataTimeStamp] = useState(); const previousLastSetDataTimeStamp = usePrevious(lastSetDataTimeStamp); const refreshTimerId = useRef(); diff --git a/src/components/Highlights/SpanInfo/useSpanInfoData.ts b/src/components/Highlights/SpanInfo/useSpanInfoData.ts index ead9f0185..8153884f6 100644 --- a/src/components/Highlights/SpanInfo/useSpanInfoData.ts +++ b/src/components/Highlights/SpanInfo/useSpanInfoData.ts @@ -1,7 +1,7 @@ import { useCallback, useEffect, useRef, useState } from "react"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; import { dispatcher } from "../../../dispatcher"; import { usePrevious } from "../../../hooks/usePrevious"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; import { actions as mainActions } from "../../Main/actions"; import { GetHighlightsSpanInfoDataPayload, SpanInfoData } from "./types"; @@ -9,7 +9,7 @@ const REFRESH_INTERVAL = 10 * 1000; // in milliseconds export const useSpanInfoData = () => { const [data, setData] = useState(); - const scope = useGlobalStore.use.scope(); + const { scope } = useConfigSelector(); const [lastSetDataTimeStamp, setLastSetDataTimeStamp] = useState(); const previousLastSetDataTimeStamp = usePrevious(lastSetDataTimeStamp); const refreshTimerId = useRef(); diff --git a/src/components/Highlights/TopIssues/highlightCards/EndpointBottleneckHighlightCard/index.tsx b/src/components/Highlights/TopIssues/highlightCards/EndpointBottleneckHighlightCard/index.tsx index e37752638..7d9f45c41 100644 --- a/src/components/Highlights/TopIssues/highlightCards/EndpointBottleneckHighlightCard/index.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/EndpointBottleneckHighlightCard/index.tsx @@ -1,6 +1,6 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; -import { useGlobalStore } from "../../../../../containers/Main/stores/useGlobalStore"; import { Duration } from "../../../../../globals"; +import { useConfigSelector } from "../../../../../store/config/useConfigSelector"; import { sendUserActionTrackingEvent } from "../../../../../utils/actions/sendUserActionTrackingEvent"; import { getDurationString } from "../../../../../utils/getDurationString"; import { SCOPE_CHANGE_EVENTS } from "../../../../Main/types"; @@ -19,8 +19,7 @@ import { EndpointBottleneckHighlightCardProps } from "./types"; export const EndpointBottleneckHighlightCard = ({ data }: EndpointBottleneckHighlightCardProps) => { - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const columnHelper = createColumnHelper>(); diff --git a/src/components/Highlights/TopIssues/highlightCards/EndpointChattyApiV2HighlightCard/index.tsx b/src/components/Highlights/TopIssues/highlightCards/EndpointChattyApiV2HighlightCard/index.tsx index 0487a138d..92fcbcd36 100644 --- a/src/components/Highlights/TopIssues/highlightCards/EndpointChattyApiV2HighlightCard/index.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/EndpointChattyApiV2HighlightCard/index.tsx @@ -1,5 +1,5 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; -import { useGlobalStore } from "../../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../../store/config/useConfigSelector"; import { sendUserActionTrackingEvent } from "../../../../../utils/actions/sendUserActionTrackingEvent"; import { SCOPE_CHANGE_EVENTS } from "../../../../Main/types"; import { Table } from "../../../common/Table"; @@ -16,8 +16,7 @@ import { EndpointChattyApiV2HighlightCardProps } from "./types"; export const EndpointChattyApiV2HighlightCard = ({ data }: EndpointChattyApiV2HighlightCardProps) => { - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const columnHelper = createColumnHelper>(); diff --git a/src/components/Highlights/TopIssues/highlightCards/EndpointHighNumberOfQueriesHighlightCard/index.tsx b/src/components/Highlights/TopIssues/highlightCards/EndpointHighNumberOfQueriesHighlightCard/index.tsx index d21ce7f7c..3a7b8efec 100644 --- a/src/components/Highlights/TopIssues/highlightCards/EndpointHighNumberOfQueriesHighlightCard/index.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/EndpointHighNumberOfQueriesHighlightCard/index.tsx @@ -1,5 +1,5 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; -import { useGlobalStore } from "../../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../../store/config/useConfigSelector"; import { sendUserActionTrackingEvent } from "../../../../../utils/actions/sendUserActionTrackingEvent"; import { SCOPE_CHANGE_EVENTS } from "../../../../Main/types"; import { Table } from "../../../common/Table"; @@ -19,8 +19,7 @@ import { EndpointHighNumberOfQueriesHighlightCardProps } from "./types"; export const EndpointHighNumberOfQueriesHighlightCard = ({ data }: EndpointHighNumberOfQueriesHighlightCardProps) => { - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const columnHelper = createColumnHelper>(); diff --git a/src/components/Highlights/TopIssues/highlightCards/EndpointQueryOptimizationV2HighlightCard/index.tsx b/src/components/Highlights/TopIssues/highlightCards/EndpointQueryOptimizationV2HighlightCard/index.tsx index 493e1fe0d..b963d68ff 100644 --- a/src/components/Highlights/TopIssues/highlightCards/EndpointQueryOptimizationV2HighlightCard/index.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/EndpointQueryOptimizationV2HighlightCard/index.tsx @@ -1,5 +1,5 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; -import { useGlobalStore } from "../../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../../store/config/useConfigSelector"; import { sendUserActionTrackingEvent } from "../../../../../utils/actions/sendUserActionTrackingEvent"; import { getDurationString } from "../../../../../utils/getDurationString"; import { SCOPE_CHANGE_EVENTS } from "../../../../Main/types"; @@ -20,8 +20,7 @@ import { EndpointQueryOptimizationV2HighlightCardProps } from "./types"; export const EndpointQueryOptimizationV2HighlightCard = ({ data }: EndpointQueryOptimizationV2HighlightCardProps) => { - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const columnHelper = createColumnHelper>(); diff --git a/src/components/Highlights/TopIssues/highlightCards/EndpointSessionInViewHighlightCard/index.tsx b/src/components/Highlights/TopIssues/highlightCards/EndpointSessionInViewHighlightCard/index.tsx index e7b66b4a5..73fbe2b49 100644 --- a/src/components/Highlights/TopIssues/highlightCards/EndpointSessionInViewHighlightCard/index.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/EndpointSessionInViewHighlightCard/index.tsx @@ -1,5 +1,5 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; -import { useGlobalStore } from "../../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../../store/config/useConfigSelector"; import { sendUserActionTrackingEvent } from "../../../../../utils/actions/sendUserActionTrackingEvent"; import { SCOPE_CHANGE_EVENTS } from "../../../../Main/types"; import { Table } from "../../../common/Table"; @@ -15,8 +15,7 @@ import { EndpointSessionInViewHighlightCardProps } from "./types"; export const EndpointSessionInViewHighlightCard = ({ data }: EndpointSessionInViewHighlightCardProps) => { - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const columnHelper = createColumnHelper>(); diff --git a/src/components/Highlights/TopIssues/highlightCards/EndpointSlowdownSourceHighlightCard/index.tsx b/src/components/Highlights/TopIssues/highlightCards/EndpointSlowdownSourceHighlightCard/index.tsx index f9fd09132..6254a3e39 100644 --- a/src/components/Highlights/TopIssues/highlightCards/EndpointSlowdownSourceHighlightCard/index.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/EndpointSlowdownSourceHighlightCard/index.tsx @@ -1,5 +1,5 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; -import { useGlobalStore } from "../../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../../store/config/useConfigSelector"; import { sendUserActionTrackingEvent } from "../../../../../utils/actions/sendUserActionTrackingEvent"; import { getDurationString } from "../../../../../utils/getDurationString"; import { SCOPE_CHANGE_EVENTS } from "../../../../Main/types"; @@ -17,8 +17,7 @@ import { EndpointSlowdownSourceHighlightCardProps } from "./types"; export const EndpointSlowdownSourceHighlightCard = ({ data }: EndpointSlowdownSourceHighlightCardProps) => { - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const columnHelper = createColumnHelper>(); diff --git a/src/components/Highlights/TopIssues/highlightCards/EndpointSpanNPlusOneHighlightCard/index.tsx b/src/components/Highlights/TopIssues/highlightCards/EndpointSpanNPlusOneHighlightCard/index.tsx index 4459d4f2c..7a5fb455f 100644 --- a/src/components/Highlights/TopIssues/highlightCards/EndpointSpanNPlusOneHighlightCard/index.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/EndpointSpanNPlusOneHighlightCard/index.tsx @@ -1,6 +1,6 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; -import { useGlobalStore } from "../../../../../containers/Main/stores/useGlobalStore"; import { Duration } from "../../../../../globals"; +import { useConfigSelector } from "../../../../../store/config/useConfigSelector"; import { sendUserActionTrackingEvent } from "../../../../../utils/actions/sendUserActionTrackingEvent"; import { getDurationString } from "../../../../../utils/getDurationString"; import { SCOPE_CHANGE_EVENTS } from "../../../../Main/types"; @@ -19,8 +19,7 @@ import { EndpointSpanNPlusOneHighlightCardProps } from "./types"; export const EndpointSpanNPlusOneHighlightCard = ({ data }: EndpointSpanNPlusOneHighlightCardProps) => { - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const columnHelper = createColumnHelper>(); diff --git a/src/components/Highlights/TopIssues/highlightCards/HotSpotHighlightCard/index.tsx b/src/components/Highlights/TopIssues/highlightCards/HotSpotHighlightCard/index.tsx index 7b2b70198..a5f6b21e2 100644 --- a/src/components/Highlights/TopIssues/highlightCards/HotSpotHighlightCard/index.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/HotSpotHighlightCard/index.tsx @@ -1,5 +1,5 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; -import { useGlobalStore } from "../../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../../store/config/useConfigSelector"; import { sendUserActionTrackingEvent } from "../../../../../utils/actions/sendUserActionTrackingEvent"; import { SCOPE_CHANGE_EVENTS } from "../../../../Main/types"; import { Table } from "../../../common/Table"; @@ -12,8 +12,7 @@ import { addEnvironmentColumns } from "../addEnvironmentColumns"; import { HotSpotHighlightCardProps } from "./types"; export const HotSpotHighlightCard = ({ data }: HotSpotHighlightCardProps) => { - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const columnHelper = createColumnHelper>(); diff --git a/src/components/Highlights/TopIssues/highlightCards/SpaNPlusOneHighlightCard/index.tsx b/src/components/Highlights/TopIssues/highlightCards/SpaNPlusOneHighlightCard/index.tsx index e3ef3fccc..e7bf27cc9 100644 --- a/src/components/Highlights/TopIssues/highlightCards/SpaNPlusOneHighlightCard/index.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/SpaNPlusOneHighlightCard/index.tsx @@ -1,6 +1,6 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; -import { useGlobalStore } from "../../../../../containers/Main/stores/useGlobalStore"; import { Duration } from "../../../../../globals"; +import { useConfigSelector } from "../../../../../store/config/useConfigSelector"; import { sendUserActionTrackingEvent } from "../../../../../utils/actions/sendUserActionTrackingEvent"; import { getDurationString } from "../../../../../utils/getDurationString"; import { SCOPE_CHANGE_EVENTS } from "../../../../Main/types"; @@ -17,8 +17,7 @@ import { SpaNPlusOneHighlightCardProps } from "./types"; export const SpaNPlusOneHighlightCard = ({ data }: SpaNPlusOneHighlightCardProps) => { - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const columnHelper = createColumnHelper>(); diff --git a/src/components/Highlights/TopIssues/highlightCards/SpanEndpointBottleneckHighlightCard/index.tsx b/src/components/Highlights/TopIssues/highlightCards/SpanEndpointBottleneckHighlightCard/index.tsx index e40ac9b91..42a30b659 100644 --- a/src/components/Highlights/TopIssues/highlightCards/SpanEndpointBottleneckHighlightCard/index.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/SpanEndpointBottleneckHighlightCard/index.tsx @@ -1,6 +1,6 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; -import { useGlobalStore } from "../../../../../containers/Main/stores/useGlobalStore"; import { Duration } from "../../../../../globals"; +import { useConfigSelector } from "../../../../../store/config/useConfigSelector"; import { sendUserActionTrackingEvent } from "../../../../../utils/actions/sendUserActionTrackingEvent"; import { getDurationString } from "../../../../../utils/getDurationString"; import { SCOPE_CHANGE_EVENTS } from "../../../../Main/types"; @@ -17,8 +17,7 @@ import { SpanEndpointBottleneckHighlightCardProps } from "./types"; export const SpanEndpointBottleneckHighlightCard = ({ data }: SpanEndpointBottleneckHighlightCardProps) => { - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const columnHelper = createColumnHelper>(); diff --git a/src/components/Highlights/TopIssues/highlightCards/SpanQueryOptimizationHighlightCard/index.tsx b/src/components/Highlights/TopIssues/highlightCards/SpanQueryOptimizationHighlightCard/index.tsx index 1528373bc..33a448c89 100644 --- a/src/components/Highlights/TopIssues/highlightCards/SpanQueryOptimizationHighlightCard/index.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/SpanQueryOptimizationHighlightCard/index.tsx @@ -1,6 +1,6 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; -import { useGlobalStore } from "../../../../../containers/Main/stores/useGlobalStore"; import { Duration } from "../../../../../globals"; +import { useConfigSelector } from "../../../../../store/config/useConfigSelector"; import { sendUserActionTrackingEvent } from "../../../../../utils/actions/sendUserActionTrackingEvent"; import { getDurationString } from "../../../../../utils/getDurationString"; import { SCOPE_CHANGE_EVENTS } from "../../../../Main/types"; @@ -19,8 +19,7 @@ import { SpanQueryOptimizationHighlightCardProps } from "./types"; export const SpanQueryOptimizationHighlightCard = ({ data }: SpanQueryOptimizationHighlightCardProps) => { - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const columnHelper = createColumnHelper>(); diff --git a/src/components/Highlights/TopIssues/highlightCards/SpanScalingHighlightCard/index.tsx b/src/components/Highlights/TopIssues/highlightCards/SpanScalingHighlightCard/index.tsx index 40e9d286c..7568115f9 100644 --- a/src/components/Highlights/TopIssues/highlightCards/SpanScalingHighlightCard/index.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/SpanScalingHighlightCard/index.tsx @@ -1,5 +1,5 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; -import { useGlobalStore } from "../../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../../store/config/useConfigSelector"; import { sendUserActionTrackingEvent } from "../../../../../utils/actions/sendUserActionTrackingEvent"; import { SCOPE_CHANGE_EVENTS } from "../../../../Main/types"; import { Table } from "../../../common/Table"; @@ -14,8 +14,7 @@ import { SpanScalingHighlightCardProps } from "./types"; export const SpanScalingHighlightCard = ({ data }: SpanScalingHighlightCardProps) => { - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const columnHelper = createColumnHelper>(); diff --git a/src/components/Highlights/TopIssues/index.tsx b/src/components/Highlights/TopIssues/index.tsx index c147402f9..5a6038543 100644 --- a/src/components/Highlights/TopIssues/index.tsx +++ b/src/components/Highlights/TopIssues/index.tsx @@ -1,8 +1,8 @@ import { Fragment, useEffect, useMemo, useState } from "react"; import { v4 as uuidv4 } from "uuid"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; import { usePagination } from "../../../hooks/usePagination"; import { usePrevious } from "../../../hooks/usePrevious"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; import { InsightType } from "../../Insights/types"; import { CrossCircleIcon } from "../../common/icons/16px/CrossCircleIcon"; import { RefreshIcon } from "../../common/icons/16px/RefreshIcon"; @@ -94,8 +94,7 @@ export const TopIssues = () => { const [isInitialLoading, setIsInitialLoading] = useState(true); const { data, getData } = useTopIssuesData(); const previousData = usePrevious(data); - const scope = useGlobalStore.use.scope(); - + const { scope } = useConfigSelector(); // Do not show unimplemented insights const filteredInsights = useMemo( () => diff --git a/src/components/Highlights/TopIssues/useTopIssuesData.ts b/src/components/Highlights/TopIssues/useTopIssuesData.ts index d2f70de19..e75546215 100644 --- a/src/components/Highlights/TopIssues/useTopIssuesData.ts +++ b/src/components/Highlights/TopIssues/useTopIssuesData.ts @@ -1,7 +1,7 @@ import { useCallback, useEffect, useRef, useState } from "react"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; import { dispatcher } from "../../../dispatcher"; import { usePrevious } from "../../../hooks/usePrevious"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; import { actions as mainActions } from "../../Main/actions"; import { GetHighlightsTopIssuesDataPayload } from "../../Main/types"; import { TopIssuesData } from "./types"; @@ -10,8 +10,7 @@ const REFRESH_INTERVAL = 10 * 1000; // in milliseconds export const useTopIssuesData = () => { const [data, setData] = useState(); - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { scope, environments } = useConfigSelector(); const [lastSetDataTimeStamp, setLastSetDataTimeStamp] = useState(); const previousLastSetDataTimeStamp = usePrevious(lastSetDataTimeStamp); const refreshTimerId = useRef(); diff --git a/src/components/Highlights/index.tsx b/src/components/Highlights/index.tsx index f77733abc..d72c6de72 100644 --- a/src/components/Highlights/index.tsx +++ b/src/components/Highlights/index.tsx @@ -1,5 +1,5 @@ -import { useGlobalStore } from "../../containers/Main/stores/useGlobalStore"; import { getFeatureFlagValue } from "../../featureFlags"; +import { useConfigSelector } from "../../store/config/useConfigSelector"; import { FeatureFlag } from "../../types"; import { Impact } from "./Impact"; import { Performance } from "./Performance"; @@ -9,7 +9,7 @@ import { TopIssues } from "./TopIssues"; import * as s from "./styles"; export const Highlights = () => { - const backendInfo = useGlobalStore.use.backendInfo(); + const { backendInfo } = useConfigSelector(); const isSpanInfoVisible = getFeatureFlagValue( backendInfo, diff --git a/src/components/Insights/InsightsCatalog/EnvironmentSelector/index.tsx b/src/components/Insights/InsightsCatalog/EnvironmentSelector/index.tsx index 885b62b52..820a9e5f8 100644 --- a/src/components/Insights/InsightsCatalog/EnvironmentSelector/index.tsx +++ b/src/components/Insights/InsightsCatalog/EnvironmentSelector/index.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; import useDimensions from "react-cool-dimensions"; -import { useGlobalStore } from "../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../store/config/useConfigSelector"; import { changeScope } from "../../../../utils/actions/changeScope"; import { sendUserActionTrackingEvent } from "../../../../utils/actions/sendUserActionTrackingEvent"; import { Environment } from "../../../common/App/types"; @@ -59,8 +59,7 @@ const sortEnvironmentsByCriticalIssues = ( export const EnvironmentSelector = ({ environments }: EnvironmentSelectorProps) => { - const scope = useGlobalStore.use.scope(); - const environment = useGlobalStore.use.environment(); + const { scope, environment } = useConfigSelector(); const [isMenuOpen, setIsMenuOpen] = useState(false); const { observe, width } = useDimensions(); const sortedEnvironments = environments.sort( diff --git a/src/components/Insights/InsightsCatalog/FilterPanel/index.tsx b/src/components/Insights/InsightsCatalog/FilterPanel/index.tsx index 79f06334c..b0d9f92f9 100644 --- a/src/components/Insights/InsightsCatalog/FilterPanel/index.tsx +++ b/src/components/Insights/InsightsCatalog/FilterPanel/index.tsx @@ -1,4 +1,5 @@ -import { useInsightsStore } from "../../../../containers/Main/stores/useInsightsStore"; +import { useInsightsSelector } from "../../../../store/insights/useInsightsSelector"; +import { useStore } from "../../../../store/useStore"; import { sendUserActionTrackingEvent } from "../../../../utils/actions/sendUserActionTrackingEvent"; import { InsightFilterType } from "../types"; import { FilterChip } from "./FilterChip"; @@ -10,8 +11,8 @@ export const FilterPanel = ({ allIssuesCount, unreadCount }: FilterPanelProps) => { - const filters = useInsightsStore.use.filters(); - const setFilters = useInsightsStore.use.setFilters(); + const { filters } = useInsightsSelector(); + const { setFilters } = useStore.getState(); const handleFilterChipClick = (selectedFilter?: InsightFilterType) => { const newFilters = new Set(filters); diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/index.tsx b/src/components/Insights/InsightsCatalog/InsightsPage/index.tsx index 2d957deba..c37818821 100644 --- a/src/components/Insights/InsightsCatalog/InsightsPage/index.tsx +++ b/src/components/Insights/InsightsCatalog/InsightsPage/index.tsx @@ -1,7 +1,7 @@ import { useEffect, useRef } from "react"; import { actions as globalActions } from "../../../../actions"; -import { useGlobalStore } from "../../../../containers/Main/stores/useGlobalStore"; import { usePersistence } from "../../../../hooks/usePersistence"; +import { useConfigSelector } from "../../../../store/config/useConfigSelector"; import { trackingEvents as globalTrackingEvents } from "../../../../trackingEvents"; import { isNumber } from "../../../../typeGuards/isNumber"; import { isUndefined } from "../../../../typeGuards/isUndefined"; @@ -488,8 +488,7 @@ export const InsightsPage = ({ isMarkAsReadButtonEnabled, isFilteringEnabled }: InsightsPageProps) => { - const scope = useGlobalStore.use.scope(); - const environment = useGlobalStore.use.environment(); + const { scope, environment } = useConfigSelector(); const [isInsightJiraTicketHintShown, setIsInsightJiraTicketHintShown] = usePersistence( IS_INSIGHT_JIRA_TICKET_HINT_SHOWN_PERSISTENCE_KEY, diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointSessionInViewInsightCard/index.tsx b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointSessionInViewInsightCard/index.tsx index fcaf63144..81120c4a3 100644 --- a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointSessionInViewInsightCard/index.tsx +++ b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/EndpointSessionInViewInsightCard/index.tsx @@ -1,5 +1,5 @@ -import { useGlobalStore } from "../../../../../../containers/Main/stores/useGlobalStore"; import { usePagination } from "../../../../../../hooks/usePagination"; +import { useConfigSelector } from "../../../../../../store/config/useConfigSelector"; import { TraceIcon } from "../../../../../common/icons/12px/TraceIcon"; import { Button } from "../../../../../common/v3/Button"; import { Pagination } from "../../../../../common/v3/Pagination"; @@ -23,7 +23,7 @@ export const EndpointSessionInViewInsightCard = ({ isMarkAsReadButtonEnabled, viewMode }: EndpointSessionInViewInsightCardProps) => { - const isJaegerEnabled = useGlobalStore.use.isJaegerEnabled(); + const { isJaegerEnabled } = useConfigSelector(); const [pageItems, page, setPage] = usePagination( insight.spans, diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpaNPlusOneInsightCard/index.tsx b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpaNPlusOneInsightCard/index.tsx index 25e0fb8b1..852cb3a02 100644 --- a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpaNPlusOneInsightCard/index.tsx +++ b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpaNPlusOneInsightCard/index.tsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import { useGlobalStore } from "../../../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../../../store/config/useConfigSelector"; import { getDurationString } from "../../../../../../utils/getDurationString"; import { TraceIcon } from "../../../../../common/icons/12px/TraceIcon"; import { Button } from "../../../../../common/v3/Button"; @@ -31,7 +31,7 @@ export const SpaNPlusOneInsightCard = ({ endpoints[0] ); const maxDurationString = getDurationString(endpointWithMaxDuration.duration); - const isJaegerEnabled = useGlobalStore.use.isJaegerEnabled(); + const { isJaegerEnabled } = useConfigSelector(); const [selectedEndpoint, setSelectedEndpoint] = useState( endpoints.length ? endpoints[0] : null ); diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpanDurationBreakdownInsightCard/index.tsx b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpanDurationBreakdownInsightCard/index.tsx index 10b52fc0b..6e555d451 100644 --- a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpanDurationBreakdownInsightCard/index.tsx +++ b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpanDurationBreakdownInsightCard/index.tsx @@ -5,10 +5,10 @@ import { useReactTable } from "@tanstack/react-table"; import { useEffect, useMemo, useState } from "react"; -import { useGlobalStore } from "../../../../../../containers/Main/stores/useGlobalStore"; import { getFeatureFlagValue } from "../../../../../../featureFlags"; import { usePagination } from "../../../../../../hooks/usePagination"; import { usePrevious } from "../../../../../../hooks/usePrevious"; +import { useConfigSelector } from "../../../../../../store/config/useConfigSelector"; import { isNumber } from "../../../../../../typeGuards/isNumber"; import { FeatureFlag } from "../../../../../../types"; import { getDurationString } from "../../../../../../utils/getDurationString"; @@ -73,7 +73,7 @@ export const SpanDurationBreakdownInsightCard = ({ items: [] }); - const backendInfo = useGlobalStore.use.backendInfo(); + const { backendInfo } = useConfigSelector(); const isQuantitySupported = getFeatureFlagValue( backendInfo, FeatureFlag.IS_DURATION_BREAKDOWN_QUANTITY_ENABLED diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpanEndpointBottleneckInsightCard/index.tsx b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpanEndpointBottleneckInsightCard/index.tsx index b8e8fa3a8..5071b09d9 100644 --- a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpanEndpointBottleneckInsightCard/index.tsx +++ b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpanEndpointBottleneckInsightCard/index.tsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import { useGlobalStore } from "../../../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../../../store/config/useConfigSelector"; import { isNull } from "../../../../../../typeGuards/isNull"; import { getDurationString } from "../../../../../../utils/getDurationString"; import { trimEndpointScheme } from "../../../../../../utils/trimEndpointScheme"; @@ -27,7 +27,7 @@ export const SpanEndpointBottleneckInsightCard = ({ isMarkAsReadButtonEnabled, viewMode }: SpanEndpointBottleneckInsightCardProps) => { - const isJaegerEnabled = useGlobalStore.use.isJaegerEnabled(); + const { isJaegerEnabled } = useConfigSelector(); const slowEndpoints = insight.slowEndpoints ?? []; const endpointWithMaxDuration = slowEndpoints.reduce( (acc, cur) => diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpanScalingInsightCard/index.tsx b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpanScalingInsightCard/index.tsx index 8be7dad73..8599972db 100644 --- a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpanScalingInsightCard/index.tsx +++ b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpanScalingInsightCard/index.tsx @@ -1,5 +1,5 @@ -import { useGlobalStore } from "../../../../../../containers/Main/stores/useGlobalStore"; import { usePagination } from "../../../../../../hooks/usePagination"; +import { useConfigSelector } from "../../../../../../store/config/useConfigSelector"; import { getDurationString } from "../../../../../../utils/getDurationString"; import { trimEndpointScheme } from "../../../../../../utils/trimEndpointScheme"; import { TraceIcon } from "../../../../../common/icons/12px/TraceIcon"; @@ -30,7 +30,7 @@ export const SpanScalingInsightCard = ({ isMarkAsReadButtonEnabled, viewMode }: SpanScalingInsightCardProps) => { - const isJaegerEnabled = useGlobalStore.use.isJaegerEnabled(); + const { isJaegerEnabled } = useConfigSelector(); const affectedEndpoints = insight.affectedEndpoints ?? []; const [pageItems, page, setPage] = usePagination( affectedEndpoints, diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpanUsagesInsightCard/index.tsx b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpanUsagesInsightCard/index.tsx index d30a16d42..a573b558b 100644 --- a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpanUsagesInsightCard/index.tsx +++ b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/SpanUsagesInsightCard/index.tsx @@ -5,9 +5,9 @@ import { useReactTable } from "@tanstack/react-table"; import { useEffect, useState } from "react"; -import { useGlobalStore } from "../../../../../../containers/Main/stores/useGlobalStore"; import { usePagination } from "../../../../../../hooks/usePagination"; import { usePrevious } from "../../../../../../hooks/usePrevious"; +import { useConfigSelector } from "../../../../../../store/config/useConfigSelector"; import { isNumber } from "../../../../../../typeGuards/isNumber"; import { InsightType } from "../../../../../../types"; import { roundTo } from "../../../../../../utils/roundTo"; @@ -43,7 +43,7 @@ export const SpanUsagesInsightCard = ({ isMarkAsReadButtonEnabled, viewMode }: SpanUsagesInsightCardProps) => { - const isJaegerEnabled = useGlobalStore.use.isJaegerEnabled(); + const { isJaegerEnabled } = useConfigSelector(); const [data, setData] = useState({ pageItems: insight.flows.slice(0, PAGE_SIZE) }); diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/common/InsightCard/InsightHeader/index.tsx b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/common/InsightCard/InsightHeader/index.tsx index b575382db..f0574c05c 100644 --- a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/common/InsightCard/InsightHeader/index.tsx +++ b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/common/InsightCard/InsightHeader/index.tsx @@ -1,4 +1,4 @@ -import { useGlobalStore } from "../../../../../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../../../../../store/config/useConfigSelector"; import { isString } from "../../../../../../../../typeGuards/isString"; import { formatTimeDistance } from "../../../../../../../../utils/formatTimeDistance"; import { getInsightTypeInfo } from "../../../../../../../../utils/getInsightTypeInfo"; @@ -38,7 +38,7 @@ export const InsightHeader = ({ lastUpdateTimer, isAsync }: InsightHeaderProps) => { - const scope = useGlobalStore.use.scope(); + const { scope } = useConfigSelector(); const insightTypeInfo = getInsightTypeInfo(insight.type, insight.subType); const statusTooltipContent = renderInsightStatusTooltipContent(insight); diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/common/InsightCard/index.tsx b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/common/InsightCard/index.tsx index d580e080c..94630ecb2 100644 --- a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/common/InsightCard/index.tsx +++ b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/common/InsightCard/index.tsx @@ -1,7 +1,7 @@ import { Fragment, useEffect, useState } from "react"; -import { useGlobalStore } from "../../../../../../../containers/Main/stores/useGlobalStore"; import { dispatcher } from "../../../../../../../dispatcher"; import { usePrevious } from "../../../../../../../hooks/usePrevious"; +import { useConfigSelector } from "../../../../../../../store/config/useConfigSelector"; import { isString } from "../../../../../../../typeGuards/isString"; import { sendUserActionTrackingEvent } from "../../../../../../../utils/actions/sendUserActionTrackingEvent"; import { Spinner } from "../../../../../../Navigation/CodeButtonMenu/Spinner"; @@ -60,7 +60,7 @@ export const InsightCard = ({ const isOperationInProgress = isDismissalChangeInProgress || isMarkingAsReadInProgress; const previousIsOperationInProgress = usePrevious(isOperationInProgress); - const isJaegerEnabled = useGlobalStore.use.isJaegerEnabled(); + const { isJaegerEnabled } = useConfigSelector(); const [insightStatus, setInsightStatus] = useState(insight.status); const isCritical = insight.criticality > HIGH_CRITICALITY_THRESHOLD; diff --git a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/common/IssueCompactCard/index.tsx b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/common/IssueCompactCard/index.tsx index e42812f7e..822c6c668 100644 --- a/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/common/IssueCompactCard/index.tsx +++ b/src/components/Insights/InsightsCatalog/InsightsPage/insightCards/common/IssueCompactCard/index.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; import { useTheme } from "styled-components"; -import { useGlobalStore } from "../../../../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../../../../store/config/useConfigSelector"; import { sendUserActionTrackingEvent } from "../../../../../../../utils/actions/sendUserActionTrackingEvent"; import { getInsightTypeInfo } from "../../../../../../../utils/getInsightTypeInfo"; import { CrossIcon } from "../../../../../../common/icons/16px/CrossIcon"; @@ -38,7 +38,7 @@ export const IssueCompactCard = ({ isCritical }: IssueCompactCardProps) => { const theme = useTheme(); - const isJaegerEnabled = useGlobalStore.use.isJaegerEnabled(); + const { isJaegerEnabled } = useConfigSelector(); const [isKebabMenuOpen, setIsKebabMenuOpen] = useState(false); const insightTypeInfo = getInsightTypeInfo(insight.type, insight.subType); const statusInfo = insight.status diff --git a/src/components/Insights/InsightsCatalog/index.tsx b/src/components/Insights/InsightsCatalog/index.tsx index aa35fbbf8..fbf276980 100644 --- a/src/components/Insights/InsightsCatalog/index.tsx +++ b/src/components/Insights/InsightsCatalog/index.tsx @@ -1,12 +1,13 @@ import { useEffect, useState } from "react"; import { createPortal } from "react-dom"; import { useTheme } from "styled-components"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; -import { useInsightsStore } from "../../../containers/Main/stores/useInsightsStore"; import { getFeatureFlagValue } from "../../../featureFlags"; import { useDebounce } from "../../../hooks/useDebounce"; import { usePersistence } from "../../../hooks/usePersistence"; import { usePrevious } from "../../../hooks/usePrevious"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; +import { useInsightsSelector } from "../../../store/insights/useInsightsSelector"; +import { useStore } from "../../../store/useStore"; import { isNumber } from "../../../typeGuards/isNumber"; import { isUndefined } from "../../../typeGuards/isUndefined"; import { FeatureFlag } from "../../../types"; @@ -65,20 +66,35 @@ export const InsightsCatalog = ({ onJiraTicketCreate, onRefresh }: InsightsCatalogProps) => { - const insightViewType = useInsightsStore.use.insightViewType(); - const mode = useInsightsStore.use.viewMode(); - const setMode = useInsightsStore.use.setViewMode(); - const page = useInsightsStore.use.page(); - const setPage = useInsightsStore.use.setPage(); - const searchInputValue = useInsightsStore.use.search(); - const setSearch = useInsightsStore.use.setSearch(); + const { + setViewMode: setMode, + setPage, + setSorting, + setSearch + } = useStore.getState(); + + const { + page, + search: searchInputValue, + sorting, + filters, + filteredInsightTypes, + data, + viewMode: mode, + insightViewType + } = useInsightsSelector(); + + const { + selectedServices, + insightStats, + environment, + environments, + scope, + backendInfo + } = useConfigSelector(); + const debouncedSearchInputValue = useDebounce(searchInputValue, 1000); - const sorting = useInsightsStore.use.sorting(); - const setSorting = useInsightsStore.use.setSorting(); - const filters = useInsightsStore.use.filters(); - const filteredInsightTypes = useInsightsStore.use.filteredInsightTypes(); - const selectedServices = useGlobalStore.use.selectedServices(); - const data = useInsightsStore.use.data(); + const insights = data?.insights ?? []; const totalCount = data?.totalCount ?? 0; const dismissedCount = data?.dismissedCount; @@ -88,13 +104,8 @@ export const InsightsCatalog = ({ pageStartItemNumber + PAGE_SIZE - 1, totalCount ); - const insightStats = useGlobalStore.use.insightStats(); - const environment = useGlobalStore.use.environment(); - const environments = useGlobalStore.use.environments(); - const scope = useGlobalStore.use.scope(); const scopeSpanCodeObjectId = scope?.span?.spanCodeObjectId; const isAtSpan = Boolean(scope?.span); - const backendInfo = useGlobalStore.use.backendInfo(); const theme = useTheme(); const { isMarkingAllAsReadInProgress, markAllAsRead } = useMarkingAllAsRead( scope?.span ?? null diff --git a/src/components/Insights/Issues/IssuesFilter/index.tsx b/src/components/Insights/Issues/IssuesFilter/index.tsx index 026efa0c8..f1d30e79c 100644 --- a/src/components/Insights/Issues/IssuesFilter/index.tsx +++ b/src/components/Insights/Issues/IssuesFilter/index.tsx @@ -1,8 +1,9 @@ import { useEffect, useMemo } from "react"; -import { useGlobalStore } from "../../../../containers/Main/stores/useGlobalStore"; -import { useInsightsStore } from "../../../../containers/Main/stores/useInsightsStore"; import { getFeatureFlagValue } from "../../../../featureFlags"; import { usePrevious } from "../../../../hooks/usePrevious"; +import { useConfigSelector } from "../../../../store/config/useConfigSelector"; +import { useInsightsSelector } from "../../../../store/insights/useInsightsSelector"; +import { useStore } from "../../../../store/useStore"; import { FeatureFlag } from "../../../../types"; import { sendUserActionTrackingEvent } from "../../../../utils/actions/sendUserActionTrackingEvent"; import { getInsightTypeInfo } from "../../../../utils/getInsightTypeInfo"; @@ -19,14 +20,10 @@ import * as s from "./styles"; import { trackingEvents } from "./tracking"; export const IssuesFilter = () => { - const filteredInsightTypes = useInsightsStore.use.filteredInsightTypes(); - const selectedServices = useGlobalStore.use.selectedServices(); - const setFilteredInsightTypes = - useInsightsStore.use.setFilteredInsightTypes(); - const setSelectedServices = useGlobalStore.use.setSelectedServices(); - const filters = useInsightsStore.use.filters(); - const backendInfo = useGlobalStore.use.backendInfo(); - const setFilters = useInsightsStore.use.setFilters(); + const { filteredInsightTypes, filters } = useInsightsSelector(); + const { selectedServices, backendInfo, scope } = useConfigSelector(); + const { setSelectedServices, setFilteredInsightTypes, setFilters } = + useStore.getState(); const isCriticalOnly = useMemo( () => filters.includes("criticality"), [filters] @@ -34,7 +31,6 @@ export const IssuesFilter = () => { const isUnreadOnly = useMemo(() => filters.includes("unread"), [filters]); const { data } = useIssuesFilters(); const previousData = usePrevious(data); - const scope = useGlobalStore.use.scope(); const scopeSpanCodeObjectId = scope?.span?.spanCodeObjectId; const isServicesFilterEnabled = Boolean( diff --git a/src/components/Insights/Issues/useIssuesFilters.ts b/src/components/Insights/Issues/useIssuesFilters.ts index 05db29de8..7bd22ac2f 100644 --- a/src/components/Insights/Issues/useIssuesFilters.ts +++ b/src/components/Insights/Issues/useIssuesFilters.ts @@ -1,9 +1,10 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { DigmaMessageError } from "../../../api/types"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; -import { useInsightsStore } from "../../../containers/Main/stores/useInsightsStore"; import { dispatcher } from "../../../dispatcher"; import { usePrevious } from "../../../hooks/usePrevious"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; +import { useInsightsSelector } from "../../../store/insights/useInsightsSelector"; +import { useStore } from "../../../store/useStore"; import { GetIssuesFiltersPayload } from "../../../types"; import { ViewMode } from "../InsightsCatalog/types"; import { actions as issuesActions } from "./actions"; @@ -22,20 +23,20 @@ const getFilters = (query: GetIssuesFiltersQuery) => { }; export const useIssuesFilters = () => { - const data = useInsightsStore.use.issuesFilters(); - const setData = useInsightsStore.use.setIssuesFilters(); + const { + issuesFilters: data, + search, + filteredInsightTypes, + viewMode, + filters + } = useInsightsSelector(); + const { setIssuesFilters: setData } = useStore.getState(); const [lastSetDataTimeStamp, setLastSetDataTimeStamp] = useState(); const previousLastSetDataTimeStamp = usePrevious(lastSetDataTimeStamp); const refreshTimerId = useRef(); - const environment = useGlobalStore.use.environment(); + const { environment, scope, backendInfo } = useConfigSelector(); const environmentId = environment?.id; - const scope = useGlobalStore.use.scope(); const spanCodeObjectId = scope?.span?.spanCodeObjectId ?? null; - const search = useInsightsStore.use.search(); - const filters = useInsightsStore.use.filters(); - const filteredInsightTypes = useInsightsStore.use.filteredInsightTypes(); - const viewMode = useInsightsStore.use.viewMode(); - const backendInfo = useGlobalStore.use.backendInfo(); const query: GetIssuesFiltersQuery = useMemo( () => ({ diff --git a/src/components/Insights/index.tsx b/src/components/Insights/index.tsx index d77e9bb2d..17dbb541c 100644 --- a/src/components/Insights/index.tsx +++ b/src/components/Insights/index.tsx @@ -1,10 +1,11 @@ import { KeyboardEvent, useCallback, useEffect, useState } from "react"; import { actions as globalActions } from "../../actions"; import { SLACK_WORKSPACE_URL } from "../../constants"; -import { useGlobalStore } from "../../containers/Main/stores/useGlobalStore"; -import { useInsightsStore } from "../../containers/Main/stores/useInsightsStore"; import { usePersistence } from "../../hooks/usePersistence"; import { usePrevious } from "../../hooks/usePrevious"; +import { useConfigSelector } from "../../store/config/useConfigSelector"; +import { useInsightsSelector } from "../../store/insights/useInsightsSelector"; +import { useStore } from "../../store/useStore"; import { trackingEvents as globalTrackingEvents } from "../../trackingEvents"; import { isUndefined } from "../../typeGuards/isUndefined"; import { openURLInDefaultBrowser } from "../../utils/actions/openURLInDefaultBrowser"; @@ -224,33 +225,39 @@ export const Insights = ({ insightViewType }: InsightsProps) => { const { data, isLoading, refresh } = useInsightsData({ areFiltersRehydrated }); - const reset = useInsightsStore.use.reset(); const [infoToOpenJiraTicket, setInfoToOpenJiraTicket] = useState>(); - const userRegistrationEmail = useGlobalStore.use.userRegistrationEmail(); + const { + backendInfo, + environment, + userRegistrationEmail, + environments, + scope + } = useConfigSelector(); const previousUserRegistrationEmail = usePrevious(userRegistrationEmail); - const environments = useGlobalStore.use.environments(); const [isRegistrationInProgress, setIsRegistrationInProgress] = useState(false); const isRegistrationEnabled = false; const isRegistrationRequired = isRegistrationEnabled && !userRegistrationEmail; - const setInsightsViewType = useInsightsStore.use.setInsightViewType(); - const storedInsightViewType = useInsightsStore.use.insightViewType(); - const filteredInsightTypes = useInsightsStore.use.filteredInsightTypes(); + const { + setInsightViewType, + setFilteredInsightTypes, + setFilters, + insightsReset: reset + } = useStore.getState(); + const { + insightViewType: storedInsightViewType, + filteredInsightTypes, + filters + } = useInsightsSelector(); + const previousFilteredInsightTypes = usePrevious(filteredInsightTypes); - const setFilteredInsightTypes = - useInsightsStore.use.setFilteredInsightTypes(); - const filters = useInsightsStore.use.filters(); const previousFilters = usePrevious(filters); - const setFilters = useInsightsStore.use.setFilters(); - const backendInfo = useGlobalStore.use.backendInfo(); const previousBackendInfo = usePrevious(backendInfo); - const scope = useGlobalStore.use.scope(); const scopeSpanCodeObjectId = scope?.span?.spanCodeObjectId; const previousScope = usePrevious(scope); const previousScopeSpanCodeObjectId = previousScope?.span?.spanCodeObjectId; - const environment = useGlobalStore.use.environment(); const environmentId = environment?.id; const previousEnvironmentId = usePrevious(environmentId); @@ -261,8 +268,8 @@ export const Insights = ({ insightViewType }: InsightsProps) => { }, [reset]); useEffect(() => { - setInsightsViewType(insightViewType); - }, [insightViewType, setInsightsViewType]); + setInsightViewType(insightViewType); + }, [insightViewType, setInsightViewType]); useEffect(() => { if ( diff --git a/src/components/Insights/insightTickets/EndpointQueryOptimizationV2InsightTicket/index.tsx b/src/components/Insights/insightTickets/EndpointQueryOptimizationV2InsightTicket/index.tsx index 06afd3740..d175a3ebd 100644 --- a/src/components/Insights/insightTickets/EndpointQueryOptimizationV2InsightTicket/index.tsx +++ b/src/components/Insights/insightTickets/EndpointQueryOptimizationV2InsightTicket/index.tsx @@ -1,5 +1,5 @@ import { ReactElement } from "react"; -import { useGlobalStore } from "../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../store/config/useConfigSelector"; import { InsightType } from "../../../../types"; import { getCriticalityLabel } from "../../../../utils/getCriticalityLabel"; import { getDurationString } from "../../../../utils/getDurationString"; @@ -23,7 +23,7 @@ export const EndpointQueryOptimizationV2InsightTicket = ({ refreshInsights, onClose }: InsightTicketProps) => { - const jaegerURL = useGlobalStore.use.jaegerURL(); + const { jaegerURL } = useConfigSelector(); const span = data.insight.span; const spanInfo = span?.spanInfo || null; diff --git a/src/components/Insights/insightTickets/EndpointSpanNPlusOneInsightTicket/index.tsx b/src/components/Insights/insightTickets/EndpointSpanNPlusOneInsightTicket/index.tsx index 7564025ed..e26d46624 100644 --- a/src/components/Insights/insightTickets/EndpointSpanNPlusOneInsightTicket/index.tsx +++ b/src/components/Insights/insightTickets/EndpointSpanNPlusOneInsightTicket/index.tsx @@ -1,5 +1,5 @@ import { ReactElement } from "react"; -import { useGlobalStore } from "../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../store/config/useConfigSelector"; import { InsightType } from "../../../../types"; import { getCriticalityLabel } from "../../../../utils/getCriticalityLabel"; import { intersperse } from "../../../../utils/intersperse"; @@ -19,7 +19,7 @@ export const EndpointSpanNPlusOneInsightTicket = ({ refreshInsights, onClose }: InsightTicketProps) => { - const jaegerURL = useGlobalStore.use.jaegerURL(); + const { jaegerURL } = useConfigSelector(); const span = data.insight.span; const spanInfo = span?.internalSpan ?? span?.clientSpan; diff --git a/src/components/Insights/insightTickets/SpaNPlusOneInsightTicket/index.tsx b/src/components/Insights/insightTickets/SpaNPlusOneInsightTicket/index.tsx index 12926c944..2e77e4904 100644 --- a/src/components/Insights/insightTickets/SpaNPlusOneInsightTicket/index.tsx +++ b/src/components/Insights/insightTickets/SpaNPlusOneInsightTicket/index.tsx @@ -1,5 +1,5 @@ import { ReactElement } from "react"; -import { useGlobalStore } from "../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../store/config/useConfigSelector"; import { getCriticalityLabel } from "../../../../utils/getCriticalityLabel"; import { intersperse } from "../../../../utils/intersperse"; import { DigmaSignature } from "../../../common/DigmaSignature"; @@ -21,7 +21,7 @@ export const SpaNPlusOneInsightTicket = ({ const spanInsight = data.insight; const { commitInfos, isLoading, codeLocations } = useSpanDataSource(data.insight.spanInfo, data.insight); - const jaegerURL = useGlobalStore.use.jaegerURL(); + const { jaegerURL } = useConfigSelector(); const endpoints = data.insight.endpoints ?? []; diff --git a/src/components/Insights/insightTickets/SpanQueryOptimizationInsightTicket/index.tsx b/src/components/Insights/insightTickets/SpanQueryOptimizationInsightTicket/index.tsx index 1b6a9040e..f6a700b4a 100644 --- a/src/components/Insights/insightTickets/SpanQueryOptimizationInsightTicket/index.tsx +++ b/src/components/Insights/insightTickets/SpanQueryOptimizationInsightTicket/index.tsx @@ -1,5 +1,5 @@ import { ReactElement } from "react"; -import { useGlobalStore } from "../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../store/config/useConfigSelector"; import { getCriticalityLabel } from "../../../../utils/getCriticalityLabel"; import { getDurationString } from "../../../../utils/getDurationString"; import { intersperse } from "../../../../utils/intersperse"; @@ -19,7 +19,7 @@ export const SpanQueryOptimizationInsightTicket = ({ onClose }: InsightTicketProps) => { const { isLoading, commitInfos } = useCommitInfos(data.insight); - const jaegerURL = useGlobalStore.use.jaegerURL(); + const { jaegerURL } = useConfigSelector(); const criticalityString = data.insight.criticality > 0 diff --git a/src/components/Insights/insightTickets/SpanScalingByRootCauseInsightTicket/index.tsx b/src/components/Insights/insightTickets/SpanScalingByRootCauseInsightTicket/index.tsx index 8ba00494b..ccccdc773 100644 --- a/src/components/Insights/insightTickets/SpanScalingByRootCauseInsightTicket/index.tsx +++ b/src/components/Insights/insightTickets/SpanScalingByRootCauseInsightTicket/index.tsx @@ -1,5 +1,5 @@ import { ReactElement } from "react"; -import { useGlobalStore } from "../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../store/config/useConfigSelector"; import { InsightType } from "../../../../types"; import { intersperse } from "../../../../utils/intersperse"; import { DigmaSignature } from "../../../common/DigmaSignature"; @@ -29,8 +29,7 @@ export const SpanScalingByRootCauseInsightTicket = ({ }: InsightTicketProps & { rootCauseSpanInfo: RootCauseSpanInfo; }) => { - const jaegerURL = useGlobalStore.use.jaegerURL(); - const digmaApiProxyPrefix = useGlobalStore.use.digmaApiProxyPrefix(); + const { jaegerURL, digmaApiProxyPrefix } = useConfigSelector(); const spanInfo = rootCauseSpanInfo; diff --git a/src/components/Insights/insightTickets/SpanScalingInsightTicket/index.tsx b/src/components/Insights/insightTickets/SpanScalingInsightTicket/index.tsx index d2ee3f13e..422ef3890 100644 --- a/src/components/Insights/insightTickets/SpanScalingInsightTicket/index.tsx +++ b/src/components/Insights/insightTickets/SpanScalingInsightTicket/index.tsx @@ -1,5 +1,5 @@ import { ReactElement } from "react"; -import { useGlobalStore } from "../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../store/config/useConfigSelector"; import { intersperse } from "../../../../utils/intersperse"; import { DigmaSignature } from "../../../common/DigmaSignature"; import { Attachment } from "../../../common/JiraTicket/types"; @@ -25,8 +25,7 @@ export const SpanScalingInsightTicket = ({ refreshInsights, onClose }: InsightTicketProps) => { - const jaegerURL = useGlobalStore.use.jaegerURL(); - const digmaApiProxyPrefix = useGlobalStore.use.digmaApiProxyPrefix(); + const { jaegerURL, digmaApiProxyPrefix } = useConfigSelector(); const insight = data.insight; diff --git a/src/components/Insights/useInsightsData.ts b/src/components/Insights/useInsightsData.ts index 75fd78096..6927e4797 100644 --- a/src/components/Insights/useInsightsData.ts +++ b/src/components/Insights/useInsightsData.ts @@ -1,11 +1,12 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { actions as globalActions } from "../../actions"; import { DigmaMessageError } from "../../api/types"; -import { useGlobalStore } from "../../containers/Main/stores/useGlobalStore"; -import { useInsightsStore } from "../../containers/Main/stores/useInsightsStore"; import { dispatcher } from "../../dispatcher"; import { getFeatureFlagValue } from "../../featureFlags"; import { usePrevious } from "../../hooks/usePrevious"; +import { useConfigSelector } from "../../store/config/useConfigSelector"; +import { useInsightsSelector } from "../../store/insights/useInsightsSelector"; +import { useStore } from "../../store/useStore"; import { FeatureFlag, GetInsightStatsPayload, @@ -131,30 +132,30 @@ const getStats = ({ export const useInsightsData = ({ areFiltersRehydrated }: UseInsightsDataProps) => { - const data = useInsightsStore.use.data(); - const setData = useInsightsStore.use.setData(); - const isLoading = useInsightsStore.use.isDataLoading(); - const setIsLoading = useInsightsStore.use.setIsDataLoading(); + const { scope, backendInfo, environment, selectedServices } = + useConfigSelector(); + const { + data, + search, + page, + sorting, + viewMode, + filters, + filteredInsightTypes, + isDataLoading: isLoading, + insightViewType + } = useInsightsSelector(); + const { setData, setIsDataLoading: setIsLoading } = useStore.getState(); const isInitialLoading = !data && isLoading; const [lastSetDataTimeStamp, setLastSetDataTimeStamp] = useState(); const previousLastSetDataTimeStamp = usePrevious(lastSetDataTimeStamp); const refreshTimerId = useRef(); - const backendInfo = useGlobalStore.use.backendInfo(); - const scope = useGlobalStore.use.scope(); - const environment = useGlobalStore.use.environment(); const environmentId = environment?.id; - const search = useInsightsStore.use.search(); - const page = useInsightsStore.use.page(); - const sorting = useInsightsStore.use.sorting(); - const viewMode = useInsightsStore.use.viewMode(); - const filters = useInsightsStore.use.filters(); - const filteredInsightTypes = useInsightsStore.use.filteredInsightTypes(); - const selectedServices = useGlobalStore.use.selectedServices(); + const filteredServices = useMemo( () => selectedServices ?? [], [selectedServices] ); - const insightViewType = useInsightsStore.use.insightViewType(); const spanCodeObjectId = scope?.span?.spanCodeObjectId ?? null; const showDismissed = viewMode === ViewMode.OnlyDismissed; const isAppReadyToGetData = useMemo( diff --git a/src/components/Main/index.tsx b/src/components/Main/index.tsx index 6ae261b03..0a101a1f7 100644 --- a/src/components/Main/index.tsx +++ b/src/components/Main/index.tsx @@ -2,13 +2,14 @@ import { useEffect, useLayoutEffect, useMemo } from "react"; import { Outlet, matchPath, useLocation } from "react-router-dom"; import { actions as globalActions } from "../../actions"; import { history } from "../../containers/Main/history"; -import { useGlobalStore } from "../../containers/Main/stores/useGlobalStore"; import { dispatcher } from "../../dispatcher"; import { HistoryEntryLocation } from "../../history/History"; import { usePersistence } from "../../hooks/usePersistence"; import { usePrevious } from "../../hooks/usePrevious"; import { logger } from "../../logging"; import { PLUGIN_EVENTS } from "../../pluginEvents"; +import { useConfigSelector } from "../../store/config/useConfigSelector"; +import { useStore } from "../../store/useStore"; import { trackingEvents as globalTrackingEvents } from "../../trackingEvents"; import { isUndefined } from "../../typeGuards/isUndefined"; import { SendPluginEventPayload } from "../../types"; @@ -49,14 +50,11 @@ const getURLToNavigateOnCodeLensClick = (scope: Scope): string | undefined => { export const Main = () => { const location = useLocation(); - const environments = useGlobalStore.use.environments(); - const environment = useGlobalStore.use.environment(); + const { environments, environment, scope, userInfo, backendInfo } = + useConfigSelector(); const previousEnvironment = usePrevious(environment); - const scope = useGlobalStore.use.scope(); - const userInfo = useGlobalStore.use.userInfo(); const userId = userInfo?.id; const previousUserId = usePrevious(userId); - const backendInfo = useGlobalStore.use.backendInfo(); const previousBackendInfo = usePrevious(backendInfo); const { goTo } = useHistory(); const updateBrowserLocation = useBrowserLocationUpdater(); @@ -65,8 +63,8 @@ export const Main = () => { "project" ); const previousPersistedServices = usePrevious(persistedServices); - const selectedServices = useGlobalStore.use.selectedServices(); - const setSelectedServices = useGlobalStore.use.setSelectedServices(); + const selectedServices = useConfigSelector().selectedServices; + const { setSelectedServices } = useStore.getState(); const isInitialized = useMemo( () => !isUndefined(persistedServices), [persistedServices] diff --git a/src/components/Main/useHistory.tsx b/src/components/Main/useHistory.tsx index 14dec04d7..a89b35177 100644 --- a/src/components/Main/useHistory.tsx +++ b/src/components/Main/useHistory.tsx @@ -1,7 +1,7 @@ import { NavigateOptions, To, resolvePath } from "react-router-dom"; import { history } from "../../containers/Main/history"; -import { useGlobalStore } from "../../containers/Main/stores/useGlobalStore"; import { HistoryEntry, HistoryEntryLocation } from "../../history/History"; +import { useConfigSelector } from "../../store/config/useConfigSelector"; import { isString } from "../../typeGuards/isString"; import { HistoryState } from "./types"; @@ -88,8 +88,7 @@ const isNewHistoryEntryNeeded = ( export const useHistory = () => { const location = history.getCurrentLocation(); - const environment = useGlobalStore.use.environment(); - const scope = useGlobalStore.use.scope(); + const { environment, scope } = useConfigSelector(); const scopeSpanCodeObjectId = scope?.span?.spanCodeObjectId; const goTo = (to: To, options?: NavigateOptions) => { diff --git a/src/components/Navigation/EnvironmentBar/EnvironmentMenu/index.tsx b/src/components/Navigation/EnvironmentBar/EnvironmentMenu/index.tsx index 5f6d1ff43..97bf24b90 100644 --- a/src/components/Navigation/EnvironmentBar/EnvironmentMenu/index.tsx +++ b/src/components/Navigation/EnvironmentBar/EnvironmentMenu/index.tsx @@ -1,4 +1,4 @@ -import { useGlobalStore } from "../../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../../store/config/useConfigSelector"; import { Environment } from "../../../common/App/types"; import { EnvironmentIcon } from "../../../common/EnvironmentIcon"; import { MenuList } from "../../common/MenuList"; @@ -9,7 +9,7 @@ export const EnvironmentMenu = ({ environments, onMenuItemClick }: EnvironmentMenuProps) => { - const environment = useGlobalStore.use.environment(); + const { environment } = useConfigSelector(); const handleMenuItemClick = (environment: Environment) => { onMenuItemClick(environment); diff --git a/src/components/Navigation/HistoryNavigationPanel/index.tsx b/src/components/Navigation/HistoryNavigationPanel/index.tsx index 091bac8bc..4fe425397 100644 --- a/src/components/Navigation/HistoryNavigationPanel/index.tsx +++ b/src/components/Navigation/HistoryNavigationPanel/index.tsx @@ -2,8 +2,8 @@ import { useEffect } from "react"; import { Location, useLocation, useNavigate } from "react-router-dom"; import { useTheme } from "styled-components"; import { history } from "../../../containers/Main/history"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; import { HistoryEntry } from "../../../history/History"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; import { changeScope } from "../../../utils/actions/changeScope"; import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActionTrackingEvent"; import { @@ -22,9 +22,7 @@ import * as s from "./styles"; export const HistoryNavigationPanel = () => { const { goBack, goForward, goTo, canGoBack, canGoForward } = useHistory(); const navigate = useNavigate(); - const environments = useGlobalStore.use.environments(); - const environment = useGlobalStore.use.environment(); - const scope = useGlobalStore.use.scope(); + const { environments, environment, scope } = useConfigSelector(); const location = useLocation() as Location; const theme = useTheme(); const updateBrowserLocation = useBrowserLocationUpdater(); diff --git a/src/components/Navigation/KebabMenu/index.tsx b/src/components/Navigation/KebabMenu/index.tsx index 18aa96ee4..8cc56800d 100644 --- a/src/components/Navigation/KebabMenu/index.tsx +++ b/src/components/Navigation/KebabMenu/index.tsx @@ -1,6 +1,6 @@ import { actions as globalActions } from "../../../actions"; import { DIGMA_DOCUMENTATION } from "../../../constants"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; import { OpenInstallationWizardPayload } from "../../../types"; import { openURLInDefaultBrowser } from "../../../utils/actions/openURLInDefaultBrowser"; import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActionTrackingEvent"; @@ -19,9 +19,7 @@ import { OpenDashboardPayload, OpenDocumentationPayload } from "../types"; import { KebabMenuProps } from "./types"; export const KebabMenu = ({ onClose }: KebabMenuProps) => { - const backendInfo = useGlobalStore.use.backendInfo(); - const digmaStatus = useGlobalStore.use.digmaStatus(); - const environment = useGlobalStore.use.environment(); + const { backendInfo, digmaStatus, environment } = useConfigSelector(); const handleOnboardingClick = () => { sendUserActionTrackingEvent(trackingEvents.ONBOARDING_LINK_CLICKED); diff --git a/src/components/Navigation/Tabs/index.tsx b/src/components/Navigation/Tabs/index.tsx index ed01c55ef..006d7e069 100644 --- a/src/components/Navigation/Tabs/index.tsx +++ b/src/components/Navigation/Tabs/index.tsx @@ -1,6 +1,6 @@ import { useMemo } from "react"; import { useLocation } from "react-router-dom"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; import { isNumber } from "../../../typeGuards/isNumber"; import { isString } from "../../../typeGuards/isString"; import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActionTrackingEvent"; @@ -85,8 +85,7 @@ const getIsNewIndicatorVisible = ( ); export const Tabs = () => { - const scope = useGlobalStore.use.scope(); - const insightStats = useGlobalStore.use.insightStats(); + const { scope, insightStats } = useConfigSelector(); const location = useLocation(); const { goTo } = useHistory(); diff --git a/src/components/Navigation/index.tsx b/src/components/Navigation/index.tsx index fe1d872b0..0e7516f88 100644 --- a/src/components/Navigation/index.tsx +++ b/src/components/Navigation/index.tsx @@ -1,6 +1,5 @@ import { useCallback, useEffect, useState } from "react"; import { actions as globalActions } from "../../actions"; -import { useGlobalStore } from "../../containers/Main/stores/useGlobalStore"; import { dispatcher } from "../../dispatcher"; import { usePrevious } from "../../hooks/usePrevious"; // import { isNull } from "../../typeGuards/isNull"; @@ -16,6 +15,7 @@ import { ThreeDotsIcon } from "../common/icons/ThreeDotsIcon"; // import { Tooltip } from "../common/v3/Tooltip"; // import { CodeButton } from "./CodeButton"; // import { CodeButtonMenu } from "./CodeButtonMenu"; +import { useConfigSelector } from "../../store/config/useConfigSelector"; import { EnvironmentBar } from "./EnvironmentBar"; import { HistoryNavigationPanel } from "./HistoryNavigationPanel"; import { KebabMenu } from "./KebabMenu"; @@ -78,11 +78,8 @@ import { // }; export const Navigation = () => { - const environments = useGlobalStore.use.environments(); - const environment = useGlobalStore.use.environment(); - const scope = useGlobalStore.use.scope(); - const userInfo = useGlobalStore.use.userInfo(); - const backendInfo = useGlobalStore.use.backendInfo(); + const { environments, environment, scope, userInfo, backendInfo } = + useConfigSelector(); const [selectedEnvironment, setSelectedEnvironment] = useState(environment); const [codeContext, setCodeContext] = useState(); // const [isCodeButtonMenuOpen, setIsCodeButtonMenuOpen] = useState(false); diff --git a/src/components/RecentActivity/EnvironmentInstructionsPanel/EnvironmentVariableCode/index.tsx b/src/components/RecentActivity/EnvironmentInstructionsPanel/EnvironmentVariableCode/index.tsx index 173e51bc4..6257d3446 100644 --- a/src/components/RecentActivity/EnvironmentInstructionsPanel/EnvironmentVariableCode/index.tsx +++ b/src/components/RecentActivity/EnvironmentInstructionsPanel/EnvironmentVariableCode/index.tsx @@ -1,6 +1,6 @@ import { Fragment, ReactNode } from "react"; -import { useGlobalStore } from "../../../../containers/Main/stores/useGlobalStore"; import { getFeatureFlagValue } from "../../../../featureFlags"; +import { useConfigSelector } from "../../../../store/config/useConfigSelector"; import { isString } from "../../../../typeGuards/isString"; import { FeatureFlag } from "../../../../types"; import { intersperse } from "../../../../utils/intersperse"; @@ -88,20 +88,19 @@ const renderEnvironmentVariables = ( }; export const EnvironmentVariableCode = () => { - const environment = useGlobalStore.use.environment(); - const backendInfo = useGlobalStore.use.backendInfo(); - + const { environment, backendInfo, userInfo, runConfig, isMicrometerProject } = + useConfigSelector(); + const isMicrometerProjectValue = isMicrometerProject ?? false; + const userId = userInfo?.id; if (!environment || !backendInfo) { return null; } const isCentralizedDeployment = backendInfo.centralize; - const isMicrometerProject = Boolean(useGlobalStore.use.isMicrometerProject()); - const userId = useGlobalStore.use.userInfo()?.id; const environmentId = environment.id; const environmentName = environment.name; const environmentType = environment.type ?? undefined; - const runConfig = useGlobalStore.use.runConfig(); + const isRunConfigSupported = Boolean(runConfig?.isRunConfigurationSupported); const javaToolOptions = isRunConfigSupported ? undefined @@ -115,7 +114,7 @@ export const EnvironmentVariableCode = () => { if (areNewInstrumentationAttributesEnabled) { if (isCentralizedDeployment) { return renderEnvironmentVariables( - isMicrometerProject, + isMicrometerProjectValue, [ ["environmentName", environmentName], ["environmentType", environmentType], @@ -125,7 +124,7 @@ export const EnvironmentVariableCode = () => { ); } else { return renderEnvironmentVariables( - isMicrometerProject, + isMicrometerProjectValue, [["environmentName", environmentName]], javaToolOptions ); @@ -133,7 +132,7 @@ export const EnvironmentVariableCode = () => { } return renderEnvironmentVariables( - isMicrometerProject, + isMicrometerProjectValue, [["environmentId", environmentId]], javaToolOptions ); diff --git a/src/components/Tests/TestTicket/index.tsx b/src/components/Tests/TestTicket/index.tsx index 8dbee9878..f10d4a5b4 100644 --- a/src/components/Tests/TestTicket/index.tsx +++ b/src/components/Tests/TestTicket/index.tsx @@ -1,5 +1,5 @@ import { ReactElement } from "react"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; import { isString } from "../../../typeGuards/isString"; import { getDurationString } from "../../../utils/getDurationString"; import { intersperse } from "../../../utils/intersperse"; @@ -23,7 +23,8 @@ export const TestTicket = ({ contextsSpanCodeObjectIds } = test; const summary = `"${name}" test failed`; - const jaegerURL = useGlobalStore.use.jaegerURL() ?? ""; + const { jaegerURL } = useConfigSelector(); + const jaegerURLString = jaegerURL ?? ""; const relatedSpans = spanContexts .filter((x) => contextsSpanCodeObjectIds.includes(x.spanCodeObjectId)) @@ -54,7 +55,7 @@ export const TestTicket = ({ ); - const traceAttachment = getTraceAttachment(jaegerURL, traceId); + const traceAttachment = getTraceAttachment(jaegerURLString, traceId); const attachments: Attachment[] = [ ...(traceAttachment ? [traceAttachment] : []) ]; diff --git a/src/components/Tests/index.tsx b/src/components/Tests/index.tsx index d679dbba6..e69599028 100644 --- a/src/components/Tests/index.tsx +++ b/src/components/Tests/index.tsx @@ -1,8 +1,8 @@ import { KeyboardEvent, useEffect, useMemo, useRef, useState } from "react"; import { actions as globalActions } from "../../actions"; -import { useGlobalStore } from "../../containers/Main/stores/useGlobalStore"; import { dispatcher } from "../../dispatcher"; import { usePrevious } from "../../hooks/usePrevious"; +import { useConfigSelector } from "../../store/config/useConfigSelector"; import { isNull } from "../../typeGuards/isNull"; import { sendTrackingEvent } from "../../utils/actions/sendTrackingEvent"; import { MenuItem } from "../common/FilterMenu/types"; @@ -65,9 +65,7 @@ export const Tests = () => { const [isInitialLoading, setIsInitialLoading] = useState(false); const [lastSetDataTimeStamp, setLastSetDataTimeStamp] = useState(); const previousLastSetDataTimeStamp = usePrevious(lastSetDataTimeStamp); - const userRegistrationEmail = useGlobalStore.use.userRegistrationEmail(); - const scope = useGlobalStore.use.scope(); - const environments = useGlobalStore.use.environments(); + const { userRegistrationEmail, scope, environments } = useConfigSelector(); const [testToOpenTicketPopup, setTestToOpenTicketPopup] = useState(); const previousUserRegistrationEmail = usePrevious(userRegistrationEmail); useState(false); diff --git a/src/components/common/App/index.tsx b/src/components/common/App/index.tsx index dbf09f4de..4e10e79d5 100644 --- a/src/components/common/App/index.tsx +++ b/src/components/common/App/index.tsx @@ -2,10 +2,10 @@ import { ErrorInfo, useContext, useEffect, useState } from "react"; import { ErrorBoundary } from "react-error-boundary"; import { ThemeProvider } from "styled-components"; import { actions } from "../../../actions"; -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; import { dispatcher } from "../../../dispatcher"; import { Theme } from "../../../globals"; import { logger } from "../../../logging"; +import { useStore } from "../../../store/useStore"; import { isBoolean } from "../../../typeGuards/isBoolean"; import { isNull } from "../../../typeGuards/isNull"; import { isObject } from "../../../typeGuards/isObject"; @@ -62,43 +62,27 @@ export const App = ({ theme, children, id }: AppProps) => { const [mainFont, setMainFont] = useState(defaultMainFont); const [codeFont, setCodeFont] = useState(defaultCodeFont); const [config, setConfig] = useState(useContext(ConfigContext)); - const setJaegerURL = useGlobalStore((state) => state.setJaegerURL); - const setIsJaegerEnabled = useGlobalStore( - (state) => state.setIsJaegerEnabled - ); - const setIsDigmaEngineInstalled = useGlobalStore( - (state) => state.setIsDigmaEngineInstalled - ); - const setIsDigmaEngineRunning = useGlobalStore( - (state) => state.setIsDigmaEngineRunning - ); - const setDigmaStatus = useGlobalStore((state) => state.setDigmaStatus); - const setIsDockerInstalled = useGlobalStore( - (state) => state.setIsDockerInstalled - ); - const setIsDockerComposeInstalled = useGlobalStore( - (state) => state.setIsDockerComposeInstalled - ); - const setDigmaApiUrl = useGlobalStore((state) => state.setDigmaApiUrl); - const setUserRegistrationEmail = useGlobalStore( - (state) => state.setUserRegistrationEmail - ); - const setIsObservabilityEnabled = useGlobalStore( - (state) => state.setIsObservabilityEnabled - ); - const setBackendInfo = useGlobalStore((state) => state.setBackendInfo); - const setEnvironments = useGlobalStore((state) => state.setEnvironments); - const setEnvironment = useGlobalStore((state) => state.setEnvironment); - const setScope = useGlobalStore((state) => state.setScope); - const setUserInfo = useGlobalStore((state) => state.setUserInfo); - const setInsightStats = useGlobalStore((state) => state.setInsightStats); - const setRunConfiguration = useGlobalStore((state) => state.setRunConfig); - const setIsMicrometerProject = useGlobalStore( - (state) => state.setIsMicrometerProject - ); - const setIsDigmathonGameFinished = useGlobalStore( - (state) => state.setIsDigmathonGameFinished - ); + const { + setJaegerURL, + setIsJaegerEnabled, + setIsDigmaEngineInstalled, + setIsDigmaEngineRunning, + setDigmaStatus, + setIsDockerInstalled, + setIsDockerComposeInstalled, + setDigmaApiUrl, + setUserRegistrationEmail, + setIsObservabilityEnabled, + setBackendInfo, + setEnvironments, + setEnvironment, + setScope, + setUserInfo, + setInsightStats, + setRunConfig, + setIsDigmathonGameFinished, + setIsMicrometerProject + } = useStore.getState(); const handleError = (error: Error, info: ErrorInfo) => { logger.error(error, info); @@ -347,7 +331,7 @@ export const App = ({ theme, children, id }: AppProps) => { ...config, runConfig: data as RunConfiguration })); - setRunConfiguration(data as RunConfiguration); + setRunConfig(data as RunConfiguration); }; dispatcher.addActionListener(actions.SET_THEME, handleSetTheme); diff --git a/src/components/common/ImpactScore/index.tsx b/src/components/common/ImpactScore/index.tsx index a8a89e554..09669e90e 100644 --- a/src/components/common/ImpactScore/index.tsx +++ b/src/components/common/ImpactScore/index.tsx @@ -1,5 +1,5 @@ -import { useGlobalStore } from "../../../containers/Main/stores/useGlobalStore"; import { getFeatureFlagValue } from "../../../featureFlags"; +import { useConfigSelector } from "../../../store/config/useConfigSelector"; import { FeatureFlag } from "../../../types"; import { BackendInfo } from "../App/types"; import { ScoreIndicator } from "../ScoreIndicator"; @@ -52,7 +52,7 @@ export const ImpactScore = ({ showIndicator, indicatorPosition }: ImpactScoreProps) => { - const backendInfo = useGlobalStore.use.backendInfo(); + const { backendInfo } = useConfigSelector(); let scoreIndicatorPosition: "start" | "end" | undefined; diff --git a/src/containers/Main/stores/createSelectors.ts b/src/containers/Main/stores/createSelectors.ts deleted file mode 100644 index 8bd74c626..000000000 --- a/src/containers/Main/stores/createSelectors.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { StoreApi, UseBoundStore } from "zustand"; - -type WithSelectors = S extends { getState: () => infer T } - ? S & { use: { [K in keyof T]: () => T[K] } } - : never; - -export const createSelectors = >>( - _store: S -) => { - const store = _store as WithSelectors; - store.use = {}; - for (const k of Object.keys(store.getState())) { - (store.use as Record)[k] = () => - store((s) => s[k as keyof typeof s]); - } - - return store; -}; diff --git a/src/containers/Main/stores/useGlobalStore.ts b/src/containers/Main/stores/useGlobalStore.ts deleted file mode 100644 index 0b73796ab..000000000 --- a/src/containers/Main/stores/useGlobalStore.ts +++ /dev/null @@ -1,166 +0,0 @@ -import { create } from "zustand"; -import { - BackendInfo, - DigmaStatus, - Environment, - InsightStats, - PersistedState, - RunConfiguration, - Scope, - UserInfo -} from "../../../components/common/App/types"; -import { isBoolean } from "../../../typeGuards/isBoolean"; -import { isEnvironment } from "../../../typeGuards/isEnvironment"; -import { isString } from "../../../typeGuards/isString"; -import { createSelectors } from "./createSelectors"; - -export interface GlobalState { - digmaApiUrl: string | null; - digmaApiProxyPrefix: string | null; - digmaStatus: DigmaStatus | null; - isDigmaEngineInstalled: boolean | null; - isDigmaEngineRunning: boolean | null; - isDockerInstalled: boolean | null; - isDockerComposeInstalled: boolean | null; - backendInfo: BackendInfo | null; - jaegerURL: string | null; - isJaegerEnabled: boolean | null; - isMicrometerProject: boolean | null; - runConfig: RunConfiguration | null; - isObservabilityEnabled: boolean | null; - productKey: string | null; - isDigmathonModeEnabled: boolean | null; - isDigmathonGameFinished: boolean | null; - environment: Environment | null; - environments: Environment[] | null; - scope: Scope | null; - insightStats: InsightStats | null; - userId: string | null; - userInfo: UserInfo | null; - userEmail: string | null; - userRegistrationEmail: string | null; - persistedState: PersistedState | null; - selectedServices: string[] | null; -} - -export const initialState: GlobalState = { - digmaApiUrl: isString(window.digmaApiUrl) ? window.digmaApiUrl : null, - digmaApiProxyPrefix: isString(window.digmaApiProxyPrefix) - ? window.digmaApiProxyPrefix - : null, - digmaStatus: null, - isDigmaEngineInstalled: isBoolean(window.isObservabilityEnabled) - ? window.isObservabilityEnabled - : null, - isDigmaEngineRunning: isBoolean(window.isDigmaEngineRunning) - ? window.isDigmaEngineRunning - : null, - isDockerInstalled: isBoolean(window.isDockerInstalled) - ? window.isDockerInstalled - : null, - isDockerComposeInstalled: isBoolean(window.isDockerComposeInstalled) - ? window.isDockerComposeInstalled - : null, - backendInfo: null, - jaegerURL: isString(window.jaegerURL) ? window.jaegerURL : null, - isJaegerEnabled: isBoolean(window.isJaegerEnabled) - ? window.isJaegerEnabled - : null, - isMicrometerProject: isBoolean(window.isMicrometerProject) - ? window.isMicrometerProject - : null, - runConfig: null, - isObservabilityEnabled: isBoolean(window.isObservabilityEnabled) - ? window.isObservabilityEnabled - : null, - productKey: isString(window.productKey) ? window.productKey : null, - isDigmathonModeEnabled: isBoolean(window.isDigmathonModeEnabled) - ? window.isDigmathonModeEnabled - : null, - isDigmathonGameFinished: isBoolean(window.isDigmathonGameFinished) - ? window.isDigmathonGameFinished - : null, - environment: isEnvironment(window.environment) ? window.environment : null, - environments: null, - scope: null, - insightStats: null, - userId: isString(window.userId) ? window.userId : null, - userInfo: null, - userEmail: isString(window.userEmail) ? window.userEmail : null, - userRegistrationEmail: isString(window.userRegistrationEmail) - ? window.userRegistrationEmail - : null, - selectedServices: null, - persistedState: null -}; - -export interface GlobalActions { - setDigmaApiUrl: (url: string) => void; - setDigmaApiProxyPrefix: (prefix: string) => void; - setDigmaStatus: (status: DigmaStatus) => void; - setIsDigmaEngineInstalled: (isInstalled: boolean) => void; - setIsDigmaEngineRunning: (isRunning: boolean) => void; - setIsDockerInstalled: (isInstalled: boolean) => void; - setIsDockerComposeInstalled: (isInstalled: boolean) => void; - setBackendInfo: (info: BackendInfo) => void; - setJaegerURL: (url: string) => void; - setIsJaegerEnabled: (isEnabled: boolean) => void; - setIsMicrometerProject: (isMicrometer: boolean) => void; - setRunConfig: (config: RunConfiguration) => void; - setIsObservabilityEnabled: (isEnabled: boolean) => void; - setProductKey: (key: string) => void; - setIsDigmathonModeEnabled: (isEnabled: boolean) => void; - setIsDigmathonGameFinished: (isFinished: boolean) => void; - setEnvironment: (environment: Environment | null) => void; - setEnvironments: (environments: Environment[]) => void; - setScope: (scope: Scope) => void; - setInsightStats: (stats: InsightStats) => void; - setUserId: (userId: string) => void; - setUserInfo: (userInfo: UserInfo) => void; - setUserEmail: (email: string) => void; - setUserRegistrationEmail: (email: string) => void; - setPersistedState: (state: PersistedState) => void; - setSelectedServices: (services: string[]) => void; - reset: () => void; -} - -export const useGlobalStore = createSelectors( - create()((set) => ({ - ...initialState, - setDigmaApiUrl: (url) => set({ digmaApiUrl: url }), - setDigmaApiProxyPrefix: (prefix) => set({ digmaApiProxyPrefix: prefix }), - setDigmaStatus: (status) => set({ digmaStatus: status }), - setIsDigmaEngineInstalled: (isInstalled) => - set({ isDigmaEngineInstalled: isInstalled }), - setIsDigmaEngineRunning: (isRunning) => - set({ isDigmaEngineRunning: isRunning }), - setIsDockerInstalled: (isInstalled) => - set({ isDockerInstalled: isInstalled }), - setIsDockerComposeInstalled: (isInstalled) => - set({ isDockerComposeInstalled: isInstalled }), - setBackendInfo: (info) => set({ backendInfo: info }), - setJaegerURL: (url) => set({ jaegerURL: url }), - setIsJaegerEnabled: (isEnabled) => set({ isJaegerEnabled: isEnabled }), - setIsMicrometerProject: (isMicrometer) => - set({ isMicrometerProject: isMicrometer }), - setRunConfig: (config) => set({ runConfig: config }), - setIsObservabilityEnabled: (isEnabled) => - set({ isObservabilityEnabled: isEnabled }), - setProductKey: (key) => set({ productKey: key }), - setIsDigmathonModeEnabled: (isEnabled) => - set({ isDigmathonModeEnabled: isEnabled }), - setIsDigmathonGameFinished: (isFinished) => - set({ isDigmathonGameFinished: isFinished }), - setEnvironment: (environment) => set({ environment }), - setEnvironments: (environments) => set({ environments }), - setScope: (scope) => set({ scope }), - setInsightStats: (stats) => set({ insightStats: stats }), - setUserId: (userId) => set({ userId }), - setUserInfo: (userInfo) => set({ userInfo }), - setUserEmail: (email) => set({ userEmail: email }), - setUserRegistrationEmail: (email) => set({ userRegistrationEmail: email }), - setPersistedState: (state) => set({ persistedState: state }), - setSelectedServices: (services) => set({ selectedServices: services }), - reset: () => set(initialState) - })) -); diff --git a/src/containers/Main/stores/useInsightsStore.ts b/src/containers/Main/stores/useInsightsStore.ts deleted file mode 100644 index 63cb210e5..000000000 --- a/src/containers/Main/stores/useInsightsStore.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { create } from "zustand"; -import { - Sorting, - SORTING_ORDER -} from "../../../components/common/SortingSelector/types"; -import { - InsightFilterType, - SORTING_CRITERION, - ViewMode -} from "../../../components/Insights/InsightsCatalog/types"; -import { IssuesFiltersData } from "../../../components/Insights/Issues/IssuesFilter/types"; -import { - InsightsData, - InsightViewType -} from "../../../components/Insights/types"; -import { createSelectors } from "./createSelectors"; - -export interface InsightsState { - data: InsightsData | null; - isDataLoading: boolean; - search: string; - page: number; - sorting: Sorting; - viewMode: ViewMode; - filters: InsightFilterType[]; - filteredInsightTypes: string[]; - insightViewType: InsightViewType | null; - issuesFilters: IssuesFiltersData | null; - areIssuesFiltersLoading: boolean; -} - -export const initialState: InsightsState = { - data: null, - isDataLoading: false, - search: "", - page: 0, - sorting: { - criterion: SORTING_CRITERION.CRITICAL_INSIGHTS, - order: SORTING_ORDER.DESC - }, - viewMode: ViewMode.All, - filters: [], - filteredInsightTypes: [], - insightViewType: null, - issuesFilters: null, - areIssuesFiltersLoading: false -}; - -export interface InsightsActions { - setData: (data: InsightsData) => void; - setIsDataLoading: (isDataLoading: boolean) => void; - setSearch: (search: string) => void; - setPage: (page: number) => void; - setSorting: (sorting: Sorting) => void; - setViewMode: (viewMode: ViewMode) => void; - setFilters: (filters: InsightFilterType[]) => void; - setFilteredInsightTypes: (insightTypes: string[]) => void; - setInsightViewType: (insightViewType: InsightViewType) => void; - setIssuesFilters: (filters: IssuesFiltersData) => void; - setAreIssuesFiltersLoading: (areIssuesFiltersLoading: boolean) => void; - reset: () => void; -} - -export const useInsightsStore = createSelectors( - create()((set) => ({ - ...initialState, - setData: (data) => set({ data }), - setIsDataLoading: (isDataLoading) => set({ isDataLoading }), - setSearch: (search) => set({ search }), - setPage: (page) => set({ page }), - setSorting: (sorting) => set({ sorting }), - setViewMode: (viewMode) => set({ viewMode }), - setFilters: (filters) => set({ filters }), - setFilteredInsightTypes: (filteredInsightTypes) => - set({ filteredInsightTypes }), - setInsightViewType: (insightViewType) => set({ insightViewType }), - setIssuesFilters: (issuesFilters) => set({ issuesFilters }), - setAreIssuesFiltersLoading: (areIssuesFiltersLoading) => - set({ areIssuesFiltersLoading }), - reset: () => set(initialState) - })) -); diff --git a/src/store/config/configSlice.ts b/src/store/config/configSlice.ts new file mode 100644 index 000000000..c6b157708 --- /dev/null +++ b/src/store/config/configSlice.ts @@ -0,0 +1,144 @@ +import { createSlice } from "zustand-slices"; +import { + BackendInfo, + DigmaStatus, + Environment, + InsightStats, + PersistedState, + RunConfiguration, + Scope, + UserInfo +} from "../../components/common/App/types"; +import { isBoolean } from "../../typeGuards/isBoolean"; +import { isEnvironment } from "../../typeGuards/isEnvironment"; +import { isString } from "../../typeGuards/isString"; + +export interface ConfigState { + digmaApiUrl: string | null; + digmaApiProxyPrefix: string | null; + digmaStatus: DigmaStatus | null; + isDigmaEngineInstalled: boolean | null; + isDigmaEngineRunning: boolean | null; + isDockerInstalled: boolean | null; + isDockerComposeInstalled: boolean | null; + backendInfo: BackendInfo | null; + jaegerURL: string | null; + isJaegerEnabled: boolean | null; + isMicrometerProject: boolean | null; + runConfig: RunConfiguration | null; + isObservabilityEnabled: boolean | null; + productKey: string | null; + isDigmathonModeEnabled: boolean | null; + isDigmathonGameFinished: boolean | null; + environment: Environment | null; + environments: Environment[] | null; + insightStats: InsightStats | null; + userId: string | null; + userInfo: UserInfo | null; + userEmail: string | null; + userRegistrationEmail: string | null; + persistedState: PersistedState | null; + selectedServices: string[] | null; + scope: Scope | null; +} + +const initialState: ConfigState = { + digmaApiUrl: isString(window.digmaApiUrl) ? window.digmaApiUrl : null, + digmaApiProxyPrefix: isString(window.digmaApiProxyPrefix) + ? window.digmaApiProxyPrefix + : null, + digmaStatus: null, + isDigmaEngineInstalled: isBoolean(window.isObservabilityEnabled) + ? window.isObservabilityEnabled + : null, + isDigmaEngineRunning: isBoolean(window.isDigmaEngineRunning) + ? window.isDigmaEngineRunning + : null, + isDockerInstalled: isBoolean(window.isDockerInstalled) + ? window.isDockerInstalled + : null, + isDockerComposeInstalled: isBoolean(window.isDockerComposeInstalled) + ? window.isDockerComposeInstalled + : null, + backendInfo: null, + jaegerURL: isString(window.jaegerURL) ? window.jaegerURL : null, + isJaegerEnabled: isBoolean(window.isJaegerEnabled) + ? window.isJaegerEnabled + : null, + isMicrometerProject: isBoolean(window.isMicrometerProject) + ? window.isMicrometerProject + : null, + runConfig: null, + isObservabilityEnabled: isBoolean(window.isObservabilityEnabled) + ? window.isObservabilityEnabled + : null, + productKey: isString(window.productKey) ? window.productKey : null, + isDigmathonModeEnabled: isBoolean(window.isDigmathonModeEnabled) + ? window.isDigmathonModeEnabled + : null, + isDigmathonGameFinished: isBoolean(window.isDigmathonGameFinished) + ? window.isDigmathonGameFinished + : null, + environment: isEnvironment(window.environment) ? window.environment : null, + environments: null, + insightStats: null, + userId: isString(window.userId) ? window.userId : null, + userInfo: null, + userEmail: isString(window.userEmail) ? window.userEmail : null, + userRegistrationEmail: isString(window.userRegistrationEmail) + ? window.userRegistrationEmail + : null, + selectedServices: null, + persistedState: null, + scope: null +}; + +const set = (update: Partial) => (state: ConfigState) => ({ + ...state, + ...update +}); + +export const configSlice = createSlice({ + name: "config", + value: initialState, + actions: { + setDigmaApiUrl: (url: string) => set({ digmaApiUrl: url }), + setDigmaApiProxyPrefix: (prefix: string) => + set({ digmaApiProxyPrefix: prefix }), + setDigmaStatus: (status: DigmaStatus) => set({ digmaStatus: status }), + setIsDigmaEngineInstalled: (isInstalled: boolean) => + set({ isDigmaEngineInstalled: isInstalled }), + setIsDigmaEngineRunning: (isRunning: boolean) => + set({ isDigmaEngineRunning: isRunning }), + setIsDockerInstalled: (isInstalled: boolean) => + set({ isDockerInstalled: isInstalled }), + setIsDockerComposeInstalled: (isInstalled: boolean) => + set({ isDockerComposeInstalled: isInstalled }), + setBackendInfo: (info: BackendInfo) => set({ backendInfo: info }), + setJaegerURL: (url: string) => set({ jaegerURL: url }), + setIsJaegerEnabled: (isEnabled: boolean) => + set({ isJaegerEnabled: isEnabled }), + setIsMicrometerProject: (isMicrometer: boolean) => + set({ isMicrometerProject: isMicrometer }), + setRunConfig: (config: RunConfiguration) => set({ runConfig: config }), + setIsObservabilityEnabled: (isEnabled: boolean) => + set({ isObservabilityEnabled: isEnabled }), + setProductKey: (key: string) => set({ productKey: key }), + setIsDigmathonModeEnabled: (isEnabled: boolean) => + set({ isDigmathonModeEnabled: isEnabled }), + setIsDigmathonGameFinished: (isFinished: boolean) => + set({ isDigmathonGameFinished: isFinished }), + setEnvironment: (environment: Environment | null) => set({ environment }), + setEnvironments: (environments: Environment[]) => set({ environments }), + setInsightStats: (stats: InsightStats) => set({ insightStats: stats }), + setUserId: (userId: string) => set({ userId }), + setUserInfo: (userInfo: UserInfo) => set({ userInfo }), + setUserEmail: (email) => set({ userEmail: email }), + setUserRegistrationEmail: (email: string) => + set({ userRegistrationEmail: email }), + setPersistedState: (state: PersistedState) => + set({ persistedState: state }), + setSelectedServices: (services: string[]) => + set({ selectedServices: services }) + } +}); diff --git a/src/store/config/useConfigSelector.ts b/src/store/config/useConfigSelector.ts new file mode 100644 index 000000000..f79e3ab64 --- /dev/null +++ b/src/store/config/useConfigSelector.ts @@ -0,0 +1,5 @@ +import { useStore } from "../useStore"; + +export const useConfigSelector = () => { + return useStore((state) => state.config); +}; diff --git a/src/store/insights/insightsSlice.ts b/src/store/insights/insightsSlice.ts new file mode 100644 index 000000000..1394fda06 --- /dev/null +++ b/src/store/insights/insightsSlice.ts @@ -0,0 +1,71 @@ +import { createSlice } from "zustand-slices"; +import { + Sorting, + SORTING_ORDER +} from "../../components/common/SortingSelector/types"; +import { + InsightFilterType, + SORTING_CRITERION, + ViewMode +} from "../../components/Insights/InsightsCatalog/types"; +import { IssuesFiltersData } from "../../components/Insights/Issues/IssuesFilter/types"; +import { InsightsData, InsightViewType } from "../../components/Insights/types"; + +interface InsightsState { + data: InsightsData | null; + isDataLoading: boolean; + search: string; + page: number; + sorting: Sorting; + viewMode: ViewMode; + filters: InsightFilterType[]; + filteredInsightTypes: string[]; + insightViewType: InsightViewType | null; + issuesFilters: IssuesFiltersData | null; + areIssuesFiltersLoading: boolean; +} + +const initialState: InsightsState = { + data: null, + isDataLoading: false, + search: "", + page: 0, + sorting: { + criterion: SORTING_CRITERION.CRITICAL_INSIGHTS, + order: SORTING_ORDER.DESC + }, + viewMode: ViewMode.All, + filters: [], + filteredInsightTypes: [], + insightViewType: null, + issuesFilters: null, + areIssuesFiltersLoading: false +}; + +const set = (update: Partial) => (state: InsightsState) => ({ + ...state, + ...update +}); + +export const insightsSlice = createSlice({ + name: "insights", + value: initialState, + actions: { + setData: (data: InsightsData) => set({ data }), + setIsDataLoading: (isDataLoading: boolean) => set({ isDataLoading }), + setSearch: (search: string) => set({ search }), + setPage: (page: number) => set({ page }), + setSorting: (sorting: Sorting) => set({ sorting }), + setViewMode: (viewMode: ViewMode) => set({ viewMode }), + setFilters: (filters: InsightFilterType[]) => set({ filters }), + setFilteredInsightTypes: (filteredInsightTypes: string[]) => + set({ filteredInsightTypes }), + setInsightViewType: (insightViewType: InsightViewType) => + set({ insightViewType }), + setIssuesFilters: (issuesFilters: IssuesFiltersData) => + set({ issuesFilters }), + setAreIssuesFiltersLoading: (areIssuesFiltersLoading: boolean) => + set({ areIssuesFiltersLoading }), + insightsReset: () => set(initialState) + } +}); diff --git a/src/store/insights/useInsightsSelector.ts b/src/store/insights/useInsightsSelector.ts new file mode 100644 index 000000000..2b9f28653 --- /dev/null +++ b/src/store/insights/useInsightsSelector.ts @@ -0,0 +1,3 @@ +import { useStore } from "../useStore"; + +export const useInsightsSelector = () => useStore((state) => state.insights); diff --git a/src/store/useStore.ts b/src/store/useStore.ts new file mode 100644 index 000000000..827bee2ba --- /dev/null +++ b/src/store/useStore.ts @@ -0,0 +1,23 @@ +import { create } from "zustand"; +import { withSlices } from "zustand-slices"; +import { Scope } from "../components/common/App/types"; +import { configSlice } from "./config/configSlice"; +import { insightsSlice } from "./insights/insightsSlice"; +import { withMutableActions } from "./withMutableActions"; + +export const useStore = create( + withMutableActions(withSlices(configSlice, insightsSlice), { + setScope: (scope: Scope) => (_, set) => { + set((state) => + state.config.scope?.span?.spanCodeObjectId !== + scope.span?.spanCodeObjectId + ? { + ...state, + config: { ...state.config, scope }, + insights: { ...state.insights, page: 0, search: "" } + } + : state + ); + } + }) +); diff --git a/src/store/withMutableActions.ts b/src/store/withMutableActions.ts new file mode 100644 index 000000000..8082881f4 --- /dev/null +++ b/src/store/withMutableActions.ts @@ -0,0 +1,63 @@ +// Inspired by: https://github.com/zustandjs/zustand-slices/blob/main/src/with-actions.ts + +type InferStateActions = Actions extends Record< + string, + (...args: never[]) => unknown +> + ? { + [actionName in keyof Actions]: ( + ...args: Parameters + ) => void; + } + : unknown; + +type IsValidActions = Extract< + keyof Actions, + keyof State +> extends never + ? Actions + : never; + +export function withMutableActions< + State, + Actions extends Record< + string, + ( + ...args: never[] + ) => ( + state: State, + set: ( + fn: ( + prevState: State & InferStateActions + ) => Partial> + ) => void + ) => void + > +>( + config: (set: (fn: (prevState: State) => Partial) => void) => State, + actions: IsValidActions +): ( + set: ( + fn: ( + prevState: State & InferStateActions + ) => Partial> + ) => void, + get: () => State & InferStateActions +) => State & InferStateActions { + return (( + set: ( + fn: ( + prevState: State & InferStateActions + ) => Partial> + ) => void, + get: () => State & InferStateActions + ) => { + const state: Record = config(set as never) as never; + for (const [actionName, actionFn] of Object.entries(actions)) { + state[actionName] = (...args: unknown[]) => { + actionFn(...(args as never[]))(get(), set); + }; + } + return state; + }) as never; +}