Skip to content

Commit

Permalink
QA: Feature branch for refactor node list (#2193)
Browse files Browse the repository at this point in the history
* Refactor / node list row (#2143)

* update classnames to match the component name

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update names in tests

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update the rest of the classnames

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* abstract node-list-row-toggle component

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* tidy up code for toggle component

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update classnames in tests

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* simplify the css

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* add tests for node-list-row-toggle

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* remove handleToggle on VisibilityIcon

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* remove redux from node-list-row

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* split node-list-row into row and filter-row

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* rename toggle icon component

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* move row and filter-row to components level

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* move css to row and filterRow

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* remove node-list-row

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* separate the row-text component

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* include parent classname

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update name for toggle-icon, to visibility-control

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* fix css and move nodeListRowHeight to config

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* adding test for new component

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update classname for tests

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* move row inside node-list

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* connect redux store to component

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* fix styling

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update name to ToggleControl

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* remove disable props as no longer needed

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* replace js code with css to simplify the code

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update classnames in cypress test

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* Styling for hovering and focus mode

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* fixing small styling

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* fix the disable styling for row

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* fix the disable styling on focus mode

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* remove one of the old test

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update name for icons for FilterRow

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* fixing the icon highlighting issue

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* remove un-used li element

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* remove styling for pipeline-nodelist__placeholder-upper and lower class as nolonger used

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update test in node-list

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update cypress tests

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* moving .pipeline-nodelist__group--all-unchecked to the parent

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* prevent page reload on form submission

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* remove wrong classname in the test

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* remove unique ID

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* apply hovering styling on the parent instead of row

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* styling for selected element

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* fixing hover styling on the icon from MUI

Signed-off-by: Huong Nguyen <huongg1409@gmail>

---------

Signed-off-by: Huong Nguyen <huongg1409@gmail>
Co-authored-by: Huong Nguyen <huongg1409@gmail>

* Refactor/node list groups (#2166)

* Create new structure and its own folder for filters or groups

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* better names for component structure

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* FiltersSectionHeading

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* filters-section

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* filters component

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* filtersSectionHeading component

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* tidy up code

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* including new tests for new components

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update and remove existing tests

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* remove un-used variables

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* remove components folder

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update tests path

Signed-off-by: Huong Nguyen <huongg1409@gmail>

---------

Signed-off-by: Huong Nguyen <huongg1409@gmail>
Co-authored-by: Huong Nguyen <huongg1409@gmail>

* Refactor/node list index (#2178)

* foundation for FiltersContext

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* remove unused props

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* node-list-context

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* restructure node-list-item as a helper function

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* rename selectors

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* rename functions in FiltersContext

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* move redux selector to node-list-context

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* fixing the hovered node issue

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* move getFilteredItems to selector

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* fix the modularpipeline highlight issue

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* Adding test for selector

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update tests

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update names to be nodes-panel

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* Fixing the filters problem

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update test

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* fixing the highlight issue through getNodesActive

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* move node-list-tree to its own component

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update row to node-list-row

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* move style to be inside node-list-tree

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* fix the filters URL update

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* update name for nodes panel context

Signed-off-by: Huong Nguyen <huongg1409@gmail>

---------

Signed-off-by: Huong Nguyen <huongg1409@gmail>
Co-authored-by: Huong Nguyen <huongg1409@gmail>

* Refactor on NodeListTree (#2177)

This is a smaller refactor. Previously, the logic for determining which nodes were disabled due to modular pipelines was duplicated in both the NodeListTree component and the getNodeDisabled selector. To improve maintainability and reduce redundancy, the getnodesDisabledViaModularPipeline logic was extracted and made into it's own selector. Now, this logic is shared and reused by both the NodeListTree component and the getNodeDisabled selector.

* fixed issue with nested focus modular pipeline

Signed-off-by: rashidakanchwala <[email protected]>

* Update RELEASE.md

Signed-off-by: rashidakanchwala <[email protected]>

* Update .telemetry

Signed-off-by: rashidakanchwala <[email protected]>

* Update pyproject.toml

Signed-off-by: rashidakanchwala <[email protected]>

* Update apps.py

Signed-off-by: rashidakanchwala <[email protected]>

* Update telemetry.html

Signed-off-by: rashidakanchwala <[email protected]>

* fix issue around parent pipelines disabled child pipelines

Signed-off-by: rashidakanchwala <[email protected]>

* include in the release note

Signed-off-by: Huong Nguyen <huongg1409@gmail>

* fixing the padding bottom gap for filters

Signed-off-by: Huong Nguyen <huongg1409@gmail>

---------

Signed-off-by: Huong Nguyen <huongg1409@gmail>
Signed-off-by: rashidakanchwala <[email protected]>
Signed-off-by: rashidakanchwala <[email protected]>
Co-authored-by: Huong Nguyen <huongg1409@gmail>
Co-authored-by: rashidakanchwala <[email protected]>
Co-authored-by: rashidakanchwala <[email protected]>
  • Loading branch information
4 people authored Nov 19, 2024
1 parent ca734e4 commit a0931ee
Show file tree
Hide file tree
Showing 58 changed files with 2,166 additions and 2,092 deletions.
2 changes: 1 addition & 1 deletion RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ Please follow the established format:
- Introduce `behaviour` prop object with `reFocus` prop (#2161)

## Bug fixes and other changes

- Improve `kedro viz build` usage documentation (#2126)
- Fix unserializable parameters value (#2122)
- Replace `watchgod` library with `watchfiles` and improve autoreload file watching filter (#2134)
- Display full dataset type with library prefix in metadata panel (#2136)
- Enable SQLite WAL mode for Azure ML to fix database locking issues (#2131)
- Replace `flake8`, `isort`, `pylint` and `black` by `ruff` (#2149)
- Refactor `DatasetStatsHook` to avoid showing error when dataset doesn't have file size info (#2174)
- Refactor `node-list-tree` component. (#2193)
- Fix 404 error when accessing the experiment tracking page on the demo site (#2179)
- Add check for port availability before starting Kedro Viz to prevent unintended browser redirects when the port is already in use (#2176)
- Include Kedro Viz version in telemetry.. (#2194)
Expand Down
2 changes: 1 addition & 1 deletion cypress/tests/ui/flowchart/flowchart.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ describe('Flowchart DAG', () => {
const nodeToToggleText = 'Parameters';

// Alias
cy.get(`.pipeline-nodelist__row__checkbox[name=${nodeToToggleText}]`).as(
cy.get(`.toggle-control__checkbox[name=${nodeToToggleText}]`).as(
'nodeToToggle'
);

Expand Down
34 changes: 17 additions & 17 deletions cypress/tests/ui/flowchart/menu.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ describe('Flowchart Menu', () => {
});

// Pipeline Label in the Menu
cy.get('.pipeline-nodelist__row__label')
cy.get('.row-text__label')
.first()
.invoke('text')
.should((pipelineLabel) => {
Expand All @@ -57,7 +57,7 @@ describe('Flowchart Menu', () => {
cy.get('.search-input__field').type(searchInput, { force: true });

// Pipeline Label in the Menu
cy.get('.pipeline-nodelist__row__label')
cy.get('.row-text__label')
.first()
.invoke('text')
.should((pipelineLabel) => {
Expand All @@ -72,7 +72,7 @@ describe('Flowchart Menu', () => {

// Action
cy.get(
`.MuiTreeItem-label > .pipeline-nodelist__row > [data-test=nodelist-data-${nodeToClickText}]`
`.MuiTreeItem-label > .node-list-tree-item-row > [data-test=node-list-tree-item--row--${nodeToClickText}]`
)
.should('exist')
.as('nodeToClick');
Expand All @@ -91,7 +91,7 @@ describe('Flowchart Menu', () => {

// Action
cy.get(
`.MuiTreeItem-label > .pipeline-nodelist__row > [data-test=nodelist-data-${nodeToHighlightText}]`
`.MuiTreeItem-label > .node-list-tree-item-row > [data-test=node-list-tree-item--row--${nodeToHighlightText}]`
)
.should('exist')
.as('nodeToHighlight');
Expand All @@ -108,7 +108,7 @@ describe('Flowchart Menu', () => {
const nodeToToggleText = 'Companies';

// Alias
cy.get(`.pipeline-nodelist__row__checkbox[name=${nodeToToggleText}]`, {
cy.get(`.toggle-control__checkbox[name=${nodeToToggleText}]`, {
timeout: 5000,
}).as('nodeToToggle');

Expand All @@ -121,7 +121,7 @@ describe('Flowchart Menu', () => {

// Assert after action
cy.__checkForText__(
`[data-test=nodelist-data-${nodeToToggleText}] > .pipeline-nodelist__row__label--faded`,
`[data-test=node-list-tree-item--row--${nodeToToggleText}] > .row-text__label--faded`,
nodeToToggleText
);
cy.get('.pipeline-node__text').should('not.contain', nodeToToggleText);
Expand All @@ -137,7 +137,7 @@ describe('Flowchart Menu', () => {

// Action
cy.get(
`[for=${nodeToFocusText}-focus] > .pipeline-nodelist__row__icon`
`[for=feature_engineering-focus]`
).click();

// Assert after action
Expand All @@ -161,34 +161,34 @@ describe('Flowchart Menu', () => {
const visibleRowLabel = 'Companies';

// Alias
cy.get(`.pipeline-nodelist__row__checkbox[name=${nodeToToggleText}]`).as(
cy.get(`.toggle-control__checkbox[name=${nodeToToggleText}]`).as(
'nodeToToggle'
);

// Assert before action
cy.get('@nodeToToggle').should('be.checked');
cy.get(
`[data-test=nodelist-data-${visibleRowLabel}] > .pipeline-nodelist__row__label`
`[data-test=node-list-tree-item--row--${visibleRowLabel}] > .row-text__label`
)
.should('not.have.class', 'pipeline-nodelist__row__label--faded')
.should('not.have.class', 'pipeline-nodelist__row__label--disabled');
.should('not.have.class', 'row-text__label--faded')
.should('not.have.class', 'row-text__label--disabled');

// Action
cy.get('@nodeToToggle').uncheck({ force: true });

// Assert after action
cy.get(
`[data-test=nodelist-data-${visibleRowLabel}] > .pipeline-nodelist__row__label`
`[data-test=node-list-tree-item--row--${visibleRowLabel}] > .row-text__label`
)
.should('have.class', 'pipeline-nodelist__row__label--faded')
.should('have.class', 'pipeline-nodelist__row__label--disabled');
.should('have.class', 'row-text__label--faded')
.should('have.class', 'row-text__label--disabled');
});

it('verifies that after checking node type URL should be updated with correct query params', () => {
const nodeToToggleText = 'Parameters';

// Alias
cy.get(`.pipeline-nodelist__row__checkbox[name=${nodeToToggleText}]`).as(
cy.get(`.toggle-control__checkbox[name=${nodeToToggleText}]`).as(
'nodeToToggle'
);

Expand All @@ -207,7 +207,7 @@ describe('Flowchart Menu', () => {
cy.visit(`/?tags=${visibleRowLabel}`);

// Alias
cy.get(`.pipeline-nodelist__row__checkbox[name=${visibleRowLabel}]`).as(
cy.get(`.toggle-control__checkbox[name=${visibleRowLabel}]`).as(
'nodeToToggle'
);

Expand All @@ -220,7 +220,7 @@ describe('Flowchart Menu', () => {
cy.visit('/?types=datasets');

// Alias
cy.get(`.pipeline-nodelist__row__checkbox[name=${visibleRowLabel}]`).as(
cy.get(`.toggle-control__checkbox[name=${visibleRowLabel}]`).as(
'nodeToToggle'
);

Expand Down
8 changes: 4 additions & 4 deletions cypress/tests/ui/toolbar/global-toolbar.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,14 @@ describe('Global Toolbar', () => {
cy.get('@isPrettyNameCheckbox').should('be.checked');

// Menu
cy.get(`[data-test="nodelist-modularPipeline-${prettifyName(modularPipelineText)}"]`).click();
cy.get(`[data-test="nodelist-${nodeNameType}-${prettyNodeNameText}"]`).should('exist');
cy.get(`[data-test="node-list-tree-item--row--${prettifyName(modularPipelineText)}"]`).click();
cy.get(`[data-test="node-list-tree-item--row--${prettyNodeNameText}"]`).should('exist');

// Flowchart
cy.get('.pipeline-node__text').should('contain', prettyNodeNameText);

// Metadata
cy.get(`[data-test="nodelist-${nodeNameType}-${prettyNodeNameText}"]`).click({ force: true });
cy.get(`[data-test="node-list-tree-item--row--${prettyNodeNameText}"]`).click({ force: true });
cy.get('.pipeline-metadata__title').should(
'have.text',
prettyNodeNameText
Expand All @@ -106,7 +106,7 @@ describe('Global Toolbar', () => {
// Assert after action
cy.__waitForPageLoad__(() => {
// Menu
cy.get(`[data-test="nodelist-${nodeNameType}-${originalNodeNameText}"]`).should('exist');
cy.get(`[data-test="node-list-tree-item--row--${originalNodeNameText}"]`).should('exist');

// Flowchart
cy.get('.pipeline-node__text').should('contain', originalNodeNameText);
Expand Down
49 changes: 49 additions & 0 deletions src/components/filters/filters-group/filters-group.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';
import classnames from 'classnames';
import FiltersRow from '../filters-row/filters-row';
import { nodeListRowHeight } from '../../../config';
import LazyList from '../../lazy-list';
import { getDataTestAttribute } from '../../../utils/get-data-test-attribute';

import './filters-group.scss';

/** A group collection of FiltersRow */
const FiltersGroup = ({ items = [], group, collapsed, onItemChange }) => (
<LazyList
height={(start, end) => (end - start) * nodeListRowHeight}
total={items.length}
>
{({ start, end, listRef, listStyle }) => (
<ul
ref={listRef}
style={listStyle}
className={classnames('filters-group', {
'filters-group--closed': collapsed,
})}
>
{items.slice(start, end).map((item) => (
<FiltersRow
allUnchecked={group.allUnchecked}
checked={item.checked}
container={'li'}
count={item.count}
dataTest={getDataTestAttribute('node-list-row', 'filter-row')}
id={item.id}
offIndicatorIcon={item.invisibleIcon}
key={item.id}
kind={group.kind}
label={item.highlightedLabel}
name={item.name}
onChange={(e) => onItemChange(e, item)}
onClick={(e) => onItemChange(e, item)}
parentClassName={'node-list-filter-row'}
visible={item.visible}
indicatorIcon={item.visibleIcon}
/>
))}
</ul>
)}
</LazyList>
);

export default FiltersGroup;
15 changes: 15 additions & 0 deletions src/components/filters/filters-group/filters-group.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@use '../../../styles/variables' as var;
@use '../../node-list-tree/styles/variables';

.filters-group {
list-style: none;
padding: 0;
margin: 0 0 1.2em;

// Avoid placeholder fade leaking out for small lists
overflow: hidden;

&--closed {
display: none;
}
}
34 changes: 34 additions & 0 deletions src/components/filters/filters-group/filters-group.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';
import FiltersGroup from './filters-group';
import { mockState, setup } from '../../../utils/state.mock';
import { getNodeTypes } from '../../../selectors/node-types';
import { getGroupedNodes } from '../../../selectors/nodes';
import { getGroups } from '../../../selectors/filtered-node-list-items';

describe('FiltersGroup Component', () => {
const mockProps = () => {
const items = getGroupedNodes(mockState.spaceflights);
const nodeTypes = getNodeTypes(mockState.spaceflights);
const groups = getGroups({ nodeTypes, items });
return { group: groups['tags'], items: [] };
};

it('renders without throwing', () => {
expect(() => setup.mount(<FiltersGroup {...mockProps()} />)).not.toThrow();
});
it('adds class when collapsed prop true', () => {
const wrapper = setup.mount(
<FiltersGroup {...mockProps()} collapsed={true} />
);
const children = wrapper.find('.filters-group');
expect(children.hasClass('filters-group--closed')).toBe(true);
});

it('removes class when collapsed prop false', () => {
const wrapper = setup.mount(
<FiltersGroup {...mockProps()} collapsed={false} />
);
const children = wrapper.find('.filters-group');
expect(children.hasClass('filters-group--closed')).toBe(false);
});
});
68 changes: 68 additions & 0 deletions src/components/filters/filters-row/filters-row.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React from 'react';
import classnames from 'classnames';
import IndicatorIcon from '../../icons/indicator';
import OffIndicatorIcon from '../../icons/indicator-off';
import { ToggleControl } from '../../ui/toggle-control/toggle-control';
import { RowText } from '../../ui/row-text/row-text';

import './filters-row.scss';

const FiltersRow = ({
allUnchecked,
checked,
children,
container: ContainerWrapper,
count,
dataTest,
id,
indicatorIcon = IndicatorIcon,
kind,
label,
name,
offIndicatorIcon = OffIndicatorIcon,
onChange,
onClick,
parentClassName,
visible,
}) => {
const Icon = checked ? indicatorIcon : offIndicatorIcon;

return (
<ContainerWrapper
className={classnames(
'filter-row kedro',
`filter-row--kind-${kind}`,
parentClassName,
{
'filter-row--visible': visible,
'filter-row--unchecked': !checked,
}
)}
title={name}
>
<RowText
kind={kind}
dataTest={dataTest}
onClick={onClick}
name={children ? null : name}
label={label}
/>
<span onClick={onClick} className={'filter-row__count'}>
{count}
</span>
<ToggleControl
allUnchecked={allUnchecked}
className={'filter-row__icon'}
IconComponent={Icon}
id={id}
isChecked={checked}
kind={kind}
name={name}
onChange={onChange}
/>
{children}
</ContainerWrapper>
);
};

export default FiltersRow;
Loading

0 comments on commit a0931ee

Please sign in to comment.