1
0
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:
andreas-unleash 2024-02-26 13:59:47 +02:00 committed by GitHub
parent 12a085f5a0
commit 4c340a5224
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 206 additions and 1 deletions

View File

@ -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) {

View File

@ -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`,
},
]);
});

View File

@ -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,
})) ?? [];