1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-28 00:17:12 +01:00

feat: show a dialog when adding a release plan to a change request enabled feature environment (#9139)

This commit is contained in:
David Leek 2025-01-23 13:48:44 +01:00 committed by GitHub
parent e774ba1b2a
commit 7aefc573dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 108 additions and 11 deletions

View File

@ -7,6 +7,8 @@ import { useReleasePlansApi } from 'hooks/api/actions/useReleasePlansApi/useRele
import useToast from 'hooks/useToast'; import useToast from 'hooks/useToast';
import { formatUnknownError } from 'utils/formatUnknownError'; import { formatUnknownError } from 'utils/formatUnknownError';
import { useReleasePlans } from 'hooks/api/getters/useReleasePlans/useReleasePlans'; import { useReleasePlans } from 'hooks/api/getters/useReleasePlans/useReleasePlans';
import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled';
import { useUiFlag } from 'hooks/useUiFlag';
const StyledIcon = styled('div')(({ theme }) => ({ const StyledIcon = styled('div')(({ theme }) => ({
width: theme.spacing(4), width: theme.spacing(4),
@ -51,6 +53,7 @@ interface IFeatureReleasePlanCardProps {
featureId: string; featureId: string;
environmentId: string; environmentId: string;
releasePlanTemplate: IReleasePlanTemplate; releasePlanTemplate: IReleasePlanTemplate;
setTemplateForChangeRequestDialog: (template: IReleasePlanTemplate) => void;
} }
export const FeatureReleasePlanCard = ({ export const FeatureReleasePlanCard = ({
@ -58,26 +61,38 @@ export const FeatureReleasePlanCard = ({
featureId, featureId,
environmentId, environmentId,
releasePlanTemplate, releasePlanTemplate,
setTemplateForChangeRequestDialog,
}: IFeatureReleasePlanCardProps) => { }: IFeatureReleasePlanCardProps) => {
const Icon = getFeatureStrategyIcon('releasePlanTemplate'); const Icon = getFeatureStrategyIcon('releasePlanTemplate');
const { trackEvent } = usePlausibleTracker(); const { trackEvent } = usePlausibleTracker();
const { refetch } = useReleasePlans(projectId, featureId, environmentId); const { refetch } = useReleasePlans(projectId, featureId, environmentId);
const { addReleasePlanToFeature } = useReleasePlansApi(); const { addReleasePlanToFeature } = useReleasePlansApi();
const { setToastApiError, setToastData } = useToast(); const { setToastApiError, setToastData } = useToast();
const { isChangeRequestConfigured } = useChangeRequestsEnabled(projectId);
const releasePlanChangeRequestsEnabled = useUiFlag(
'releasePlanChangeRequests',
);
const addReleasePlan = async () => { const addReleasePlan = async () => {
try { try {
await addReleasePlanToFeature( if (
featureId, releasePlanChangeRequestsEnabled &&
releasePlanTemplate.id, isChangeRequestConfigured(environmentId)
projectId, ) {
environmentId, setTemplateForChangeRequestDialog(releasePlanTemplate);
); } else {
setToastData({ await addReleasePlanToFeature(
type: 'success', featureId,
text: 'Release plan added', releasePlanTemplate.id,
}); projectId,
refetch(); environmentId,
);
setToastData({
type: 'success',
text: 'Release plan added',
});
refetch();
}
} catch (error: unknown) { } catch (error: unknown) {
setToastApiError(formatUnknownError(error)); setToastApiError(formatUnknownError(error));
} }

View File

@ -11,6 +11,8 @@ import { formatCreateStrategyPath } from '../FeatureStrategyCreate/FeatureStrate
import MoreVert from '@mui/icons-material/MoreVert'; import MoreVert from '@mui/icons-material/MoreVert';
import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
import { useUiFlag } from 'hooks/useUiFlag'; import { useUiFlag } from 'hooks/useUiFlag';
import { ReleasePlanAddChangeRequestDialog } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanAddChangeRequestDialog';
import type { IReleasePlanTemplate } from 'interfaces/releasePlans';
interface IFeatureStrategyMenuProps { interface IFeatureStrategyMenuProps {
label: string; label: string;
@ -50,6 +52,8 @@ export const FeatureStrategyMenu = ({
const [anchor, setAnchor] = useState<Element>(); const [anchor, setAnchor] = useState<Element>();
const navigate = useNavigate(); const navigate = useNavigate();
const { trackEvent } = usePlausibleTracker(); const { trackEvent } = usePlausibleTracker();
const [templateForChangeRequestDialog, setTemplateForChangeRequestDialog] =
useState<IReleasePlanTemplate | undefined>();
const isPopoverOpen = Boolean(anchor); const isPopoverOpen = Boolean(anchor);
const popoverId = isPopoverOpen ? 'FeatureStrategyMenuPopover' : undefined; const popoverId = isPopoverOpen ? 'FeatureStrategyMenuPopover' : undefined;
const flagOverviewRedesignEnabled = useUiFlag('flagOverviewRedesign'); const flagOverviewRedesignEnabled = useUiFlag('flagOverviewRedesign');
@ -115,6 +119,9 @@ export const FeatureStrategyMenu = ({
projectId={projectId} projectId={projectId}
featureId={featureId} featureId={featureId}
environmentId={environmentId} environmentId={environmentId}
setTemplateForChangeRequestDialog={
setTemplateForChangeRequestDialog
}
/> />
</Popover> </Popover>
</StyledStrategyMenu> </StyledStrategyMenu>
@ -175,8 +182,17 @@ export const FeatureStrategyMenu = ({
projectId={projectId} projectId={projectId}
featureId={featureId} featureId={featureId}
environmentId={environmentId} environmentId={environmentId}
setTemplateForChangeRequestDialog={
setTemplateForChangeRequestDialog
}
/> />
</Popover> </Popover>
<ReleasePlanAddChangeRequestDialog
onClosing={() => setTemplateForChangeRequestDialog(undefined)}
featureId={featureId}
environmentId={environmentId}
releaseTemplate={templateForChangeRequestDialog}
/>
</StyledStrategyMenu> </StyledStrategyMenu>
); );
}; };

View File

@ -4,11 +4,13 @@ import { FeatureStrategyMenuCard } from '../FeatureStrategyMenuCard/FeatureStrat
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { useReleasePlanTemplates } from 'hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplates'; import { useReleasePlanTemplates } from 'hooks/api/getters/useReleasePlanTemplates/useReleasePlanTemplates';
import { FeatureReleasePlanCard } from '../FeatureReleasePlanCard/FeatureReleasePlanCard'; import { FeatureReleasePlanCard } from '../FeatureReleasePlanCard/FeatureReleasePlanCard';
import type { IReleasePlanTemplate } from 'interfaces/releasePlans';
interface IFeatureStrategyMenuCardsProps { interface IFeatureStrategyMenuCardsProps {
projectId: string; projectId: string;
featureId: string; featureId: string;
environmentId: string; environmentId: string;
setTemplateForChangeRequestDialog: (template: IReleasePlanTemplate) => void;
} }
const StyledTypography = styled(Typography)(({ theme }) => ({ const StyledTypography = styled(Typography)(({ theme }) => ({
@ -20,6 +22,7 @@ export const FeatureStrategyMenuCards = ({
projectId, projectId,
featureId, featureId,
environmentId, environmentId,
setTemplateForChangeRequestDialog,
}: IFeatureStrategyMenuCardsProps) => { }: IFeatureStrategyMenuCardsProps) => {
const { strategies } = useStrategies(); const { strategies } = useStrategies();
const { templates } = useReleasePlanTemplates(); const { templates } = useReleasePlanTemplates();
@ -68,6 +71,9 @@ export const FeatureStrategyMenuCards = ({
featureId={featureId} featureId={featureId}
environmentId={environmentId} environmentId={environmentId}
releasePlanTemplate={template} releasePlanTemplate={template}
setTemplateForChangeRequestDialog={
setTemplateForChangeRequestDialog
}
/> />
</ListItem> </ListItem>
))} ))}

View File

@ -0,0 +1,60 @@
import { Dialogue } from 'component/common/Dialogue/Dialogue';
import useToast from 'hooks/useToast';
import { styled, Button } from '@mui/material';
import type { IReleasePlanTemplate } from 'interfaces/releasePlans';
const StyledBoldSpan = styled('span')(({ theme }) => ({
fontWeight: theme.typography.fontWeightBold,
}));
interface IReleasePlanAddChangeRequestDialogProps {
featureId: string;
environmentId: string;
releaseTemplate: IReleasePlanTemplate | undefined;
onClosing: () => void;
}
export const ReleasePlanAddChangeRequestDialog = ({
featureId,
environmentId,
releaseTemplate,
onClosing,
}: IReleasePlanAddChangeRequestDialogProps) => {
const { setToastData } = useToast();
const addReleasePlanToChangeRequest = async () => {
setToastData({
type: 'success',
text: 'Added to draft',
});
onClosing();
};
return (
<Dialogue
title='Request changes'
open={Boolean(releaseTemplate)}
secondaryButtonText='Cancel'
onClose={() => {
onClosing();
}}
customButton={
<Button
color='primary'
variant='contained'
onClick={addReleasePlanToChangeRequest}
autoFocus={true}
>
Add suggestion to draft
</Button>
}
>
<p>
<StyledBoldSpan>Add</StyledBoldSpan> release template{' '}
<StyledBoldSpan>{releaseTemplate?.name}</StyledBoldSpan> to{' '}
<StyledBoldSpan>{featureId}</StyledBoldSpan> in{' '}
<StyledBoldSpan>{environmentId}</StyledBoldSpan>
</p>
</Dialogue>
);
};