-
Notifications
You must be signed in to change notification settings - Fork 86
Fixes and improvements for selecting WP version #1189
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
Changes from all commits
387cd83
8d18fb6
77c55aa
995a52a
bd47da2
fb4405a
7e1f1c3
01cb442
a044248
e0d46d8
741b350
e4e75d9
723f3e5
7fc4e89
73fdf7f
88f70be
5b45eb7
7b535cc
fcd57de
6ace737
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| import semver from 'semver'; | ||
|
|
||
| type Option = { label: string; value: string }; | ||
|
|
||
| export const addWpVersionToList = ( newOption: Option, options: Option[] ): Option[] => { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| const currentVer = semver.coerce( newOption.value ); | ||
|
|
||
| // Being extra cautious here, if the version is not valid, we add it to the end of the list. | ||
| if ( ! currentVer ) { | ||
| return [ ...options, newOption ]; | ||
| } | ||
|
|
||
| const firstOlderVersionIndex = options.findIndex( ( compareVersion ) => { | ||
| const compareVer = semver.coerce( compareVersion.value ); | ||
| return compareVer && semver.gt( currentVer, compareVer ); | ||
| } ); | ||
|
|
||
| if ( firstOlderVersionIndex === -1 ) { | ||
| return [ ...options, newOption ]; | ||
| } else { | ||
| return [ | ||
| ...options.slice( 0, firstOlderVersionIndex ), | ||
| newOption, | ||
| ...options.slice( firstOlderVersionIndex ), | ||
| ]; | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| import { SelectControl, Icon } from '@wordpress/components'; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now we have separate component which doesn't store any context, so it's already used in 2 places and can be easily reused in the future, w/o extra conditions. |
||
| import { warning } from '@wordpress/icons'; | ||
| import { useI18n } from '@wordpress/react-i18n'; | ||
| import offlineIcon from 'src/components/offline-icon'; | ||
| import { Tooltip } from 'src/components/tooltip'; | ||
| import { useOffline } from 'src/hooks/use-offline'; | ||
| import { cx } from 'src/lib/cx'; | ||
| import { isWordPressDevVersion } from 'src/lib/version-utils'; | ||
| import { isWordPressBetaVersion } from 'src/lib/wordpress-version-utils'; | ||
| import { useGetWordPressVersions } from 'src/stores/wordpress-versions-api'; | ||
| import { DEFAULT_WORDPRESS_VERSION } from 'vendor/wp-now/src/constants'; | ||
| import { addWpVersionToList } from './add-wp-version-to-list'; | ||
|
|
||
| type WPVersionSelectorProps = { | ||
| selectedValue: string; | ||
| onChange: ( version: string ) => void; | ||
| errorMessage?: string | null; | ||
| disabled?: boolean; | ||
| /** Is used if you want to add a custom option to the list, for example the current version of a site */ | ||
| extraOptions?: { label: string; value: string }[]; | ||
| /** Fallback options shown when available versions couldn't be fetched */ | ||
| fallbackOptions: { label: string; value: string }[]; | ||
| }; | ||
|
|
||
| export const WPVersionSelector = ( { | ||
| selectedValue, | ||
| onChange, | ||
| errorMessage, | ||
| disabled = false, | ||
| extraOptions, | ||
| fallbackOptions, | ||
| }: WPVersionSelectorProps ) => { | ||
| const { __ } = useI18n(); | ||
| const isOffline = useOffline(); | ||
| const offlineMessage = __( 'Changing WordPress version requires an internet connection.' ); | ||
| const { data: wpVersions = [] } = useGetWordPressVersions(); | ||
|
|
||
| let betaVersions: { label: string; value: string }[] = wpVersions.filter( | ||
| ( version ) => version.isBeta || version.isDevelopment | ||
| ); | ||
| let stableVersions: { label: string; value: string }[] = wpVersions.filter( | ||
| ( version ) => ! version.isBeta && ! version.isDevelopment && version.value !== 'latest' | ||
| ); | ||
| extraOptions?.forEach( ( extraOption ) => { | ||
| const alreadyExists = wpVersions.some( ( version ) => version.value === extraOption.value ); | ||
| if ( alreadyExists ) { | ||
| return; | ||
| } | ||
|
|
||
| if ( | ||
| isWordPressBetaVersion( extraOption.value ) || | ||
| isWordPressDevVersion( extraOption.value ) | ||
| ) { | ||
| betaVersions = addWpVersionToList( extraOption, betaVersions ); | ||
| } else { | ||
| stableVersions = addWpVersionToList( extraOption, stableVersions ); | ||
| } | ||
| } ); | ||
|
|
||
| return ( | ||
| <label className="flex flex-1 flex-col gap-1.5 leading-4"> | ||
| <span className="font-semibold flex items-center gap-2"> | ||
| { __( 'WordPress version' ) } | ||
| { selectedValue !== 'latest' && ( | ||
| <Tooltip | ||
| text={ __( 'WordPress Core automatic updates will be disabled for this site.' ) } | ||
| placement="top" | ||
| > | ||
| <Icon icon={ warning } size={ 16 } /> | ||
| </Tooltip> | ||
| ) } | ||
| </span> | ||
| <Tooltip | ||
| disabled={ ! isOffline } | ||
| icon={ offlineIcon } | ||
| text={ offlineMessage } | ||
| placement="top-start" | ||
| className="flex flex-1 flex-col" | ||
| > | ||
| <SelectControl | ||
| className={ cx( errorMessage && 'error-select-control' ) } | ||
| disabled={ disabled || isOffline } | ||
| value={ selectedValue } | ||
| onChange={ onChange } | ||
| __next40pxDefaultSize | ||
| __nextHasNoMarginBottom | ||
| > | ||
| { wpVersions.length > 0 ? ( | ||
| <> | ||
| <optgroup label={ __( 'Auto-updating' ) }> | ||
| <option key={ DEFAULT_WORDPRESS_VERSION } value={ DEFAULT_WORDPRESS_VERSION }> | ||
| { __( 'latest' ) } | ||
| </option> | ||
| </optgroup> | ||
| <optgroup label={ __( 'Beta & Nightly' ) }> | ||
| { betaVersions.map( ( { label, value } ) => ( | ||
| <option key={ value } value={ value }> | ||
| { label } | ||
| </option> | ||
| ) ) } | ||
| </optgroup> | ||
| <optgroup label={ __( 'Stable Versions' ) }> | ||
| { stableVersions.map( ( { label, value } ) => ( | ||
| <option key={ value } value={ value }> | ||
| { label } | ||
| </option> | ||
| ) ) } | ||
| </optgroup> | ||
| </> | ||
| ) : ( | ||
| fallbackOptions.map( ( { label, value } ) => ( | ||
| <option key={ value } value={ value }> | ||
| { label } | ||
| </option> | ||
| ) ) | ||
| ) } | ||
| </SelectControl> | ||
| </Tooltip> | ||
| </label> | ||
| ); | ||
| }; | ||
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.
Nice! A single component 💪