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

feat: read only milestone progression in cr (#10882)

This commit is contained in:
Mateusz Kwasniewski 2025-10-29 09:54:39 +01:00 committed by GitHub
parent 25abe054a4
commit c2ec77ba6e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 67 additions and 38 deletions

View File

@ -144,13 +144,7 @@ export const ConsolidatedProgressionChanges: FC<{
</ChangeItemWrapper> </ChangeItemWrapper>
<TabPanel> <TabPanel>
{readonly ? ( {readonly ? (
<ReadonlyMilestoneListRenderer <ReadonlyMilestoneListRenderer plan={modifiedPlan} />
plan={modifiedPlan}
milestonesWithAutomation={milestonesWithAutomation}
milestonesWithDeletedAutomation={
milestonesWithDeletedAutomation
}
/>
) : ( ) : (
<EditableMilestoneListRenderer <EditableMilestoneListRenderer
plan={modifiedPlan} plan={modifiedPlan}

View File

@ -3,7 +3,10 @@ import type { IReleasePlan } from 'interfaces/releasePlans';
import type { ChangeMilestoneProgressionSchema } from 'openapi'; import type { ChangeMilestoneProgressionSchema } from 'openapi';
import { ReleasePlanMilestone } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestone'; import { ReleasePlanMilestone } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestone';
import { MilestoneAutomationSection } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/MilestoneAutomationSection.tsx'; import { MilestoneAutomationSection } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/MilestoneAutomationSection.tsx';
import { MilestoneTransitionDisplay } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/MilestoneTransitionDisplay.tsx'; import {
MilestoneTransitionDisplay,
ReadonlyMilestoneTransitionDisplay,
} from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/MilestoneTransitionDisplay.tsx';
import type { MilestoneStatus } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestoneStatus.tsx'; import type { MilestoneStatus } from 'component/feature/FeatureView/FeatureOverview/ReleasePlan/ReleasePlanMilestone/ReleasePlanMilestoneStatus.tsx';
import { Badge } from 'component/common/Badge/Badge'; import { Badge } from 'component/common/Badge/Badge';
@ -41,9 +44,10 @@ const MilestoneListRendererCore = ({
{plan.milestones.map((milestone, index) => { {plan.milestones.map((milestone, index) => {
const isNotLastMilestone = index < plan.milestones.length - 1; const isNotLastMilestone = index < plan.milestones.length - 1;
const nextMilestoneId = plan.milestones[index + 1]?.id || ''; const nextMilestoneId = plan.milestones[index + 1]?.id || '';
const shouldShowAutomation = const shouldShowAutomation = readonly
milestonesWithAutomation.has(milestone.id) || ? milestone.transitionCondition !== undefined
milestonesWithDeletedAutomation.has(milestone.id); : milestonesWithAutomation.has(milestone.id) ||
milestonesWithDeletedAutomation.has(milestone.id);
const showAutomation = const showAutomation =
isNotLastMilestone && shouldShowAutomation; isNotLastMilestone && shouldShowAutomation;
@ -64,27 +68,39 @@ const MilestoneListRendererCore = ({
const automationSection = const automationSection =
showAutomation && milestone.transitionCondition ? ( showAutomation && milestone.transitionCondition ? (
<MilestoneAutomationSection status={status}> <MilestoneAutomationSection status={status}>
<MilestoneTransitionDisplay {readonly ? (
intervalMinutes={ <ReadonlyMilestoneTransitionDisplay
milestone.transitionCondition intervalMinutes={
.intervalMinutes milestone.transitionCondition
} .intervalMinutes
targetMilestoneId={nextMilestoneId} }
sourceMilestoneStartedAt={milestone.startedAt} status={status}
onSave={async (payload) => { />
await onUpdateAutomation( ) : (
milestone.id, <MilestoneTransitionDisplay
payload, intervalMinutes={
); milestone.transitionCondition
return { shouldReset: true }; .intervalMinutes
}} }
onDelete={() => targetMilestoneId={nextMilestoneId}
onDeleteAutomation(milestone.id) sourceMilestoneStartedAt={
} milestone.startedAt
milestoneName={milestone.name} }
status={status} onSave={async (payload) => {
badge={badge} await onUpdateAutomation(
/> milestone.id,
payload,
);
return { shouldReset: true };
}}
onDelete={() =>
onDeleteAutomation(milestone.id)
}
milestoneName={milestone.name}
status={status}
badge={badge}
/>
)}
</MilestoneAutomationSection> </MilestoneAutomationSection>
) : undefined; ) : undefined;

View File

@ -87,12 +87,7 @@ export const ProgressionChange: FC<ProgressionChangeProps> = ({
</ChangeItemWrapper> </ChangeItemWrapper>
<TabPanel> <TabPanel>
{readonly ? ( {readonly ? (
<ReadonlyMilestoneListRenderer <ReadonlyMilestoneListRenderer plan={modifiedPlan} />
plan={modifiedPlan}
milestonesWithAutomation={
new Set([sourceId].filter(Boolean))
}
/>
) : ( ) : (
<EditableMilestoneListRenderer <EditableMilestoneListRenderer
plan={modifiedPlan} plan={modifiedPlan}

View File

@ -109,6 +109,30 @@ interface IMilestoneTransitionDisplayProps {
badge?: ReactNode; badge?: ReactNode;
} }
export const ReadonlyMilestoneTransitionDisplay = ({
intervalMinutes,
status,
}: {
intervalMinutes: number;
status?: MilestoneStatus;
}) => {
const initial = getTimeValueAndUnitFromMinutes(intervalMinutes);
return (
<StyledDisplayContainer>
<StyledContentGroup>
<StyledIcon status={status} />
<StyledLabel status={status}>
Proceed to the next milestone after
</StyledLabel>
<span style={{ fontSize: 'inherit' }}>
{initial.value} {initial.unit}
</span>
</StyledContentGroup>
</StyledDisplayContainer>
);
};
export const MilestoneTransitionDisplay = ({ export const MilestoneTransitionDisplay = ({
intervalMinutes, intervalMinutes,
targetMilestoneId, targetMilestoneId,