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

[Logs UI] Identify critical features of EuiDataGrid suited for dynamic data #148417

Closed
1 task done
Tracked by #134412
weltenwort opened this issue Jan 4, 2023 · 6 comments
Closed
1 task done
Tracked by #134412
Assignees
Labels
Feature:Logs UI Logs UI feature Team:Infra Monitoring UI - DEPRECATED DEPRECATED - Label for the Infra Monitoring UI team. Use Team:obs-ux-infra_services

Comments

@weltenwort
Copy link
Member

weltenwort commented Jan 4, 2023

📓 Summary

We want to display the log entries in the log stream component in a bi-directional infinitely-scrolling and incrementally-loading stream as we do right now, but with the UX of the EuiDataGrid.

We are currently using the EuiDataGrid react component in our application, but we have encountered some issues with its out-of-the-box behaviour. Specifically, we cannot use the component as-is due to compatibility issues and the desire to achieve a bi-directional infinite scroll.

The current implementation for the EuiDataGrid component does not expose the internal UI elements that we would need to bring a similar user experience to the Logs stream.

We would like to conduct an analysis of the EuiDataGrid component to identify all of its features and determine which ones we want to keep and abstract from the original component in order to achieve a bi-directional infinite scroll on our implementation, where we can ideally abstract all the presentational components and reuse them to visualize the current Logs stream.

Expected Outcome

Through this analysis, we hope to identify which features of the EuiDataGrid component is necessary for our application and which ones can be abstracted away in order to achieve a bi-directional infinite scroll. This will allow us to determine the complexity of implementing these features and plan accordingly.

Steps

  1. Review the documentation for the EuiDataGrid react component.
  2. Identify all of the features and functionality of the component.
  3. Determine which features are necessary for our application and which can be abstracted away and reused for our implementation.

List of Features

1st iteration

  • Header rendering ✅
  • Cell rendering and actions ✅
  • Row actions ✅
  • Row custom size ✅ (reuse existing controls for wrapping rows content)
  • Toolbar visibility & options ✅

2nd iteration

  • Column visibility ✅
  • Column resizing ✅
  • Column reordering ✅
  • Column sorting ✅ Nice to have (secondary sorting, the primary column is always the timestamp column)

Next steps

  • Keyboard navigation - Nice to have
  • Full-screen mode - Nice to have
  • Data grid Schema - Nice to have, but difficult to detect the columns schema
  • In-Memory feature

Further tasks:

  • Agree with the team on the identified features and select the ones that we want to keep. We will then be able to analyze the implementation of these features and determine how complex it would be to abstract them from the original component.
@weltenwort weltenwort added Feature:Logs UI Logs UI feature Team:Infra Monitoring UI - DEPRECATED DEPRECATED - Label for the Infra Monitoring UI team. Use Team:obs-ux-infra_services labels Jan 4, 2023
@elasticmachine
Copy link
Contributor

Pinging @elastic/infra-monitoring-ui (Team:Infra Monitoring UI)

@tonyghiani tonyghiani changed the title [Logs UI] Create variant of EuiDataGrid suited for dynamic data [Logs UI] Identify critical features of EuiDataGrid suited for dynamic data Jan 5, 2023
@weltenwort weltenwort removed their assignment Jan 5, 2023
@tonyghiani
Copy link
Contributor

tonyghiani commented Jan 11, 2023

Ideally, we’d like to abstract and expose into purely presentational components the UI element used to represent some DataGrid features.

This could help us to iteratively update the UI of the Logs stream without attaching any additional logic to our existing component, giving the same appearance as the EuiDataGrid for the first iteration.

The components we can potentially abstract and expose first could be:

EuiDataGridHeader and EuiDataGridHeaderCell

These two presentation components will be basically used to compose the heading of the DataGrid from a presentational perspective, in order to get a sticky header bar and the column definitions.

It means extracting the presentational wrappers in the following files:

Usage example

import {
  EuiDataGridHeader,
  EuiDataGridHeaderCell
} from '@elastic/eui';

<EuiDataGridHeader>
  <EuiDataGridHeaderCell>date</EuiDataGridHeaderCell>
  <EuiDataGridHeaderCell>author</EuiDataGridHeaderCell>
  <EuiDataGridHeaderCell>message</EuiDataGridHeaderCell>
</EuiDataGridHeader>

EuiDataGridRow, EuiDataGridRowCell, EuiDataGridRowCellActions

Similarly to the heading, these two presentational components would be used for the rendering of single rows and the content of their columns.

It means extracting the presentational wrappers in the following files:

Usage example

import { EuiDataGridRow, EuiDataGridRowCell, EuiDataGridRowCellActions } from '@elastic/eui';

<>
  <EuiDataGridRow>
    <EuiDataGridRowCell>11:25:52.587</EuiDataGridRowCell>
    <EuiDataGridRowCell>
      generic
      <EuiDataGridRowCellActions />
    </EuiDataGridRowCell>
    <EuiDataGridRowCell>
      error message to show
      <EuiDataGridRowCellActions />
    </EuiDataGridRowCell>
  </EuiDataGridRow>
  <EuiDataGridRow>
    <EuiDataGridRowCell>11:25:55.542</EuiDataGridRowCell>
    <EuiDataGridRowCell>
      generic
      <EuiDataGridRowCellActions />
    </EuiDataGridRowCell>
    <EuiDataGridRowCell>
      error message to show
      <EuiDataGridRowCellActions />
    </EuiDataGridRowCell>
  </EuiDataGridRow>
</>

EuiDataGridToolbar

The EuiDataGridToolbar will allow to wrap together the actions related to the rendered DataGrid. It could come with some predefined controls used in the EuiDataGrid already, such as FullScreen and RowSize controls.

It means extracting the presentational wrappers in the following files:

Usage example

import { EuiDataGridToolbar } from '@elastic/eui';

<EuiDataGridToolbar>
  <EuiDataGridToolbar.FullScreenControl />
  <EuiDataGridToolbar.RowSizeControl />
</EuiDataGridToolbar>

This refactor should be transparent and must not change the functionality of the EuiDataGrid component, it will be made only for extracting the visual pieces of the component and exposing them to be reused.

Any opinion is more than welcome to refine this issue and come up with an implementation plan.

@tonyghiani
Copy link
Contributor

A more concrete example of future usage could be the following, in which we compose the grid using only the presentational components and adding column actions where required:

import { EuiDataGridRow, EuiDataGridRowCell, EuiDataGridRowCellActions } from '@elastic/eui';

const data = [
  { timestamp: '11:25:52.587', author: 'generic', message: 'error 1' },
  { timestamp: '11:25:55.542', author: 'generic', message: 'error 2' },
];

function LogsUI() {
  const likeAction = useCallback(
    ({ rowIndex, columnId, Component }) => {
      return (
        <Component
          onClick={() => alert(`Hi ${data[rowIndex][columnId].raw}`)}
          iconType='heart'
          aria-label={`Liked ${data[rowIndex][columnId].raw}!`}
        >
          Like it!
        </Component>
      );
    },
    [data]
  );

  return (
    <GridContainer>
      {data.map((row, rowIndex) => {
        return (
          <EuiDataGridRow>
            <EuiDataGridRowCell>{row.timestamp}</EuiDataGridRowCell>
            <EuiDataGridRowCell
              renderCellActions={({ showActions }) =>
                showActions && (
                  <EuiDataGridRowCellActions
                    cellActions={[likeAction]}
                    rowIndex={rowIndex}
                    colIndex={1}
                    columnId='author'
                  />
                )
              }
            >
              {row.author}
            </EuiDataGridRowCell>
            <EuiDataGridRowCell>{row.timestamp}</EuiDataGridRowCell>
          </EuiDataGridRow>
        );
      })}
    </GridContainer>
  );
}

I still have doubts on how flexible we want to make these components. For example, the rendering of the EuiDataGridRowCellActions is currently delegated to the EuiDataGridRowCell through the property renderCellActions, which decided where to position the actions inside the cell.
Enhancing the cell to render using the render-props pattern, can give more flexibility on where to render actions (or anything else) inside the cell, but it could result in a more complex structure.

It should look like

<EuiDataGridRowCell>
  {({ showActions }) => (
    <>
      {row.author}
      {showActions && (
        <EuiDataGridRowCellActions
          cellActions={[likeAction]}
          rowIndex={rowIndex}
          colIndex={1}
          columnId='author'
        />
      )}
    </>
  )}
</EuiDataGridRowCell>

In terms of implementation, the EuiDataGridRowCellActions would be almost fully the same.

@weltenwort
Copy link
Member Author

Thanks for these examples. The render prop approach seems preferable to me because it is a good middle ground of providing flexibility but also following the design patterns established by the grid.

Would you be able to also give an example of what the corresponding usage site in the EuiDataGrid would look like after the extraction (assuming we go with the render props approach)?

@weltenwort
Copy link
Member Author

This has given us lots of insights. @tonyghiani would you agree that we can consider it "closed"? We can refer back to the learnings next time we work on rendering a table of log entries.

@tonyghiani
Copy link
Contributor

Agree, with all the upcoming changes I guess there isn't much more to analyze here and we can always come back to this in future 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Logs UI Logs UI feature Team:Infra Monitoring UI - DEPRECATED DEPRECATED - Label for the Infra Monitoring UI team. Use Team:obs-ux-infra_services
Projects
None yet
Development

No branches or pull requests

3 participants