diff --git a/frontend/src/component/project/Project/ProjectFeatureToggles/FeatureToggleSwitch/FeatureToggleSwitch.tsx b/frontend/src/component/project/Project/ProjectFeatureToggles/FeatureToggleSwitch/FeatureToggleSwitch.tsx index 5ffdfbeafb..27abd7a111 100644 --- a/frontend/src/component/project/Project/ProjectFeatureToggles/FeatureToggleSwitch/FeatureToggleSwitch.tsx +++ b/frontend/src/component/project/Project/ProjectFeatureToggles/FeatureToggleSwitch/FeatureToggleSwitch.tsx @@ -1,4 +1,4 @@ -import { useState, VFC } from 'react'; +import { useCallback, useState, VFC } from 'react'; import { Box, styled } from '@mui/material'; import PermissionSwitch from 'component/common/PermissionSwitch/PermissionSwitch'; import { UPDATE_FEATURE_ENVIRONMENT } from 'component/providers/AccessProvider/permissions'; @@ -68,37 +68,45 @@ export const FeatureToggleSwitch: VFC = ({ onToggle(projectId, feature.name, environmentName, !isChecked); }; - const handleToggleEnvironmentOn = async ( - shouldActivateDisabled = false - ) => { - try { - setIsChecked(!isChecked); - await toggleFeatureEnvironmentOn( - projectId, - feature.name, - environmentName, - shouldActivateDisabled - ); - setToastData({ - type: 'success', - title: `Available in ${environmentName}`, - text: `${feature.name} is now available in ${environmentName} based on its defined strategies.`, - }); - callback(); - } catch (error: unknown) { - if ( - error instanceof Error && - error.message === ENVIRONMENT_STRATEGY_ERROR - ) { - showInfoBox && showInfoBox(); - } else { - setToastApiError(formatUnknownError(error)); + const handleToggleEnvironmentOn = useCallback( + async (shouldActivateDisabled = false) => { + try { + setIsChecked(!isChecked); + await toggleFeatureEnvironmentOn( + projectId, + feature.name, + environmentName, + shouldActivateDisabled + ); + setToastData({ + type: 'success', + title: `Available in ${environmentName}`, + text: `${feature.name} is now available in ${environmentName} based on its defined strategies.`, + }); + callback(); + } catch (error: unknown) { + if ( + error instanceof Error && + error.message === ENVIRONMENT_STRATEGY_ERROR + ) { + showInfoBox && showInfoBox(); + } else { + setToastApiError(formatUnknownError(error)); + } + rollbackIsChecked(); } - rollbackIsChecked(); - } - }; + }, + [ + rollbackIsChecked, + setToastApiError, + showInfoBox, + setToastData, + toggleFeatureEnvironmentOn, + setIsChecked, + ] + ); - const handleToggleEnvironmentOff = async () => { + const handleToggleEnvironmentOff = useCallback(async () => { try { setIsChecked(!isChecked); await toggleFeatureEnvironmentOff( @@ -116,54 +124,15 @@ export const FeatureToggleSwitch: VFC = ({ setToastApiError(formatUnknownError(error)); rollbackIsChecked(); } - }; + }, [ + toggleFeatureEnvironmentOff, + setToastData, + setToastApiError, + rollbackIsChecked, + setIsChecked, + ]); - const onClick = async (e: React.MouseEvent) => { - if (isChangeRequestConfigured(environmentName)) { - e.preventDefault(); - if (featureHasOnlyDisabledStrategies()) { - setShowEnabledDialog(true); - } else { - onChangeRequestToggle( - feature.name, - environmentName, - !value, - false - ); - } - return; - } - if (value) { - await handleToggleEnvironmentOff(); - return; - } - - if (featureHasOnlyDisabledStrategies()) { - setShowEnabledDialog(true); - } else { - await handleToggleEnvironmentOn(); - } - }; - - const onActivateStrategies = async () => { - if (isChangeRequestConfigured(environmentName)) { - onChangeRequestToggle(feature.name, environmentName, !value, true); - } else { - await handleToggleEnvironmentOn(true); - } - setShowEnabledDialog(false); - }; - - const onAddDefaultStrategy = async () => { - if (isChangeRequestConfigured(environmentName)) { - onChangeRequestToggle(feature.name, environmentName, !value, false); - } else { - await handleToggleEnvironmentOn(); - } - setShowEnabledDialog(false); - }; - - const featureHasOnlyDisabledStrategies = () => { + const featureHasOnlyDisabledStrategies = useCallback(() => { const featureEnvironment = feature?.environments?.find( env => env.name === environmentName ); @@ -172,7 +141,69 @@ export const FeatureToggleSwitch: VFC = ({ featureEnvironment?.strategies?.length > 0 && featureEnvironment?.strategies?.every(strategy => strategy.disabled) ); - }; + }, [environmentName]); + + const onClick = useCallback( + async (e: React.MouseEvent) => { + if (isChangeRequestConfigured(environmentName)) { + e.preventDefault(); + if (featureHasOnlyDisabledStrategies()) { + setShowEnabledDialog(true); + } else { + onChangeRequestToggle( + feature.name, + environmentName, + !value, + false + ); + } + return; + } + if (value) { + await handleToggleEnvironmentOff(); + return; + } + + if (featureHasOnlyDisabledStrategies()) { + setShowEnabledDialog(true); + } else { + await handleToggleEnvironmentOn(); + } + }, + [ + isChangeRequestConfigured, + onChangeRequestToggle, + handleToggleEnvironmentOff, + setShowEnabledDialog, + ] + ); + + const onActivateStrategies = useCallback(async () => { + if (isChangeRequestConfigured(environmentName)) { + onChangeRequestToggle(feature.name, environmentName, !value, true); + } else { + await handleToggleEnvironmentOn(true); + } + setShowEnabledDialog(false); + }, [ + handleToggleEnvironmentOn, + setShowEnabledDialog, + isChangeRequestConfigured, + onChangeRequestToggle, + ]); + + const onAddDefaultStrategy = useCallback(async () => { + if (isChangeRequestConfigured(environmentName)) { + onChangeRequestToggle(feature.name, environmentName, !value, false); + } else { + await handleToggleEnvironmentOn(); + } + setShowEnabledDialog(false); + }, [ + isChangeRequestConfigured, + onChangeRequestToggle, + handleToggleEnvironmentOn, + ]); const key = `${feature.name}-${environmentName}`; @@ -188,7 +219,7 @@ export const FeatureToggleSwitch: VFC = ({ ? `Disable feature in ${environmentName}` : `Enable feature in ${environmentName}` } - checked={value} + checked={isChecked} environmentId={environmentName} projectId={projectId} permission={UPDATE_FEATURE_ENVIRONMENT}