1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-11-10 01:19:53 +01:00

feat: add use template button to strategies selector on flag config pane (#9605)

This commit is contained in:
Simon Hornby 2025-03-25 14:18:20 +02:00 committed by GitHub
parent dbc953b222
commit 9106fbf721
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 87 additions and 47 deletions

View File

@ -20,6 +20,7 @@ import { useReleasePlans } from 'hooks/api/getters/useReleasePlans/useReleasePla
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled'; import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
import { formatUnknownError } from 'utils/formatUnknownError'; import { formatUnknownError } from 'utils/formatUnknownError';
import { useUiFlag } from 'hooks/useUiFlag'; import { useUiFlag } from 'hooks/useUiFlag';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
interface IFeatureStrategyMenuProps { interface IFeatureStrategyMenuProps {
label: string; label: string;
@ -57,6 +58,7 @@ export const FeatureStrategyMenu = ({
disableReason, disableReason,
}: IFeatureStrategyMenuProps) => { }: IFeatureStrategyMenuProps) => {
const [anchor, setAnchor] = useState<Element>(); const [anchor, setAnchor] = useState<Element>();
const [onlyReleasePlans, setOnlyReleasePlans] = useState<boolean>(false);
const navigate = useNavigate(); const navigate = useNavigate();
const { trackEvent } = usePlausibleTracker(); const { trackEvent } = usePlausibleTracker();
const [selectedTemplate, setSelectedTemplate] = const [selectedTemplate, setSelectedTemplate] =
@ -71,8 +73,9 @@ export const FeatureStrategyMenu = ({
usePendingChangeRequests(projectId); usePendingChangeRequests(projectId);
const { refetch } = useReleasePlans(projectId, featureId, environmentId); const { refetch } = useReleasePlans(projectId, featureId, environmentId);
const { addReleasePlanToFeature } = useReleasePlansApi(); const { addReleasePlanToFeature } = useReleasePlansApi();
const { isOss } = useUiConfig();
const releasePlansEnabled = useUiFlag('releasePlans'); const releasePlansEnabled = useUiFlag('releasePlans');
const displayReleasePlanButton = !isOss() && releasePlansEnabled;
const crProtected = const crProtected =
releasePlansEnabled && isChangeRequestConfigured(environmentId); releasePlansEnabled && isChangeRequestConfigured(environmentId);
@ -90,6 +93,12 @@ export const FeatureStrategyMenu = ({
}; };
const openMoreStrategies = (event: React.SyntheticEvent) => { const openMoreStrategies = (event: React.SyntheticEvent) => {
setOnlyReleasePlans(false);
setAnchor(event.currentTarget);
};
const openReleasePlans = (event: React.SyntheticEvent) => {
setOnlyReleasePlans(true);
setAnchor(event.currentTarget); setAnchor(event.currentTarget);
}; };
@ -151,6 +160,27 @@ export const FeatureStrategyMenu = ({
return ( return (
<StyledStrategyMenu onClick={(event) => event.stopPropagation()}> <StyledStrategyMenu onClick={(event) => event.stopPropagation()}>
{displayReleasePlanButton ? (
<>
<PermissionButton
data-testid='ADD_TEMPLATE_BUTTON'
permission={CREATE_FEATURE_STRATEGY}
projectId={projectId}
environmentId={environmentId}
onClick={openReleasePlans}
aria-labelledby={popoverId}
variant='outlined'
sx={{ minWidth: matchWidth ? '282px' : 'auto' }}
disabled={Boolean(disableReason)}
tooltipProps={{
title: disableReason ? disableReason : undefined,
}}
>
Use template
</PermissionButton>
</>
) : null}
<PermissionButton <PermissionButton
data-testid='ADD_STRATEGY_BUTTON' data-testid='ADD_STRATEGY_BUTTON'
permission={CREATE_FEATURE_STRATEGY} permission={CREATE_FEATURE_STRATEGY}
@ -198,6 +228,7 @@ export const FeatureStrategyMenu = ({
projectId={projectId} projectId={projectId}
featureId={featureId} featureId={featureId}
environmentId={environmentId} environmentId={environmentId}
onlyReleasePlans={onlyReleasePlans}
onAddReleasePlan={(template) => { onAddReleasePlan={(template) => {
setSelectedTemplate(template); setSelectedTemplate(template);
setAddReleasePlanOpen(true); setAddReleasePlanOpen(true);

View File

@ -10,6 +10,7 @@ interface IFeatureStrategyMenuCardsProps {
projectId: string; projectId: string;
featureId: string; featureId: string;
environmentId: string; environmentId: string;
onlyReleasePlans: boolean;
onAddReleasePlan: (template: IReleasePlanTemplate) => void; onAddReleasePlan: (template: IReleasePlanTemplate) => void;
} }
@ -22,10 +23,12 @@ export const FeatureStrategyMenuCards = ({
projectId, projectId,
featureId, featureId,
environmentId, environmentId,
onlyReleasePlans,
onAddReleasePlan, onAddReleasePlan,
}: IFeatureStrategyMenuCardsProps) => { }: IFeatureStrategyMenuCardsProps) => {
const { strategies } = useStrategies(); const { strategies } = useStrategies();
const { templates } = useReleasePlanTemplates(); const { templates } = useReleasePlanTemplates();
const allStrategies = !onlyReleasePlans;
const preDefinedStrategies = strategies.filter( const preDefinedStrategies = strategies.filter(
(strategy) => !strategy.deprecated && !strategy.editable, (strategy) => !strategy.deprecated && !strategy.editable,
@ -43,20 +46,22 @@ export const FeatureStrategyMenuCards = ({
}; };
return ( return (
<List dense> <List dense>
<> {allStrategies ? (
<StyledTypography color='textSecondary'> <>
Default strategy for {environmentId} environment <StyledTypography color='textSecondary'>
</StyledTypography> Default strategy for {environmentId} environment
<ListItem key={defaultStrategy.name}> </StyledTypography>
<FeatureStrategyMenuCard <ListItem key={defaultStrategy.name}>
projectId={projectId} <FeatureStrategyMenuCard
featureId={featureId} projectId={projectId}
environmentId={environmentId} featureId={featureId}
strategy={defaultStrategy} environmentId={environmentId}
defaultStrategy={true} strategy={defaultStrategy}
/> defaultStrategy={true}
</ListItem> />
</> </ListItem>
</>
) : null}
<ConditionallyRender <ConditionallyRender
condition={templates.length > 0} condition={templates.length > 0}
show={ show={
@ -75,39 +80,43 @@ export const FeatureStrategyMenuCards = ({
</> </>
} }
/> />
<StyledTypography color='textSecondary'> {allStrategies ? (
Predefined strategy types <>
</StyledTypography> <StyledTypography color='textSecondary'>
{preDefinedStrategies.map((strategy) => ( Predefined strategy types
<ListItem key={strategy.name}> </StyledTypography>
<FeatureStrategyMenuCard {preDefinedStrategies.map((strategy) => (
projectId={projectId} <ListItem key={strategy.name}>
featureId={featureId} <FeatureStrategyMenuCard
environmentId={environmentId} projectId={projectId}
strategy={strategy} featureId={featureId}
environmentId={environmentId}
strategy={strategy}
/>
</ListItem>
))}
<ConditionallyRender
condition={customStrategies.length > 0}
show={
<>
<StyledTypography color='textSecondary'>
Custom strategies
</StyledTypography>
{customStrategies.map((strategy) => (
<ListItem key={strategy.name}>
<FeatureStrategyMenuCard
projectId={projectId}
featureId={featureId}
environmentId={environmentId}
strategy={strategy}
/>
</ListItem>
))}
</>
}
/> />
</ListItem> </>
))} ) : null}
<ConditionallyRender
condition={customStrategies.length > 0}
show={
<>
<StyledTypography color='textSecondary'>
Custom strategies
</StyledTypography>
{customStrategies.map((strategy) => (
<ListItem key={strategy.name}>
<FeatureStrategyMenuCard
projectId={projectId}
featureId={featureId}
environmentId={environmentId}
strategy={strategy}
/>
</ListItem>
))}
</>
}
/>
</List> </List>
); );
}; };