mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-20 00:08:02 +01:00
fix: track conflicts in new strategy screen (#6337)
Fixes a bug where the conflict tracking was only in the old feature strategy edit screen. - Ports the conflict tracking to the NewFeatureStrategyEdit screen Closes # [1-2093](https://linear.app/unleash/issue/1-2093/cr-conflict-detection-in-new-strategy-edit-screen) --------- Signed-off-by: andreas-unleash <andreas@getunleash.ai>
This commit is contained in:
parent
12a085f5a0
commit
4c340a5224
@ -30,6 +30,11 @@ import { NewFeatureStrategyForm } from 'component/feature/FeatureStrategy/Featur
|
|||||||
import { NewStrategyVariants } from 'component/feature/StrategyTypes/NewStrategyVariants';
|
import { NewStrategyVariants } from 'component/feature/StrategyTypes/NewStrategyVariants';
|
||||||
import { constraintId } from 'component/common/ConstraintAccordion/ConstraintAccordionList/createEmptyConstraint';
|
import { constraintId } from 'component/common/ConstraintAccordion/ConstraintAccordionList/createEmptyConstraint';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
import { useScheduledChangeRequestsWithStrategy } from 'hooks/api/getters/useScheduledChangeRequestsWithStrategy/useScheduledChangeRequestsWithStrategy';
|
||||||
|
import {
|
||||||
|
getChangeRequestConflictCreatedData,
|
||||||
|
getChangeRequestConflictCreatedDataFromScheduleData,
|
||||||
|
} from './change-request-conflict-data';
|
||||||
|
|
||||||
const useTitleTracking = () => {
|
const useTitleTracking = () => {
|
||||||
const [previousTitle, setPreviousTitle] = useState<string>('');
|
const [previousTitle, setPreviousTitle] = useState<string>('');
|
||||||
@ -103,7 +108,7 @@ export const NewFeatureStrategyEdit = () => {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { addChange } = useChangeRequestApi();
|
const { addChange } = useChangeRequestApi();
|
||||||
const { isChangeRequestConfigured } = useChangeRequestsEnabled(projectId);
|
const { isChangeRequestConfigured } = useChangeRequestsEnabled(projectId);
|
||||||
const { refetch: refetchChangeRequests } =
|
const { refetch: refetchChangeRequests, data: pendingChangeRequests } =
|
||||||
usePendingChangeRequests(projectId);
|
usePendingChangeRequests(projectId);
|
||||||
const { setPreviousTitle } = useTitleTracking();
|
const { setPreviousTitle } = useTitleTracking();
|
||||||
|
|
||||||
@ -134,6 +139,37 @@ export const NewFeatureStrategyEdit = () => {
|
|||||||
}
|
}
|
||||||
}, [feature]);
|
}, [feature]);
|
||||||
|
|
||||||
|
const { trackEvent } = usePlausibleTracker();
|
||||||
|
const { changeRequests: scheduledChangeRequestThatUseStrategy } =
|
||||||
|
useScheduledChangeRequestsWithStrategy(projectId, strategyId);
|
||||||
|
|
||||||
|
const pendingCrsUsingThisStrategy = getChangeRequestConflictCreatedData(
|
||||||
|
pendingChangeRequests,
|
||||||
|
featureId,
|
||||||
|
strategyId,
|
||||||
|
uiConfig,
|
||||||
|
);
|
||||||
|
|
||||||
|
const scheduledCrsUsingThisStrategy =
|
||||||
|
getChangeRequestConflictCreatedDataFromScheduleData(
|
||||||
|
scheduledChangeRequestThatUseStrategy,
|
||||||
|
uiConfig,
|
||||||
|
);
|
||||||
|
|
||||||
|
const emitConflictsCreatedEvents = (): void =>
|
||||||
|
[
|
||||||
|
...pendingCrsUsingThisStrategy,
|
||||||
|
...scheduledCrsUsingThisStrategy,
|
||||||
|
].forEach((data) =>
|
||||||
|
trackEvent('change_request', {
|
||||||
|
props: {
|
||||||
|
...data,
|
||||||
|
action: 'edit-strategy',
|
||||||
|
eventType: 'conflict-created',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
segments: savedStrategySegments,
|
segments: savedStrategySegments,
|
||||||
refetchSegments: refetchSavedStrategySegments,
|
refetchSegments: refetchSavedStrategySegments,
|
||||||
@ -201,6 +237,7 @@ export const NewFeatureStrategyEdit = () => {
|
|||||||
} else {
|
} else {
|
||||||
await onStrategyEdit(payload);
|
await onStrategyEdit(payload);
|
||||||
}
|
}
|
||||||
|
emitConflictsCreatedEvents();
|
||||||
refetchFeature();
|
refetchFeature();
|
||||||
navigate(formatFeaturePath(projectId, featureId));
|
navigate(formatFeaturePath(projectId, featureId));
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
|
@ -0,0 +1,113 @@
|
|||||||
|
import { IUiConfig } from 'interfaces/uiConfig';
|
||||||
|
import {
|
||||||
|
getChangeRequestConflictCreatedData,
|
||||||
|
getChangeRequestConflictCreatedDataFromScheduleData,
|
||||||
|
} from './change-request-conflict-data';
|
||||||
|
|
||||||
|
const uiConfig: Pick<IUiConfig, 'baseUriPath' | 'versionInfo'> = {
|
||||||
|
baseUriPath: '/some-base-uri',
|
||||||
|
};
|
||||||
|
const unleashIdentifier = uiConfig.baseUriPath;
|
||||||
|
const featureId = 'flag-with-deleted-scheduler';
|
||||||
|
const strategyId = 'ed2ffa14-004c-4ed1-931b-78761681c54a';
|
||||||
|
|
||||||
|
const changeRequestWithStrategy = {
|
||||||
|
id: 105,
|
||||||
|
features: [
|
||||||
|
{
|
||||||
|
name: featureId,
|
||||||
|
changes: [
|
||||||
|
{
|
||||||
|
action: 'updateStrategy' as const,
|
||||||
|
payload: {
|
||||||
|
id: strategyId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
state: 'In review' as const,
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeRequestWithoutStrategy = {
|
||||||
|
id: 106,
|
||||||
|
features: [
|
||||||
|
{
|
||||||
|
name: featureId,
|
||||||
|
changes: [
|
||||||
|
{
|
||||||
|
action: 'deleteStrategy' as const,
|
||||||
|
payload: {
|
||||||
|
id: strategyId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: featureId,
|
||||||
|
changes: [
|
||||||
|
{
|
||||||
|
action: 'addStrategy' as const,
|
||||||
|
payload: {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
state: 'In review' as const,
|
||||||
|
};
|
||||||
|
|
||||||
|
test('it finds crs that update a strategy', () => {
|
||||||
|
const results = getChangeRequestConflictCreatedData(
|
||||||
|
[changeRequestWithStrategy],
|
||||||
|
featureId,
|
||||||
|
strategyId,
|
||||||
|
uiConfig,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(results).toStrictEqual([
|
||||||
|
{
|
||||||
|
state: changeRequestWithStrategy.state,
|
||||||
|
changeRequest: `${unleashIdentifier}#${changeRequestWithStrategy.id}`,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it does not return crs that do not update a strategy', () => {
|
||||||
|
const results = getChangeRequestConflictCreatedData(
|
||||||
|
[changeRequestWithoutStrategy],
|
||||||
|
featureId,
|
||||||
|
strategyId,
|
||||||
|
uiConfig,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(results).toStrictEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it maps scheduled change request data', () => {
|
||||||
|
const scheduledChanges = [
|
||||||
|
{
|
||||||
|
id: 103,
|
||||||
|
environment: 'development',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 104,
|
||||||
|
environment: 'development',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const results = getChangeRequestConflictCreatedDataFromScheduleData(
|
||||||
|
scheduledChanges,
|
||||||
|
uiConfig,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(results).toStrictEqual([
|
||||||
|
{
|
||||||
|
state: 'Scheduled',
|
||||||
|
changeRequest: `${unleashIdentifier}#103`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
state: 'Scheduled',
|
||||||
|
changeRequest: `${unleashIdentifier}#104`,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
@ -0,0 +1,55 @@
|
|||||||
|
import {
|
||||||
|
ChangeRequestState,
|
||||||
|
ChangeRequestType,
|
||||||
|
IChangeRequestFeature,
|
||||||
|
IFeatureChange,
|
||||||
|
} from 'component/changeRequest/changeRequest.types';
|
||||||
|
import { ScheduledChangeRequestViewModel } from 'hooks/api/getters/useScheduledChangeRequestsWithStrategy/useScheduledChangeRequestsWithStrategy';
|
||||||
|
import { IUiConfig } from 'interfaces/uiConfig';
|
||||||
|
import { getUniqueChangeRequestId } from 'utils/unique-change-request-id';
|
||||||
|
|
||||||
|
type ChangeRequestConflictCreatedData = {
|
||||||
|
changeRequest: string;
|
||||||
|
state: ChangeRequestState;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getChangeRequestConflictCreatedData = (
|
||||||
|
changeRequests:
|
||||||
|
| {
|
||||||
|
state: ChangeRequestType['state'];
|
||||||
|
id: ChangeRequestType['id'];
|
||||||
|
features: {
|
||||||
|
name: IChangeRequestFeature['name'];
|
||||||
|
changes: (Pick<IFeatureChange, 'action'> & {
|
||||||
|
payload: { id?: number | string };
|
||||||
|
})[];
|
||||||
|
}[];
|
||||||
|
}[]
|
||||||
|
| undefined,
|
||||||
|
featureId: string,
|
||||||
|
strategyId: string,
|
||||||
|
uiConfig: Pick<IUiConfig, 'baseUriPath' | 'versionInfo'>,
|
||||||
|
): ChangeRequestConflictCreatedData[] =>
|
||||||
|
changeRequests
|
||||||
|
?.filter((cr) =>
|
||||||
|
cr.features
|
||||||
|
.find((feature) => feature.name === featureId)
|
||||||
|
?.changes.some(
|
||||||
|
(change) =>
|
||||||
|
change.action === 'updateStrategy' &&
|
||||||
|
change.payload.id === strategyId,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.map((cr) => ({
|
||||||
|
changeRequest: getUniqueChangeRequestId(uiConfig, cr.id),
|
||||||
|
state: cr.state,
|
||||||
|
})) ?? [];
|
||||||
|
|
||||||
|
export const getChangeRequestConflictCreatedDataFromScheduleData = (
|
||||||
|
changeRequests: Pick<ScheduledChangeRequestViewModel, 'id'>[] | undefined,
|
||||||
|
uiConfig: Pick<IUiConfig, 'baseUriPath' | 'versionInfo'>,
|
||||||
|
): ChangeRequestConflictCreatedData[] =>
|
||||||
|
changeRequests?.map((cr) => ({
|
||||||
|
changeRequest: getUniqueChangeRequestId(uiConfig, cr.id),
|
||||||
|
state: 'Scheduled' as const,
|
||||||
|
})) ?? [];
|
Loading…
Reference in New Issue
Block a user