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 { constraintId } from 'component/common/ConstraintAccordion/ConstraintAccordionList/createEmptyConstraint';
|
||||
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 [previousTitle, setPreviousTitle] = useState<string>('');
|
||||
@ -103,7 +108,7 @@ export const NewFeatureStrategyEdit = () => {
|
||||
const navigate = useNavigate();
|
||||
const { addChange } = useChangeRequestApi();
|
||||
const { isChangeRequestConfigured } = useChangeRequestsEnabled(projectId);
|
||||
const { refetch: refetchChangeRequests } =
|
||||
const { refetch: refetchChangeRequests, data: pendingChangeRequests } =
|
||||
usePendingChangeRequests(projectId);
|
||||
const { setPreviousTitle } = useTitleTracking();
|
||||
|
||||
@ -134,6 +139,37 @@ export const NewFeatureStrategyEdit = () => {
|
||||
}
|
||||
}, [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 {
|
||||
segments: savedStrategySegments,
|
||||
refetchSegments: refetchSavedStrategySegments,
|
||||
@ -201,6 +237,7 @@ export const NewFeatureStrategyEdit = () => {
|
||||
} else {
|
||||
await onStrategyEdit(payload);
|
||||
}
|
||||
emitConflictsCreatedEvents();
|
||||
refetchFeature();
|
||||
navigate(formatFeaturePath(projectId, featureId));
|
||||
} 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