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

Calendly Block: Show an error when the embed url is not found #14814

Merged
merged 4 commits into from
Mar 17, 2020

Conversation

Copons
Copy link
Contributor

@Copons Copons commented Feb 26, 2020

Fixes #14805

Changes proposed in this Pull Request:

  • Show a loading spinner when loading the embed.
  • Show an error when the embed url is not found.

When inserting an URL, the block tests it through the resolve-redirect endpoint.
On success, it sets the block's attributes and loads the embed.
On fail, it empties the URL attributes and shows an error notice.

Feb-26-2020 16-45-27

To make this work with the automatic block transformation when pasting a Calendly URL, the resolve-redirect check runs on block mount, and whenever the URL attribute changes.
This, unless the block style is link, as this implies that the URL passed the test already (and showing a "loading spinner" would look awkward.

Is this a new feature or does it add/remove features to an existing part of Jetpack?

  • If you're an Automattician, include a shortlink to the p2 discussion with Jetpack Product here.

Testing instructions:

  • Insert a Calendly block and add a correct Calendly URL.
  • Make sure the block has a loading spinner and then show the embed as expected.
  • Insert a second Calendly block with a correct URL, and set it as link style.
  • Save and reload the editor.
  • Make sure both blocks show up fine; the embedded one should show the loading spinner, while the other should not.
  • Insert another Calendly block, this time using an incorrect Calendly URL (e.g. https://calendly.com/totally-incorrect-url).
  • After the loading spinner, the block should revert to the placeholder with an error notice.
  • Save and reload. The incorrect block should show up in placeholder state.
  • Try again by pasting a correct and an incorrect URL in the editor. Make sure the behaviour of both transforms is the same as described above.

Proposed changelog entry for your changes:

  • Calendly block: Show an error when the embed URL is not found.

@Copons Copons added [Type] Enhancement Changes to an existing feature — removing, adding, or changing parts of it [Status] Needs Review To request a review from Crew. Label will be renamed soon. [Focus] Blocks Issues related to the block editor, aka Gutenberg, and its extensions developed in Jetpack [Block] Calendly labels Feb 26, 2020
@Copons Copons requested a review from a team February 26, 2020 16:55
@Copons Copons requested a review from a team as a code owner February 26, 2020 16:55
@Copons Copons self-assigned this Feb 26, 2020
@matticbot
Copy link
Contributor

Caution: This PR has changes that must be merged to WordPress.com
Hello Copons! These changes need to be synced to WordPress.com - If you 're an a11n, please commandeer, review, and approve D39450-code before merging this PR. Thank you!

@jetpackbot
Copy link

jetpackbot commented Feb 26, 2020

Thank you for the great PR description!

When this PR is ready for review, please apply the [Status] Needs Review label. If you are an a11n, please have someone from your team review the code if possible. The Jetpack team will also review this PR and merge it to be included in the next Jetpack release.

Scheduled Jetpack release: April 7, 2020.
Scheduled code freeze: March 31, 2020

Generated by 🚫 dangerJS against 26fafa2

jeherve
jeherve previously approved these changes Feb 26, 2020
Copy link
Member

@jeherve jeherve left a comment

Choose a reason for hiding this comment

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

This works well for me. 🚢

@jeherve jeherve added this to the 8.4 milestone Feb 26, 2020
@jeherve jeherve added [Status] Ready to Merge Go ahead, you can push that green button! and removed [Status] Needs Review To request a review from Crew. Label will be renamed soon. labels Feb 26, 2020
apeatling
apeatling previously approved these changes Feb 26, 2020
Copy link
Member

@apeatling apeatling left a comment

Choose a reason for hiding this comment

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

Followed all steps and they worked as described. 👍

@@ -65,6 +68,25 @@ export default function CalendlyEdit( props ) {
</>
);

useEffect( () => {
if ( ! url || 'link' === style ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

As you can change the URL and get it wrong, do you think it would be good to cover checking the URL for the link style too? I realise we probably don't want to show the spinner, but it would be good to let them it's invalid.

image

Copy link
Member

@scruffian scruffian left a comment

Choose a reason for hiding this comment

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

I agree that it would be good to do this check for both styles of embed...

@Copons
Copy link
Contributor Author

Copons commented Mar 4, 2020

@pablinos The useEffect here is triggered when the block mounts and the url changes.
It happens in these cases:

  1. When the visual editor loads from scratch.
  2. When the user switches from code to visual editor.
  3. When the user pastes a Calendly URL that gets transformed into a Calendly block.

Cases 1 and 2: we don't really need to check the URL, as it's implied that it has been already checked (more about it later).
If you try to change the URL in the code editor, the block should break anyway.

Case 3 is where this comes into play.
Since pasting a link always results in an embedded block, we can safely avoid testing for link style blocks.
On the other hand, for the same reason we are basically forced to test on embedded blocks regardless.


Now, the resolve-redirect check runs always when you manually change the embed code (see the parseEmbedCode method).
So if you have a link style block and change its URL, it will pass through resolve-redirect.


Now, by testing this again I could see two things that look off to me:

  1. I'm kinda wondering why the useEffect is not triggered when the URL changes after a parseEmbedCode.
    I mean, it works as it should, but I'm curious why. 😄
    I'm probably failing to notice something that I already solved a few days ago and totally forgot, though.

  2. Unfortunately, the useEffect is triggered by the block preview in the style selector as well...
    I'm not super keen in having dozens of useless calls to /resolve-redirect/https://calendly.com/wordpresscom/jetpack-block-example, so I'll need to discard that case as well.

@jeherve jeherve added [Status] Needs Author Reply We would need you to make some changes or provide some more details about your PR. Thank you! and removed [Status] Ready to Merge Go ahead, you can push that green button! labels Mar 4, 2020
@Copons Copons added [Status] In Progress and removed [Status] Needs Author Reply We would need you to make some changes or provide some more details about your PR. Thank you! labels Mar 4, 2020
@Copons Copons dismissed stale reviews from apeatling and jeherve via 10b5d6a March 4, 2020 15:40
@matticbot
Copy link
Contributor

Copons, Your synced wpcom patch D39450-code has been updated.

@scruffian
Copy link
Member

This looks good. My only concern is that it really slows down the preview in the sidebar. I see this for quite a long time:
Screenshot 2020-03-04 at 15 47 47

@Copons
Copy link
Contributor Author

Copons commented Mar 4, 2020

I'm kinda wondering why the useEffect is not triggered when the URL changes after a parseEmbedCode.

Ok, for some reasons I was wrong on this, or my dev tools skills aren't good enough.
useEffect was indeed being triggered when the url was changed by parseEmbedCode resulting in one additional, unnecessary, apiFetch call.

This happened because the useEffect was conditionally running whenever props.attributes.url changed, as I was under the impression that pasting an URL would first create an empty block, and then fill it with the URL, thus requiring the check to run on url change.

This is not the case: as it turns out, pasting an URL directly creates the block with the url prefilled.
So useEffect effectively needs to only run on component mount (empty array [] as second argument), instead of on url change ([ url ] as second argument).

What does this mean practically? Let's see case by case.

  1. Normal block creation
    Block is inserted empty. useEffect exits immediately. When the user inserts the URL, parseEmbedCode tests it.

  2. Block transform on pasted URL
    User pastes a Calendly URL. Block is created with the url attribute prefilled. useEffect tests it.

  3. URL is changed from sidebar
    parseEmbedCode tests the URL. Since the block is already mounted, useEffect doesn't even run.

  4. Editor loads with block in embed mode
    If block has no URL, nothing happens. Otherwise, useEffect tests it.
    This is an unintended (but unavoidable as far as I know) side effect of the case 2.

  5. Editor loads with block in link mode
    Since case 2 (pasting a Calendly URL) can only create a block in embed mode, we don't need to test the URL on old blocks in link mode. useEffect exits immediately.

  6. Block example renders in the inserter or the sidebar
    useEffect exists immediately when the URL to test is the Calendly example URL.

@Copons
Copy link
Contributor Author

Copons commented Mar 4, 2020

My only concern is that it really slows down the preview in the sidebar.

@scruffian have you tried with the latest changes? Specifically 08f921a should fix exactly that, as before we were also unintentionally resolving the example URL, and so slowing down the render of the preview embed.

Mar-04-2020 10-01-21

@Copons
Copy link
Contributor Author

Copons commented Mar 4, 2020

I wonder if we could do away with useEffect altogether by calling parseEmbedCode when we paste the embed code...

I've tried this a bit, as it seems like the most sensible solution, but I think the async gets in the way.
If I try to run the resolve test with await in the transform before creating the block, nothing happens when the response come back.
Though, I might be doing something dumb in there, so feel free to give it a try if you have some spare cycles.

return;
}
setResolveUrl( true );
apiFetch( { path: `/wpcom/v2/resolve-redirect/${ url }` } ).then(
Copy link
Member

Choose a reason for hiding this comment

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

Now that we rely on wpcom/v2/resolve-redirect here, in the Pinterest block, and in the Eventbrite block, would it make sense / be possible to extract this into a shared function maybe? What do you think?

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 thinking!
I'll update this PR by adding an utility function, and then will take care of the other blocks separately to avoid bloating this.

@jeherve jeherve added [Status] Needs Author Reply We would need you to make some changes or provide some more details about your PR. Thank you! and removed [Status] Needs Review To request a review from Crew. Label will be renamed soon. labels Mar 5, 2020
@Copons Copons force-pushed the fix/14805-calendly-error-on-wrong-url branch from 10b5d6a to 84d25ef Compare March 5, 2020 19:01
@matticbot
Copy link
Contributor

Copons, Your synced wpcom patch D39450-code has been updated.

@matticbot
Copy link
Contributor

Copons, Your synced wpcom patch D39450-code has been updated.

@Copons
Copy link
Contributor Author

Copons commented Mar 5, 2020

In 26fafa2 I've created a new testEmbedUrl utility that should greatly simplify how we test embeddable URLs with resolve-redirect, while leaving enough freedom to each implementation.

I think the function documentation is clear enough, and there's also an example, but for the sake of clarity:

  • testEmbedUrl accepts an optional setIsResolvingUrl argument, based upon the useState pattern, which will automatically update the block state with the resolve-redirect state (basically sets isResolvingUrl = true before calling the endpoint, and isResolvingUrl = false before resolving the promise).
    This should turn out to be useful to have a loading state in the block.
    Also, this doesn't work with the old this.setState(). Blocks that still use it will need to keep track of the request state manually.

  • testEmbedUrl returns a promise, so each block will need to handle the success in .then() and the fail in .catch().
    This is mostly because each block do different stuff when testing the URL. In some cases (like in Calendly's useEffect) they don't even need to handle a success case.
    I'm not a huge fan of thenables, but I think having an async/await approach here would be much less readable, or verbose (useEffect callbacks, for example, can't be async, so one would need to create a new async function that awaits for the test, and call that function inside the useEffect... not really a great dev experience!)

tl;dr this is how it works:

const Block = () => {
  const [ url, setUrl ] = useState( '' );
  const [ isResolvingUrl, setIsResolvingUrl ] = useState( false );

  const setUrlAttribute = () => {
    testEmbedUrl( url, setIsResolvingUrl )
      .then( () => setAttribute( { url } ) )
      .catch( () => setAttribute( { url: undefined } ) );
  };

  if ( isResolvingUrl ) {
    return <Spinner />;
  }
  return (
    <form onSubmit={ setUrlAttribute }>
      <TextControl value={ url } onChange={ setUrl } />
    </form>
  );
}

@Copons Copons added [Status] Needs Review To request a review from Crew. Label will be renamed soon. and removed [Status] Needs Author Reply We would need you to make some changes or provide some more details about your PR. Thank you! labels Mar 5, 2020
Copy link
Member

@scruffian scruffian left a comment

Choose a reason for hiding this comment

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

LGTM

@apeatling apeatling self-requested a review March 6, 2020 23:27
Copy link
Member

@apeatling apeatling left a comment

Choose a reason for hiding this comment

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

Tested and confirmed working. 👍

Copy link
Member

@jeherve jeherve 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 good to me. It should be good to merge!

Since it introduces a new file, you'll need to rebuild the matching wpcom diff manually I'm afraid.

@jeherve jeherve added [Status] Ready to Merge Go ahead, you can push that green button! and removed [Status] Needs Review To request a review from Crew. Label will be renamed soon. labels Mar 17, 2020
@Copons Copons merged commit e105cbd into master Mar 17, 2020
@Copons Copons deleted the fix/14805-calendly-error-on-wrong-url branch March 17, 2020 17:03
@matticbot matticbot added [Status] Needs Changelog and removed [Status] Ready to Merge Go ahead, you can push that green button! labels Mar 17, 2020
@Copons
Copy link
Contributor Author

Copons commented Mar 17, 2020

r204401-wpcom

jeherve added a commit that referenced this pull request Mar 20, 2020
jeherve added a commit that referenced this pull request Mar 31, 2020
* Initial changelog entry

* Changelog: add #14904

* Changelog: add #14910

* Changelog: add #14913

* Changelog: add #14916

* Changelog: add #14922

* Changelog: add #14924

* Changelog: add #14925

* Changelog: add #14928

* Changelog: add #14840

* Changelog: add #14841

* Changelog: add #14842

* Changelog: add #14826

* Changelog: add #14835

* Changelog: add #14859

* Changelog: add #14884

* Changelog: add #14888

* Changelog: add #14817

* Changelog: add #14814

* Changelog: add #14819

* Changelog;: add #14797

* Changelog: add #14798

* Changelog: add #14802

* Changelog: add #13676

* Changelog: add #13744

* Changelog: add #13777

* Changelog: add #14446

* Changelog: add #14739

* Changelog: add #14770

* Changelog: add #14784

* Changelog: add #14897

* Changelog: add #14898

* Changelog: add #14968

* Changelog: add #14985

* Changelog: add #15044

* Changelog: add #15052

* Update to remove Podcast since it remains in Beta

* Changelog: add #14803

* Changelog: add #15028

* Changelog: add #15065

* Changelog:add #14886

* Changelog: add #15118

* Changelog: add #14990

* Changelog: add #14528

* Changelog: add #15120

* Changelog: add #15126

* Changelog: add #15049

* Chanegelog: add #14852

* Changelog: add #15090

* Changelog: add #15138

* Changelog: add #15124

* Changelog:add #15055

* Changelog: add #15017

* Changelog: add #15109

* Changelog: add #15145

* Changelog:add #15096

* Changelog:add #15153

* Changelog: add #15133

* Changelog: add #14960

* Changelog: add #15127

* Changelog: add #15056

* Copy current changelog to changelog archive.

* Clarify changelog description
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Block] Calendly [Focus] Blocks Issues related to the block editor, aka Gutenberg, and its extensions developed in Jetpack Touches WP.com Files [Type] Enhancement Changes to an existing feature — removing, adding, or changing parts of it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Calendly Block: Show an error when the embed url is not found
7 participants