-
Notifications
You must be signed in to change notification settings - Fork 334
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
Added copy to clipboard button to external output area #954
Conversation
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.
Thank you for the pr! 🎉
Nice job figuring this out overall! There are a couple things to fix, should be no big deal.
Welcome and let me know if you have questions!
lib/components/output-area.js
Outdated
<div | ||
className="btn icon icon-clippy" | ||
onClick={ function() { | ||
atom.clipboard.write(kernel.outputStore.outputs[kernel.outputStore.index].text.trim()); |
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.
The main reason tests are not passing is because flow wants you to handle cases where kernel
or kernel.outputStore
are undefined.
It should be fine if you do something like:
if (!kernel || !kernel.outputStore) return;
just above this line.
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.
Stream outputs, e.g. from print()
, have an output.text
property. Other execution results have no text
property so we will need to look for output.data
mime bundles, with 'text/plain' being the lowest/plainest common denominator.
// add up top:
import { toJS } from "mobx";
import _ from "lodash";
// ...
const handleClick = () => {
if (!kernel || !kernel.outputStore) return;
// output should be converted to a plain js object first:
const output = toJS(kernel.outputStore.outputs[kernel.outputStore.index]);
// check for a text property and fall back to data["text/plain"]
// there are other ways of doing this if you like, but for example:
const textOrBundle = _.has(output, "text")
? output.text
: output.data["text/plain"];
atom.clipboard.write(textOrBundle);
atom.notifications.addSuccess("Copied to clipboard");
};
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 didn't realize that the output might not be something with an output.text
property, thanks for catching that. The style thing was a good idea as well.
I do have a question as far as the case where kernel
or kernel.outputStore
are undefined. That entire function is (or was, as I moved it out of an anonymous function) nested inside a div that wouldn't even appear if kernel.outputStore.outputs.length
returned a value less than or equal to 0. Would that condition not require that both kernel
and kernel.outputStore
be defined?
lib/components/output-area.js
Outdated
flex: "0 0 auto", | ||
width: "fit-content" | ||
}} | ||
> |
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.
Minor thing 😄
Since we are using the same style, why not put this into a variable right below EmptyMessage
up top:
const buttonStyle = {
flex: "0 0 auto",
width: "fit-content"
};
// then in the component:
style={buttonStyle}
lib/components/output-area.js
Outdated
@@ -17,8 +19,24 @@ const EmptyMessage = () => { | |||
); | |||
}; | |||
|
|||
const handleClick = () => { | |||
//convert output to a plain js object | |||
const output = toJS(kernel.outputStore.outputs[kernel.outputStore.index]); |
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.
kernel
isn't defined here so this fails tests. It should come from the store like below.
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.
☝️ you can check if you caught the flow errors locally by running npm run flow
from the root of your hydrogen project directory.
@rgbkrk I was thinking you could just move handleClick
into the outputArea
observer function, then add:
const handleClick = () => {
if (!kernel || !kernel.outputStore) return;
to satisfy flow?
I just merged in a PR that changed formatting, you'll need to rebase (and likely make sure to upgrade dependencies). |
@callmeish want to join our slack channel? This is close, but the minor details like flow and the conflicts from our prettier upgrade could be confusing 😆 |
Rebased, tested, should be good now. Thanks a bunch for the tip on local flow testing. |
@callmeish Thanks a lot for the work and the rebase! To fix this a interactive rebase is necessary: git remote update
git checkout copy-external-output
git rebase -i upstream/master Remove the commits unrelated to this PR in the editor that will pop up and you should be good to go. If you need help with this feel free to join our slack channel. |
and fix button styling E.g. plotly doesn't return text/plain mime type
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.
@callmeish Since we're waiting with #978 for this to be merge, I rebase this PR and appended a minor fix for the case where no text/plain
mime type is available (e.g. plotly plot).
This should now be good to merge.
Thanks again for digging into this. I invited you to the nteract organisation 🎉 .
We're very happy if you'd like to help us maintaining Hydrogen.
const handleClick = () => { | ||
if (!kernel || !kernel.outputStore) return; | ||
//convert output to a plain js object | ||
const output = toJS(kernel.outputStore.outputs[kernel.outputStore.index]); |
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'm not sure if we really need to convert it but it doesn't hurt.
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 had some error without it (not consistently)
An alternative approach would be to get the text directly from the DOM as it is done in the result view component. |
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.
Thanks @callmeish, I hope you stick around!
I like this approach as well, another benefit is it can be done without refs which the react docs say should be used sparingly. |
We could run |
Addressed the feature request in #845. Testing using python scripts gives identical functionality to hydrogen without these changes, the only difference being the added copy to clipboard button.