diff --git a/src/Components/Blueprints/BlueprintsSideBar.tsx b/src/Components/Blueprints/BlueprintsSideBar.tsx index 6c1dd852..9422f8e3 100644 --- a/src/Components/Blueprints/BlueprintsSideBar.tsx +++ b/src/Components/Blueprints/BlueprintsSideBar.tsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useState } from 'react'; +import React, { useCallback } from 'react'; import { Bullseye, @@ -17,7 +17,6 @@ import { import { PlusCircleIcon, SearchIcon } from '@patternfly/react-icons'; import { SVGIconProps } from '@patternfly/react-icons/dist/esm/createIcon'; import useChrome from '@redhat-cloud-services/frontend-components/useChrome'; -import { ChromeUser } from '@redhat-cloud-services/types'; import debounce from 'lodash/debounce'; import { Link } from 'react-router-dom'; @@ -29,6 +28,7 @@ import { PAGINATION_LIMIT, PAGINATION_OFFSET, } from '../../constants'; +import { useGetUser } from '../../Hooks'; import { useGetBlueprintsQuery } from '../../store/backendApi'; import { selectBlueprintSearchInput, @@ -60,8 +60,8 @@ type emptyBlueprintStateProps = { }; const BlueprintsSidebar = () => { - const [userData, setUserData] = useState(undefined); const { analytics, auth } = useChrome(); + const { userData } = useGetUser(auth); const selectedBlueprintId = useAppSelector(selectSelectedBlueprintId); const blueprintSearchInput = useAppSelector(selectBlueprintSearchInput); @@ -73,16 +73,6 @@ const BlueprintsSidebar = () => { offset: blueprintsOffset, }; - useEffect(() => { - (async () => { - const data = await auth.getUser(); - setUserData(data); - })(); - // This useEffect hook should run *only* on mount and therefore has an empty - // dependency array. eslint's exhaustive-deps rule does not support this use. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - if (blueprintSearchInput) { searchParams.search = blueprintSearchInput; } diff --git a/src/Components/Blueprints/BuildImagesButton.tsx b/src/Components/Blueprints/BuildImagesButton.tsx index 6304d98a..431b765b 100644 --- a/src/Components/Blueprints/BuildImagesButton.tsx +++ b/src/Components/Blueprints/BuildImagesButton.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { Button, @@ -16,11 +16,13 @@ import { } from '@patternfly/react-core'; import { MenuToggleElement } from '@patternfly/react-core/dist/esm/components/MenuToggle/MenuToggle'; import useChrome from '@redhat-cloud-services/frontend-components/useChrome'; -import { ChromeUser } from '@redhat-cloud-services/types'; import { skipToken } from '@reduxjs/toolkit/query'; import { AMPLITUDE_MODULE_NAME, targetOptions } from '../../constants'; -import { useComposeBPWithNotification as useComposeBlueprintMutation } from '../../Hooks'; +import { + useComposeBPWithNotification as useComposeBlueprintMutation, + useGetUser, +} from '../../Hooks'; import { useGetBlueprintQuery } from '../../store/backendApi'; import { selectSelectedBlueprintId } from '../../store/BlueprintSlice'; import { useAppSelector } from '../../store/hooks'; @@ -37,18 +39,7 @@ export const BuildImagesButton = ({ children }: BuildImagesButtonPropTypes) => { const { trigger: buildBlueprint, isLoading: imageBuildLoading } = useComposeBlueprintMutation(); const { analytics, auth } = useChrome(); - - const [userData, setUserData] = useState(undefined); - - useEffect(() => { - (async () => { - const data = await auth.getUser(); - setUserData(data); - })(); - // This useEffect hook should run *only* on mount and therefore has an empty - // dependency array. eslint's exhaustive-deps rule does not support this use. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const { userData } = useGetUser(auth); const onBuildHandler = async () => { if (selectedBlueprintId) { diff --git a/src/Components/Blueprints/DeleteBlueprintModal.tsx b/src/Components/Blueprints/DeleteBlueprintModal.tsx index afd209d5..230deeed 100644 --- a/src/Components/Blueprints/DeleteBlueprintModal.tsx +++ b/src/Components/Blueprints/DeleteBlueprintModal.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { Button, @@ -9,14 +9,16 @@ import { ModalVariant, } from '@patternfly/react-core'; import useChrome from '@redhat-cloud-services/frontend-components/useChrome'; -import { ChromeUser } from '@redhat-cloud-services/types'; import { AMPLITUDE_MODULE_NAME, PAGINATION_LIMIT, PAGINATION_OFFSET, } from '../../constants'; -import { useDeleteBPWithNotification as useDeleteBlueprintMutation } from '../../Hooks'; +import { + useDeleteBPWithNotification as useDeleteBlueprintMutation, + useGetUser, +} from '../../Hooks'; import { backendApi, useGetBlueprintsQuery } from '../../store/backendApi'; import { selectBlueprintSearchInput, @@ -42,17 +44,7 @@ export const DeleteBlueprintModal: React.FunctionComponent< const blueprintsLimit = useAppSelector(selectLimit) || PAGINATION_LIMIT; const dispatch = useAppDispatch(); const { analytics, auth } = useChrome(); - const [userData, setUserData] = useState(undefined); - - useEffect(() => { - (async () => { - const data = await auth.getUser(); - setUserData(data); - })(); - // This useEffect hook should run *only* on mount and therefore has an empty - // dependency array. eslint's exhaustive-deps rule does not support this use. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const { userData } = useGetUser(auth); const searchParams: GetBlueprintsApiArg = { limit: blueprintsLimit, diff --git a/src/Components/CreateImageWizard/steps/Registration/index.tsx b/src/Components/CreateImageWizard/steps/Registration/index.tsx index bd96d505..081fd54e 100644 --- a/src/Components/CreateImageWizard/steps/Registration/index.tsx +++ b/src/Components/CreateImageWizard/steps/Registration/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { ClipboardCopy, @@ -16,6 +16,7 @@ import ActivationKeysList from './components/ActivationKeysList'; import Registration from './components/Registration'; import SatelliteRegistration from './components/SatelliteRegistration'; +import { useGetUser } from '../../../../Hooks'; import { useAppSelector } from '../../../../store/hooks'; import { selectActivationKey, @@ -24,18 +25,7 @@ import { const RegistrationStep = () => { const { auth } = useChrome(); - const [orgId, setOrgId] = useState(undefined); - - useEffect(() => { - (async () => { - const userData = await auth.getUser(); - const id = userData?.identity?.internal?.org_id; - setOrgId(id); - })(); - // This useEffect hook should run *only* on mount and therefore has an empty - // dependency array. eslint's exhaustive-deps rule does not support this use. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const { orgId } = useGetUser(auth); const activationKey = useAppSelector(selectActivationKey); const registrationType = useAppSelector(selectRegistrationType); diff --git a/src/Components/CreateImageWizard/steps/Review/Footer/CreateDropdown.tsx b/src/Components/CreateImageWizard/steps/Review/Footer/CreateDropdown.tsx index f05d4668..ba26cfda 100644 --- a/src/Components/CreateImageWizard/steps/Review/Footer/CreateDropdown.tsx +++ b/src/Components/CreateImageWizard/steps/Review/Footer/CreateDropdown.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useState } from 'react'; import { Button, @@ -14,12 +14,12 @@ import { Spinner, } from '@patternfly/react-core'; import useChrome from '@redhat-cloud-services/frontend-components/useChrome'; -import { ChromeUser } from '@redhat-cloud-services/types'; import { AMPLITUDE_MODULE_NAME } from '../../../../../constants'; import { useComposeBPWithNotification as useComposeBlueprintMutation, useCreateBPWithNotification as useCreateBlueprintMutation, + useGetUser, } from '../../../../../Hooks'; import { setBlueprintId } from '../../../../../store/BlueprintSlice'; import { CockpitCreateBlueprintRequest } from '../../../../../store/cockpit/types'; @@ -44,19 +44,8 @@ export const CreateSaveAndBuildBtn = ({ setIsOpen, isDisabled, }: CreateDropdownProps) => { - const [userData, setUserData] = useState(undefined); - const { analytics, auth, isBeta } = useChrome(); - - useEffect(() => { - (async () => { - const data = await auth.getUser(); - setUserData(data); - })(); - // This useEffect hook should run *only* on mount and therefore has an empty - // dependency array. eslint's exhaustive-deps rule does not support this use. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const { userData } = useGetUser(auth); const packages = useAppSelector(selectPackages); @@ -113,17 +102,7 @@ export const CreateSaveButton = ({ isDisabled, }: CreateDropdownProps) => { const { analytics, auth, isBeta } = useChrome(); - const [userData, setUserData] = useState(undefined); - - useEffect(() => { - (async () => { - const data = await auth.getUser(); - setUserData(data); - })(); - // This useEffect hook should run *only* on mount and therefore has an empty - // dependency array. eslint's exhaustive-deps rule does not support this use. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const { userData } = useGetUser(auth); const packages = useAppSelector(selectPackages); diff --git a/src/Components/CreateImageWizard/steps/Review/Footer/EditDropdown.tsx b/src/Components/CreateImageWizard/steps/Review/Footer/EditDropdown.tsx index cc025a9f..6cc19cc3 100644 --- a/src/Components/CreateImageWizard/steps/Review/Footer/EditDropdown.tsx +++ b/src/Components/CreateImageWizard/steps/Review/Footer/EditDropdown.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { DropdownItem, @@ -9,11 +9,11 @@ import { Spinner, } from '@patternfly/react-core'; import useChrome from '@redhat-cloud-services/frontend-components/useChrome'; -import { ChromeUser } from '@redhat-cloud-services/types'; import { AMPLITUDE_MODULE_NAME } from '../../../../../constants'; import { useComposeBPWithNotification as useComposeBlueprintMutation, + useGetUser, useUpdateBPWithNotification as useUpdateBlueprintMutation, } from '../../../../../Hooks'; import { CockpitCreateBlueprintRequest } from '../../../../../store/cockpit/types'; @@ -37,19 +37,8 @@ export const EditSaveAndBuildBtn = ({ blueprintId, isDisabled, }: EditDropdownProps) => { - const [userData, setUserData] = useState(undefined); - const { analytics, auth, isBeta } = useChrome(); - - useEffect(() => { - (async () => { - const data = await auth.getUser(); - setUserData(data); - })(); - // This useEffect hook should run *only* on mount and therefore has an empty - // dependency array. eslint's exhaustive-deps rule does not support this use. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const { userData } = useGetUser(auth); const { trigger: buildBlueprint } = useComposeBlueprintMutation(); const packages = useAppSelector(selectPackages); @@ -105,19 +94,8 @@ export const EditSaveButton = ({ blueprintId, isDisabled, }: EditDropdownProps) => { - const [userData, setUserData] = useState(undefined); - const { analytics, auth, isBeta } = useChrome(); - - useEffect(() => { - (async () => { - const data = await auth.getUser(); - setUserData(data); - })(); - // This useEffect hook should run *only* on mount and therefore has an empty - // dependency array. eslint's exhaustive-deps rule does not support this use. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const { userData } = useGetUser(auth); const packages = useAppSelector(selectPackages); diff --git a/src/Components/CreateImageWizard/steps/Review/Footer/Footer.tsx b/src/Components/CreateImageWizard/steps/Review/Footer/Footer.tsx index c12d590f..f6a35745 100644 --- a/src/Components/CreateImageWizard/steps/Review/Footer/Footer.tsx +++ b/src/Components/CreateImageWizard/steps/Review/Footer/Footer.tsx @@ -18,6 +18,7 @@ import { EditSaveAndBuildBtn, EditSaveButton } from './EditDropdown'; import { useCreateBPWithNotification as useCreateBlueprintMutation, + useGetUser, useUpdateBPWithNotification as useUpdateBlueprintMutation, } from '../../../../../Hooks'; import { resolveRelPath } from '../../../../../Utilities/path'; @@ -33,6 +34,7 @@ const ReviewWizardFooter = () => { const { isSuccess: isUpdateSuccess, reset: resetUpdate } = useUpdateBlueprintMutation({ fixedCacheKey: 'updateBlueprintKey' }); const { auth } = useChrome(); + const { orgId } = useGetUser(auth); const { composeId } = useParams(); const [isOpen, setIsOpen] = useState(false); const store = useStore(); @@ -52,14 +54,12 @@ const ReviewWizardFooter = () => { const getBlueprintPayload = async () => { if (!process.env.IS_ON_PREMISE) { - const userData = await auth.getUser(); - const orgId = userData?.identity?.internal?.org_id; const requestBody = orgId && mapRequestFromState(store, orgId); return requestBody; } - // NOTE: This should be fine on-prem, we should - // be able to ignore the `org-id` + // NOTE: This is fine for on prem because we save the org id + // to state through a form field in the registration step return mapRequestFromState(store, ''); }; diff --git a/src/Components/ImagesTable/ImageDetails.tsx b/src/Components/ImagesTable/ImageDetails.tsx index 809b0394..21b8a0db 100644 --- a/src/Components/ImagesTable/ImageDetails.tsx +++ b/src/Components/ImagesTable/ImageDetails.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { Alert, @@ -13,11 +13,11 @@ import { } from '@patternfly/react-core'; import { ExternalLinkAltIcon } from '@patternfly/react-icons'; import useChrome from '@redhat-cloud-services/frontend-components/useChrome'; -import { ChromeUser } from '@redhat-cloud-services/types'; import ClonesTable from './ClonesTable'; import { AMPLITUDE_MODULE_NAME } from '../../constants'; +import { useGetUser } from '../../Hooks'; import { useGetComposeStatusQuery } from '../../store/backendApi'; import { extractProvisioningList } from '../../store/helpers'; import { @@ -134,19 +134,9 @@ type AwsDetailsPropTypes = { export const AwsDetails = ({ compose }: AwsDetailsPropTypes) => { const options = compose.request.image_requests[0].upload_request.options; - const [userData, setUserData] = useState(undefined); const { analytics, auth } = useChrome(); - - useEffect(() => { - (async () => { - const data = await auth.getUser(); - setUserData(data); - })(); - // This useEffect hook should run *only* on mount and therefore has an empty - // dependency array. eslint's exhaustive-deps rule does not support this use. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const { userData } = useGetUser(auth); if (!isAwsUploadRequestOptions(options)) { throw TypeError( diff --git a/src/Components/ImagesTable/ImagesTable.tsx b/src/Components/ImagesTable/ImagesTable.tsx index 8c9118a1..69af395c 100644 --- a/src/Components/ImagesTable/ImagesTable.tsx +++ b/src/Components/ImagesTable/ImagesTable.tsx @@ -25,7 +25,6 @@ import { Tr, } from '@patternfly/react-table'; import useChrome from '@redhat-cloud-services/frontend-components/useChrome'; -import { ChromeUser } from '@redhat-cloud-services/types'; import { useFlag } from '@unleash/proxy-client-react'; import { useDispatch } from 'react-redux'; import { NavigateFunction, useNavigate } from 'react-router-dom'; @@ -59,6 +58,7 @@ import { SEARCH_INPUT, STATUS_POLLING_INTERVAL, } from '../../constants'; +import { useGetUser } from '../../Hooks'; import { useGetBlueprintComposesQuery, useGetBlueprintsQuery, @@ -94,7 +94,6 @@ import { OciLaunchModal } from '../Launch/OciLaunchModal'; const ImagesTable = () => { const [page, setPage] = useState(1); const [perPage, setPerPage] = useState(10); - const [userData, setUserData] = useState(undefined); const selectedBlueprintId = useAppSelector(selectSelectedBlueprintId); const blueprintSearchInput = @@ -107,16 +106,7 @@ const ImagesTable = () => { const blueprintsLimit = useAppSelector(selectLimit) || PAGINATION_LIMIT; const { analytics, auth } = useChrome(); - - useEffect(() => { - (async () => { - const data = await auth.getUser(); - setUserData(data); - })(); - // This useEffect hook should run *only* on mount and therefore has an empty - // dependency array. eslint's exhaustive-deps rule does not support this use. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const { userData } = useGetUser(auth); const searchParamsGetBlueprints: GetBlueprintsApiArg = { limit: blueprintsLimit, @@ -481,18 +471,8 @@ type AwsRowPropTypes = { const AwsRow = ({ compose, composeStatus, rowIndex }: AwsRowPropTypes) => { const navigate = useNavigate(); - const [userData, setUserData] = useState(undefined); const { analytics, auth } = useChrome(); - - useEffect(() => { - (async () => { - const data = await auth.getUser(); - setUserData(data); - })(); - // This useEffect hook should run *only* on mount and therefore has an empty - // dependency array. eslint's exhaustive-deps rule does not support this use. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const { userData } = useGetUser(auth); const target = ; const status = ; @@ -567,18 +547,8 @@ const Row = ({ details, instance, }: RowPropTypes) => { - const [userData, setUserData] = useState(undefined); const { analytics, auth } = useChrome(); - - useEffect(() => { - (async () => { - const data = await auth.getUser(); - setUserData(data); - })(); - // This useEffect hook should run *only* on mount and therefore has an empty - // dependency array. eslint's exhaustive-deps rule does not support this use. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const { userData } = useGetUser(auth); const [isExpanded, setIsExpanded] = useState(false); const handleToggle = () => setIsExpanded(!isExpanded); diff --git a/src/Components/ImagesTable/Instance.tsx b/src/Components/ImagesTable/Instance.tsx index 4af6f5e9..254f0b05 100644 --- a/src/Components/ImagesTable/Instance.tsx +++ b/src/Components/ImagesTable/Instance.tsx @@ -1,4 +1,4 @@ -import React, { Suspense, useEffect, useState } from 'react'; +import React, { Suspense, useState } from 'react'; import path from 'path'; @@ -20,7 +20,6 @@ import { } from '@patternfly/react-core/dist/esm/components/List/List'; import { ExternalLinkAltIcon } from '@patternfly/react-icons'; import useChrome from '@redhat-cloud-services/frontend-components/useChrome'; -import { ChromeUser } from '@redhat-cloud-services/types'; import { useLoadModule, useScalprum } from '@scalprum/react-core'; import cockpit from 'cockpit'; import { useNavigate } from 'react-router-dom'; @@ -31,6 +30,7 @@ import { MODAL_ANCHOR, SEARCH_INPUT, } from '../../constants'; +import { useGetUser } from '../../Hooks'; import { useGetBlueprintsQuery, useGetComposeStatusQuery, @@ -101,19 +101,9 @@ const ProvisioningLink = ({ composeStatus, }: ProvisioningLinkPropTypes) => { const launchEofFlag = useFlag('image-builder.launcheof'); - const [userData, setUserData] = useState(undefined); const { analytics, auth } = useChrome(); - - useEffect(() => { - (async () => { - const data = await auth.getUser(); - setUserData(data); - })(); - // This useEffect hook should run *only* on mount and therefore has an empty - // dependency array. eslint's exhaustive-deps rule does not support this use. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const { userData } = useGetUser(auth); const [isModalOpen, setIsModalOpen] = useState(false); const [exposedScalprumModule, error] = useLoadModule( diff --git a/src/Components/ImagesTable/Status.tsx b/src/Components/ImagesTable/Status.tsx index b3c4ca8a..fbe08ceb 100644 --- a/src/Components/ImagesTable/Status.tsx +++ b/src/Components/ImagesTable/Status.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import './ImageBuildStatus.scss'; import { @@ -24,13 +24,13 @@ import { PendingIcon, } from '@patternfly/react-icons'; import useChrome from '@redhat-cloud-services/frontend-components/useChrome'; -import { ChromeUser } from '@redhat-cloud-services/types'; import { AMPLITUDE_MODULE_NAME, AWS_S3_EXPIRATION_TIME_IN_HOURS, OCI_STORAGE_EXPIRATION_TIME_IN_DAYS, } from '../../constants'; +import { useGetUser } from '../../Hooks'; import { useGetComposeStatusQuery } from '../../store/backendApi'; import { CockpitComposesResponseItem } from '../../store/cockpit/types'; import { @@ -122,18 +122,8 @@ export const CloudStatus = ({ compose }: CloudStatusPropTypes) => { const { data, isSuccess } = useGetComposeStatusQuery({ composeId: compose.id, }); - const [userData, setUserData] = useState(undefined); const { analytics, auth } = useChrome(); - - useEffect(() => { - (async () => { - const data = await auth.getUser(); - setUserData(data); - })(); - // This useEffect hook should run *only* on mount and therefore has an empty - // dependency array. eslint's exhaustive-deps rule does not support this use. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + const { userData } = useGetUser(auth); if (!isSuccess) { return ; diff --git a/src/Hooks/index.tsx b/src/Hooks/index.tsx index df6abc94..cb2f6aef 100644 --- a/src/Hooks/index.tsx +++ b/src/Hooks/index.tsx @@ -4,3 +4,4 @@ export { useDeleteBPWithNotification } from './MutationNotifications/useDeleteBP export { useFixupBPWithNotification } from './MutationNotifications/useFixupBPWithNotification'; export { useComposeBPWithNotification } from './MutationNotifications/useComposeBPWithNotification'; export { useCloneComposeWithNotification } from './MutationNotifications/useCloneComposeWithNotification'; +export { useGetUser } from './useGetUser'; diff --git a/src/Hooks/useGetUser.tsx b/src/Hooks/useGetUser.tsx new file mode 100644 index 00000000..445bdf22 --- /dev/null +++ b/src/Hooks/useGetUser.tsx @@ -0,0 +1,24 @@ +import { useEffect, useState } from 'react'; + +import { ChromeUser } from '@redhat-cloud-services/types'; + +export const useGetUser = (auth: { getUser(): Promise }) => { + const [userData, setUserData] = useState(undefined); + const [orgId, setOrgId] = useState(undefined); + + useEffect(() => { + (async () => { + if (!process.env.IS_ON_PREMISE) { + const data = await auth.getUser(); + const id = data?.identity.internal?.org_id; + setUserData(data); + setOrgId(id); + } + })(); + // This useEffect hook should run *only* on mount and therefore has an empty + // dependency array. eslint's exhaustive-deps rule does not support this use. + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return { userData, orgId }; +};