diff --git a/api/portainer.go b/api/portainer.go index 49b53f97d..0a5ae6380 100644 --- a/api/portainer.go +++ b/api/portainer.go @@ -1557,7 +1557,9 @@ const ( ) // List of supported features -var SupportedFeatureFlags = []featureflags.Feature{} +var SupportedFeatureFlags = []featureflags.Feature{ + "fdo", +} const ( _ AuthenticationMethod = iota diff --git a/app/react/components/Tip/TextTip/TextTip.tsx b/app/react/components/Tip/TextTip/TextTip.tsx index 628241895..aff8a40e0 100644 --- a/app/react/components/Tip/TextTip/TextTip.tsx +++ b/app/react/components/Tip/TextTip/TextTip.tsx @@ -19,10 +19,10 @@ export function TextTip({ children, }: PropsWithChildren) { return ( -

+

{children} -

+
); } diff --git a/app/react/portainer/environments/ListView/ImportFdoDeviceButton.tsx b/app/react/portainer/environments/ListView/ImportFdoDeviceButton.tsx index 82a6752f6..8683155da 100644 --- a/app/react/portainer/environments/ListView/ImportFdoDeviceButton.tsx +++ b/app/react/portainer/environments/ListView/ImportFdoDeviceButton.tsx @@ -4,13 +4,20 @@ import { Button } from '@@/buttons'; import { Link } from '@@/Link'; import { useSettings } from '../../settings/queries'; +import { + FeatureFlag, + useFeatureFlag, +} from '../../feature-flags/useFeatureFlag'; export function ImportFdoDeviceButton() { + const flagEnabledQuery = useFeatureFlag(FeatureFlag.FDO); + const isFDOEnabledQuery = useSettings( - (settings) => settings.fdoConfiguration.enabled + (settings) => settings.fdoConfiguration.enabled, + flagEnabledQuery.data ); - if (!isFDOEnabledQuery.data) { + if (!isFDOEnabledQuery.data || !flagEnabledQuery.data) { return null; } @@ -21,6 +28,7 @@ export function ImportFdoDeviceButton() { icon={Plus} as={Link} props={{ to: 'portainer.endpoints.importDevice' }} + className="ml-[5px]" > Import FDO device diff --git a/app/react/portainer/feature-flags/useFeatureFlag.ts b/app/react/portainer/feature-flags/useFeatureFlag.ts new file mode 100644 index 000000000..9cf6c720e --- /dev/null +++ b/app/react/portainer/feature-flags/useFeatureFlag.ts @@ -0,0 +1,19 @@ +import { usePublicSettings } from '../settings/queries'; + +export enum FeatureFlag { + FDO = 'fdo', +} + +export function useFeatureFlag( + flag: FeatureFlag, + { + onSuccess, + enabled = true, + }: { onSuccess?: (isEnabled: boolean) => void; enabled?: boolean } = {} +) { + return usePublicSettings({ + select: (settings) => settings.Features[flag], + onSuccess, + enabled, + }); +} diff --git a/app/react/portainer/feature-flags/useRedirectFeatureFlag.ts b/app/react/portainer/feature-flags/useRedirectFeatureFlag.ts index 86af99070..a5c6cd581 100644 --- a/app/react/portainer/feature-flags/useRedirectFeatureFlag.ts +++ b/app/react/portainer/feature-flags/useRedirectFeatureFlag.ts @@ -1,22 +1,6 @@ import { useRouter } from '@uirouter/react'; -import { usePublicSettings } from '@/react/portainer/settings/queries'; - -export enum FeatureFlag {} - -export function useFeatureFlag( - flag: FeatureFlag, - { - onSuccess, - enabled = true, - }: { onSuccess?: (isEnabled: boolean) => void; enabled?: boolean } = {} -) { - return usePublicSettings({ - select: (settings) => settings.Features[flag], - onSuccess, - enabled, - }); -} +import { FeatureFlag, useFeatureFlag } from './useFeatureFlag'; export function useRedirectFeatureFlag( flag: FeatureFlag, diff --git a/app/react/portainer/feature-flags/withFeatureFlag.tsx b/app/react/portainer/feature-flags/withFeatureFlag.tsx index ad1663270..a3c0e0c7f 100644 --- a/app/react/portainer/feature-flags/withFeatureFlag.tsx +++ b/app/react/portainer/feature-flags/withFeatureFlag.tsx @@ -1,6 +1,6 @@ import { ComponentType } from 'react'; -import { FeatureFlag, useFeatureFlag } from './useRedirectFeatureFlag'; +import { FeatureFlag, useFeatureFlag } from './useFeatureFlag'; export function withFeatureFlag( WrappedComponent: ComponentType, diff --git a/app/react/portainer/settings/EdgeComputeView/SettingsFDO/SettingsFDO.tsx b/app/react/portainer/settings/EdgeComputeView/SettingsFDO/SettingsFDO.tsx index be1f0c940..b5042fb73 100644 --- a/app/react/portainer/settings/EdgeComputeView/SettingsFDO/SettingsFDO.tsx +++ b/app/react/portainer/settings/EdgeComputeView/SettingsFDO/SettingsFDO.tsx @@ -3,6 +3,10 @@ import { Formik, Field, Form } from 'formik'; import { Laptop } from 'lucide-react'; import { FDOConfiguration } from '@/portainer/hostmanagement/fdo/model'; +import { + FeatureFlag, + useFeatureFlag, +} from '@/react/portainer/feature-flags/useFeatureFlag'; import { Switch } from '@@/form-components/SwitchField/Switch'; import { FormControl } from '@@/form-components/FormControl'; @@ -28,6 +32,25 @@ interface Props { } export function SettingsFDO({ settings, onSubmit }: Props) { + const flagEnabledQuery = useFeatureFlag(FeatureFlag.FDO); + + if (!flagEnabledQuery.data) { + return ( + + + + Since FDO is still an experimental feature that requires additional + infrastructure, it has been temporarily hidden in the UI. + + + + ); + } + + return ; +} + +export function SettingsFDOForm({ settings, onSubmit }: Props) { const fdoConfiguration = settings ? settings.fdoConfiguration : null; const initialFDOEnabled = fdoConfiguration ? fdoConfiguration.enabled : false;