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

Move DashboardEmptyScreen inside DashboardViewport #51939

Merged
merged 29 commits into from
Dec 10, 2019

Conversation

majagrubic
Copy link
Contributor

@majagrubic majagrubic commented Nov 30, 2019

Summary

Intro

As part of the Dashboard-first project, we'll need to add Visualization from the dashboard. I was prototyping this flow, and there was a visible flick where the empty dashboard screen was still shown before the visualization appeared, visible from the GIF below:
save_visualization

What this PR contains?

For the flick to go away, empty screen needs to be inside DashboardViewport. This PR refactors the code so that DashboardEmptyScreen is rendered inside DashboardViewport and gets all the relevant info it needs to render through container input.

What this PR does not contain?

This PR does not actually add visualization from the dashboard. It does not change the layout nor the actions of the empty dashboard screen. It will be added in a subsequent PR for easier review.

How best to review this?

I've add some comments to the relevant places below to help with the review. Some things to look out for: panel rendering, time application, fullscreen mode, report generation.

Checklist

Use strikethroughs to remove checklist items you don't feel are applicable to this PR.

For maintainers

showLinkToVisualize: shouldShowEditHelp,
};
if (shouldShowEditHelp) {
emptyScreenProps.onVisualizeClick = noop;
Copy link
Contributor Author

@majagrubic majagrubic Nov 30, 2019

Choose a reason for hiding this comment

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

noop for now as we're not in fact adding visualizations yet.

@@ -735,6 +750,8 @@ export class DashboardAppController {
}
};

navActions[TopNavIds.VISUALIZE] = async () => {};
Copy link
Contributor Author

@majagrubic majagrubic Nov 30, 2019

Choose a reason for hiding this comment

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

noop for now, this is where the new logic for adding the visualization will live.

)}
<DashboardGrid container={container} />
<div>
{isEmptyState ? this.renderEmptyScreen() : null}
Copy link
Contributor Author

@majagrubic majagrubic Nov 30, 2019

Choose a reason for hiding this comment

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

The empty screen needs to be inside dashboardViewport, but mustn't be inside inside data-shared-items-container or else its content will be included in the report generation. This DOM structure effectively means we could have emptyScreen AND dashboard panels rendered on the screen at the same time, but if the state is always reset appropriately, this should never happen.

Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of leaving it as a possibility to render both at the same time, should we specifically case the renderings? I wouldn't bet on state always being reset appropriately 😬 (though maybe I'm a pessimist).

@@ -240,6 +240,7 @@ export abstract class Container<
...this.input.panels,
[panelState.explicitInput.id]: panelState,
},
isEmptyState: false,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Adding a new panel means it's not an empty state any more, so need to reset.

@elasticmachine
Copy link
Contributor

💔 Build Failed

@majagrubic majagrubic marked this pull request as ready for review November 30, 2019 17:24
@majagrubic majagrubic requested review from a team as code owners November 30, 2019 17:24
@majagrubic majagrubic requested review from a team, timroes and myasonik November 30, 2019 17:25
@majagrubic majagrubic added release_note:skip Skip the PR/issue when compiling release notes v8.0.0 v7.6.0 labels Nov 30, 2019
@elasticmachine
Copy link
Contributor

💔 Build Failed

@majagrubic
Copy link
Contributor Author

Jenkins, test this

@elasticmachine
Copy link
Contributor

💔 Build Failed

@majagrubic
Copy link
Contributor Author

Jenkins, test this

@majagrubic majagrubic force-pushed the maja/swithc-to-visualize branch from c7f1ffb to a34c220 Compare December 1, 2019 10:48
@elasticmachine
Copy link
Contributor

💔 Build Failed

@majagrubic majagrubic added the Team:Visualizations Visualization editors, elastic-charts and infrastructure label Dec 1, 2019
@elasticmachine
Copy link
Contributor

💔 Build Failed

@majagrubic majagrubic requested review from flash1293 and removed request for timroes December 6, 2019 11:44
@majagrubic
Copy link
Contributor Author

majagrubic commented Dec 6, 2019

I updated the code again, since the empty state was not being reset properly, which caused the exit fullscreen button to being rendered twice, which was messing the functional test. I updated that one functional test as well, I still don't understand how it was ever passing.

@elasticmachine
Copy link
Contributor

💔 Build Failed

@majagrubic
Copy link
Contributor Author

Jenkins, test this

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

@majagrubic
Copy link
Contributor Author

@elasticmachine merge upstream

@flash1293
Copy link
Contributor

Not 100% sure whether introduced by this PR, but when the "Use margin between panels" setting is disabled, the light gray background color isn't shown across the full height anymore:
Screenshot 2019-12-09 at 11 40 19

@@ -143,6 +142,16 @@ export class DashboardAppController {
}
$scope.showSaveQuery = dashboardCapabilities.saveQuery as boolean;

$scope.getShouldShowEditHelp = () =>
Copy link
Contributor

@flash1293 flash1293 Dec 9, 2019

Choose a reason for hiding this comment

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

Why are those put on the scope? I can't find a place in angular where they are used

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good point. they were on the scope previously, so I just left them there, but it's true that there's no good reason why they should remain there.

dashboardContainer.renderEmpty = () => {
const shouldShowEditHelp = $scope.getShouldShowEditHelp();
const shouldShowViewHelp = $scope.getShouldShowViewHelp();
const isEmptyState = shouldShowEditHelp || shouldShowViewHelp;
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems like those two functions are always used like this. Would it make sense to put them into a single function and just call it directly here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, there is distinction between edit and view screen, it's used in the getEmptyScreenProps to decide which screen should be rendered.

<h2>{constants.fillDashboardTitle}</h2>
{showLinkToVisualize ? addVisualizationParagraph : enterEditModeParagraph}
</React.Fragment>
<EuiPage className="dshStartScreen" restrictWidth={'36em'}>
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: could use restrictWidth="36em"

@@ -234,6 +257,15 @@ export class DashboardAppController {
if (!isErrorEmbeddable(container)) {
dashboardContainer = container;

dashboardContainer.renderEmpty = () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

It feels like we are mixing responsibilities here. From my perspective, the dashboard app and the dashboard container are two separate pieces of code that serve different purposes.

Is it absolutely necessary the container knows about the empty state panel? Couldn't we make that a private detail of the app to keep the interface between the container and the app as small as possible (not injecting the renderEmpty function in a kind of dirty way into the container)? For example we could not render the container at all as long as it's empty and directly render the empty screen from the app itself in line 317:
instead of

container.render(dashboardDom);

we are calling

if (isEmpty) {
 reactDom.render(<DashboardEmptyScreen {...propsNStuff} />, dashboardDom);
} else {
  container.render(dashboardDom);
}

Now if there is an important reason the dashboard container has to know it can be empty, would it make more sense have the empty screen component living in the dashboard container itself instead of the dashboard app? In that scenario the app would just pass in a boolean prop like showEmptyScreen or something like this and the container would take care of the rest.

Copy link
Contributor Author

@majagrubic majagrubic Dec 9, 2019

Choose a reason for hiding this comment

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

Please see one of my comments above. Empty screen needs to live inside the dashboardViewport, mainly for the reporting to work properly. data-shared-items container needs to remain where it is. Removing that wrapper will cause the report of empty screen to fail. Putting it around DashboardEmptyScreen means the content of the empty screen will be included in the report.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now if there is an important reason the dashboard container has to know it can be empty, would it make more sense have the empty screen component living in the dashboard container itself instead of the dashboard app? In that scenario the app would just pass in a boolean prop like showEmptyScreen or something like this and the container would take care of the rest.

I am not quite sure I fully understand this question, but I think there are two things to note:

  1. The props of the empty screen are still unfortunately defined on the dashboard_app_controller: https://github.com/elastic/kibana/pull/51939/files#diff-b2738a4dec941f426bf944b70d057b75R185
  2. DasbhoardContainer is receiving renderEmpty in "a hacky way" as it can't go through input, because all inputs must be serializable

@majagrubic
Copy link
Contributor Author

majagrubic commented Dec 9, 2019

Re: margins on empty screen, same thing on master:
Screenshot 2019-12-09 at 11 47 00

I'll fix it in one of the next iterations.

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.

Synced offline with @majagrubic and I see how the places things are placed ties into the further plans with this, so this LGTM. Nits can be addressed, but it's not blocking the PR.

@majagrubic
Copy link
Contributor Author

majagrubic commented Dec 9, 2019

thank @flash1293 and @streamich for all the help in getting this done 🙇‍♀ lots more refactoring coming, stay tuned 🎉

@elasticmachine
Copy link
Contributor

💚 Build Succeeded

History

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

Copy link
Contributor

@cchaos cchaos left a comment

Choose a reason for hiding this comment

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

My comments aren't vital to merging this PR, but something to consider changing now. Otherwise we can do a follow-on PR.

Comment on lines +100 to +111
<EuiPageBody>
<EuiPageContent verticalPosition="center" horizontalPosition="center">
<EuiIcon type="dashboardApp" size="xxl" color="subdued" />
<EuiSpacer size="s" />
<EuiText grow={true}>
<h2 key={0.5}>{constants.fillDashboardTitle}</h2>
</EuiText>
<EuiSpacer size="m" />
{showLinkToVisualize ? addVisualizationParagraph : enterEditModeParagraph}
</EuiPageContent>
</EuiPageBody>
</EuiPage>
Copy link
Contributor

Choose a reason for hiding this comment

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

This whole thing can actually be simplified using the EuiEmptyPrompt component. But I can do that in a follow up PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This screen is going to change soon, so I would suggest against additional refactoring of it now.

const { renderEmpty } = this.props;
const { isFullScreenMode } = this.state;
return (
<div className="dshDashboardEmptyScreen">
Copy link
Contributor

Choose a reason for hiding this comment

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

This class is only used for tests and has not styles attached to it so its been better practice to use it as a data-test-subj instead. This way if styles were to be added or such, there wouldn't be conflicts between tests and styles.

return (
<React.Fragment>
{this.state.isEmptyState ? this.renderEmptyScreen() : null}
{this.renderContainerScreen()}
Copy link
Contributor

Choose a reason for hiding this comment

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

If you render only the empty state or the container screen, then the split background color problem will be gone.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm afraid this needs to stay as is for reporting to work properly for now. But I'm planning on a bigger refactor that will hopefully eliminate this hack then.

@@ -34,7 +34,7 @@
.dshLayout-isMaximizedPanel {
height: 100% !important; /* 1. */
width: 100%;
position: absolute;
position: absolute !important;
Copy link
Contributor

Choose a reason for hiding this comment

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

The /* 1. */ comment refers to the comment at the top explaining this part, can you also add this comment indicator to the end of this line.

@majagrubic
Copy link
Contributor Author

Thanx @cchaos, will address some of your comments in a follow-up PR.

@majagrubic majagrubic merged commit 717e40c into elastic:master Dec 10, 2019
@majagrubic majagrubic deleted the maja/swithc-to-visualize branch December 10, 2019 15:05
majagrubic pushed a commit to majagrubic/kibana that referenced this pull request Dec 10, 2019
* Prototyping adding Visualization to Dashboard

* i18n fixes

* Remvoing dashboard empty screen directive

* Updating test for empty dashboard screen

* Removing unused state variable

* Adding a test for DashboardViewPort

* i18n & minor fixes

* Fixing fullscreen mode view

* Fixing failing functional test (hopefully)

* Minor style fix

* Fixing EUI text, rendering empty screen OR the panels

* Fixing empty screen in fullscreen mode

* Update snapshot

* Trying to render empty screen from Angular controller

* refactor: 💡 don't pass renderEmpty through inputs

And make sure isEmptyState is not stale.

* Fixing tests after Vadim's commit

* Removing unnecessary isEmptyStateProps

* Skipping failing test

* Removing unnecessary en.json file

* Re-adding emptyState, reintroducing functional test

* Fixing ja-JP file

* Undoing my thing to the functional test
majagrubic pushed a commit that referenced this pull request Dec 11, 2019
* Prototyping adding Visualization to Dashboard

* i18n fixes

* Remvoing dashboard empty screen directive

* Updating test for empty dashboard screen

* Removing unused state variable

* Adding a test for DashboardViewPort

* i18n & minor fixes

* Fixing fullscreen mode view

* Fixing failing functional test (hopefully)

* Minor style fix

* Fixing EUI text, rendering empty screen OR the panels

* Fixing empty screen in fullscreen mode

* Update snapshot

* Trying to render empty screen from Angular controller

* refactor: 💡 don't pass renderEmpty through inputs

And make sure isEmptyState is not stale.

* Fixing tests after Vadim's commit

* Removing unnecessary isEmptyStateProps

* Skipping failing test

* Removing unnecessary en.json file

* Re-adding emptyState, reintroducing functional test

* Fixing ja-JP file

* Undoing my thing to the functional test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Dashboard Dashboard related features release_note:skip Skip the PR/issue when compiling release notes Team:Visualizations Visualization editors, elastic-charts and infrastructure v7.6.0 v8.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants