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

[Lens] New summary row feature for datatable #101075

Merged
merged 22 commits into from
Jun 9, 2021

Conversation

dej611
Copy link
Contributor

@dej611 dej611 commented Jun 1, 2021

Summary

Fixes #84558

This PR adds the summary row feature to the Lens datatable visualization.

List of features:

  • compute sum, average, count, minimum, maximum for numeric values
    • each column can set its own function
    • strict number validation of columns (field meta + actual rows data)
    • works with transposed columns
    • Formatters are inherited from columns
    • count uses the default numeric formatter
    • Column alignment configuration is used
  • do not export the summary row in CSV
  • No dynamic coloring for summary rows

Lens editor:

Screenshot 2021-06-01 at 19 12 03

Transposed columns:

Screenshot 2021-06-01 at 19 11 13

Last value is not supported yet

Screenshot 2021-06-01 at 19 11 22

Open questions:

Last value (and similarly Intervals custom ranges)

Initially I've also added the count + unique_count for string columns, but had to remove it due to issues with dimension transitions.
I think there's some potential in having them, but I guess that for V1 is ok to not have it.

In terms of implementation detail, I think, the visualization ought to know a bit more meta information about the dimension update, in order to reset the right options, or it is pretty easy to land on inconsistent states. This was the issue I faced when transitioning from one operation to another.

What is Count counting?

Currently count takes into account only rows with actual data, ignoring empty rows. Is that ok?

Checklist

Delete any items that are not applicable to this PR.

For maintainers

@dej611 dej611 added release_note:enhancement Team:Visualizations Visualization editors, elastic-charts and infrastructure v8.0.0 Feature:Lens v7.14.0 auto-backport Deprecated - use backport:version if exact versions are needed labels Jun 1, 2021
@wylieconlon wylieconlon changed the title [Lens]] New summary row feature for datatable [Lens] New summary row feature for datatable Jun 1, 2021
@flash1293
Copy link
Contributor

This looks pretty good! For transposed columns, space per column gets tight quickly (we have the same issue with the headers). I'm fine with solving this along with the headers though. Some tools seem to move the summary label to the non-transposed column and only the show the value per transposed column, but it would probably not work well in all cases.

I think avoiding summary rows for string columns in the first version is a good call as it adds quite a bit of complexity and seems like an edge case. Let's keep it simple as long as we can.

Can we rename Count to Value count and make sure it's handling last value array values in the expected way? Just to not re-use a name that has another meaning in the same UI.

@dej611
Copy link
Contributor Author

dej611 commented Jun 3, 2021

@elasticmachine merge upstream

@dej611
Copy link
Contributor Author

dej611 commented Jun 3, 2021

  • Renamed Count => Values count
  • Enabled empty string as valid label string
  • Configuration override when transitioning to invalid states (string columns)

Screenshot 2021-06-03 at 14 22 11

Copy link
Contributor

@flash1293 flash1293 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks almost good to me, just some uncertainty around the handling of array values. It looks like right now we don't treat the current column as "summarizeable" if there are array values, but it seems like it's a small addition to do so and remove an element of surprise ("why is the summary row disappearing if I change my time range"?). If this is complex to do I think we can also leave it like it works right now.

@@ -358,6 +361,8 @@ export const getDatatableVisualization = ({
reverse: false, // managed at UI level
};

const HasNoSummaryRow = column.summaryRow == null || column.summaryRow === 'none';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: hasNoSummaryRow

isNumeric &&
currentData?.rows.every(({ [accessor]: value }) => typeof value === 'number' || value == null);

return { isNumeric, hasAllNumericValues: hasFieldNumericValues };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: This is causing the summary row to disappear completely from table and config flyout if there is an array value (which can happen because of last value). Did this happen on purpose? Or should we treat each array value as a separate value in terms of summary calculation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this function could workout whether numeric arrays are available as well and report that.
I planned to use this function also for other feature checks as well where non-numeric columns may lead to issues.

On the other hand, considering numeric arrays as valid numeric values may be a good solution. In this case I'd probably show a warning about the presence of array values and compute them as valid values.

@dej611
Copy link
Contributor Author

dej611 commented Jun 3, 2021

  • Added support for array numeric values (Last value)
    • When array values are detected a warning sign is shown with some explanation on how array values are handled

Screenshot 2021-06-03 at 19 25 44

@flash1293
Copy link
Contributor

@elasticmachine merge upstream

@flash1293
Copy link
Contributor

The test failure looks like a real problem - maybe the test above has to close the flyout? Looks like the color menu is still open:
Screenshot 2021-06-04 at 09 07 37

I'm not sure whether we need a warning here - the behavior seems intuitive to me. It's what I would expect to happen, so I don't think we need to make people aware. What do you think?

@dej611
Copy link
Contributor Author

dej611 commented Jun 4, 2021

The test failure looks like a real problem - maybe the test above has to close the flyout? Looks like the color menu is still open:
Screenshot 2021-06-04 at 09 07 37

I'm not sure whether we need a warning here - the behavior seems intuitive to me. It's what I would expect to happen, so I don't think we need to make people aware. What do you think?

Yes, I did expect it some failure yesterday. I had problems to run the functional tests locally yesterday so I pushed to have a report here 😅

@flash1293
Copy link
Contributor

I'm not sure whether we need a warning here - the behavior seems intuitive to me. It's what I would expect to happen, so I don't think we need to make people aware. What do you think?

@dej611 Did you miss this comment?

@dej611
Copy link
Contributor Author

dej611 commented Jun 4, 2021

Yes I saw it, but when attempting to do it I realised it may be non so intuitive to compute the summaries on arrays.
I went for the most complete solution here. I think it's worth having the warning message.

@flash1293
Copy link
Contributor

non so intuitive to compute the summaries on arrays

Can you explain why? cc @ghudgins - I think it's too scary of a tool for the situation.

@dej611
Copy link
Contributor Author

dej611 commented Jun 4, 2021

  • Removed warning message in case of array values

Screenshot 2021-06-04 at 17 52 42

@dej611 dej611 marked this pull request as ready for review June 4, 2021 15:53
@dej611 dej611 requested a review from a team June 4, 2021 15:53
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-app (Team:KibanaApp)

@dej611
Copy link
Contributor Author

dej611 commented Jun 7, 2021

@elasticmachine merge upstream

Copy link
Contributor

@flash1293 flash1293 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like there is some leftover logic which is causing a bug

const value = row[accessor];
hasFieldOnlyNumberValues = hasFieldOnlyNumberValues && isValidNumber(value);
hasFieldNumericValues =
(hasFieldNumericValues && hasFieldOnlyNumberValues) ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is not correct - if there are arrays in the current column and the last row doesn't have a value, hasFieldNumericValues will become false: (first FEMALE column doesn't have a summary because the last row is undefined)
Screenshot 2021-06-07 at 14 18 38

Also I found this logic extremely hard to follow and it seems like it's not used anywhere - hasNumberValues is never accessed and it seems like this function is only returning a complex object because of this and can be simplified to this for all consumers:

export function isNumericField(currentData: Datatable | undefined, accessor: string) {
  return currentData?.rows.every(row => {
    const val = row[accessor];
    return isValidNumber(val) || Array.isArray(val) && val.every(isValidNumber);
  });
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The specific distinction in this function was propaedeutical for more than this specific case, that's the reason it is in the root folder.
I've built on top of this PR a fix for dynamic coloring using this utility.

I've reworked it a bit to fix this specific issue and speed up the computation in case it's not valid. In case you think it's best to have something lighter and more feature specific I can rewrite it as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't know whether we are ever going to need it, please let's remove it for now. I only found this issue by chance because the data I was testing with had that specific case.

@dej611
Copy link
Contributor Author

dej611 commented Jun 7, 2021

Just noticed that the Summary row is using a different component than another "select-like" field as Value Format:

Screenshot 2021-06-07 at 18 35 31

Screenshot 2021-06-07 at 18 35 36

Should the Summary row be converted into a ComboBox in this case, or it's ok as is?

@dej611
Copy link
Contributor Author

dej611 commented Jun 7, 2021

Migrated to combobox. If Select is preferred I can always revert the last commit

Screenshot 2021-06-07 at 19 11 24

@flash1293
Copy link
Contributor

Seems like some tests have to be adjusted for combo box

const summaryValue = computeFinalValue(columnArgs.summaryRow, columnArgs.columnId, table.rows);
// ignore the coluymn formatter for the count case
if (columnArgs.summaryRow === 'count') {
return summaryValue;
Copy link
Contributor

@flash1293 flash1293 Jun 8, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we use the default number formatter here?

Otherwise the values don't get formatted at all:
Screenshot 2021-06-08 at 14 18 23

options={getSummaryRowOptions()}
selectedOptions={[
{
label: fallbackSummaryLabel,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is picking up the user supplied summary label as the selected summary function:
Screenshot 2021-06-08 at 14 17 54

Especially confusing for no label:
Screenshot 2021-06-08 at 14 17 29

summaryRowValue: config.summaryRowValue,
...getFinalSummaryConfiguration(config.columnId, config, firstTable),
}))
.filter(({ summaryRow }) => summaryRow !== 'none');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the only column with a summary row is hidden, it will show a weird empty row (note the thin gray line below the thick black one):
Screenshot 2021-06-08 at 14 05 02

Should be easy to fix take into account the hidden flag and filter columnsWithSummary

@dej611
Copy link
Contributor Author

dej611 commented Jun 8, 2021

Addressed the reported issues w/ unit tests to cover them:

Screenshot 2021-06-08 at 15 04 56

Screenshot 2021-06-08 at 15 05 07

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
lens 670 672 +2

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
lens 1.3MB 1.3MB +6.7KB

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

Copy link
Contributor

@flash1293 flash1293 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, great work!

@dej611 dej611 merged commit e3c3b6f into elastic:master Jun 9, 2021
@dej611 dej611 deleted the lens/total-row-table branch June 9, 2021 12:27
kibanamachine added a commit to kibanamachine/kibana that referenced this pull request Jun 9, 2021
* ✨ New summary row feature for datatable

* ✨ Allow empty strings behind flag + tests

* 🐛 Address the transition problem + refactor

* ✅ Add some unit tests

* ✅ Add first functional tests

* 👌 first feedback addressed

* ✨ Make it handle numeric array values

* 📝 Improved message

* ✅ Fix functional test

* 🔥 Remove warning message for last value

* 🚨 Remove unused import

* 🐛 Fix a bug with last value

* 👌 Integrated feedback

* 💄 Migrated to combobox

* ✅ Fix unit tests + restore right data-test-id

* 🏷️ Fix type issue

* 👌 Address all issues reported

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
@kibanamachine
Copy link
Contributor

💚 Backport successful

Status Branch Result
7.x

This backport PR will be merged automatically after passing CI.

kibanamachine added a commit that referenced this pull request Jun 9, 2021
* ✨ New summary row feature for datatable

* ✨ Allow empty strings behind flag + tests

* 🐛 Address the transition problem + refactor

* ✅ Add some unit tests

* ✅ Add first functional tests

* 👌 first feedback addressed

* ✨ Make it handle numeric array values

* 📝 Improved message

* ✅ Fix functional test

* 🔥 Remove warning message for last value

* 🚨 Remove unused import

* 🐛 Fix a bug with last value

* 👌 Integrated feedback

* 💄 Migrated to combobox

* ✅ Fix unit tests + restore right data-test-id

* 🏷️ Fix type issue

* 👌 Address all issues reported

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>

Co-authored-by: Marco Liberati <dej611@users.noreply.github.com>
gmmorris added a commit to gmmorris/kibana that referenced this pull request Jun 9, 2021
* master:
  clarify which parts of TM are experimental (elastic#101757)
  Add sh scripts with _bulk_action route usage examples (elastic#101736)
  [Uptime] Only register route in side nav if uptime show capability is true (elastic#101709)
  Use KIBANA_DOCS in doc link service (elastic#101667)
  [Alerting][Event log] Persisting duration information for active alerts in event log (elastic#101387)
  Address design issues in Discover/Graph (elastic#101584)
  Optimize performance for document table (elastic#101715)
  Change file data visualizer links to point to new location in home application (elastic#101393)
  [Fleet] Tighten policy permissions, take II (elastic#97366)
  [ML] Add debounce to the severity control update  (elastic#101581)
  [Fleet] Fix routing issues with `getPath` and `history.push` (elastic#101658)
  [APM] Add link-to/transaction route (elastic#101731)
  [Index Patterns] Runtime fields CRUD REST API  (elastic#101164)
  [ILM] Refactor types and fix missing aria labels (elastic#101518)
  [Lens] New summary row feature for datatable (elastic#101075)
  Blocks save event filter with a white space name (elastic#101599)
  Improve security server types (elastic#101661)
  [APM] Replace side nav with tabs on Settings page (elastic#101460)
  [APM] Only register items in side nav if user has permissions to see app (elastic#101707)
  [Security solution][Endpoint] Add back button when to the event filters list (elastic#101280)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auto-backport Deprecated - use backport:version if exact versions are needed Feature:Lens release_note:enhancement Team:Visualizations Visualization editors, elastic-charts and infrastructure v7.14.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Lens] Support summary row for table
5 participants