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

Add value to inactive state of VideoPress #38748

Merged
merged 35 commits into from
Aug 9, 2024

Conversation

CodeyGuyDylan
Copy link
Contributor

@CodeyGuyDylan CodeyGuyDylan commented Aug 6, 2024

Proposed changes:

  • When the VideoPress card is inactive but the user has videos, show how many videos they could improve with VideoPress
  • Fix some type errors in both the PHP and React side
  • Import VideoPress package into My Jetpack to use later for VideoPress stats

Other information:

  • Have you written new tests for your changes, if applicable?
  • Have you checked the E2E test CI results, and verified that your changes do not break them?
  • Have you tested your changes on WordPress.com, if applicable (if so, you'll see a generated comment below with a script to run)?

Jetpack product discussion

P2: p1HpG7-rb7-p2

Does this pull request change what data or activity we track or use?

No

Testing instructions:

  1. Checkout this branch onto the Jetpack Backup standalone plugin (any plugin other than the main Jetpack plugin or VideoPress
  2. Go to My Jetpack and make sure the VideoPress card looks inactive and no errors are thrown
    image
  3. Now add a video to your site (or multiple videos). Go back to My Jetpack and you should see the number of videos plus an updated description
    image
  4. If you install the VideoPress (or Jetpack) plugin, you should see the same thing if it is not active
    image
  5. Activate the plugin and you should see the regular description (this will be updated in a future PR)
    image
  6. Now remove the videos. You should see some description letting them know they can start by uploading their first video
    image
  7. Now in the console, log out myJetpackInitialState.videopress and make sure the featuredStats are being loaded. They're probably all 0 since your site is new, but it's enough for now that the data is loading
    image

@CodeyGuyDylan CodeyGuyDylan changed the title Add/value to videopress card Add value to inactive state of VideoPress Aug 6, 2024
Copy link
Contributor

github-actions bot commented Aug 6, 2024

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WordPress.com Simple site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin, and enable the add/value-to-videopress-card branch.

    • For jetpack-mu-wpcom changes, also add define( 'JETPACK_MU_WPCOM_LOAD_VIA_BETA_PLUGIN', true ); to your wp-config.php file.
  • To test on Simple, run the following command on your sandbox:

    bin/jetpack-downloader test jetpack add/value-to-videopress-card
    
    bin/jetpack-downloader test jetpack-mu-wpcom-plugin add/value-to-videopress-card
    

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@github-actions github-actions bot added [Package] My Jetpack [Plugin] Backup A plugin that allows users to save every change and get back online quickly with one-click restores. [Plugin] Boost A feature to speed up the site and improve performance. [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ [Plugin] Migration [Plugin] Protect A plugin with features to protect a site: brute force protection, security scanning, and a WAF. [Plugin] Search A plugin to add an instant search modal to your site to help visitors find content faster. [Plugin] Social Issues about the Jetpack Social plugin [Plugin] Starter Plugin [Plugin] VideoPress A standalone plugin to add high-quality VideoPress videos to your site. labels Aug 6, 2024
Copy link
Contributor

github-actions bot commented Aug 6, 2024

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Team Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


The e2e test report can be found here. Please note that it can take a few minutes after the e2e tests checks are complete for the report to be available.


Once your PR is ready for review, check one last time that all required checks appearing at the bottom of this PR are passing or skipped.
Then, add the "[Status] Needs Team Review" label and ask someone from your team review the code. Once reviewed, it can then be merged.
If you need an extra review from someone familiar with the codebase, you can update the labels from "[Status] Needs Team Review" to "[Status] Needs Review", and in that case Jetpack Approvers will do a final review of your PR.

@github-actions github-actions bot added the [Status] Needs Author Reply We would need you to make some changes or provide some more details about your PR. Thank you! label Aug 6, 2024
@CodeyGuyDylan CodeyGuyDylan force-pushed the add/value-to-videopress-card branch from faed468 to da0bb73 Compare August 6, 2024 18:52
Copy link
Contributor

@robertsreberski robertsreberski left a comment

Choose a reason for hiding this comment

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

Looks good 😄 I've tried to give feedback / sometimes opinions through the code, you can apply when you feel it's appropriate!

@@ -85,7 +87,7 @@ const ConnectedProductCard: FC< ConnectedProductCardProps > = ( {

const DefaultDescription = () => {
// Replace the last space with a non-breaking space to prevent widows
const cardDescription = defaultDescription.replace( /\s(?=[^\s]*$)/, '\u00A0' );
const cardDescription = preventWidows( defaultDescription );
Copy link
Contributor

Choose a reason for hiding this comment

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

Reducing technical debt 💪 great!

@@ -0,0 +1,6 @@
import type { FC } from 'react';

export type ProductCardType = FC< {
Copy link
Contributor

Choose a reason for hiding this comment

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

Idea for name: ProductCardComponent/ProductCardFC? I like the unification!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ProductCardComponent sounds better to me, thanks!

import './style.scss';

const VideopressCard: ProductCardType = ( { admin } ) => {
const slug = 'videopress';
Copy link
Contributor

Choose a reason for hiding this comment

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

We could consider putting static variables outside of component scope?

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 don't think it matters too much but we definitely could do that 🤔 And it'd be easy to do it now before we get too far into the product card projects

slug={ slug }
showMenu
admin={ admin }
Description={ descriptionText ? Description : null }
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe Description variable could be already null if descriptionText is not provided?

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 tried this but Description is a function so it does not return null until after it is passed to the function. I think we need to do it inline here 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, my bad! I thought we can do something like this useCallback( descriptionText ? () => <Description /> : null, [ descriptionText ] ); But I see we cannot.

p.description {
color: var( --jp-gray-70 );
font-size: var( --font-body-small );
margin: 0 0 1rem 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
margin: 0 0 1rem 0;
margin: 0 0 1rem;

);
}

return <></>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not null?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's just a habit to return some sort of component, shouldn't make any difference but I'll update it to null 😄

const VideoPressValueSection: FC< VideoPressValueSectionProps > = ( { isPluginActive, data } ) => {
if ( ! isPluginActive && data.videoCount ) {
return (
<div className={ 'videopress-card__video-count' }>
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
<div className={ 'videopress-card__video-count' }>
<div className="videopress-card__video-count">

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice catch 😆

if ( ! isPluginActive && data.videoCount ) {
return (
<div className={ 'videopress-card__video-count' }>
<span>{ data.videoCount }</span>
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need <span> tag 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.

Hmmm I prefer it rather than just having text straight in the <div> element 🤔 Does that logic sound decent to you?

Copy link
Contributor

Choose a reason for hiding this comment

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

Why cannot we have <span className="videopress-card__video-count">?

The logic sounds good to me, thanks for explaining!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That could work style-wise 🤔

I think I just like container enclosed items such as this. But I think I agree with you that it is not necessary in this case

}

/**
* This will collect a count of all the items that could be backed up
* This is used to show what backup could be doing if it is not enabled
*
* @return array
* @return WP_Error|\WP_REST_Response
Copy link
Contributor

Choose a reason for hiding this comment

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

Usually, these kind of changes to php docs "irritate" phan 😅 maybe the static check will pass if you revert it / change to WP_Error|array?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm this was throwing a warning since array is not what is returned 🤔 But it's been this way for a while and if it's going to cause some phan shenanigans then maybe I'll just revert that

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It seems like that didn't fix the phan errors 😓 Maybe I'll just move it back to array and see if that helps

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 reverted it back to array and I'm still getting the PHAN errors 😢

Copy link
Contributor

Choose a reason for hiding this comment

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

I saw your conversation in jetpack devs channel, glad you got it fixed!

@@ -277,6 +278,10 @@ public static function enqueue_scripts() {
array( 'blocked_logins' => (int) get_site_option( 'jetpack_protect_blocked_attempts', 0 ) )
),
),
'videopress' => array(
'featuredStats' => self::get_videopress_stats(),
'videoCount' => array_sum( (array) wp_count_attachments( 'video' ) ),
Copy link
Contributor

Choose a reason for hiding this comment

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

we could include that code in self::get_videopress_stats() function?
I think it's a nice practice not to perform any transformations in the array definition itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a good note, I'll get that moved

@CodeyGuyDylan CodeyGuyDylan force-pushed the add/value-to-videopress-card branch from bb386f5 to 5bc5af6 Compare August 7, 2024 21:44
@CodeyGuyDylan CodeyGuyDylan added [Status] Needs Team Review and removed [Status] Needs Author Reply We would need you to make some changes or provide some more details about your PR. Thank you! [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ [Plugin] Backup A plugin that allows users to save every change and get back online quickly with one-click restores. [Plugin] Boost A feature to speed up the site and improve performance. [Plugin] Search A plugin to add an instant search modal to your site to help visitors find content faster. [Plugin] Social Issues about the Jetpack Social plugin [Plugin] Starter Plugin [Plugin] Protect A plugin with features to protect a site: brute force protection, security scanning, and a WAF. [Plugin] VideoPress A standalone plugin to add high-quality VideoPress videos to your site. [Plugin] Migration labels Aug 7, 2024
@CodeyGuyDylan CodeyGuyDylan force-pushed the add/value-to-videopress-card branch from a79438a to ee0ce3e Compare August 8, 2024 15:19
Copy link
Contributor

@robertsreberski robertsreberski left a comment

Choose a reason for hiding this comment

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

Thanks for the changes here! One more portion of minor feedback.

isDataLoading?: boolean;
Description?: FC;
additionalActions?: AdditionalAction[];
secondaryAction?: SecondaryAction;
upgradeInInterstitial?: boolean;
primaryActionOverride?: AdditionalAction;
primaryActionOverride?: { [ key: string ]: AdditionalAction };
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
primaryActionOverride?: { [ key: string ]: AdditionalAction };
primaryActionOverride?: Record< strong, AdditionalAction >

Comment on lines 26 to 27
// We don't have a card for Security or Extras, and scan is displayed as protect.
Exclude< JetpackModule, 'extras' | 'scan' | 'security' >,
Exclude< JetpackModule, 'extras' | 'scan' | 'security' | 'ai' >,
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's update the comment above as well. Currently it's a bit confusing because in a way "ai" card is displayed (I'm aware it's about reducing redundancy of "jetpack-ai" and "ai" - but I might forget it in ~3 months 😅)

);
};
const ProtectCard: ProductCardComponent = props => (
<ProductCard { ...props } slug={ PRODUCT_SLUGS.PROTECT } upgradeInInterstitial={ true }>
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
<ProductCard { ...props } slug={ PRODUCT_SLUGS.PROTECT } upgradeInInterstitial={ true }>
<ProductCard { ...props } slug={ PRODUCT_SLUGS.PROTECT } upgradeInInterstitial>

slug={ slug }
showMenu
admin={ admin }
Description={ descriptionText ? Description : null }
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, my bad! I thought we can do something like this useCallback( descriptionText ? () => <Description /> : null, [ descriptionText ] ); But I see we cannot.

if ( ! isPluginActive && data.videoCount ) {
return (
<div className={ 'videopress-card__video-count' }>
<span>{ data.videoCount }</span>
Copy link
Contributor

Choose a reason for hiding this comment

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

Why cannot we have <span className="videopress-card__video-count">?

The logic sounds good to me, thanks for explaining!

PROTECT: 'protect',
VIDEOPRESS: 'videopress',
STATS: 'stats',
} satisfies Record< string, JetpackModule >;
Copy link
Contributor

Choose a reason for hiding this comment

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

Learned new Typescript syntax today, thanks 😁

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 also learned that yesterday 😅 It seems like the best way to enforce the value of the object, but infer the types of the key. That way when you're using this in a typescript file, you will be limited to certain keys and still be able to see the value of the key 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The other implementations I tried either had the key as a generic "string" type which is problematic as you could use any key you wanted without a typescript error, or the key would be defined but the value would be a generic "string" type and I wanted it to be linked to the JetpackModules type

}

/**
* This will collect a count of all the items that could be backed up
* This is used to show what backup could be doing if it is not enabled
*
* @return array
* @return WP_Error|\WP_REST_Response
Copy link
Contributor

Choose a reason for hiding this comment

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

I saw your conversation in jetpack devs channel, glad you got it fixed!

).part;
};

export default preventWidows;
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for extending logic of that function! What do you think about adding a reference to the source in the comment in this file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's a good note, I'll add that

@CodeyGuyDylan CodeyGuyDylan merged commit 6e45519 into trunk Aug 9, 2024
72 of 73 checks passed
@CodeyGuyDylan CodeyGuyDylan deleted the add/value-to-videopress-card branch August 9, 2024 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants