Skip to content
This repository has been archived by the owner on Nov 27, 2023. It is now read-only.

Commit

Permalink
feat(flows): Add mechanism to navigate between flows
Browse files Browse the repository at this point in the history
Currently, all existing flows are being shown. This behavior
is not useful when there are many flows at the same time or
somewhat complex flows.

In addition to that, there's no mechanism to delete an existing
flow.

This commit provides a way to toggle the visibility of individual
flows, by leveraging a flows list that also provides the functionality
of deleting individual flows.

relates to: #801
  • Loading branch information
lordrip committed Jun 1, 2023
1 parent 0f7c0fa commit e5fe329
Show file tree
Hide file tree
Showing 27 changed files with 1,116 additions and 231 deletions.
2 changes: 1 addition & 1 deletion src/components/Catalog.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Catalog } from './Catalog';
import KaotoDrawer from './KaotoDrawer';
import { KaotoDrawer } from './KaotoDrawer';
import { DrawerContentBody } from '@patternfly/react-core';
import { StoryFn, Meta } from '@storybook/react';

Expand Down
22 changes: 11 additions & 11 deletions src/components/DSL/DSLSelector.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ describe('DSLSelector.tsx', () => {
test('component renders', () => {
const wrapper = render(<DSLSelector onSelect={onSelect} />);

const toggle = wrapper.queryByTestId('dsl-select');
const toggle = wrapper.queryByTestId('dsl-list-dropdown');
expect(toggle).toBeInTheDocument();
});

test('should toggle list of DSLs', async () => {
const wrapper = render(<DSLSelector onSelect={onSelect} />);
const toggle = await wrapper.findByTestId('dsl-select');
const toggle = await wrapper.findByTestId('dsl-list-dropdown');

/** Open Select */
act(() => {
Expand All @@ -56,7 +56,7 @@ describe('DSLSelector.tsx', () => {

test('should show list of DSLs', async () => {
const wrapper = render(<DSLSelector onSelect={onSelect} />);
const toggle = await wrapper.findByTestId('dsl-select');
const toggle = await wrapper.findByTestId('dsl-list-dropdown');

/** Open Select */
act(() => {
Expand All @@ -69,7 +69,7 @@ describe('DSLSelector.tsx', () => {

test('should show selected value', async () => {
const wrapper = render(<DSLSelector onSelect={onSelect} selectedDsl={dsl} />);
const toggle = await wrapper.findByTestId('dsl-select');
const toggle = await wrapper.findByTestId('dsl-list-dropdown');

/** Open Select */
act(() => {
Expand All @@ -94,7 +94,7 @@ describe('DSLSelector.tsx', () => {

test('should not have anything selected if "isStatic=true"', async () => {
const wrapper = render(<DSLSelector onSelect={onSelect} isStatic />);
const toggle = await wrapper.findByTestId('dsl-select');
const toggle = await wrapper.findByTestId('dsl-list-dropdown');

/** Open Select */
act(() => {
Expand Down Expand Up @@ -122,7 +122,7 @@ describe('DSLSelector.tsx', () => {
const wrapper = render(
<DSLSelector onSelect={onSelect} selectedDsl={capabilitiesStub.dsls[2]} />,
);
const toggle = await wrapper.findByTestId('dsl-select');
const toggle = await wrapper.findByTestId('dsl-list-dropdown');

/** Open Select */
act(() => {
Expand All @@ -138,7 +138,7 @@ describe('DSLSelector.tsx', () => {

test('should have selected the first DSL if selectedDsl is not provided', async () => {
const wrapper = render(<DSLSelector onSelect={onSelect} />);
const toggle = await wrapper.findByTestId('dsl-select');
const toggle = await wrapper.findByTestId('dsl-list-dropdown');

/** Open Select */
act(() => {
Expand All @@ -154,7 +154,7 @@ describe('DSLSelector.tsx', () => {

test('should close Select when pressing ESC', async () => {
const wrapper = render(<DSLSelector onSelect={onSelect} />);
const toggle = await wrapper.findByTestId('dsl-select');
const toggle = await wrapper.findByTestId('dsl-list-dropdown');

/** Open Select */
act(() => {
Expand All @@ -179,7 +179,7 @@ describe('DSLSelector.tsx', () => {

test('should call onSelect callback when provided', async () => {
const wrapper = render(<DSLSelector onSelect={onSelect} isStatic />);
const toggle = await wrapper.findByTestId('dsl-select');
const toggle = await wrapper.findByTestId('dsl-list-dropdown');

/** Open Select */
act(() => {
Expand All @@ -199,7 +199,7 @@ describe('DSLSelector.tsx', () => {

test('should not call onSelect spy when not provided', async () => {
const wrapper = render(<DSLSelector onSelect={undefined} isStatic />);
const toggle = await wrapper.findByTestId('dsl-select');
const toggle = await wrapper.findByTestId('dsl-list-dropdown');

/** Open Select */
act(() => {
Expand All @@ -219,7 +219,7 @@ describe('DSLSelector.tsx', () => {

test('should not call onSelect spy when the selected id does not exist', async () => {
const wrapper = render(<DSLSelector onSelect={onSelect} isStatic />);
const toggle = await wrapper.findByTestId('dsl-select');
const toggle = await wrapper.findByTestId('dsl-list-dropdown');

/** Open Select */
act(() => {
Expand Down
36 changes: 29 additions & 7 deletions src/components/DSL/DSLSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useSettingsStore } from '@kaoto/store';
import { IDsl } from '@kaoto/types';
import { MenuToggle, MenuToggleElement } from '@patternfly/react-core';
import { MenuToggle, MenuToggleAction, MenuToggleElement } from '@patternfly/react-core';
import { Select, SelectList, SelectOption } from '@patternfly/react-core/next';
import {
FunctionComponent,
Expand All @@ -19,16 +19,21 @@ interface IDSLSelector extends PropsWithChildren {
}

export const DSLSelector: FunctionComponent<IDSLSelector> = (props) => {
const capabilities = useSettingsStore((state) => state.settings.capabilities, shallow);
const { capabilities, dsl } = useSettingsStore(
({ settings }) => ({ capabilities: settings.capabilities, dsl: settings.dsl }),
shallow,
);
const [isOpen, setIsOpen] = useState(false);
const [selected, setSelected] = useState<IDsl | undefined>(
props.isStatic ? undefined : props.selectedDsl ?? capabilities[0],
);

/** Toggle the DSL dropdown */
const onToggleClick = () => {
setIsOpen(!isOpen);
};

/** Selecting a DSL checking the the existing flows */
const onSelect = useCallback(
(
_: ReactMouseEvent<Element, MouseEvent> | undefined,
Expand All @@ -48,21 +53,38 @@ export const DSLSelector: FunctionComponent<IDSLSelector> = (props) => {
[capabilities, props],
);

/** Selecting the same DSL directly*/
const onNewSameTypeRoute = useCallback(() => {
onSelect(undefined, dsl.name);
}, [dsl.name, onSelect]);

const toggle = (toggleRef: Ref<MenuToggleElement>) => (
<MenuToggle
data-testid="dsl-select"
data-testid="dsl-list-dropdown"
ref={toggleRef}
onClick={onToggleClick}
isExpanded={isOpen}
isFullWidth
>
{props.children}
</MenuToggle>
splitButtonOptions={{
variant: 'action',
items: [
<MenuToggleAction
id="dsl-list-btn"
key="dsl-list-btn"
data-testid="dsl-list-btn"
aria-label="DSL list"
onClick={onNewSameTypeRoute}
>
{props.children}
</MenuToggleAction>,
],
}}
/>
);

return (
<Select
id="dsl-select"
id="dsl-list-select"
isOpen={isOpen}
selected={selected?.name}
onSelect={onSelect}
Expand Down
23 changes: 18 additions & 5 deletions src/components/DSL/NewFlow.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,22 @@ describe('NewFlow.tsx', () => {
});
});

test('should add a new flow with the same type upon clicking on the action button', async () => {
const wrapper = render(<NewFlow />)
const trigger = await wrapper.findByTestId('dsl-list-btn');

/** Open Select */
act(() => {
fireEvent.click(trigger);
});

expect(useFlowsStore.getState().flows).toHaveLength(1);
expect(useFlowsStore.getState().flows[0].dsl).toEqual('Integration');
});

test('should add a new flow', async () => {
const wrapper = render(<NewFlow />);
const trigger = await wrapper.findByText('New route');
const trigger = await wrapper.findByTestId('dsl-list-dropdown');

/** Open Select */
act(() => {
Expand All @@ -38,7 +51,7 @@ describe('NewFlow.tsx', () => {
useFlowsStore.getState().addNewFlow('Integration');

const wrapper = render(<NewFlow />);
const trigger = await wrapper.findByText('New route');
const trigger = await wrapper.findByTestId('dsl-list-dropdown');

/** Open Select */
act(() => {
Expand All @@ -59,7 +72,7 @@ describe('NewFlow.tsx', () => {
useFlowsStore.getState().addNewFlow('Integration');

const wrapper = render(<NewFlow />);
const trigger = await wrapper.findByText('New route');
const trigger = await wrapper.findByTestId('dsl-list-dropdown');

/** Open Select */
act(() => {
Expand All @@ -85,7 +98,7 @@ describe('NewFlow.tsx', () => {
useFlowsStore.getState().addNewFlow('Integration');

const wrapper = render(<NewFlow />);
const trigger = await wrapper.findByText('New route');
const trigger = await wrapper.findByTestId('dsl-list-dropdown');

/** Open Select */
act(() => {
Expand All @@ -111,7 +124,7 @@ describe('NewFlow.tsx', () => {
useFlowsStore.getState().addNewFlow('Integration');

const wrapper = render(<NewFlow />);
const trigger = await wrapper.findByText('New route');
const trigger = await wrapper.findByTestId('dsl-list-dropdown');

/** Open Select */
act(() => {
Expand Down
50 changes: 25 additions & 25 deletions src/components/DSL/NewFlow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ConfirmationModal } from '../ConfirmationModal';
import { DSLSelector } from './DSLSelector';
import { FlowsStoreFacade, useFlowsStore, useSettingsStore } from '@kaoto/store';
import { IDsl } from '@kaoto/types';
import { Tooltip } from '@patternfly/react-core';
import { PlusIcon } from '@patternfly/react-icons';
import { FunctionComponent, PropsWithChildren, useCallback, useState } from 'react';
import { shallow } from 'zustand/shallow';
Expand All @@ -23,34 +22,35 @@ export const NewFlow: FunctionComponent<PropsWithChildren> = () => {
const [proposedDsl, setProposedNewDsl] = useState<IDsl>();
const [isConfirmationModalOpen, setIsConfirmationModalOpen] = useState(false);

const checkBeforeAddNewFlow = useCallback((dsl: IDsl) => {
const isSameDsl = FlowsStoreFacade.isSameDsl(dsl.name);
const checkBeforeAddNewFlow = useCallback(
(dsl: IDsl) => {
const isSameDsl = FlowsStoreFacade.isSameDsl(dsl.name);

if (isSameDsl) {
/**
* If it's the same DSL as we have in the existing Flows list,
* we don't need to do anything special, just add a new flow if
* supported
*/
addNewFlow(dsl.name);
} else {
/**
* If it is not the same DSL, this operation might result in
* removing the existing flows, so then we warn the user first
*/
setProposedNewDsl(dsl);
setIsConfirmationModalOpen(true);
}
}, [addNewFlow]);
if (isSameDsl) {
/**
* If it's the same DSL as we have in the existing Flows list,
* we don't need to do anything special, just add a new flow if
* supported
*/
addNewFlow(dsl.name);
} else {
/**
* If it is not the same DSL, this operation might result in
* removing the existing flows, so then we warn the user first
*/
setProposedNewDsl(dsl);
setIsConfirmationModalOpen(true);
}
},
[addNewFlow],
);

return (
<>
<Tooltip content="Create a new route" position="right">
<DSLSelector isStatic onSelect={checkBeforeAddNewFlow}>
<PlusIcon />
<span className="pf-u-m-sm-on-lg">New route</span>
</DSLSelector>
</Tooltip>
<DSLSelector isStatic onSelect={checkBeforeAddNewFlow}>
<PlusIcon />
<span className="pf-u-m-sm-on-lg">New route</span>
</DSLSelector>

<ConfirmationModal
handleCancel={() => {
Expand Down
2 changes: 0 additions & 2 deletions src/components/Extension.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,3 @@ export function Extension(props: Props) {
</StepErrorBoundary>
);
}

export default Extension;
Loading

0 comments on commit e5fe329

Please sign in to comment.