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

feat: add autocopy functionality to CopyToClipboard (#10328) #13037

Merged
merged 1 commit into from
Feb 17, 2021

Conversation

michael-s-molina
Copy link
Member

SUMMARY

I left the copy button in autocopy mode just in case the user navigates to another tab, copy some content, comes back to the application and wants to copy the link again without reopening the modal or popover.

Alert PR improves notification positioning with right and bottom margins helping the user to notice the message.

@junlincc @rusackas

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

Screen Shot 2021-02-09 at 4 17 48 PM

Screen Shot 2021-02-09 at 4 28 09 PM

Screen Shot 2021-02-09 at 4 21 32 PM

Screen Shot 2021-02-09 at 4 23 29 PM

TEST PLAN

1 - Go to a dashboard
2- Click on a chart 3 dots icon
3 - Select share chart
4 - The link should be automatically copied to clipboard

1 - Go to explore
2 - Click on chain icon in top right corner
3 - The link should be automatically copied to clipboard

ADDITIONAL INFORMATION

  • Has associated issue
  • Changes UI
  • Requires DB Migration.
  • Confirm DB Migration upgrade and downgrade tested.
  • Introduces new feature or API
  • Removes existing feature or API

@codecov-io
Copy link

codecov-io commented Feb 9, 2021

Codecov Report

Merging #13037 (0f40a2b) into master (9cd0165) will increase coverage by 19.74%.
The diff coverage is 78.94%.

Impacted file tree graph

@@             Coverage Diff             @@
##           master   #13037       +/-   ##
===========================================
+ Coverage   53.38%   73.13%   +19.74%     
===========================================
  Files         489      546       +57     
  Lines       17315    20183     +2868     
  Branches     4482     5275      +793     
===========================================
+ Hits         9244    14761     +5517     
+ Misses       8071     5297     -2774     
- Partials        0      125      +125     
Flag Coverage Δ
cypress 53.58% <77.77%> (+0.19%) ⬆️
javascript 61.93% <78.94%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
...set-frontend/src/components/URLShortLinkButton.jsx 100.00% <ø> (ø)
...rset-frontend/src/components/URLShortLinkModal.tsx 81.48% <ø> (+3.70%) ⬆️
...set-frontend/src/views/CRUD/welcome/ChartTable.tsx 76.08% <ø> (+72.86%) ⬆️
...frontend/src/views/CRUD/welcome/DashboardTable.tsx 62.50% <ø> (+60.50%) ⬆️
...t-frontend/src/views/CRUD/welcome/SavedQueries.tsx 62.50% <ø> (+54.70%) ⬆️
...perset-frontend/src/components/CopyToClipboard.jsx 77.27% <60.00%> (+20.12%) ⬆️
superset-frontend/src/components/Button/index.tsx 100.00% <100.00%> (ø)
superset-frontend/src/utils/copy.ts 92.30% <100.00%> (+88.14%) ⬆️
...tend/src/filters/components/Select/controlPanel.ts 18.18% <0.00%> (-81.82%) ⬇️
superset-frontend/src/views/index.tsx 25.00% <0.00%> (-75.00%) ⬇️
... and 412 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9cd0165...0f40a2b. Read the comment docs.

} else {
renderedChildren = Children.toArray(children);
}

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
const renderedChildren = Children.toArray(element?.type == React.Fragment ? element.props.children : children);

Not sure if it's easier to read in a one liner and/or with a null-coalescing operator. ¯\_(ツ)_/¯

@rusackas
Copy link
Member

This looks like some great engineering work @michael-s-molina , and I'm giving it a review. Meanwhile, just thinking about the feature, I have a small UX concern/curiosity for @zuzana-vej and/or @junlincc that I feel I should raise.

Were flows around the email function considered, where the user might have something on the clipboard (e.g. the contents of an email) that gets nuked by this automatic copying? While it saves a click, I hope we're not frustrating other users even more.

I'm wondering if that does potential UX harm by overwriting the contents of the clipboard when there's no clear indication that the "share" button will do so. I suspect that's why most sites (Youtube as one example) don't do this.

If the intent of the change is simply to remove a click, then I wonder if Share should trigger a modal in the first place, which requires a click to close. The design of the Share button on Reddit, for example, serves the same purpose - open the menu, click "copy" and it just goes away unobtrusively.

Copy link
Member

@rusackas rusackas left a comment

Choose a reason for hiding this comment

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

Minor nit/question, but generally looks good to me from a code perspective, so I'm approving.

Before merging, I just want to make sure this is the approach we want to take on the UI/UX front in general though, as there may be other ways to save a click (or two) without surprising the user in an impactful way.

@ktmud
Copy link
Member

ktmud commented Feb 10, 2021

I share the same concern with @rusackas on the implicitness of the auto-copy behavior and how it may accidentally override users' existing clipboard.

I'm wondering if we can replace the share button with a copy icon or move the share functionality (under two links, "Copy sharable URL" and "Share via Email") under the hamburger menu.

I'd imagine the frustration mentioned in #10328 mostly come from the "slow" animation of the popover and the fact that you have to move your mouse horizontally to the left to find the Copy icon. Putting the copy link in a dropdown menu might make the action flow smoother.

@zuzana-vej
Copy link
Contributor

@rusackas Good point, haven't thought about that. There were few users who provided feedback that they need to copy twice just to share a link. Sharing a link is very common and action users perform many times even every day, while the share via email is not - but just because our users don't user it much doesn't mean others in community don't, and I can see how this could be confusing in general.

@ktmud generally the feedback was that user needs 2 clicks, and that the copy button is small and user needs to navigate to it. Which on dashboard means moving mouse very far. On Chart Explore not but still user needs to move to the left to navigate to the small icon. Displaying the option to copy link RIGHT BELLOW the share link button (and then the email option below that) could be much better user experience (still 2 clicks, but much easier), which also addresses @rusackas's concern. The other option is to have two icons as @ktmud suggested too.

@nytai
Copy link
Member

nytai commented Feb 10, 2021

+1 on this concern. I think there's a reason why the copy to clipboard is a separate action than share for almost all instances where this functionality appears. Wiping the user's clipboard and adding a new item is something that should only happen with the user's consent. I don't think "share" implies this consent.

I think this could be solved by having the popover appear on hover or moving the copy clipboard button much closer to where the user mouse would be after taking the "share" action. @ktmud's solution also sound viable. In the case of dashboard, opening a modal does seem a bit heavy. Would we be open to revising that design to use a popover instead, or at least change to something that matches the other design?

@michael-s-molina
Copy link
Member Author

Thank you all for the valuable feedback. Nice catch @rusackas! I really like @ktmud's solution with fewer clicks and seamless integration with the interface. I even simulated this behavior bellow:

Screen Shot 2021-02-10 at 8 12 35 AM

Screen Shot 2021-02-10 at 8 15 36 AM

What do you all think?

@ktmud
Copy link
Member

ktmud commented Feb 10, 2021

@michael-s-molina Thanks for the quick simulation!

I think this works for the dashboard page. For the Explore page though, looking at this more, I'm now no so sure about replacing the icon as it's not very clear what does a copy icon mean. Most first-time users would probably associate it with copying the data, the query, or the chart metadata, not a short-url.

Here's another proposal: wow about we keep the popover but make it open on hover and remove the animation?

@michael-s-molina
Copy link
Member Author

michael-s-molina commented Feb 10, 2021

@michael-s-molina Thanks for the quick simulation!

I think this works for the dashboard page. For the Explore page though, looking at this more, I'm now no so sure about replacing the icon as it's not very clear what does a copy icon mean. Most first-time users would probably associate it with copying the data, the query, or the chart metadata, not a short-url.

Here's another proposal: wow about we keep the popover but make it open on hover and remove the animation?

@ktmud I totally agree about the copy icon but I really like the idea to remove the popover and make this action more straightforward. Can't we just use the Fontawesome link icon? It's already being used in other copy buttons like this one:

Screen Shot 2021-02-10 at 4 01 52 PM

I think the user will quickly assimilate, and also we have the tooltip to help. It would look like this:

Screen Shot 2021-02-10 at 4 34 38 PM

or

Screen Shot 2021-02-10 at 4 35 14 PM

What do you think?

@ktmud
Copy link
Member

ktmud commented Feb 10, 2021

I think the link icon works, too, but let's make sure to add a tooltip "Copy chart URL to clipboard". It'll change the behavior of an existing icon, but maybe that won't be a big issue with the added tooltip?

What do you all think? @evans @junlincc @nytai @zuzana-vej ?

@zuzana-vej
Copy link
Contributor

I think the 2nd image (link icon and email icon) is good. Only thing is that dashboard and explore have slightly different behavior (one has two icons and one has another menu item in the dropdown). But I think it's probably ok and I think it will save users time. In terms of the behavior (on Explore) changing, I think that's very straightfoward for users to get used to.

@junlincc junlincc added need:design-review Requires input/approval from a Designer design-sys-revisit labels Feb 11, 2021
@junlincc
Copy link
Member

junlincc commented Feb 11, 2021

We have plan of moving those buttons and share under menu, leaving only copy link directly accessible from the view. let's keep discussion of this temporary solution light. Signing off from Product and Design. Thanks so much @michael-s-molina !

@michael-s-molina
Copy link
Member Author

In this last commit I did the following changes in addition to original changes:

  • Changed icons to use Icon component except for JSON and CSV because we don’t have equivalent icons yet. Maybe with Diego's PR (refactor: New Icon system with Enhanced Antd Custom Icon #12229) we can replace these in the future.

  • When clicked copy and email buttons were generating a different short URL even when the main URL had no change. I fixed this to avoid unnecessary POST requests.

  • Added tooltip for all action buttons in Explore

hover

  • Removed outline border when active

Screen Shot 2021-02-12 at 9 14 22 AM

  • Changed dashboard copy/email from modal to menu item

Screen Shot 2021-02-15 at 8 52 26 AM

  • Changed chart copy/email from modal to menu item

Screen Shot 2021-02-15 at 8 52 10 AM

I also created a React hook called useUrlShortener for the cases where we need a short version of an URL.

@ktmud
Copy link
Member

ktmud commented Feb 15, 2021

This is so cool. Thanks for all the updates and the attention to details! @michael-s-molina

@junlincc
Copy link
Member

@ktmud you wanna approve the code?

@junlincc junlincc added explore Namespace | Anything related to Explore and removed need:design-review Requires input/approval from a Designer labels Feb 16, 2021
Copy link
Member

@ktmud ktmud left a comment

Choose a reason for hiding this comment

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

Code LGTM with a couple of small comments.

A small UX suggestion: instead of using toast, you may also just updated the tooltip when copied was successful (you can even show a "Loading..." while fetching the shortened URL in the tooltip, too)

copied-to-clipboard

@@ -79,19 +79,19 @@ describe('HeaderActionsDropdown', () => {
expect(menu.find(SaveModal)).not.toExist();
});

it('should render five Menu items', () => {
it('should render four Menu items', () => {
Copy link
Member

Choose a reason for hiding this comment

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

These count assertions can probably be moved into other tests so you don't have to keep track of whether the test title is consistent. But no need to update if this already works.

Copy link
Member Author

Choose a reason for hiding this comment

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

I changed to "should render available Menu items" since this is nested in a describe with the role being tested. This way future changes are not going to impact this text.

slice: PropTypes.object,
addDangerToast: PropTypes.func.isRequired,
addSuccessToast: PropTypes.func.isRequired,
};
Copy link
Member

@ktmud ktmud Feb 16, 2021

Choose a reason for hiding this comment

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

Next time, if we are to update propTypes, might as well just convert the whole component into tsx first.

You could also convert it to a functional component and use the useToasts hook.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated to typescript!

...rest
} = props;

const getShortUrl = useUrlShortener(url);
Copy link
Member

Choose a reason for hiding this comment

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

I think you can just let useUrlShortener return shortUrl itself and add a loading state if shortUrl is falsy.

Copy link
Member Author

Choose a reason for hiding this comment

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

The idea here was correct but the implementation was not. The idea is that useUrlShortener returns an async function to delay the POST request to the moment the user actually clicks the option. As an async function you can infer loading and error states. I fixed the code to reflect this. Previously the error route (when the server throws an error) was not functioning and now is fixed also.

addSuccessToast(t('Copied to clipboard!'));
} catch (error) {
addDangerToast(
t('Sorry, your browser does not support copying. Use Ctrl / Cmd + C!'),
Copy link
Member

@ktmud ktmud Feb 16, 2021

Choose a reason for hiding this comment

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

I don't think there is a place to Ctrl + C from anymore after the updated UI.

Copy link
Member Author

Choose a reason for hiding this comment

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

Great catch! Fixed.


async function onShareByEmail() {
try {
const bodyWithLink = t('%s%s', emailBody, getShortUrl());
Copy link
Member

Choose a reason for hiding this comment

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

t is probably not needed if this is just simple string concatenation.

Copy link
Member Author

Choose a reason for hiding this comment

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

I checked that the parent component is responsible for the translation of email body. No need here. Removed.

@ktmud
Copy link
Member

ktmud commented Feb 16, 2021

@ktmud you wanna approve the code?

Was just reviewing and testing this locally. 😃

@junlincc
Copy link
Member

@michael-s-molina @ktmud Thank you both for perfecting this change! this is way better than my original expectation! We will still need to revisit the layout in the near future, but sure to keep the essence from this PR. ♥️

@michael-s-molina
Copy link
Member Author

michael-s-molina commented Feb 17, 2021

Code LGTM with a couple of small comments.

A small UX suggestion: instead of using toast, you may also just updated the tooltip when copied was successful (you can even show a "Loading..." while fetching the shortened URL in the tooltip, too)

copied-to-clipboard

@ktmud Accepted you suggestion. Now we update the tooltip.

Copy link
Member

@ktmud ktmud left a comment

Choose a reason for hiding this comment

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

One last comment, but let's do it in another PR (if you think it's necessary).

Comment on lines +102 to +109
try {
setCopyTooltip(t('Loading...'));
const shortUrl = await getShortUrl();
await copyTextToClipboard(shortUrl);
setCopyTooltip(t('Copied to clipboard!'));
} catch (error) {
setCopyTooltip(t('Sorry, your browser does not support copying.'));
}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
try {
setCopyTooltip(t('Loading...'));
const shortUrl = await getShortUrl();
await copyTextToClipboard(shortUrl);
setCopyTooltip(t('Copied to clipboard!'));
} catch (error) {
setCopyTooltip(t('Sorry, your browser does not support copying.'));
}
let shortUrl;
try {
setCopyTooltip(t('Loading...'));
shortUrl = await getShortUrl();
} catch (error) {
setCopyTooltip(t('ERROR: failed to generate chart URL.'));
return;
}
try {
await copyTextToClipboard(shortUrl);
setCopyTooltip(t('Copied to clipboard!'));
} catch (error) {
setCopyTooltip(t('Sorry, your browser does not support copying.'));
}

I think we can use two try/catch to distinguish backend error from browser support error. For browsers that does not support copying, maybe you can also show the shortened URL in the tooltip (or an alert box, or a modal) so users can copy it themselves.

@ktmud ktmud merged commit ad4ca22 into apache:master Feb 17, 2021
@mistercrunch mistercrunch added 🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels 🚢 1.2.0 labels Mar 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏷️ bot A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels explore Namespace | Anything related to Explore size/XL 🚢 1.2.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants