-
Notifications
You must be signed in to change notification settings - Fork 8.2k
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
Add pluggable panel action tests #20163
Merged
stacey-gammon
merged 8 commits into
elastic:master
from
stacey-gammon:2018-06-19-pluggable-panel-action-test
Jul 28, 2018
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
9f632bd
Add pluggable panel action tests
stacey-gammon 0cbc185
address code review comments
stacey-gammon 09585eb
Merge branch 'master' of https://github.com/elastic/kibana into 2018-…
stacey-gammon a173d48
update inspector snapshot
stacey-gammon c9eec1b
Merge branch 'master' of https://github.com/elastic/kibana into 2018-…
stacey-gammon 5036e6e
Merge branch 'master' of https://github.com/elastic/kibana into 2018-…
stacey-gammon 07a4d3c
remove temp declared ts module now that eui has EuiFlyout typings
stacey-gammon 02304c5
address code comments
stacey-gammon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
import React from 'react'; | ||
|
||
import { EuiFlyout } from '@elastic/eui'; | ||
import { EventEmitter } from 'events'; | ||
import ReactDOM from 'react-dom'; | ||
|
||
let activeSession: FlyoutSession | null = null; | ||
|
||
const CONTAINER_ID = 'flyout-container'; | ||
|
||
function getOrCreateContainerElement() { | ||
let container = document.getElementById(CONTAINER_ID); | ||
if (!container) { | ||
container = document.createElement('div'); | ||
container.id = CONTAINER_ID; | ||
document.body.appendChild(container); | ||
} | ||
return container; | ||
} | ||
|
||
/** | ||
* A FlyoutSession describes the session of one opened flyout panel. It offers | ||
* methods to close the flyout panel again. If you open a flyout panel you should make | ||
* sure you call {@link FlyoutSession#close} when it should be closed. | ||
* Since a flyout could also be closed without calling this method (e.g. because | ||
* the user closes it), you must listen to the "closed" event on this instance. | ||
* It will be emitted whenever the flyout will be closed and you should throw | ||
* away your reference to this instance whenever you receive that event. | ||
* @extends EventEmitter | ||
*/ | ||
class FlyoutSession extends EventEmitter { | ||
/** | ||
* Binds the current flyout session to an Angular scope, meaning this flyout | ||
* session will be closed as soon as the Angular scope gets destroyed. | ||
* @param {object} scope - An angular scope object to bind to. | ||
*/ | ||
public bindToAngularScope(scope: ng.IScope): void { | ||
const removeWatch = scope.$on('$destroy', () => this.close()); | ||
this.on('closed', () => removeWatch()); | ||
} | ||
|
||
/** | ||
* Closes the opened flyout as long as it's still the open one. | ||
* If this is not the active session anymore, this method won't do anything. | ||
* If this session was still active and a flyout was closed, the 'closed' | ||
* event will be emitted on this FlyoutSession instance. | ||
*/ | ||
public close(): void { | ||
if (activeSession === this) { | ||
const container = document.getElementById(CONTAINER_ID); | ||
if (container) { | ||
ReactDOM.unmountComponentAtNode(container); | ||
this.emit('closed'); | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Opens a flyout panel with the given component inside. You can use | ||
* {@link FlyoutSession#close} on the return value to close the flyout. | ||
* | ||
* @param flyoutChildren - Mounts the children inside a fly out panel | ||
* @return {FlyoutSession} The session instance for the opened flyout panel. | ||
*/ | ||
export function openFlyout( | ||
flyoutChildren: React.ReactNode, | ||
flyoutProps: { | ||
onClose?: () => void; | ||
'data-test-subj'?: string; | ||
} = {} | ||
): FlyoutSession { | ||
// If there is an active inspector session close it before opening a new one. | ||
if (activeSession) { | ||
activeSession.close(); | ||
} | ||
const container = getOrCreateContainerElement(); | ||
const session = (activeSession = new FlyoutSession()); | ||
const onClose = () => { | ||
if (flyoutProps.onClose) { | ||
flyoutProps.onClose(); | ||
} | ||
session.close(); | ||
}; | ||
|
||
ReactDOM.render( | ||
<EuiFlyout {...flyoutProps} onClose={onClose}> | ||
{flyoutChildren} | ||
</EuiFlyout>, | ||
container | ||
); | ||
|
||
return session; | ||
} | ||
|
||
export { FlyoutSession }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you under | ||
* the Apache License, Version 2.0 (the "License"); you may | ||
* not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the License is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
* KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations | ||
* under the License. | ||
*/ | ||
|
||
export * from './flyout_session'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a few thoughts about this. Should EuiFlyout itself just coordinate this internally, essentially acting like a singleton and ensuring only one flyout is ever visible at a time? It almost seems like that would be a sensible design.
Alternatively, we could do that ourselves, and keep this inside the React lifecycle by just making it a plain React component. Something like this, maybe:
The advantage there is that consumers can use it like any other React component. It'd be styled to have a fixed position, etc, but could show/ hide based on props / state changes without special cases or whatever.
It'd be consumed like this:
Or something.
You could pass it an Angular scope as an optional param, too, if that's a case that needs handling.
The advantage to either of those ^^^ approaches is that the lifecycle of the flyout is normal React stuff, no special DOM manipulation or possible leaking edge cases.
If we keep the current solution (which is fine by me), it seems like it might be nice to optionally pass the container in, so that callers could pass a container that is managed by React / destroyed by React and not have to worry about cleanup or extraneous references.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer your first solutions - having flyout be a singleton. I can't think of any good situation where we should have two flyouts.
I would prefer to leave it as is though in this PR, just for the sake of unblocking some things (Tim wants to add inspector tests, I want to extend the panel action tests, and we both want to generalize this approach to all plugins not just panels). I think we'll have to address the flyout changes soon, though, as what should happen if you open a panel action with a flyout while an inspector is open?