diff --git a/cmd/ui/src/App.tsx b/cmd/ui/src/App.tsx index 2204c716b7..e29a8ed54b 100644 --- a/cmd/ui/src/App.tsx +++ b/cmd/ui/src/App.tsx @@ -18,14 +18,13 @@ import { Box } from '@mui/material'; import makeStyles from '@mui/styles/makeStyles'; import React, { useEffect } from 'react'; import { useQueryClient } from 'react-query'; -import { useSelector } from 'react-redux'; import { useLocation } from 'react-router-dom'; import { AppNotifications } from 'bh-shared-ui'; import Notifier from 'src/components/Notifier'; import { initialize } from 'src/ducks/auth/authSlice'; import { ROUTE_EXPIRED_PASSWORD, ROUTE_LOGIN, ROUTE_USER_DISABLED } from 'src/ducks/global/routes'; import { featureFlagKeys, getFeatureFlags } from 'src/hooks/useFeatureFlags'; -import { AppState, useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; import { initializeBHEClient } from 'src/utils'; import Content from 'src/views/Content'; import Header from 'src/components/Header'; @@ -51,7 +50,7 @@ const useStyles = makeStyles((theme) => ({ const App: React.FC = () => { const classes = useStyles(); - const authState = useSelector((state: AppState) => state.auth); + const authState = useAppSelector((state) => state.auth); const queryClient = useQueryClient(); const dispatch = useAppDispatch(); const location = useLocation(); diff --git a/cmd/ui/src/components/AuthenticatedRoute/AuthenticatedRoute.tsx b/cmd/ui/src/components/AuthenticatedRoute/AuthenticatedRoute.tsx index c4e1c5f56c..a2542e782c 100644 --- a/cmd/ui/src/components/AuthenticatedRoute/AuthenticatedRoute.tsx +++ b/cmd/ui/src/components/AuthenticatedRoute/AuthenticatedRoute.tsx @@ -14,15 +14,14 @@ // // SPDX-License-Identifier: Apache-2.0 -import { useSelector } from 'react-redux'; import { Navigate, useLocation } from 'react-router-dom'; import { authExpiredSelector } from 'src/ducks/auth/authSlice'; import { ROUTE_EXPIRED_PASSWORD, ROUTE_LOGIN } from 'src/ducks/global/routes'; -import { AppState } from 'src/store'; +import { useAppSelector } from 'src/store'; const AuthenticatedRoute: React.FC<{ children: any }> = ({ children }): React.ReactElement => { - const authState = useSelector((state: AppState) => state.auth); - const isAuthExpired = useSelector(authExpiredSelector); + const authState = useAppSelector((state) => state.auth); + const isAuthExpired = useAppSelector(authExpiredSelector); const location = useLocation(); // If user is not authenticated, redirect to login screen diff --git a/cmd/ui/src/components/GraphButtons/GraphButtons.tsx b/cmd/ui/src/components/GraphButtons/GraphButtons.tsx index 8a0ce3b0fb..8f6f435025 100644 --- a/cmd/ui/src/components/GraphButtons/GraphButtons.tsx +++ b/cmd/ui/src/components/GraphButtons/GraphButtons.tsx @@ -23,10 +23,9 @@ import { random } from 'graphology-layout'; import forceAtlas2 from 'graphology-layout-forceatlas2'; import isEmpty from 'lodash/isEmpty'; import { FC } from 'react'; -import { useSelector } from 'react-redux'; import { resetCamera } from 'src/ducks/graph/utils'; import { RankDirection, layoutDagre } from 'src/hooks/useLayoutDagre/useLayoutDagre'; -import { AppState } from 'src/store'; +import { useAppSelector } from 'src/store'; interface GraphButtonsProps { rankDirection?: RankDirection; @@ -43,7 +42,7 @@ const GraphButtons: FC = ({ rankDirection, options, nonLayout if (isEmpty(options)) options = { standard: false, sequential: false }; const { standard, sequential } = options; - const exportableGraphState = useSelector((state: AppState) => state.explore.export); + const exportableGraphState = useAppSelector((state) => state.explore.export); const sigma = useSigma(); const graph = sigma.getGraph(); diff --git a/cmd/ui/src/components/GraphEdgeEvents.tsx b/cmd/ui/src/components/GraphEdgeEvents.tsx index 66c9539bb8..95878864a0 100644 --- a/cmd/ui/src/components/GraphEdgeEvents.tsx +++ b/cmd/ui/src/components/GraphEdgeEvents.tsx @@ -17,7 +17,6 @@ import { useSigma } from '@react-sigma/core'; import { setEdgeInfoOpen, setSelectedEdge } from 'bh-shared-ui'; import { FC, useCallback } from 'react'; -import { useSelector } from 'react-redux'; import { setEntityInfoOpen } from 'src/ducks/entityinfo/actions'; import { calculateEdgeDistanceForLabel, @@ -26,11 +25,11 @@ import { getEdgeSourceAndTargetDisplayData, } from 'src/ducks/graph/utils'; import { bezier } from 'src/rendering/utils/bezier'; -import { AppState, useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; const GraphEdgeEvents: FC = () => { const dispatch = useAppDispatch(); - const graphState = useSelector((state: AppState) => state.explore); + const graphState = useAppSelector((state) => state.explore); const sigma = useSigma(); const camera = sigma.getCamera(); diff --git a/cmd/ui/src/components/GraphEvents.tsx b/cmd/ui/src/components/GraphEvents.tsx index 42c83de8e8..33df851c9e 100644 --- a/cmd/ui/src/components/GraphEvents.tsx +++ b/cmd/ui/src/components/GraphEvents.tsx @@ -18,11 +18,10 @@ import { useRegisterEvents, useSetSettings, useSigma } from '@react-sigma/core'; import { setSelectedEdge } from 'bh-shared-ui'; import { AbstractGraph, Attributes } from 'graphology-types'; import { FC, useEffect, useRef, useState } from 'react'; -import { useSelector } from 'react-redux'; import { SigmaNodeEventPayload } from 'sigma/sigma'; import { getEdgeDataFromKey, getEdgeSourceAndTargetDisplayData, resetCamera } from 'src/ducks/graph/utils'; import { bezier } from 'src/rendering/utils/bezier'; -import { AppState, useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; export interface GraphEventProps { onDoubleClickNode?: (id: string) => void; @@ -42,8 +41,8 @@ export const GraphEvents: FC = ({ edgeReducer, }) => { const dispatch = useAppDispatch(); - const selectedEdge = useSelector((state: AppState) => state.edgeinfo.selectedEdge); - const selectedNode = useSelector((state: AppState) => state.entityinfo.selectedNode); + const selectedEdge = useAppSelector((state) => state.edgeinfo.selectedEdge); + const selectedNode = useAppSelector((state) => state.entityinfo.selectedNode); const sigma = useSigma(); const registerEvents = useRegisterEvents(); diff --git a/cmd/ui/src/components/Notifier.tsx b/cmd/ui/src/components/Notifier.tsx index 871a522272..cac3da1ed1 100644 --- a/cmd/ui/src/components/Notifier.tsx +++ b/cmd/ui/src/components/Notifier.tsx @@ -19,9 +19,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { IconButton, SvgIcon } from '@mui/material'; import { useSnackbar } from 'notistack'; import React, { useCallback, useEffect } from 'react'; -import { useSelector } from 'react-redux'; import { removeSnackbar } from 'src/ducks/global/actions'; -import { AppState, useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; let displayed: string[] = []; @@ -30,7 +29,7 @@ const Notifier: React.FC = () => { const { enqueueSnackbar, closeSnackbar } = useSnackbar(); - const notifications = useSelector((state: AppState) => state.global.view.notifications); + const notifications = useAppSelector((state) => state.global.view.notifications); const storeDisplayed = (id: string) => { displayed = [...displayed, id]; diff --git a/cmd/ui/src/store.ts b/cmd/ui/src/store.ts index 2d307865f9..e3c0ef230d 100644 --- a/cmd/ui/src/store.ts +++ b/cmd/ui/src/store.ts @@ -18,7 +18,7 @@ import { combineReducers, configureStore } from '@reduxjs/toolkit'; import { enableMapSet } from 'immer'; import Cookies from 'js-cookie'; import throttle from 'lodash/throttle'; -import { useDispatch } from 'react-redux'; +import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; import createSagaMiddleware from 'redux-saga'; import * as reducers from 'src/ducks'; import { edgeinfo } from 'bh-shared-ui'; @@ -94,6 +94,7 @@ store.subscribe( ); export type AppState = ReturnType; +export const useAppSelector: TypedUseSelectorHook = useSelector export type AppDispatch = typeof store.dispatch; export const useAppDispatch = () => useDispatch(); diff --git a/cmd/ui/src/views/Content.tsx b/cmd/ui/src/views/Content.tsx index cd8eb90a75..353b17a7df 100644 --- a/cmd/ui/src/views/Content.tsx +++ b/cmd/ui/src/views/Content.tsx @@ -18,14 +18,13 @@ import { Box, CircularProgress } from '@mui/material'; import makeStyles from '@mui/styles/makeStyles'; import React, { Suspense, useEffect } from 'react'; import { ErrorBoundary } from 'react-error-boundary'; -import { useSelector } from 'react-redux'; import { Route, Routes } from 'react-router-dom'; import { GenericErrorBoundaryFallback, apiClient } from 'bh-shared-ui'; import { ListAssetGroups } from 'src/ducks/assetgroups/actionCreators'; import { fullyAuthenticatedSelector } from 'src/ducks/auth/authSlice'; import { fetchAssetGroups, setDomain } from 'src/ducks/global/actions'; import * as routes from 'src/ducks/global/routes'; -import { useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; import AuthenticatedRoute from 'src/components/AuthenticatedRoute'; const Login = React.lazy(() => import('src/views/Login')); @@ -52,8 +51,8 @@ const useStyles = makeStyles({ const Content: React.FC = () => { const classes = useStyles(); const dispatch = useAppDispatch(); - const authState = useSelector((state: any) => state.auth); - const isFullyAuthenticated = useSelector(fullyAuthenticatedSelector); + const authState = useAppSelector((state) => state.auth); + const isFullyAuthenticated = useAppSelector(fullyAuthenticatedSelector); useEffect(() => { if (isFullyAuthenticated) { diff --git a/cmd/ui/src/views/ExpiredPassword.tsx b/cmd/ui/src/views/ExpiredPassword.tsx index 192fc68683..4a4f3a5ffa 100644 --- a/cmd/ui/src/views/ExpiredPassword.tsx +++ b/cmd/ui/src/views/ExpiredPassword.tsx @@ -15,19 +15,19 @@ // SPDX-License-Identifier: Apache-2.0 import React from 'react'; -import { useSelector } from 'react-redux'; + import { Navigate } from 'react-router-dom'; import { authExpiredSelector, logout, updateExpiredPassword } from 'src/ducks/auth/authSlice'; import LoginPage from 'src/components/LoginPage'; import PasswordResetForm from 'src/components/PasswordResetForm'; import { ROUTE_HOME } from 'src/ducks/global/routes'; -import { AppState, useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; const PasswordReset: React.FC = () => { /* Hooks */ const dispatch = useAppDispatch(); - const authState = useSelector((state: AppState) => state.auth); - const authExpired = useSelector(authExpiredSelector); + const authState = useAppSelector((state) => state.auth); + const authExpired = useAppSelector(authExpiredSelector); /* Event Handlers */ const handleSubmit = (password: string) => { diff --git a/cmd/ui/src/views/Explore/ContextMenu/AssetGroupMenuItem.tsx b/cmd/ui/src/views/Explore/ContextMenu/AssetGroupMenuItem.tsx index b954403692..dac4376c08 100644 --- a/cmd/ui/src/views/Explore/ContextMenu/AssetGroupMenuItem.tsx +++ b/cmd/ui/src/views/Explore/ContextMenu/AssetGroupMenuItem.tsx @@ -18,10 +18,9 @@ import { Button, Dialog, DialogActions, DialogContent, DialogTitle, MenuItem } f import { apiClient, useNotifications } from 'bh-shared-ui'; import { FC, useState } from 'react'; import { useMutation, useQuery } from 'react-query'; -import { useSelector } from 'react-redux'; import { selectTierZeroAssetGroupId } from 'src/ducks/assetgroups/reducer'; import { toggleTierZeroNode } from 'src/ducks/explore/actions'; -import { AppState, useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; const AssetGroupMenuItem: FC<{ assetGroupId: string; assetGroupName: string }> = ({ assetGroupId, assetGroupName }) => { const { addNotification } = useNotifications(); @@ -29,8 +28,8 @@ const AssetGroupMenuItem: FC<{ assetGroupId: string; assetGroupName: string }> = const [open, setOpen] = useState(false); - const selectedNode = useSelector((state: AppState) => state.entityinfo.selectedNode); - const tierZeroAssetGroupId = useSelector(selectTierZeroAssetGroupId); + const selectedNode = useAppSelector((state) => state.entityinfo.selectedNode); + const tierZeroAssetGroupId = useAppSelector(selectTierZeroAssetGroupId); const isMenuItemForTierZero = assetGroupId === tierZeroAssetGroupId; diff --git a/cmd/ui/src/views/Explore/ContextMenu/ContextMenu.tsx b/cmd/ui/src/views/Explore/ContextMenu/ContextMenu.tsx index 461f04715a..422031863a 100644 --- a/cmd/ui/src/views/Explore/ContextMenu/ContextMenu.tsx +++ b/cmd/ui/src/views/Explore/ContextMenu/ContextMenu.tsx @@ -17,9 +17,8 @@ import { Menu, MenuItem } from '@mui/material'; import { FC } from 'react'; -import { useSelector } from 'react-redux'; import { destinationNodeSelected, sourceNodeSelected, tabChanged } from 'src/ducks/searchbar/actions'; -import { AppState, useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; import { selectOwnedAssetGroupId, selectTierZeroAssetGroupId } from 'src/ducks/assetgroups/reducer'; import AssetGroupMenuItem from './AssetGroupMenuItem'; import CopyMenuItem from './CopyMenuItem'; @@ -30,10 +29,10 @@ const ContextMenu: FC<{ contextMenu: { mouseX: number; mouseY: number } | null; }) => { const dispatch = useAppDispatch(); - const selectedNode = useSelector((state: AppState) => state.entityinfo.selectedNode); + const selectedNode = useAppSelector((state) => state.entityinfo.selectedNode); - const ownedAssetGroupId = useSelector(selectOwnedAssetGroupId); - const tierZeroAssetGroupId = useSelector(selectTierZeroAssetGroupId); + const ownedAssetGroupId = useAppSelector(selectOwnedAssetGroupId); + const tierZeroAssetGroupId = useAppSelector(selectTierZeroAssetGroupId); const handleSetStartingNode = () => { if (selectedNode) { diff --git a/cmd/ui/src/views/Explore/ContextMenu/CopyMenuItem.tsx b/cmd/ui/src/views/Explore/ContextMenu/CopyMenuItem.tsx index 2d47dddb61..4d964d0c86 100644 --- a/cmd/ui/src/views/Explore/ContextMenu/CopyMenuItem.tsx +++ b/cmd/ui/src/views/Explore/ContextMenu/CopyMenuItem.tsx @@ -18,8 +18,7 @@ import { faCaretRight } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { MenuItem, Tooltip, TooltipProps, styled, tooltipClasses } from '@mui/material'; import { useNotifications } from 'bh-shared-ui'; -import { useSelector } from 'react-redux'; -import { AppState } from 'src/store'; +import { useAppSelector } from 'src/store'; const StyledTooltip = styled(({ className, ...props }: TooltipProps) => ( @@ -38,7 +37,7 @@ const StyledTooltip = styled(({ className, ...props }: TooltipProps) => ( const CopyMenuItem = () => { const { addNotification } = useNotifications(); - const selectedNode = useSelector((state: AppState) => state.entityinfo.selectedNode); + const selectedNode = useAppSelector((state) => state.entityinfo.selectedNode); const handleCopyDisplayName = () => { if (selectedNode) { diff --git a/cmd/ui/src/views/Explore/EdgeInfo/EdgeInfoCollapsibleSection.tsx b/cmd/ui/src/views/Explore/EdgeInfo/EdgeInfoCollapsibleSection.tsx index 7cc03e3db3..63d0b3c173 100644 --- a/cmd/ui/src/views/Explore/EdgeInfo/EdgeInfoCollapsibleSection.tsx +++ b/cmd/ui/src/views/Explore/EdgeInfo/EdgeInfoCollapsibleSection.tsx @@ -19,8 +19,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Accordion, AccordionDetails, AccordionSummary } from '@mui/material'; import { EdgeInfoState, EdgeSections, edgeSectionToggle, SubHeader, useCollapsibleSectionStyles } from 'bh-shared-ui'; import React, { PropsWithChildren } from 'react'; -import { useSelector } from 'react-redux'; -import { AppState, useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; export const EdgeInfoCollapsibleSection: React.FC< PropsWithChildren<{ @@ -31,7 +30,7 @@ export const EdgeInfoCollapsibleSection: React.FC< const styles = useCollapsibleSectionStyles(); const dispatch = useAppDispatch(); - const edgeInfoState: EdgeInfoState = useSelector((state: AppState) => state.edgeinfo); + const edgeInfoState: EdgeInfoState = useAppSelector((state) => state.edgeinfo); const expanded = edgeInfoState.expandedSections[section]; diff --git a/cmd/ui/src/views/Explore/ExploreSearch/CypherSearch.tsx b/cmd/ui/src/views/Explore/ExploreSearch/CypherSearch.tsx index 18800ba3a2..1e9c8ff275 100644 --- a/cmd/ui/src/views/Explore/ExploreSearch/CypherSearch.tsx +++ b/cmd/ui/src/views/Explore/ExploreSearch/CypherSearch.tsx @@ -31,9 +31,8 @@ import { useCreateSavedQuery, } from 'bh-shared-ui'; import { useState } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; import { cypherQueryEdited, cypherSearch } from 'src/ducks/searchbar/actions'; -import { AppState } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; import CommonSearches from './CommonSearches'; import SaveQueryDialog from './SaveQueryDialog'; import { addSnackbar } from 'src/ducks/global/actions'; @@ -83,9 +82,9 @@ const schema = { }; const useCypherEditor = () => { - const cypherQuery = useSelector((state: AppState) => state.search.cypher.searchTerm); + const cypherQuery = useAppSelector((state) => state.search.cypher.searchTerm); - const dispatch = useDispatch(); + const dispatch = useAppDispatch(); const setCypherQuery = (query: string) => dispatch(cypherQueryEdited(query)); @@ -107,7 +106,7 @@ const CypherSearch = () => { const [showCommonQueries, setShowCommonQueries] = useState(false); const [showEgg, setShowEgg] = useState(false); const [showSaveQueryDialog, setShowSaveQueryDialog] = useState(false); - const dispatch = useDispatch(); + const dispatch = useAppDispatch(); const handleCypherSearch = () => { if (cypherQuery) { diff --git a/cmd/ui/src/views/Explore/ExploreSearch/EdgeFilter.tsx b/cmd/ui/src/views/Explore/ExploreSearch/EdgeFilter.tsx index 6acb1f8c2c..c9a755f347 100644 --- a/cmd/ui/src/views/Explore/ExploreSearch/EdgeFilter.tsx +++ b/cmd/ui/src/views/Explore/ExploreSearch/EdgeFilter.tsx @@ -20,8 +20,7 @@ import { Button } from '@mui/material'; import makeStyles from '@mui/styles/makeStyles'; import { useEffect, useRef, useState } from 'react'; import EdgeFilteringDialog, { EdgeCheckboxType } from './EdgeFilteringDialog'; -import { useSelector } from 'react-redux'; -import { AppState, useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; import { pathfindingSearch, pathFiltersSaved } from 'src/ducks/searchbar/actions'; const useStyles = makeStyles((theme) => ({ @@ -44,7 +43,7 @@ const EdgeFilter = () => { const [isActiveFilters, setIsActiveFilters] = useState(false); const initialFilterState = useRef([]); - const pathFilters = useSelector((state: AppState) => state.search.pathFilters); + const pathFilters = useAppSelector((state) => state.search.pathFilters); useEffect(() => { // if user has applied filters, set active diff --git a/cmd/ui/src/views/Explore/ExploreSearch/EdgeFilteringDialog.tsx b/cmd/ui/src/views/Explore/ExploreSearch/EdgeFilteringDialog.tsx index 3150658fd1..806a970e7b 100644 --- a/cmd/ui/src/views/Explore/ExploreSearch/EdgeFilteringDialog.tsx +++ b/cmd/ui/src/views/Explore/ExploreSearch/EdgeFilteringDialog.tsx @@ -39,10 +39,9 @@ import { import { useState } from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons'; -import { useSelector } from 'react-redux'; import { pathFiltersSaved } from 'src/ducks/searchbar/actions'; import { AllEdgeTypes, Category, Subcategory } from 'bh-shared-ui'; -import { AppState, useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; interface EdgeFilteringDialogProps { isOpen: boolean; @@ -51,7 +50,7 @@ interface EdgeFilteringDialogProps { } const EdgeFilteringDialog = ({ isOpen, handleCancel, handleApply }: EdgeFilteringDialogProps) => { - const selectedFilters: EdgeCheckboxType[] = useSelector((state: AppState) => state.search.pathFilters); + const selectedFilters: EdgeCheckboxType[] = useAppSelector((state) => state.search.pathFilters); const onCancel = () => { handleCancel(); diff --git a/cmd/ui/src/views/Explore/ExploreSearch/ExploreSearch.tsx b/cmd/ui/src/views/Explore/ExploreSearch/ExploreSearch.tsx index c6675ea24e..6fa269f1b5 100644 --- a/cmd/ui/src/views/Explore/ExploreSearch/ExploreSearch.tsx +++ b/cmd/ui/src/views/Explore/ExploreSearch/ExploreSearch.tsx @@ -20,9 +20,8 @@ import { Box, Collapse, Paper, Tab, Tabs, Theme, useMediaQuery, useTheme } from import makeStyles from '@mui/styles/makeStyles'; import { Icon } from 'bh-shared-ui'; import React, { useState } from 'react'; -import { useSelector } from 'react-redux'; import { CYPHER_SEARCH, PATHFINDING_SEARCH, PRIMARY_SEARCH } from 'src/ducks/searchbar/types'; -import { AppState, useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; import CypherSearch from './CypherSearch'; import NodeSearch from './NodeSearch'; import PathfindingSearch from './PathfindingSearch'; @@ -61,7 +60,7 @@ const ExploreSearch = ({ handleColumns }: ExploreSearchProps) => { const matches = useMediaQuery(theme.breakpoints.down('md')); const dispatch = useAppDispatch(); - const tabKey = useSelector((state: AppState) => state.search.activeTab); + const tabKey = useAppSelector((state) => state.search.activeTab); const activeTab = tabNameMap[tabKey]; const [showSearchWidget, setShowSearchWidget] = useState(true); diff --git a/cmd/ui/src/views/Explore/ExploreSearch/NodeSearch.tsx b/cmd/ui/src/views/Explore/ExploreSearch/NodeSearch.tsx index 3f4975164a..46129d8d5c 100644 --- a/cmd/ui/src/views/Explore/ExploreSearch/NodeSearch.tsx +++ b/cmd/ui/src/views/Explore/ExploreSearch/NodeSearch.tsx @@ -14,16 +14,15 @@ // // SPDX-License-Identifier: Apache-2.0 -import { useSelector } from 'react-redux'; import ExploreSearchCombobox from '../ExploreSearchCombobox'; import { SearchNodeType, SourceNodeEditedAction, SourceNodeSelectedAction } from 'src/ducks/searchbar/types'; -import { AppState, useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; import { sourceNodeEdited, sourceNodeSelected } from 'src/ducks/searchbar/actions'; const NodeSearch = () => { const dispatch = useAppDispatch(); - const primary = useSelector((state: AppState) => state.search.primary); + const primary = useAppSelector((state) => state.search.primary); const { searchTerm, value: selectedItem } = primary; const handleNodeEdited = (edit: string): SourceNodeEditedAction => dispatch(sourceNodeEdited(edit)); diff --git a/cmd/ui/src/views/Explore/ExploreSearch/PathfindingSearch.tsx b/cmd/ui/src/views/Explore/ExploreSearch/PathfindingSearch.tsx index 276cb4e90c..45d7816780 100644 --- a/cmd/ui/src/views/Explore/ExploreSearch/PathfindingSearch.tsx +++ b/cmd/ui/src/views/Explore/ExploreSearch/PathfindingSearch.tsx @@ -27,20 +27,19 @@ import { import EdgeFilter from './EdgeFilter'; import ExploreSearchCombobox from '../ExploreSearchCombobox'; import PathfindingSwapButton from './PathfindingSwapButton'; -import { AppState, useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; import { destinationNodeEdited, destinationNodeSelected, sourceNodeEdited, sourceNodeSelected, } from 'src/ducks/searchbar/actions'; -import { useSelector } from 'react-redux'; const PathfindingSearch = () => { const dispatch = useAppDispatch(); - const primary = useSelector((state: AppState) => state.search.primary); - const secondary = useSelector((state: AppState) => state.search.secondary); + const primary = useAppSelector((state) => state.search.primary); + const secondary = useAppSelector((state) => state.search.secondary); const { searchTerm: sourceInputValue, value: sourceSelectedItem } = primary; const { searchTerm: destinationInputValue, value: destinationSelectedItem } = secondary; diff --git a/cmd/ui/src/views/Explore/ExploreSearch/PathfindingSwapButton.tsx b/cmd/ui/src/views/Explore/ExploreSearch/PathfindingSwapButton.tsx index 67fe172513..6c48b89f7f 100644 --- a/cmd/ui/src/views/Explore/ExploreSearch/PathfindingSwapButton.tsx +++ b/cmd/ui/src/views/Explore/ExploreSearch/PathfindingSwapButton.tsx @@ -19,9 +19,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Button } from '@mui/material'; import makeStyles from '@mui/styles/makeStyles'; import { useCallback } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; import { destinationNodeSelected, sourceNodeSelected } from 'src/ducks/searchbar/actions'; -import { AppState } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; const useStyles = makeStyles((theme) => ({ swapButton: { @@ -37,9 +36,9 @@ const useStyles = makeStyles((theme) => ({ const PathfindingSwapButton = () => { const classes = useStyles(); - const dispatch = useDispatch(); + const dispatch = useAppDispatch(); - const { primary, secondary } = useSelector((state: AppState) => state.search); + const { primary, secondary } = useAppSelector((state) => state.search); const swapPathfindingInputs = useCallback(() => { const newSourceNode = secondary.value; diff --git a/cmd/ui/src/views/Explore/GraphView.tsx b/cmd/ui/src/views/Explore/GraphView.tsx index e32194d42c..8fa8a442a9 100644 --- a/cmd/ui/src/views/Explore/GraphView.tsx +++ b/cmd/ui/src/views/Explore/GraphView.tsx @@ -31,7 +31,6 @@ import { Attributes } from 'graphology-types'; import { GraphNodes } from 'js-client-library'; import isEmpty from 'lodash/isEmpty'; import { FC, useEffect, useState } from 'react'; -import { useSelector } from 'react-redux'; import { Link as RouterLink } from 'react-router-dom'; import { SigmaNodeEventPayload } from 'sigma/sigma'; import { GraphButtonOptions } from 'src/components/GraphButtons/GraphButtons'; @@ -44,7 +43,7 @@ import { GlobalOptionsState } from 'src/ducks/global/types'; import { discardChanges } from 'src/ducks/tierzero/actions'; import { RankDirection } from 'src/hooks/useLayoutDagre/useLayoutDagre'; import useToggle from 'src/hooks/useToggle'; -import { AppState, useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; import { transformFlatGraphResponse } from 'src/utils'; import EdgeInfoPane from 'src/views/Explore/EdgeInfo/EdgeInfoPane'; import EntityInfoPanel from 'src/views/Explore/EntityInfo/EntityInfoPanel'; @@ -58,9 +57,9 @@ const GraphView: FC = () => { const theme = useTheme(); const dispatch = useAppDispatch(); - const graphState: GraphState = useSelector((state: AppState) => state.explore); - const opts: GlobalOptionsState = useSelector((state: AppState) => state.global.options); - const formIsDirty = Object.keys(useSelector((state: AppState) => state.tierzero).changelog).length > 0; + const graphState: GraphState = useAppSelector((state) => state.explore); + const opts: GlobalOptionsState = useAppSelector((state) => state.global.options); + const formIsDirty = Object.keys(useAppSelector((state) => state.tierzero).changelog).length > 0; const [graphologyGraph, setGraphologyGraph] = useState>(); const [currentNodes, setCurrentNodes] = useState({}); @@ -225,12 +224,12 @@ const GraphView: FC = () => { }; const GridItems = () => { - const selectedNode = useSelector((state: AppState) => state.entityinfo.selectedNode); + const selectedNode = useAppSelector((state) => state.entityinfo.selectedNode); const columnsDefault = { xs: 6, md: 5, lg: 4, xl: 3 }; const cypherSearchColumns = { xs: 6, md: 6, lg: 6, xl: 4 }; - const edgeInfoState: EdgeInfoState = useSelector((state: AppState) => state.edgeinfo); + const edgeInfoState: EdgeInfoState = useAppSelector((state) => state.edgeinfo); const [columns, setColumns] = useState(columnsDefault); const theme = useTheme(); diff --git a/cmd/ui/src/views/Explore/Search/Menu/MenuContainer.tsx b/cmd/ui/src/views/Explore/Search/Menu/MenuContainer.tsx index dbc24ff88d..1b2d26bd5b 100644 --- a/cmd/ui/src/views/Explore/Search/Menu/MenuContainer.tsx +++ b/cmd/ui/src/views/Explore/Search/Menu/MenuContainer.tsx @@ -33,12 +33,11 @@ import createStyles from '@mui/styles/createStyles'; import makeStyles from '@mui/styles/makeStyles'; import withStyles from '@mui/styles/withStyles'; import React, { useState } from 'react'; -import { useSelector } from 'react-redux'; import { ConfirmationDialog } from 'bh-shared-ui'; import { initGraph, startAssetGroupQuery } from 'src/ducks/explore/actions'; import { setAssetGroupEdit, setAssetGroupIndex } from 'src/ducks/global/actions'; import { setTierZeroSelection } from 'src/ducks/tierzero/actions'; -import { AppState, useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; import ActionsMenu from './ActionsMenu'; const useStyles = makeStyles((theme) => ({ @@ -98,8 +97,8 @@ const MenuTab = withStyles(() => const MenuContainer: React.FC = () => { const styles = useStyles(); const dispatch = useAppDispatch(); - const assetGroups = useSelector((state: AppState) => state.global.options.assetGroups); - const domain = useSelector((state: AppState) => state.global.options.domain); + const assetGroups = useAppSelector((state) => state.global.options.assetGroups); + const domain = useAppSelector((state) => state.global.options.domain); const [selectedAssetGroup, setSelectedAssetGroup] = useState(null); const [anchorEl, setAnchorEl] = React.useState(null); diff --git a/cmd/ui/src/views/GroupManagement/GroupManagement.test.tsx b/cmd/ui/src/views/GroupManagement/GroupManagement.test.tsx index 97d9fd4735..5bf84960e3 100644 --- a/cmd/ui/src/views/GroupManagement/GroupManagement.test.tsx +++ b/cmd/ui/src/views/GroupManagement/GroupManagement.test.tsx @@ -54,7 +54,13 @@ describe('GroupManagement', () => { const setup = async () => await act(async () => { const user = userEvent.setup(); - const screen = render(); + const screen = render(, { + initialState: { + global: { + options: { domain: {} }, + }, + }, + }); return { user, screen }; }); diff --git a/cmd/ui/src/views/GroupManagement/GroupManagement.tsx b/cmd/ui/src/views/GroupManagement/GroupManagement.tsx index 28a89302db..4731e859ac 100644 --- a/cmd/ui/src/views/GroupManagement/GroupManagement.tsx +++ b/cmd/ui/src/views/GroupManagement/GroupManagement.tsx @@ -20,21 +20,19 @@ import { SelectedNode } from 'src/ducks/entityinfo/types'; import { useState } from 'react'; import { AssetGroup, AssetGroupMember } from 'js-client-library'; import { faGem } from '@fortawesome/free-solid-svg-icons'; -import { useSelector } from 'react-redux'; -import { Domain } from 'src/ducks/global/types'; import { setSelectedNode } from 'src/ducks/entityinfo/actions'; import { useNavigate } from 'react-router-dom'; import { ROUTE_EXPLORE } from 'src/ducks/global/routes'; import { sourceNodeSelected } from 'src/ducks/searchbar/actions'; import { TIER_ZERO_LABEL, TIER_ZERO_TAG } from 'src/constants'; -import { useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; import { dataCollectionMessage } from '../QA/utils'; const GroupManagement = () => { const dispatch = useAppDispatch(); const navigate = useNavigate(); - const globalDomain: Domain = useSelector((state: any) => state.global.options.domain); + const globalDomain = useAppSelector((state) => state.global.options.domain); // Kept out of the shared UI due to diff between GraphNodeTypes across apps const [openNode, setOpenNode] = useState(null); @@ -73,6 +71,7 @@ const GroupManagement = () => { }); }; + if (!globalDomain) return null; return ( { /* Hooks */ @@ -34,7 +34,7 @@ const Login: React.FC = () => { const queryClient = useQueryClient(); - const authState = useSelector((state: AppState) => state.auth); + const authState = useAppSelector((state) => state.auth); const [useSAML, setUseSAML] = useState(false); diff --git a/cmd/ui/src/views/QA/QA.tsx b/cmd/ui/src/views/QA/QA.tsx index a3f39e79e0..a9fe83df7c 100644 --- a/cmd/ui/src/views/QA/QA.tsx +++ b/cmd/ui/src/views/QA/QA.tsx @@ -24,12 +24,11 @@ import { TenantInfo, } from 'bh-shared-ui'; import { useEffect, useState } from 'react'; -import { useSelector } from 'react-redux'; -import { AppState } from 'src/store'; import { dataCollectionMessage } from './utils'; +import { useAppSelector } from 'src/store'; const QualityAssurance: React.FC = () => { - const domain = useSelector((state: AppState) => state.global.options.domain); + const domain = useAppSelector((state) => state.global.options.domain); const [contextType, setContextType] = useState(domain?.type || null); const [contextId, setContextId] = useState(domain?.id || null); const [dataError, setDataError] = useState(false); diff --git a/cmd/ui/src/views/Users/Users.tsx b/cmd/ui/src/views/Users/Users.tsx index 2f086fa787..1ee7757027 100644 --- a/cmd/ui/src/views/Users/Users.tsx +++ b/cmd/ui/src/views/Users/Users.tsx @@ -18,7 +18,7 @@ import { Box, Button, Paper } from '@mui/material'; import { DateTime } from 'luxon'; import { useState } from 'react'; import { useMutation, useQuery } from 'react-query'; -import { useSelector } from 'react-redux'; + import { ConfirmationDialog, DataTable, @@ -34,7 +34,7 @@ import { NewUser, UpdatedUser } from 'src/ducks/auth/types'; import { addSnackbar } from 'src/ducks/global/actions'; import useToggle from 'src/hooks/useToggle'; import { User } from 'src/hooks/useUsers'; -import { AppState, useAppDispatch } from 'src/store'; +import { useAppDispatch, useAppSelector } from 'src/store'; import CreateUserDialog from 'src/views/Users/CreateUserDialog'; import UpdateUserDialog from 'src/views/Users/UpdateUserDialog'; import UserActionsMenu from 'src/views/Users/UserActionsMenu'; @@ -54,7 +54,7 @@ const Users = () => { const [disable2FAError, setDisable2FAError] = useState(''); const [disable2FASecret, setDisable2FASecret] = useState(''); - const self = useSelector((state: AppState) => state.auth.user); + const self = useAppSelector((state) => state.auth.user); const getSelfQuery = useQuery(['getSelf'], ({ signal }) => apiClient.getSelf({ signal }).then((res) => res.data.data)