forked from evergreen-ci/spruce
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
EVG-19954: Force save when changing providers (evergreen-ci#2028)
- Loading branch information
Showing
7 changed files
with
263 additions
and
105 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
import { useState } from "react"; | ||
import { useMutation } from "@apollo/client"; | ||
import styled from "@emotion/styled"; | ||
import { Radio, RadioGroup } from "@leafygreen-ui/radio-group"; | ||
import { Body, BodyProps } from "@leafygreen-ui/typography"; | ||
import pluralize from "pluralize"; | ||
import { useDistroSettingsAnalytics } from "analytics"; | ||
import { ConfirmationModal } from "components/ConfirmationModal"; | ||
import { size } from "constants/tokens"; | ||
import { useToastContext } from "context/toast"; | ||
import { | ||
DistroOnSaveOperation, | ||
DistroQuery, | ||
SaveDistroMutation, | ||
SaveDistroMutationVariables, | ||
} from "gql/generated/types"; | ||
import { SAVE_DISTRO } from "gql/mutations"; | ||
import { useDistroSettingsContext } from "./Context"; | ||
import { formToGqlMap } from "./tabs/transformers"; | ||
import { FormToGqlFunction, WritableDistroSettingsType } from "./tabs/types"; | ||
|
||
type SaveModalProps = { | ||
banner?: React.ReactNode; | ||
distro: DistroQuery["distro"]; | ||
onCancel?: () => void; | ||
onConfirm?: () => void; | ||
open: boolean; | ||
tab: WritableDistroSettingsType; | ||
}; | ||
|
||
export const SaveModal: React.FC<SaveModalProps> = ({ | ||
banner, | ||
distro, | ||
onCancel, | ||
onConfirm, | ||
open, | ||
tab, | ||
}) => { | ||
const { sendEvent } = useDistroSettingsAnalytics(); | ||
const dispatchToast = useToastContext(); | ||
|
||
const { getTab, saveTab } = useDistroSettingsContext(); | ||
const { formData } = getTab(tab); | ||
const [onSaveOperation, setOnSaveOperation] = useState( | ||
DistroOnSaveOperation.None | ||
); | ||
|
||
const [saveDistro] = useMutation< | ||
SaveDistroMutation, | ||
SaveDistroMutationVariables | ||
>(SAVE_DISTRO, { | ||
onCompleted({ saveDistro: { hostCount } }) { | ||
saveTab(tab); | ||
dispatchToast.success( | ||
`Updated distro${ | ||
onSaveOperation !== DistroOnSaveOperation.None | ||
? ` and scheduled ${hostCount} ${pluralize( | ||
"host", | ||
hostCount | ||
)} to update` | ||
: "" | ||
}.` | ||
); | ||
}, | ||
onError(err) { | ||
dispatchToast.error(err.message); | ||
}, | ||
refetchQueries: ["Distro"], | ||
}); | ||
|
||
const handleSave = () => { | ||
// Only perform the save operation if the tab is valid. | ||
// eslint-disable-next-line no-prototype-builtins | ||
if (formToGqlMap.hasOwnProperty(tab)) { | ||
const formToGql: FormToGqlFunction<typeof tab> = formToGqlMap[tab]; | ||
const changes = formToGql(formData, distro); | ||
saveDistro({ | ||
variables: { | ||
distro: changes, | ||
onSave: onSaveOperation, | ||
}, | ||
}); | ||
sendEvent({ name: "Save distro", section: tab }); | ||
} | ||
}; | ||
|
||
return ( | ||
<ConfirmationModal | ||
buttonText="Save" | ||
data-cy="save-modal" | ||
open={open} | ||
onCancel={() => { | ||
onCancel?.(); | ||
}} | ||
onConfirm={() => { | ||
onConfirm?.(); | ||
handleSave(); | ||
}} | ||
title="Save page" | ||
> | ||
{banner} | ||
<StyledBody> | ||
Evergreen can perform one of the following actions on save: | ||
</StyledBody> | ||
<RadioGroup | ||
onChange={(e) => | ||
setOnSaveOperation(e.target.value as DistroOnSaveOperation) | ||
} | ||
value={onSaveOperation} | ||
> | ||
<Radio value={DistroOnSaveOperation.None}> | ||
Nothing, only new hosts will have updated distro settings applied | ||
</Radio> | ||
<Radio value={DistroOnSaveOperation.Decommission}> | ||
Decommission hosts of this distro | ||
</Radio> | ||
<Radio value={DistroOnSaveOperation.RestartJasper}> | ||
Restart Jasper service on running hosts of this distro | ||
</Radio> | ||
<Radio value={DistroOnSaveOperation.Reprovision}> | ||
Reprovision running hosts of this distro | ||
</Radio> | ||
</RadioGroup> | ||
</ConfirmationModal> | ||
); | ||
}; | ||
|
||
const StyledBody = styled(Body)<BodyProps>` | ||
margin-bottom: ${size.xs}; | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,36 @@ | ||
import { useMemo } from "react"; | ||
import { useDistroSettingsContext } from "../../Context"; | ||
import { BaseTab } from "../BaseTab"; | ||
import { | ||
FormToGqlFunction, | ||
WritableDistroSettingsTabs, | ||
WritableDistroSettingsType, | ||
} from "../types"; | ||
import { getFormSchema } from "./getFormSchema"; | ||
import { TabProps } from "./types"; | ||
|
||
export const ProviderTab: React.FC<TabProps> = ({ distroData }) => { | ||
const initialFormState = distroData; | ||
import { ProviderFormState, TabProps } from "./types"; | ||
import { UnsavedModal } from "./UnsavedModal"; | ||
|
||
export const ProviderTab: React.FC<TabProps> = ({ distro, distroData }) => { | ||
const formSchema = useMemo(() => getFormSchema(), []); | ||
|
||
const { getTab } = useDistroSettingsContext(); | ||
|
||
// @ts-expect-error - see TabState for details. | ||
const { | ||
formData, | ||
initialData, | ||
}: { | ||
formData: ProviderFormState; | ||
initialData: ReturnType<FormToGqlFunction<WritableDistroSettingsType>>; | ||
} = getTab(WritableDistroSettingsTabs.Provider); | ||
|
||
return ( | ||
<BaseTab formSchema={formSchema} initialFormState={initialFormState} /> | ||
<> | ||
{/* Use conditional rendering instead of the shouldBlock prop so that modifying fields other than the provider triggers the standard navigation warning modal */} | ||
{initialData?.provider !== formData?.provider?.providerName && ( | ||
<UnsavedModal distro={distro} shouldBlock /> | ||
)} | ||
<BaseTab formSchema={formSchema} initialFormState={distroData} /> | ||
</> | ||
); | ||
}; |
Oops, something went wrong.