[Drilldowns] Preserve state when selecting different action factory (#65074)

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Anton Dosov 2020-05-07 13:18:56 +02:00 committed by GitHub
parent 6ef45e17d4
commit 3604f5d21a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 112 additions and 37 deletions

View file

@ -32,9 +32,9 @@ export interface ActionWizardProps {
/**
* Action factory selected changed
* null - means user click "change" and removed action factory selection
* empty - means user click "change" and removed action factory selection
*/
onActionFactoryChange: (actionFactory: ActionFactory | null) => void;
onActionFactoryChange: (actionFactory?: ActionFactory) => void;
/**
* current config for currently selected action factory
@ -71,7 +71,7 @@ export const ActionWizard: React.FC<ActionWizardProps> = ({
actionFactory={currentActionFactory}
showDeselect={actionFactories.length > 1}
onDeselect={() => {
onActionFactoryChange(null);
onActionFactoryChange(undefined);
}}
context={context}
config={config}

View file

@ -167,7 +167,7 @@ export function Demo({ actionFactories }: { actionFactories: Array<ActionFactory
config?: ActionBaseConfig;
}>({});
function changeActionFactory(newActionFactory: ActionFactory | null) {
function changeActionFactory(newActionFactory?: ActionFactory) {
if (!newActionFactory) {
// removing action factory
return setState({});

View file

@ -173,6 +173,42 @@ test('Create only mode', async () => {
expect(await mockDynamicActionManager.state.get().events.length).toBe(1);
});
test('After switching between action factories state is restored', async () => {
const screen = render(
<FlyoutManageDrilldowns
placeContext={{}}
dynamicActionManager={mockDynamicActionManager}
viewMode={'create'}
/>
);
// wait for initial render. It is async because resolving compatible action factories is async
await wait(() => expect(screen.getAllByText(/Create/i).length).toBeGreaterThan(0));
fireEvent.change(screen.getByLabelText(/name/i), {
target: { value: 'test' },
});
fireEvent.click(screen.getByText(/Go to URL/i));
fireEvent.change(screen.getByLabelText(/url/i), {
target: { value: 'https://elastic.co' },
});
// change to dashboard
fireEvent.click(screen.getByText(/change/i));
fireEvent.click(screen.getByText(/Go to Dashboard/i));
// change back to url
fireEvent.click(screen.getByText(/change/i));
fireEvent.click(screen.getByText(/Go to URL/i));
expect(screen.getByLabelText(/url/i)).toHaveValue('https://elastic.co');
expect(screen.getByLabelText(/name/i)).toHaveValue('test');
fireEvent.click(screen.getAllByText(/Create Drilldown/i)[1]);
await wait(() => expect(notifications.toasts.addSuccess).toBeCalled());
expect(await (mockDynamicActionManager.state.get().events[0].action.config as any).url).toBe(
'https://elastic.co'
);
});
test.todo("Error when can't fetch drilldown list");
test("Error when can't save drilldown changes", async () => {

View file

@ -41,6 +41,72 @@ export interface FlyoutDrilldownWizardProps<CurrentActionConfig extends object =
actionFactoryContext?: object;
}
function useWizardConfigState(
initialDrilldownWizardConfig?: DrilldownWizardConfig
): [
DrilldownWizardConfig,
{
setName: (name: string) => void;
setActionConfig: (actionConfig: object) => void;
setActionFactory: (actionFactory?: ActionFactory) => void;
}
] {
const [wizardConfig, setWizardConfig] = useState<DrilldownWizardConfig>(
() =>
initialDrilldownWizardConfig ?? {
name: '',
}
);
const [actionConfigCache, setActionConfigCache] = useState<Record<string, object>>(
initialDrilldownWizardConfig?.actionFactory
? {
[initialDrilldownWizardConfig.actionFactory
.id]: initialDrilldownWizardConfig.actionConfig!,
}
: {}
);
return [
wizardConfig,
{
setName: (name: string) => {
setWizardConfig({
...wizardConfig,
name,
});
},
setActionConfig: (actionConfig: object) => {
setWizardConfig({
...wizardConfig,
actionConfig,
});
},
setActionFactory: (actionFactory?: ActionFactory) => {
if (actionFactory) {
setWizardConfig({
...wizardConfig,
actionFactory,
actionConfig: actionConfigCache[actionFactory.id] ?? actionFactory.createConfig(),
});
} else {
if (wizardConfig.actionFactory?.id) {
setActionConfigCache({
...actionConfigCache,
[wizardConfig.actionFactory.id]: wizardConfig.actionConfig!,
});
}
setWizardConfig({
...wizardConfig,
actionFactory: undefined,
actionConfig: undefined,
});
}
},
},
];
}
export function FlyoutDrilldownWizard<CurrentActionConfig extends object = object>({
onClose,
onBack,
@ -53,11 +119,8 @@ export function FlyoutDrilldownWizard<CurrentActionConfig extends object = objec
drilldownActionFactories,
actionFactoryContext,
}: FlyoutDrilldownWizardProps<CurrentActionConfig>) {
const [wizardConfig, setWizardConfig] = useState<DrilldownWizardConfig>(
() =>
initialDrilldownWizardConfig ?? {
name: '',
}
const [wizardConfig, { setActionFactory, setActionConfig, setName }] = useWizardConfigState(
initialDrilldownWizardConfig
);
const isActionValid = (
@ -95,35 +158,11 @@ export function FlyoutDrilldownWizard<CurrentActionConfig extends object = objec
>
<FormDrilldownWizard
name={wizardConfig.name}
onNameChange={newName => {
setWizardConfig({
...wizardConfig,
name: newName,
});
}}
onNameChange={setName}
actionConfig={wizardConfig.actionConfig}
onActionConfigChange={newActionConfig => {
setWizardConfig({
...wizardConfig,
actionConfig: newActionConfig,
});
}}
onActionConfigChange={setActionConfig}
currentActionFactory={wizardConfig.actionFactory}
onActionFactoryChange={actionFactory => {
if (!actionFactory) {
setWizardConfig({
...wizardConfig,
actionFactory: undefined,
actionConfig: undefined,
});
} else {
setWizardConfig({
...wizardConfig,
actionFactory,
actionConfig: actionFactory.createConfig(),
});
}
}}
onActionFactoryChange={setActionFactory}
actionFactories={drilldownActionFactories}
actionFactoryContext={actionFactoryContext!}
/>

View file

@ -19,7 +19,7 @@ export interface FormDrilldownWizardProps {
onNameChange?: (name: string) => void;
currentActionFactory?: ActionFactory;
onActionFactoryChange?: (actionFactory: ActionFactory | null) => void;
onActionFactoryChange?: (actionFactory?: ActionFactory) => void;
actionFactoryContext: object;
actionConfig?: object;