1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-04-10 01:16:39 +02:00

chore: track metrics for how many CRs are moved into next state with conflicts (#6109)

Use React's context to track how many CRs are moved into their next
state with conflicts present.

This PR wraps environment change requests and change request overviews
in a change request plausible context that contains a
`willOverwriteStrategyChanges` property. This property is updated by the
diff calculation if there are any conflicts and then read by the
`changeState` function in the `useChangeRequestApi` hook.

As long as at least one of the strategies in the CR contain conflicts,
it will be marked as overwriting changes.
This commit is contained in:
Thomas Heartman 2024-02-05 18:27:11 +09:00 committed by GitHub
parent 1d18187f7d
commit 73c4c62ea3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 87 additions and 26 deletions

View File

@ -1,8 +1,10 @@
import { Box, styled } from '@mui/material';
import { IChangeRequestUpdateStrategy } from 'component/changeRequest/changeRequest.types';
import { useChangeRequestPlausibleContext } from 'component/changeRequest/ChangeRequestContext';
import { useUiFlag } from 'hooks/useUiFlag';
import { IFeatureStrategy } from 'interfaces/strategy';
import { getChangesThatWouldBeOverwritten } from './strategy-change-diff-calculation';
import { useEffect } from 'react';
const ChangesToOverwriteWarning = styled(Box)(({ theme }) => ({
color: theme.palette.warning.dark,
@ -76,6 +78,14 @@ export const ChangesToOverwrite: React.FC<{
const changesThatWouldBeOverwritten = checkForChanges
? getChangesThatWouldBeOverwritten(currentStrategy, change)
: null;
const { registerWillOverwriteStrategyChanges } =
useChangeRequestPlausibleContext();
useEffect(() => {
if (changesThatWouldBeOverwritten) {
registerWillOverwriteStrategyChanges();
}
}, [changesThatWouldBeOverwritten]);
if (!changesThatWouldBeOverwritten) {
return null;

View File

@ -0,0 +1,15 @@
import { createContext, useContext } from 'react';
const defaultContext = {
willOverwriteStrategyChanges: false,
registerWillOverwriteStrategyChanges: () => {},
};
const ChangeRequestPlausibleContext = createContext(defaultContext);
export const ChangeRequestPlausibleProvider =
ChangeRequestPlausibleContext.Provider;
export const useChangeRequestPlausibleContext = (): typeof defaultContext => {
return useContext(ChangeRequestPlausibleContext);
};

View File

@ -1,4 +1,4 @@
import { VFC } from 'react';
import { useState, VFC } from 'react';
import { Box, Button, styled, Typography } from '@mui/material';
import { DynamicSidebarModal } from 'component/common/SidebarModal/SidebarModal';
import { PageContent } from 'component/common/PageContent/PageContent';
@ -11,6 +11,7 @@ import useToast from 'hooks/useToast';
import { formatUnknownError } from 'utils/formatUnknownError';
import { EnvironmentChangeRequest } from './EnvironmentChangeRequest/EnvironmentChangeRequest';
import { ReviewChangesHeader } from './ReviewChangesHeader/ReviewChangesHeader';
import { ChangeRequestPlausibleProvider } from '../ChangeRequestContext';
interface IChangeRequestSidebarProps {
open: boolean;
@ -76,15 +77,18 @@ export const ChangeRequestSidebar: VFC<IChangeRequestSidebarProps> = ({
loading,
refetch: refetchChangeRequest,
} = usePendingChangeRequests(project);
const { changeState, discardDraft } = useChangeRequestApi();
const { discardDraft } = useChangeRequestApi();
const { setToastApiError } = useToast();
const [
changeRequestChangesWillOverwrite,
setChangeRequestChangesWillOverwrite,
] = useState(false);
const onReview = async (draftId: number, comment?: string) => {
const onReview = async (
changeState: (project: string) => Promise<void>,
) => {
try {
await changeState(project, draftId, 'Draft', {
state: 'In review',
comment,
});
await changeState(project);
refetchChangeRequest();
} catch (error: unknown) {
setToastApiError(formatUnknownError(error));
@ -130,19 +134,29 @@ export const ChangeRequestSidebar: VFC<IChangeRequestSidebarProps> = ({
header={<ReviewChangesHeader />}
>
{data?.map((environmentChangeRequest) => (
<EnvironmentChangeRequest
<ChangeRequestPlausibleProvider
key={environmentChangeRequest.id}
environmentChangeRequest={environmentChangeRequest}
onClose={onClose}
onReview={onReview}
onDiscard={onDiscard}
value={{
willOverwriteStrategyChanges:
changeRequestChangesWillOverwrite,
registerWillOverwriteStrategyChanges: () =>
setChangeRequestChangesWillOverwrite(true),
}}
>
<ChangeRequest
changeRequest={environmentChangeRequest}
onNavigate={onClose}
onRefetch={refetchChangeRequest}
/>
</EnvironmentChangeRequest>
<EnvironmentChangeRequest
key={environmentChangeRequest.id}
environmentChangeRequest={environmentChangeRequest}
onClose={onClose}
onReview={onReview}
onDiscard={onDiscard}
>
<ChangeRequest
changeRequest={environmentChangeRequest}
onNavigate={onClose}
onRefetch={refetchChangeRequest}
/>
</EnvironmentChangeRequest>
</ChangeRequestPlausibleProvider>
))}
</StyledPageContent>
</DynamicSidebarModal>

View File

@ -23,6 +23,7 @@ import { useAuthUser } from 'hooks/api/getters/useAuth/useAuthUser';
import Input from 'component/common/Input/Input';
import { ChangeRequestTitle } from './ChangeRequestTitle';
import { UpdateCount } from 'component/changeRequest/UpdateCount';
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
const SubmitChangeRequestButton: FC<{ onClick: () => void; count: number }> = ({
onClick,
@ -56,7 +57,7 @@ const ChangeRequestContent = styled(Box)(({ theme }) => ({
export const EnvironmentChangeRequest: FC<{
environmentChangeRequest: ChangeRequestType;
onClose: () => void;
onReview: (id: number, comment?: string) => void;
onReview: (changeState: (project: string) => Promise<void>) => void;
onDiscard: (id: number) => void;
}> = ({ environmentChangeRequest, onClose, onReview, onDiscard, children }) => {
const theme = useTheme();
@ -64,6 +65,12 @@ export const EnvironmentChangeRequest: FC<{
const [commentText, setCommentText] = useState('');
const { user } = useAuthUser();
const [title, setTitle] = useState(environmentChangeRequest.title);
const { changeState } = useChangeRequestApi();
const sendToReview = async (project: string) =>
changeState(project, environmentChangeRequest.id, 'Draft', {
state: 'In review',
comment: commentText,
});
return (
<Box key={environmentChangeRequest.id}>
@ -141,12 +148,7 @@ export const EnvironmentChangeRequest: FC<{
show={
<>
<SubmitChangeRequestButton
onClick={() =>
onReview(
environmentChangeRequest.id,
commentText,
)
}
onClick={() => onReview(sendToReview)}
count={changesCount(
environmentChangeRequest,
)}

View File

@ -41,6 +41,7 @@ import { Badge } from 'component/common/Badge/Badge';
import { ProjectDoraMetrics } from './ProjectDoraMetrics/ProjectDoraMetrics';
import { UiFlags } from 'interfaces/uiConfig';
import { HiddenProjectIconWithTooltip } from './HiddenProjectIconWithTooltip/HiddenProjectIconWithTooltip';
import { ChangeRequestPlausibleProvider } from 'component/changeRequest/ChangeRequestContext';
const StyledBadge = styled(Badge)(({ theme }) => ({
position: 'absolute',
@ -76,6 +77,11 @@ export const Project = () => {
const [showDelDialog, setShowDelDialog] = useState(false);
const [
changeRequestChangesWillOverwrite,
setChangeRequestChangesWillOverwrite,
] = useState(false);
const tabs: ITab[] = [
{
title: 'Overview',
@ -293,7 +299,18 @@ export const Project = () => {
/>
<Route
path='change-requests/:id'
element={<ChangeRequestOverview />}
element={
<ChangeRequestPlausibleProvider
value={{
willOverwriteStrategyChanges:
changeRequestChangesWillOverwrite,
registerWillOverwriteStrategyChanges: () =>
setChangeRequestChangesWillOverwrite(true),
}}
>
<ChangeRequestOverview />
</ChangeRequestPlausibleProvider>
}
/>
<Route path='settings/*' element={<ProjectSettings />} />
<Route path='metrics' element={<ProjectDoraMetrics />} />

View File

@ -3,6 +3,7 @@ import { usePlausibleTracker } from '../../../usePlausibleTracker';
import { PlausibleChangeRequestState } from 'component/changeRequest/changeRequest.types';
import { getUniqueChangeRequestId } from 'utils/unique-change-request-id';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { useChangeRequestPlausibleContext } from 'component/changeRequest/ChangeRequestContext';
export interface IChangeSchema {
feature: string | null;
@ -33,6 +34,7 @@ export const useChangeRequestApi = () => {
propagateErrors: true,
});
const { uiConfig } = useUiConfig();
const { willOverwriteStrategyChanges } = useChangeRequestPlausibleContext();
const addChange = async (
project: string,
@ -75,6 +77,7 @@ export const useChangeRequestApi = () => {
props: {
eventType: payload.state,
previousState,
willOverwriteStrategyChanges,
id: getUniqueChangeRequestId(uiConfig, changeRequestId),
},
});