-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of github.com:inmanta/web-console into issue/59…
…86-header-colors
- Loading branch information
Showing
15 changed files
with
300 additions
and
38 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
description: Add button to disable expert mode from the banner | ||
issue-nr: 5942 | ||
change-type: minor | ||
destination-branches: [master, iso7] | ||
sections: | ||
minor-improvement: "{{description}}" |
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,5 @@ | ||
change-type: patch | ||
description: "Build(deps): Bump http-proxy-middleware from 2.0.6 to 2.0.7" | ||
destination-branches: | ||
- master | ||
sections: {} |
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
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 @@ | ||
export * from "./useUpdateEnvConfig"; |
71 changes: 71 additions & 0 deletions
71
src/Data/Managers/V2/POST/UpdateEnvConfig/useUpdateEnvConfig.ts
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,71 @@ | ||
import { | ||
UseMutationResult, | ||
useMutation, | ||
useQueryClient, | ||
} from "@tanstack/react-query"; | ||
import { ParsedNumber } from "@/Core"; | ||
import { PrimaryBaseUrlManager } from "@/UI"; | ||
import { Dict } from "@/UI/Components"; | ||
import { useFetchHelpers } from "../../helpers"; | ||
|
||
interface ConfigUpdate { | ||
id: string; | ||
value: string | boolean | ParsedNumber | Dict; | ||
} | ||
|
||
/** | ||
* React Query hook for updating environment configuration settings. | ||
* | ||
* @param {string} environment - The environment to use for creating headers. | ||
* @returns {UseMutationResult<void, Error, ConfigUpdate, unknown>}- The mutation object from `useMutation` hook. | ||
*/ | ||
export const useUpdateEnvConfig = ( | ||
environment: string, | ||
): UseMutationResult<void, Error, ConfigUpdate, unknown> => { | ||
const client = useQueryClient(); | ||
|
||
const baseUrlManager = new PrimaryBaseUrlManager( | ||
globalThis.location.origin, | ||
globalThis.location.pathname, | ||
); | ||
const { createHeaders, handleErrors } = useFetchHelpers(); | ||
const headers = createHeaders(environment); | ||
const baseUrl = baseUrlManager.getBaseUrl(process.env.API_BASEURL); | ||
|
||
/** | ||
* Update the environment configuration setting. | ||
* | ||
* @param {ConfigUpdate} configUpdate - The info about the config setting to update | ||
* | ||
* @returns {Promise<void>} - The promise object of the fetch request. | ||
* @throws {Error} If the response is not successful, an error with the error message is thrown. | ||
*/ | ||
const updateConfig = async (configUpdate: ConfigUpdate): Promise<void> => { | ||
const { id, value } = configUpdate; | ||
|
||
const response = await fetch( | ||
baseUrl + `/api/v2/environment_settings/${id}`, | ||
{ | ||
method: "POST", | ||
body: JSON.stringify({ value }), | ||
headers, | ||
}, | ||
); | ||
|
||
await handleErrors(response); | ||
}; | ||
|
||
return useMutation({ | ||
mutationFn: updateConfig, | ||
mutationKey: ["update_env_config"], | ||
onSuccess: () => { | ||
client.invalidateQueries({ | ||
queryKey: ["get_env_config"], //for the future rework of the env getter | ||
}); | ||
client.invalidateQueries({ | ||
queryKey: ["get_env_details"], //for the future rework of the env getter | ||
}); | ||
document.dispatchEvent(new Event("settings-update")); | ||
}, | ||
}); | ||
}; |
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,134 @@ | ||
import React, { act } from "react"; | ||
import { MemoryRouter } from "react-router-dom"; | ||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; | ||
import { render, screen, waitFor } from "@testing-library/react"; | ||
import userEvent from "@testing-library/user-event"; | ||
import { StoreProvider } from "easy-peasy"; | ||
import { HttpResponse, http } from "msw"; | ||
import { setupServer } from "msw/node"; | ||
import { getStoreInstance } from "@/Data"; | ||
import * as useUpdateEnvConfig from "@/Data/Managers/V2/POST/UpdateEnvConfig/useUpdateEnvConfig"; //import with that exact path is required for mock to work correctly | ||
import { dependencies } from "@/Test"; | ||
import { DependencyProvider } from "@/UI/Dependency"; | ||
import { ExpertBanner } from "./ExpertBanner"; | ||
|
||
const setup = (flag: boolean) => { | ||
const client = new QueryClient(); | ||
|
||
dependencies.environmentModifier.useIsExpertModeEnabled = jest.fn(() => flag); | ||
const store = getStoreInstance(); | ||
|
||
return ( | ||
<MemoryRouter initialEntries={[{ search: "?env=aaa" }]}> | ||
<DependencyProvider | ||
dependencies={{ | ||
...dependencies, | ||
}} | ||
> | ||
<QueryClientProvider client={client}> | ||
<StoreProvider store={store}> | ||
<ExpertBanner environmentId="aaa" /> | ||
</StoreProvider> | ||
</QueryClientProvider> | ||
</DependencyProvider> | ||
</MemoryRouter> | ||
); | ||
}; | ||
|
||
describe("Given ExpertBanner", () => { | ||
it("When expert_mode is set to true Then should render,", () => { | ||
render(setup(true)); | ||
|
||
expect( | ||
screen.getByText("LSM expert mode is enabled, proceed with caution."), | ||
).toBeVisible(); | ||
|
||
expect(screen.getByText("Disable expert mode")).toBeVisible(); | ||
}); | ||
|
||
it("When expert_mode is set to true AND user clicks to disable expert mode it Then should fire mutation function", async () => { | ||
const mutateSpy = jest.fn(); | ||
const spy = jest | ||
.spyOn(useUpdateEnvConfig, "useUpdateEnvConfig") | ||
.mockReturnValue({ | ||
data: undefined, | ||
error: null, | ||
failureCount: 0, | ||
isError: false, | ||
isIdle: false, | ||
isSuccess: true, | ||
isPending: false, | ||
reset: jest.fn(), | ||
isPaused: false, | ||
context: undefined, | ||
variables: { | ||
id: "", | ||
value: "", | ||
}, | ||
failureReason: null, | ||
submittedAt: 0, | ||
mutateAsync: jest.fn(), | ||
status: "success", | ||
mutate: mutateSpy, | ||
}); | ||
|
||
render(setup(true)); | ||
|
||
await act(async () => { | ||
await userEvent.click(screen.getByText("Disable expert mode")); | ||
}); | ||
|
||
expect(mutateSpy).toHaveBeenCalledWith({ | ||
id: "enable_lsm_expert_mode", | ||
value: false, | ||
}); | ||
spy.mockRestore(); | ||
}); | ||
|
||
it("When expert_mode is set to true AND user clicks to disable expert mode it AND something was wrong with the request Then AlertToast with error message should open", async () => { | ||
const server = setupServer( | ||
http.post( | ||
"/api/v2/environment_settings/enable_lsm_expert_mode", | ||
async () => { | ||
return HttpResponse.json( | ||
{ | ||
message: "Request or referenced resource does not exist", | ||
}, | ||
{ | ||
status: 404, | ||
}, | ||
); | ||
}, | ||
), | ||
); | ||
|
||
server.listen(); | ||
render(setup(true)); | ||
|
||
await act(async () => { | ||
await userEvent.click(screen.getByText("Disable expert mode")); | ||
}); | ||
|
||
await waitFor(() => { | ||
expect(screen.getByText("Something went wrong")).toBeVisible(); | ||
}); | ||
expect( | ||
screen.getByText("Request or referenced resource does not exist"), | ||
).toBeVisible(); | ||
|
||
expect( | ||
screen.getByText("LSM expert mode is enabled, proceed with caution."), | ||
).toBeVisible(); | ||
expect(screen.getByText("Disable expert mode")).toBeVisible(); | ||
|
||
server.close(); | ||
}); | ||
|
||
it("When expert_mode is set to false Then should not render,", () => { | ||
render(setup(false)); | ||
|
||
expect( | ||
screen.queryByText("LSM expert mode is enabled, proceed with caution."), | ||
).toBeNull(); | ||
}); | ||
}); |
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,20 +1,74 @@ | ||
import React, { useContext } from "react"; | ||
import { Banner } from "@patternfly/react-core"; | ||
import React, { useContext, useEffect, useState } from "react"; | ||
import { Banner, Button, Flex, Spinner } from "@patternfly/react-core"; | ||
import styled from "styled-components"; | ||
import { useUpdateEnvConfig } from "@/Data/Managers/V2/POST/UpdateEnvConfig"; | ||
import { DependencyContext } from "@/UI/Dependency"; | ||
import { words } from "@/UI/words"; | ||
import { ToastAlert } from "../ToastAlert"; | ||
|
||
export const ExpertBanner = () => { | ||
interface Props { | ||
environmentId: string; | ||
} | ||
|
||
/** | ||
* A React component that displays a banner when the expert mode is enabled. | ||
* | ||
* @props {object} props - The properties passed to the component. | ||
* @prop {string} environmentId -The ID of the environment. | ||
* @returns { React.FC<Props> | null} The rendered banner if the expert mode is enabled, otherwise null. | ||
*/ | ||
export const ExpertBanner: React.FC<Props> = ({ environmentId }) => { | ||
const [errorMessage, setMessage] = useState<string | undefined>(undefined); | ||
const { environmentModifier } = useContext(DependencyContext); | ||
const { mutate, isError, error } = useUpdateEnvConfig(environmentId); | ||
const [isLoading, setIsLoading] = useState(false); // isLoading is to indicate the asynchronous operation is in progress, as we need to wait until setting will be updated, getters are still in the V1 - task https://github.com/inmanta/web-console/issues/5999 | ||
|
||
useEffect(() => { | ||
if (isError) { | ||
setMessage(error.message); | ||
setIsLoading(false); | ||
} | ||
}, [isError, error]); | ||
|
||
return environmentModifier.useIsExpertModeEnabled() ? ( | ||
<React.Fragment> | ||
<> | ||
{isError && errorMessage && ( | ||
<ToastAlert | ||
data-testid="ToastAlert" | ||
title={words("error")} | ||
message={errorMessage} | ||
setMessage={setMessage} | ||
/> | ||
)} | ||
<Banner | ||
isSticky | ||
variant="red" | ||
id="expert-mode-banner" | ||
aria-label="expertModeActive" | ||
> | ||
LSM expert mode is enabled, proceed with caution. | ||
<Flex | ||
justifyContent={{ default: "justifyContentCenter" }} | ||
gap={{ default: "gapXs" }} | ||
> | ||
{words("banner.expertMode")} | ||
<Button | ||
variant="link" | ||
isInline | ||
onClick={() => { | ||
setIsLoading(true); | ||
mutate({ id: "enable_lsm_expert_mode", value: false }); | ||
}} | ||
> | ||
{words("banner.disableExpertMode")} | ||
</Button> | ||
{isLoading && <StyledSpinner size="sm" />} | ||
</Flex> | ||
</Banner> | ||
</React.Fragment> | ||
</> | ||
) : null; | ||
}; | ||
|
||
const StyledSpinner = styled(Spinner)` | ||
margin-left: 0.5rem; | ||
--pf-v5-c-spinner--Color: white; | ||
`; |
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
Oops, something went wrong.