Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ISW - Install Illuminate Step #21638

Merged
merged 11 commits into from
Feb 18, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,10 @@ type DataTiering = {
};

type InputSetupWizard = {
steps: {
[key in InputSetupWizardStep]?: StepType;
};
};
EnterpriseInputSetupWizard: React.ComponentType<{
openSteps: {[key in InputSetupWizardStep]?: StepType},
}>
}

type License = {
EnterpriseTrafficGraph: React.ComponentType;
Expand Down
36 changes: 18 additions & 18 deletions graylog2-web-interface/src/components/common/Wizard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ describe('<Wizard />', () => {
];

it('should render with 3 steps', async () => {
render(<Wizard steps={steps} />);
render(<Wizard onStepChange={jest.fn} steps={steps} />);

await screen.findByText('Component1');
});

it('should render with 3 steps and children', async () => {
render(
<Wizard steps={steps}>
<Wizard onStepChange={jest.fn} steps={steps}>
<span>Preview</span>
</Wizard>,
);
Expand All @@ -49,14 +49,14 @@ describe('<Wizard />', () => {
});

it('should render in horizontal mode with 3 steps', async () => {
render(<Wizard steps={steps} horizontal />);
render(<Wizard onStepChange={jest.fn} steps={steps} horizontal />);

await screen.findByText('Component1');
});

it('should render in horizontal mode with 3 steps and children', async () => {
render(
<Wizard steps={steps} horizontal>
<Wizard onStepChange={jest.fn} steps={steps} horizontal>
<span>Preview</span>
</Wizard>,
);
Expand All @@ -66,7 +66,7 @@ describe('<Wizard />', () => {

describe('When used in an uncontrolled way', () => {
it('should render step 1 when nothing was clicked', async () => {
render(<Wizard steps={steps} />);
render(<Wizard onStepChange={jest.fn} steps={steps} />);

await screen.findByText('Component1');

Expand All @@ -78,7 +78,7 @@ describe('<Wizard />', () => {
});

it('should render step 2 when clicked on step 2', async () => {
render(<Wizard steps={steps} />);
render(<Wizard onStepChange={jest.fn} steps={steps} />);

await screen.findByText('Title1');
await userEvent.click(await screen.findByText('Title2'));
Expand All @@ -93,7 +93,7 @@ describe('<Wizard />', () => {
});

it('should render step 2 when clicked on next', async () => {
render(<Wizard steps={steps} />);
render(<Wizard onStepChange={jest.fn} steps={steps} />);

await userEvent.click(await nextButton());

Expand All @@ -107,7 +107,7 @@ describe('<Wizard />', () => {
});

it('should render step 3 when two times clicked on next', async () => {
render(<Wizard steps={steps} />);
render(<Wizard onStepChange={jest.fn} steps={steps} />);

await userEvent.click(await nextButton());
await screen.findByText('Component2');
Expand Down Expand Up @@ -145,7 +145,7 @@ describe('<Wizard />', () => {

describe('When used in a controlled way', () => {
it('should render active step given from prop', async () => {
render(<Wizard steps={steps} activeStep="Key2" />);
render(<Wizard onStepChange={jest.fn} steps={steps} activeStep="Key2" />);

await screen.findByText('Component2');

Expand All @@ -161,14 +161,14 @@ describe('<Wizard />', () => {
});

it('should change the active step when prop changes', async () => {
const { rerender } = render(<Wizard steps={steps} activeStep="Key2" />);
const { rerender } = render(<Wizard onStepChange={jest.fn} steps={steps} activeStep="Key2" />);

await screen.findByText('Component2');

expect(screen.queryByText('Component1')).not.toBeInTheDocument();
expect(screen.queryByText('Component3')).not.toBeInTheDocument();

rerender(<Wizard steps={steps} activeStep="Key1" />);
rerender(<Wizard onStepChange={jest.fn} steps={steps} activeStep="Key1" />);

await screen.findByText('Component1');

Expand All @@ -181,15 +181,15 @@ describe('<Wizard />', () => {
const consoleWarn = console.warn;

console.warn = jest.fn();
const { rerender } = render(<Wizard steps={steps} activeStep={0} />);
const { rerender } = render(<Wizard onStepChange={jest.fn} steps={steps} activeStep={0} />);

await screen.findByText('Component1');

expect(screen.queryByText('Component2')).not.toBeInTheDocument();
expect(screen.queryByText('Component3')).not.toBeInTheDocument();
expect(console.warn).toHaveBeenCalledTimes(1);

rerender(<Wizard steps={steps} activeStep="Key12314" />);
rerender(<Wizard onStepChange={jest.fn} steps={steps} activeStep="Key12314" />);

await screen.findByText('Component1');

Expand Down Expand Up @@ -224,7 +224,7 @@ describe('<Wizard />', () => {
it('should respect disabled flag for a step', async () => {
steps[1].disabled = true;
steps[2].disabled = true;
render(<Wizard steps={steps} />);
render(<Wizard onStepChange={jest.fn} steps={steps} />);

await userEvent.click(await nextButton());

Expand All @@ -244,24 +244,24 @@ describe('<Wizard />', () => {
});

it('should render next/previous buttons by default', async () => {
const { rerender } = render(<Wizard steps={steps} />);
const { rerender } = render(<Wizard onStepChange={jest.fn} steps={steps} />);

expect(await nextButton()).toBeInTheDocument();
expect(await previousButton()).toBeInTheDocument();

rerender(<Wizard steps={steps} horizontal />);
rerender(<Wizard onStepChange={jest.fn} steps={steps} horizontal />);

expect(screen.getByLabelText('Next')).toBeInTheDocument();
expect(screen.getByLabelText('Previous')).toBeInTheDocument();
});

it('should hide next/previous buttons if hidePreviousNextButtons is set', async () => {
const { rerender } = render(<Wizard steps={steps} hidePreviousNextButtons />);
const { rerender } = render(<Wizard onStepChange={jest.fn} steps={steps} hidePreviousNextButtons />);

expect(screen.queryByRole('button', { name: 'Next' })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'Previous' })).not.toBeInTheDocument();

rerender(<Wizard steps={steps} horizontal hidePreviousNextButtons />);
rerender(<Wizard onStepChange={jest.fn} steps={steps} horizontal hidePreviousNextButtons />);

expect(screen.queryByLabelText('Next')).not.toBeInTheDocument();
expect(screen.queryByLabelText('Previous')).not.toBeInTheDocument();
Expand Down
19 changes: 11 additions & 8 deletions graylog2-web-interface/src/components/common/Wizard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,10 @@ const StyledNav: React.ComponentType<any> = styled(Nav)<{ $style?: 'stepper' }>(
background-color: ${theme.colors.global.link};
}
}

&.disabled > a {
color: ${theme.colors.text.disabled};
}

> a {
border-radius: 0;
Expand Down Expand Up @@ -273,14 +277,14 @@ export type StepType = {
export type StepsType = Array<StepType>;
type Props = {
steps: StepsType;
activeStep: StepKey | null | undefined;
activeStep?: StepKey | null | undefined;
onStepChange: (StepKey) => void;
children: React.ReactNode;
horizontal: boolean;
justified: boolean;
containerClassName: string;
hidePreviousNextButtons: boolean;
style: 'stepper' | undefined;
children?: React.ReactNode;
horizontal?: boolean;
justified?: boolean;
containerClassName?: string;
hidePreviousNextButtons?: boolean;
style?: 'stepper' | undefined;
};

type State = {
Expand All @@ -297,7 +301,6 @@ class Wizard extends React.Component<Props, State> {
static defaultProps = {
children: undefined,
activeStep: undefined,
onStepChange: () => {},
horizontal: false,
justified: false,
containerClassName: 'content',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,13 @@
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
import * as React from 'react';
import { useEffect, useCallback, useMemo } from 'react';
import { useCallback, useEffect, useMemo } from 'react';
import { PluginStore } from 'graylog-web-plugin/plugin';

import { Modal } from 'components/bootstrap';
import { Wizard as CommonWizard } from 'components/common';
import { INPUT_WIZARD_STEPS } from 'components/inputs/InputSetupWizard/types';
import useInputSetupWizard from 'components/inputs/InputSetupWizard/hooks/useInputSetupWizard';
import { getStepConfigOrData } from 'components/inputs/InputSetupWizard/helpers/stepHelper';

import InputSetupWizardStepsProvider from './contexts/InputSetupWizardStepsProvider';
import type { WizardData } from './types';
Expand All @@ -35,96 +34,88 @@ type Props = {
};

const Wizard = ({ show, input, onClose }: Props) => {
const {
activeStep,
setActiveStep,
orderedSteps,
setOrderedSteps,
stepsConfig,
setStepsConfig,
setWizardData,
wizardData,
} = useInputSetupWizard();

const enterpriseSteps = PluginStore.exports('inputSetupWizard').find((plugin) => !!plugin.steps)?.steps;

const initialStepsConfig = {
[INPUT_WIZARD_STEPS.SETUP_ROUTING]: {
enabled: true,
},
[INPUT_WIZARD_STEPS.START_INPUT]: {
enabled: true,
},
[INPUT_WIZARD_STEPS.INPUT_DIAGNOSIS]: {
enabled: true,
},
};
const { activeStep, setActiveStep, orderedSteps, setOrderedSteps, setWizardData, wizardData } = useInputSetupWizard();
const EnterpriseWizard = PluginStore.exports('inputSetupWizard').find(plugin => !!plugin.EnterpriseInputSetupWizard)?.EnterpriseInputSetupWizard;

useEffect(() => {
setStepsConfig(initialStepsConfig);
setWizardData({ ...wizardData, input }); // eslint-disable-next-line react-hooks/exhaustive-deps
}, []); // Initial setup: intentionally ommiting dependencies to prevent from unneccesary rerenders

const steps = useMemo(() => {
const defaultSteps = {
const steps = useMemo(() => ({
[INPUT_WIZARD_STEPS.SETUP_ROUTING]: {
key: INPUT_WIZARD_STEPS.SETUP_ROUTING,
title: <>Routing</>,
component: <SetupRoutingStep />,
disabled: !getStepConfigOrData(stepsConfig, INPUT_WIZARD_STEPS.SETUP_ROUTING, 'enabled'),
title: (
<>
Routing
</>
),
component: (
<SetupRoutingStep />
),
disabled: true,
},
[INPUT_WIZARD_STEPS.START_INPUT]: {
key: INPUT_WIZARD_STEPS.START_INPUT,
title: <>Launch</>,
component: <StartInputStep />,
disabled: !getStepConfigOrData(stepsConfig, INPUT_WIZARD_STEPS.START_INPUT, 'enabled'),
title: (
<>
Launch
</>
),
component: (
<StartInputStep />
),
disabled: true,
},
[INPUT_WIZARD_STEPS.INPUT_DIAGNOSIS]: {
key: INPUT_WIZARD_STEPS.INPUT_DIAGNOSIS,
title: <>Diagnosis</>,
component: <InputDiagnosisStep onClose={() => onClose()} />,
disabled: !getStepConfigOrData(stepsConfig, INPUT_WIZARD_STEPS.INPUT_DIAGNOSIS, 'enabled'),
title: (
<>
Diagnosis
</>
),
component: (
<InputDiagnosisStep onClose={() => onClose()} />
),
disabled: true,
},
};
if (enterpriseSteps) return { ...defaultSteps, ...enterpriseSteps };

return defaultSteps;
}, [enterpriseSteps, stepsConfig, onClose]);
}
), [onClose]);

const determineFirstStep = useCallback(() => {
const setInitialSteps = useCallback(() => {
setOrderedSteps([INPUT_WIZARD_STEPS.SETUP_ROUTING, INPUT_WIZARD_STEPS.START_INPUT, INPUT_WIZARD_STEPS.INPUT_DIAGNOSIS]);
setActiveStep(INPUT_WIZARD_STEPS.SETUP_ROUTING);
setOrderedSteps([
INPUT_WIZARD_STEPS.SETUP_ROUTING,
INPUT_WIZARD_STEPS.START_INPUT,
INPUT_WIZARD_STEPS.INPUT_DIAGNOSIS,
]);
}, [setActiveStep, setOrderedSteps]);
}, [setOrderedSteps, setActiveStep])

useEffect(() => {
if (EnterpriseWizard) return;
if (!activeStep) {
determineFirstStep();
setInitialSteps()
}
}, [EnterpriseWizard, activeStep, setInitialSteps])

if (activeStep && orderedSteps.length < 1) {
setOrderedSteps([activeStep]);
}
}, [activeStep, determineFirstStep, orderedSteps, setOrderedSteps]);
if (!show) return null;

if (!show || orderedSteps.length < 1) return null;
const orderedStepsConfig = orderedSteps.map((step) => steps[step]);

return (
<Modal show onHide={onClose} backdrop={false}>
<Modal.Header closeButton>Input Setup Wizard</Modal.Header>
<Modal.Body>
<InputSetupWizardStepsProvider>
<CommonWizard
activeStep={activeStep}
hidePreviousNextButtons
horizontal
justified
onStepChange={setActiveStep}
steps={orderedSteps.map((step) => steps[step])}
{EnterpriseWizard ? (
<EnterpriseWizard
openSteps={steps}
/>
) : (
orderedSteps.length > 0 && (
<CommonWizard activeStep={activeStep}
hidePreviousNextButtons
horizontal
justified
onStepChange={setActiveStep}
steps={orderedStepsConfig} />
)
)}
</InputSetupWizardStepsProvider>
</Modal.Body>
</Modal>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
* along with this program. If not, see
* <http://www.mongodb.com/licensing/server-side-public-license>.
*/
import { INPUT_WIZARD_STEPS } from 'components/inputs/InputSetupWizard/types';

export const INPUT_SETUP_MODE_FEATURE_FLAG = 'setup_mode';

export default INPUT_SETUP_MODE_FEATURE_FLAG;

export const DEFAULT_ORDERED_STEPS = [INPUT_WIZARD_STEPS.SETUP_ROUTING, INPUT_WIZARD_STEPS.START_INPUT, INPUT_WIZARD_STEPS.INPUT_DIAGNOSIS];
Loading
Loading