mirror of
https://github.com/strapi/strapi.git
synced 2025-09-21 06:22:30 +00:00
Merge branch 'main' into fix/clean-test-warnings
This commit is contained in:
commit
1039e207c0
1
examples/getstarted/.gitignore
vendored
1
examples/getstarted/.gitignore
vendored
@ -110,6 +110,7 @@ testApp
|
|||||||
license.txt
|
license.txt
|
||||||
exports
|
exports
|
||||||
*.cache
|
*.cache
|
||||||
|
dist
|
||||||
build
|
build
|
||||||
documentation
|
documentation
|
||||||
.strapi-updater.json
|
.strapi-updater.json
|
||||||
|
1
examples/kitchensink-ts/.gitignore
vendored
1
examples/kitchensink-ts/.gitignore
vendored
@ -110,5 +110,6 @@ coverage
|
|||||||
license.txt
|
license.txt
|
||||||
exports
|
exports
|
||||||
*.cache
|
*.cache
|
||||||
|
dist
|
||||||
build
|
build
|
||||||
.strapi-updater.json
|
.strapi-updater.json
|
||||||
|
1
examples/kitchensink/.gitignore
vendored
1
examples/kitchensink/.gitignore
vendored
@ -110,5 +110,6 @@ coverage
|
|||||||
license.txt
|
license.txt
|
||||||
exports
|
exports
|
||||||
*.cache
|
*.cache
|
||||||
|
dist
|
||||||
build
|
build
|
||||||
.strapi-updater.json
|
.strapi-updater.json
|
||||||
|
@ -62,6 +62,15 @@ async function initProject(projectName, program) {
|
|||||||
await checkInstallPath(resolve(projectName));
|
await checkInstallPath(resolve(projectName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const programFlags = program.options
|
||||||
|
.reduce((acc, { short, long }) => [...acc, short, long], [])
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
if (program.template && programFlags.includes(program.template)) {
|
||||||
|
console.error(`${program.template} is not a valid template`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
const hasDatabaseOptions = databaseOptions.some((opt) => program[opt]);
|
const hasDatabaseOptions = databaseOptions.some((opt) => program[opt]);
|
||||||
|
|
||||||
if (program.quickstart && hasDatabaseOptions) {
|
if (program.quickstart && hasDatabaseOptions) {
|
||||||
|
@ -110,5 +110,6 @@ coverage
|
|||||||
license.txt
|
license.txt
|
||||||
exports
|
exports
|
||||||
*.cache
|
*.cache
|
||||||
|
dist
|
||||||
build
|
build
|
||||||
.strapi-updater.json
|
.strapi-updater.json
|
||||||
|
@ -0,0 +1,110 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import semver from 'semver';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useIntl } from 'react-intl';
|
||||||
|
import { Tooltip } from '@strapi/design-system/Tooltip';
|
||||||
|
import { Button } from '@strapi/design-system/Button';
|
||||||
|
import { Box } from '@strapi/design-system/Box';
|
||||||
|
import Duplicate from '@strapi/icons/Duplicate';
|
||||||
|
|
||||||
|
const TooltipButton = ({ description, installMessage, disabled, handleCopy, pluginName }) => (
|
||||||
|
<Tooltip data-testid={`tooltip-${pluginName}`} description={description}>
|
||||||
|
<Box>
|
||||||
|
<Button
|
||||||
|
size="S"
|
||||||
|
startIcon={<Duplicate />}
|
||||||
|
variant="secondary"
|
||||||
|
disabled={disabled}
|
||||||
|
onClick={handleCopy}
|
||||||
|
>
|
||||||
|
{installMessage}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
|
||||||
|
const CardButton = ({ strapiPeerDepVersion, strapiAppVersion, handleCopy, pluginName }) => {
|
||||||
|
const { formatMessage } = useIntl();
|
||||||
|
const versionRange = semver.validRange(strapiPeerDepVersion);
|
||||||
|
const isCompatible = semver.satisfies(strapiAppVersion, versionRange);
|
||||||
|
|
||||||
|
const installMessage = formatMessage({
|
||||||
|
id: 'admin.pages.MarketPlacePage.plugin.copy',
|
||||||
|
defaultMessage: 'Copy install command',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Only plugins receive a strapiAppVersion
|
||||||
|
if (strapiAppVersion) {
|
||||||
|
if (!versionRange) {
|
||||||
|
return (
|
||||||
|
<TooltipButton
|
||||||
|
installMessage={installMessage}
|
||||||
|
pluginName={pluginName}
|
||||||
|
description={formatMessage(
|
||||||
|
{
|
||||||
|
id: 'admin.pages.MarketPlacePage.plugin.version.null',
|
||||||
|
defaultMessage:
|
||||||
|
'Unable to verify compatibility with your Strapi version: "{strapiAppVersion}"',
|
||||||
|
},
|
||||||
|
{ strapiAppVersion }
|
||||||
|
)}
|
||||||
|
handleCopy={handleCopy}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isCompatible) {
|
||||||
|
return (
|
||||||
|
<TooltipButton
|
||||||
|
installMessage={installMessage}
|
||||||
|
pluginName={pluginName}
|
||||||
|
description={formatMessage(
|
||||||
|
{
|
||||||
|
id: 'admin.pages.MarketPlacePage.plugin.version',
|
||||||
|
defaultMessage:
|
||||||
|
'Update your Strapi version: "{strapiAppVersion}" to: "{versionRange}"',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
strapiAppVersion,
|
||||||
|
versionRange,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button size="S" startIcon={<Duplicate />} variant="secondary" onClick={handleCopy}>
|
||||||
|
{installMessage}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
TooltipButton.defaultProps = {
|
||||||
|
disabled: false,
|
||||||
|
handleCopy: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
TooltipButton.propTypes = {
|
||||||
|
description: PropTypes.string.isRequired,
|
||||||
|
installMessage: PropTypes.string.isRequired,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
handleCopy: PropTypes.func,
|
||||||
|
pluginName: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
CardButton.defaultProps = {
|
||||||
|
strapiAppVersion: null,
|
||||||
|
strapiPeerDepVersion: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
CardButton.propTypes = {
|
||||||
|
strapiAppVersion: PropTypes.string,
|
||||||
|
strapiPeerDepVersion: PropTypes.string,
|
||||||
|
handleCopy: PropTypes.func.isRequired,
|
||||||
|
pluginName: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CardButton;
|
@ -1,20 +1,34 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import { CopyToClipboard } from 'react-copy-to-clipboard';
|
|
||||||
import { useNotification, useTracking } from '@strapi/helper-plugin';
|
import { useNotification, useTracking } from '@strapi/helper-plugin';
|
||||||
import { Box } from '@strapi/design-system/Box';
|
import { Box } from '@strapi/design-system/Box';
|
||||||
import { Icon } from '@strapi/design-system/Icon';
|
import { Icon } from '@strapi/design-system/Icon';
|
||||||
import { Typography } from '@strapi/design-system/Typography';
|
import { Typography } from '@strapi/design-system/Typography';
|
||||||
import Check from '@strapi/icons/Check';
|
import Check from '@strapi/icons/Check';
|
||||||
import Duplicate from '@strapi/icons/Duplicate';
|
import CardButton from './CardButton';
|
||||||
import { Button } from '@strapi/design-system/Button';
|
|
||||||
|
|
||||||
const InstallPluginButton = ({ isInstalled, isInDevelopmentMode, commandToCopy }) => {
|
const InstallPluginButton = ({
|
||||||
|
isInstalled,
|
||||||
|
isInDevelopmentMode,
|
||||||
|
commandToCopy,
|
||||||
|
strapiAppVersion,
|
||||||
|
strapiPeerDepVersion,
|
||||||
|
pluginName,
|
||||||
|
}) => {
|
||||||
const toggleNotification = useNotification();
|
const toggleNotification = useNotification();
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const { trackUsage } = useTracking();
|
const { trackUsage } = useTracking();
|
||||||
|
|
||||||
|
const handleCopy = () => {
|
||||||
|
navigator.clipboard.writeText(commandToCopy);
|
||||||
|
trackUsage('willInstallPlugin');
|
||||||
|
toggleNotification({
|
||||||
|
type: 'success',
|
||||||
|
message: { id: 'admin.pages.MarketPlacePage.plugin.copy.success' },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Already installed
|
// Already installed
|
||||||
if (isInstalled) {
|
if (isInstalled) {
|
||||||
return (
|
return (
|
||||||
@ -33,23 +47,12 @@ const InstallPluginButton = ({ isInstalled, isInDevelopmentMode, commandToCopy }
|
|||||||
// In development, show install button
|
// In development, show install button
|
||||||
if (isInDevelopmentMode) {
|
if (isInDevelopmentMode) {
|
||||||
return (
|
return (
|
||||||
<CopyToClipboard
|
<CardButton
|
||||||
onCopy={() => {
|
strapiAppVersion={strapiAppVersion}
|
||||||
trackUsage('willInstallPlugin');
|
strapiPeerDepVersion={strapiPeerDepVersion}
|
||||||
toggleNotification({
|
handleCopy={handleCopy}
|
||||||
type: 'success',
|
pluginName={pluginName}
|
||||||
message: { id: 'admin.pages.MarketPlacePage.plugin.copy.success' },
|
/>
|
||||||
});
|
|
||||||
}}
|
|
||||||
text={commandToCopy}
|
|
||||||
>
|
|
||||||
<Button size="S" startIcon={<Duplicate />} variant="secondary">
|
|
||||||
{formatMessage({
|
|
||||||
id: 'admin.pages.MarketPlacePage.plugin.copy',
|
|
||||||
defaultMessage: 'Copy install command',
|
|
||||||
})}
|
|
||||||
</Button>
|
|
||||||
</CopyToClipboard>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,10 +60,18 @@ const InstallPluginButton = ({ isInstalled, isInDevelopmentMode, commandToCopy }
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
InstallPluginButton.defaultProps = {
|
||||||
|
strapiAppVersion: null,
|
||||||
|
strapiPeerDepVersion: null,
|
||||||
|
};
|
||||||
|
|
||||||
InstallPluginButton.propTypes = {
|
InstallPluginButton.propTypes = {
|
||||||
isInstalled: PropTypes.bool.isRequired,
|
isInstalled: PropTypes.bool.isRequired,
|
||||||
isInDevelopmentMode: PropTypes.bool.isRequired,
|
isInDevelopmentMode: PropTypes.bool.isRequired,
|
||||||
commandToCopy: PropTypes.string.isRequired,
|
commandToCopy: PropTypes.string.isRequired,
|
||||||
|
strapiAppVersion: PropTypes.string,
|
||||||
|
strapiPeerDepVersion: PropTypes.string,
|
||||||
|
pluginName: PropTypes.string.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default InstallPluginButton;
|
export default InstallPluginButton;
|
||||||
|
@ -32,6 +32,7 @@ const NpmPackageCard = ({
|
|||||||
useYarn,
|
useYarn,
|
||||||
isInDevelopmentMode,
|
isInDevelopmentMode,
|
||||||
npmPackageType,
|
npmPackageType,
|
||||||
|
strapiAppVersion,
|
||||||
}) => {
|
}) => {
|
||||||
const { attributes } = npmPackage;
|
const { attributes } = npmPackage;
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
@ -139,6 +140,9 @@ const NpmPackageCard = ({
|
|||||||
isInstalled={isInstalled}
|
isInstalled={isInstalled}
|
||||||
isInDevelopmentMode={isInDevelopmentMode}
|
isInDevelopmentMode={isInDevelopmentMode}
|
||||||
commandToCopy={commandToCopy}
|
commandToCopy={commandToCopy}
|
||||||
|
strapiAppVersion={strapiAppVersion}
|
||||||
|
strapiPeerDepVersion={attributes.strapiVersion}
|
||||||
|
pluginName={attributes.name}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Flex>
|
</Flex>
|
||||||
@ -147,6 +151,7 @@ const NpmPackageCard = ({
|
|||||||
|
|
||||||
NpmPackageCard.defaultProps = {
|
NpmPackageCard.defaultProps = {
|
||||||
isInDevelopmentMode: false,
|
isInDevelopmentMode: false,
|
||||||
|
strapiAppVersion: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
NpmPackageCard.propTypes = {
|
NpmPackageCard.propTypes = {
|
||||||
@ -164,12 +169,14 @@ NpmPackageCard.propTypes = {
|
|||||||
validated: PropTypes.bool.isRequired,
|
validated: PropTypes.bool.isRequired,
|
||||||
madeByStrapi: PropTypes.bool.isRequired,
|
madeByStrapi: PropTypes.bool.isRequired,
|
||||||
strapiCompatibility: PropTypes.oneOf(['v3', 'v4']),
|
strapiCompatibility: PropTypes.oneOf(['v3', 'v4']),
|
||||||
|
strapiVersion: PropTypes.string,
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
isInstalled: PropTypes.bool.isRequired,
|
isInstalled: PropTypes.bool.isRequired,
|
||||||
useYarn: PropTypes.bool.isRequired,
|
useYarn: PropTypes.bool.isRequired,
|
||||||
isInDevelopmentMode: PropTypes.bool,
|
isInDevelopmentMode: PropTypes.bool,
|
||||||
npmPackageType: PropTypes.string.isRequired,
|
npmPackageType: PropTypes.string.isRequired,
|
||||||
|
strapiAppVersion: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default NpmPackageCard;
|
export default NpmPackageCard;
|
||||||
|
@ -9,6 +9,7 @@ const NpmPackagesGrid = ({
|
|||||||
useYarn,
|
useYarn,
|
||||||
isInDevelopmentMode,
|
isInDevelopmentMode,
|
||||||
npmPackageType,
|
npmPackageType,
|
||||||
|
strapiAppVersion,
|
||||||
}) => {
|
}) => {
|
||||||
// Check if an individual package is in the dependencies
|
// Check if an individual package is in the dependencies
|
||||||
const isAlreadyInstalled = useCallback(
|
const isAlreadyInstalled = useCallback(
|
||||||
@ -26,6 +27,7 @@ const NpmPackagesGrid = ({
|
|||||||
useYarn={useYarn}
|
useYarn={useYarn}
|
||||||
isInDevelopmentMode={isInDevelopmentMode}
|
isInDevelopmentMode={isInDevelopmentMode}
|
||||||
npmPackageType={npmPackageType}
|
npmPackageType={npmPackageType}
|
||||||
|
strapiAppVersion={strapiAppVersion}
|
||||||
/>
|
/>
|
||||||
</GridItem>
|
</GridItem>
|
||||||
))}
|
))}
|
||||||
@ -35,6 +37,7 @@ const NpmPackagesGrid = ({
|
|||||||
|
|
||||||
NpmPackagesGrid.defaultProps = {
|
NpmPackagesGrid.defaultProps = {
|
||||||
installedPackageNames: [],
|
installedPackageNames: [],
|
||||||
|
strapiAppVersion: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
NpmPackagesGrid.propTypes = {
|
NpmPackagesGrid.propTypes = {
|
||||||
@ -43,6 +46,7 @@ NpmPackagesGrid.propTypes = {
|
|||||||
useYarn: PropTypes.bool.isRequired,
|
useYarn: PropTypes.bool.isRequired,
|
||||||
isInDevelopmentMode: PropTypes.bool.isRequired,
|
isInDevelopmentMode: PropTypes.bool.isRequired,
|
||||||
npmPackageType: PropTypes.string.isRequired,
|
npmPackageType: PropTypes.string.isRequired,
|
||||||
|
strapiAppVersion: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default NpmPackagesGrid;
|
export default NpmPackagesGrid;
|
||||||
|
@ -50,7 +50,7 @@ const MarketPlacePage = () => {
|
|||||||
const toggleNotification = useNotification();
|
const toggleNotification = useNotification();
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
const [npmPackageType, setNpmPackageType] = useState('plugin');
|
const [npmPackageType, setNpmPackageType] = useState('plugin');
|
||||||
const { autoReload: isInDevelopmentMode, dependencies, useYarn } = useAppInfos();
|
const { autoReload: isInDevelopmentMode, dependencies, useYarn, strapiVersion } = useAppInfos();
|
||||||
const isOnline = useNavigatorOnLine();
|
const isOnline = useNavigatorOnLine();
|
||||||
|
|
||||||
useFocusWhenNavigate();
|
useFocusWhenNavigate();
|
||||||
@ -247,6 +247,7 @@ const MarketPlacePage = () => {
|
|||||||
useYarn={useYarn}
|
useYarn={useYarn}
|
||||||
isInDevelopmentMode={isInDevelopmentMode}
|
isInDevelopmentMode={isInDevelopmentMode}
|
||||||
npmPackageType="plugin"
|
npmPackageType="plugin"
|
||||||
|
strapiAppVersion={strapiVersion}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
|
@ -1223,38 +1223,46 @@ exports[`Marketplace page renders and matches the plugin tab snapshot 1`] = `
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<button
|
<span>
|
||||||
aria-disabled="false"
|
|
||||||
class="c51 c52"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
aria-hidden="true"
|
aria-describedby="tooltip-3"
|
||||||
class="c53 c54 c55"
|
class=""
|
||||||
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<svg
|
<button
|
||||||
fill="none"
|
aria-disabled="false"
|
||||||
height="1em"
|
class="c51 c52"
|
||||||
viewBox="0 0 24 24"
|
type="button"
|
||||||
width="1em"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
>
|
||||||
<path
|
<div
|
||||||
d="M1.056 24h15.906c.583 0 1.056-.473 1.056-1.056V7.028c0-.583-.473-1.056-1.056-1.056H1.056C.473 5.972 0 6.445 0 7.028v15.916C0 23.527.473 24 1.056 24z"
|
aria-hidden="true"
|
||||||
fill="#212134"
|
class="c53 c54 c55"
|
||||||
/>
|
>
|
||||||
<path
|
<svg
|
||||||
d="M8.094 2.111h13.795v13.795h-1.127v2.112h2.182A1.056 1.056 0 0024 16.962V1.056A1.056 1.056 0 0022.944 0H7.038a1.056 1.056 0 00-1.056 1.056v2.252h2.112V2.11z"
|
fill="none"
|
||||||
fill="#212134"
|
height="1em"
|
||||||
/>
|
viewBox="0 0 24 24"
|
||||||
</svg>
|
width="1em"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M1.056 24h15.906c.583 0 1.056-.473 1.056-1.056V7.028c0-.583-.473-1.056-1.056-1.056H1.056C.473 5.972 0 6.445 0 7.028v15.916C0 23.527.473 24 1.056 24z"
|
||||||
|
fill="#212134"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M8.094 2.111h13.795v13.795h-1.127v2.112h2.182A1.056 1.056 0 0024 16.962V1.056A1.056 1.056 0 0022.944 0H7.038a1.056 1.056 0 00-1.056 1.056v2.252h2.112V2.11z"
|
||||||
|
fill="#212134"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="c56 c57"
|
||||||
|
>
|
||||||
|
Copy install command
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<span
|
</span>
|
||||||
class="c56 c57"
|
|
||||||
>
|
|
||||||
Copy install command
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1340,38 +1348,47 @@ exports[`Marketplace page renders and matches the plugin tab snapshot 1`] = `
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<button
|
<span>
|
||||||
aria-disabled="false"
|
|
||||||
class="c51 c52"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
aria-hidden="true"
|
aria-describedby="tooltip-5"
|
||||||
class="c53 c54 c55"
|
class=""
|
||||||
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<svg
|
<button
|
||||||
fill="none"
|
aria-disabled="true"
|
||||||
height="1em"
|
class="c51 c52"
|
||||||
viewBox="0 0 24 24"
|
disabled=""
|
||||||
width="1em"
|
type="button"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
>
|
||||||
<path
|
<div
|
||||||
d="M1.056 24h15.906c.583 0 1.056-.473 1.056-1.056V7.028c0-.583-.473-1.056-1.056-1.056H1.056C.473 5.972 0 6.445 0 7.028v15.916C0 23.527.473 24 1.056 24z"
|
aria-hidden="true"
|
||||||
fill="#212134"
|
class="c53 c54 c55"
|
||||||
/>
|
>
|
||||||
<path
|
<svg
|
||||||
d="M8.094 2.111h13.795v13.795h-1.127v2.112h2.182A1.056 1.056 0 0024 16.962V1.056A1.056 1.056 0 0022.944 0H7.038a1.056 1.056 0 00-1.056 1.056v2.252h2.112V2.11z"
|
fill="none"
|
||||||
fill="#212134"
|
height="1em"
|
||||||
/>
|
viewBox="0 0 24 24"
|
||||||
</svg>
|
width="1em"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M1.056 24h15.906c.583 0 1.056-.473 1.056-1.056V7.028c0-.583-.473-1.056-1.056-1.056H1.056C.473 5.972 0 6.445 0 7.028v15.916C0 23.527.473 24 1.056 24z"
|
||||||
|
fill="#212134"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M8.094 2.111h13.795v13.795h-1.127v2.112h2.182A1.056 1.056 0 0024 16.962V1.056A1.056 1.056 0 0022.944 0H7.038a1.056 1.056 0 00-1.056 1.056v2.252h2.112V2.11z"
|
||||||
|
fill="#212134"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="c56 c57"
|
||||||
|
>
|
||||||
|
Copy install command
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<span
|
</span>
|
||||||
class="c56 c57"
|
|
||||||
>
|
|
||||||
Copy install command
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1410,7 +1427,7 @@ exports[`Marketplace page renders and matches the plugin tab snapshot 1`] = `
|
|||||||
Documentation
|
Documentation
|
||||||
<span>
|
<span>
|
||||||
<div
|
<div
|
||||||
aria-describedby="tooltip-3"
|
aria-describedby="tooltip-7"
|
||||||
class="c43"
|
class="c43"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
@ -1579,38 +1596,47 @@ exports[`Marketplace page renders and matches the plugin tab snapshot 1`] = `
|
|||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<button
|
<span>
|
||||||
aria-disabled="false"
|
|
||||||
class="c51 c52"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
aria-hidden="true"
|
aria-describedby="tooltip-9"
|
||||||
class="c53 c54 c55"
|
class=""
|
||||||
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<svg
|
<button
|
||||||
fill="none"
|
aria-disabled="true"
|
||||||
height="1em"
|
class="c51 c52"
|
||||||
viewBox="0 0 24 24"
|
disabled=""
|
||||||
width="1em"
|
type="button"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
>
|
||||||
<path
|
<div
|
||||||
d="M1.056 24h15.906c.583 0 1.056-.473 1.056-1.056V7.028c0-.583-.473-1.056-1.056-1.056H1.056C.473 5.972 0 6.445 0 7.028v15.916C0 23.527.473 24 1.056 24z"
|
aria-hidden="true"
|
||||||
fill="#212134"
|
class="c53 c54 c55"
|
||||||
/>
|
>
|
||||||
<path
|
<svg
|
||||||
d="M8.094 2.111h13.795v13.795h-1.127v2.112h2.182A1.056 1.056 0 0024 16.962V1.056A1.056 1.056 0 0022.944 0H7.038a1.056 1.056 0 00-1.056 1.056v2.252h2.112V2.11z"
|
fill="none"
|
||||||
fill="#212134"
|
height="1em"
|
||||||
/>
|
viewBox="0 0 24 24"
|
||||||
</svg>
|
width="1em"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M1.056 24h15.906c.583 0 1.056-.473 1.056-1.056V7.028c0-.583-.473-1.056-1.056-1.056H1.056C.473 5.972 0 6.445 0 7.028v15.916C0 23.527.473 24 1.056 24z"
|
||||||
|
fill="#212134"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M8.094 2.111h13.795v13.795h-1.127v2.112h2.182A1.056 1.056 0 0024 16.962V1.056A1.056 1.056 0 0022.944 0H7.038a1.056 1.056 0 00-1.056 1.056v2.252h2.112V2.11z"
|
||||||
|
fill="#212134"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="c56 c57"
|
||||||
|
>
|
||||||
|
Copy install command
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<span
|
</span>
|
||||||
class="c56 c57"
|
|
||||||
>
|
|
||||||
Copy install command
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -2724,7 +2750,7 @@ exports[`Marketplace page renders and matches the provider tab snapshot 1`] = `
|
|||||||
Amazon Ses
|
Amazon Ses
|
||||||
<span>
|
<span>
|
||||||
<div
|
<div
|
||||||
aria-describedby="tooltip-9"
|
aria-describedby="tooltip-21"
|
||||||
class="c43"
|
class="c43"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
@ -2856,7 +2882,7 @@ exports[`Marketplace page renders and matches the provider tab snapshot 1`] = `
|
|||||||
AWS S3
|
AWS S3
|
||||||
<span>
|
<span>
|
||||||
<div
|
<div
|
||||||
aria-describedby="tooltip-11"
|
aria-describedby="tooltip-23"
|
||||||
class="c43"
|
class="c43"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
@ -2988,7 +3014,7 @@ exports[`Marketplace page renders and matches the provider tab snapshot 1`] = `
|
|||||||
Cloudinary
|
Cloudinary
|
||||||
<span>
|
<span>
|
||||||
<div
|
<div
|
||||||
aria-describedby="tooltip-13"
|
aria-describedby="tooltip-25"
|
||||||
class="c43"
|
class="c43"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
@ -3110,7 +3136,7 @@ exports[`Marketplace page renders and matches the provider tab snapshot 1`] = `
|
|||||||
Local Upload
|
Local Upload
|
||||||
<span>
|
<span>
|
||||||
<div
|
<div
|
||||||
aria-describedby="tooltip-15"
|
aria-describedby="tooltip-27"
|
||||||
class="c43"
|
class="c43"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
@ -3242,7 +3268,7 @@ exports[`Marketplace page renders and matches the provider tab snapshot 1`] = `
|
|||||||
Mailgun
|
Mailgun
|
||||||
<span>
|
<span>
|
||||||
<div
|
<div
|
||||||
aria-describedby="tooltip-17"
|
aria-describedby="tooltip-29"
|
||||||
class="c43"
|
class="c43"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
@ -3374,7 +3400,7 @@ exports[`Marketplace page renders and matches the provider tab snapshot 1`] = `
|
|||||||
Nodemailer
|
Nodemailer
|
||||||
<span>
|
<span>
|
||||||
<div
|
<div
|
||||||
aria-describedby="tooltip-19"
|
aria-describedby="tooltip-31"
|
||||||
class="c43"
|
class="c43"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
@ -3506,7 +3532,7 @@ exports[`Marketplace page renders and matches the provider tab snapshot 1`] = `
|
|||||||
Rackspace
|
Rackspace
|
||||||
<span>
|
<span>
|
||||||
<div
|
<div
|
||||||
aria-describedby="tooltip-21"
|
aria-describedby="tooltip-33"
|
||||||
class="c43"
|
class="c43"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
@ -3638,7 +3664,7 @@ exports[`Marketplace page renders and matches the provider tab snapshot 1`] = `
|
|||||||
SendGrid
|
SendGrid
|
||||||
<span>
|
<span>
|
||||||
<div
|
<div
|
||||||
aria-describedby="tooltip-23"
|
aria-describedby="tooltip-35"
|
||||||
class="c43"
|
class="c43"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
@ -3770,7 +3796,7 @@ exports[`Marketplace page renders and matches the provider tab snapshot 1`] = `
|
|||||||
Sendmail
|
Sendmail
|
||||||
<span>
|
<span>
|
||||||
<div
|
<div
|
||||||
aria-describedby="tooltip-25"
|
aria-describedby="tooltip-37"
|
||||||
class="c43"
|
class="c43"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
screen,
|
screen,
|
||||||
getByText,
|
getByText,
|
||||||
queryByText,
|
queryByText,
|
||||||
|
getByRole,
|
||||||
} from '@testing-library/react';
|
} from '@testing-library/react';
|
||||||
import { IntlProvider } from 'react-intl';
|
import { IntlProvider } from 'react-intl';
|
||||||
import { QueryClient, QueryClientProvider } from 'react-query';
|
import { QueryClient, QueryClientProvider } from 'react-query';
|
||||||
@ -35,6 +36,7 @@ jest.mock('@strapi/helper-plugin', () => ({
|
|||||||
'@strapi/plugin-documentation': '4.2.0',
|
'@strapi/plugin-documentation': '4.2.0',
|
||||||
'@strapi/provider-upload-cloudinary': '4.2.0',
|
'@strapi/provider-upload-cloudinary': '4.2.0',
|
||||||
},
|
},
|
||||||
|
strapiVersion: '4.1.0',
|
||||||
useYarn: true,
|
useYarn: true,
|
||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
@ -215,7 +217,7 @@ describe('Marketplace page', () => {
|
|||||||
expect(pluginCardText).toEqual(null);
|
expect(pluginCardText).toEqual(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows the installed text for installed plugins', async () => {
|
it('shows the installed text for installed plugins', () => {
|
||||||
render(App);
|
render(App);
|
||||||
const pluginsTab = screen.getByRole('tab', { name: /plugins/i });
|
const pluginsTab = screen.getByRole('tab', { name: /plugins/i });
|
||||||
fireEvent.click(pluginsTab);
|
fireEvent.click(pluginsTab);
|
||||||
@ -235,7 +237,7 @@ describe('Marketplace page', () => {
|
|||||||
expect(notInstalledText).toBeVisible();
|
expect(notInstalledText).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('shows the installed text for installed providers', async () => {
|
it('shows the installed text for installed providers', () => {
|
||||||
// Open providers tab
|
// Open providers tab
|
||||||
render(App);
|
render(App);
|
||||||
const providersTab = screen.getByRole('tab', { name: /providers/i });
|
const providersTab = screen.getByRole('tab', { name: /providers/i });
|
||||||
@ -255,4 +257,38 @@ describe('Marketplace page', () => {
|
|||||||
const notInstalledText = queryByText(notInstalledCard, /copy install command/i);
|
const notInstalledText = queryByText(notInstalledCard, /copy install command/i);
|
||||||
expect(notInstalledText).toBeVisible();
|
expect(notInstalledText).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('disables the button and shows compatibility tooltip message when version provided', async () => {
|
||||||
|
const { getByTestId } = render(App);
|
||||||
|
const alreadyInstalledCard = screen
|
||||||
|
.getAllByTestId('npm-package-card')
|
||||||
|
.find((div) => div.innerHTML.includes('Transformer'));
|
||||||
|
const button = getByRole(alreadyInstalledCard, 'button', { name: /copy install command/i });
|
||||||
|
const tooltip = getByTestId(`tooltip-Transformer`);
|
||||||
|
fireEvent.mouseOver(button);
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(tooltip).toBeVisible();
|
||||||
|
});
|
||||||
|
expect(button).toBeDisabled();
|
||||||
|
expect(tooltip).toBeInTheDocument();
|
||||||
|
expect(tooltip).toHaveTextContent('Update your Strapi version: "4.1.0" to: "4.0.7"');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows compatibility tooltip message when no version provided', async () => {
|
||||||
|
const { getByTestId } = render(App);
|
||||||
|
const alreadyInstalledCard = screen
|
||||||
|
.getAllByTestId('npm-package-card')
|
||||||
|
.find((div) => div.innerHTML.includes('Config Sync'));
|
||||||
|
const button = getByRole(alreadyInstalledCard, 'button', { name: /copy install command/i });
|
||||||
|
const tooltip = getByTestId(`tooltip-Config Sync`);
|
||||||
|
fireEvent.mouseOver(button);
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(tooltip).toBeVisible();
|
||||||
|
});
|
||||||
|
expect(button).not.toBeDisabled();
|
||||||
|
expect(tooltip).toBeInTheDocument();
|
||||||
|
expect(tooltip).toHaveTextContent(
|
||||||
|
'Unable to verify compatibility with your Strapi version: "4.1.0"'
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -48,6 +48,7 @@ const handlers = [
|
|||||||
validated: false,
|
validated: false,
|
||||||
madeByStrapi: false,
|
madeByStrapi: false,
|
||||||
strapiCompatibility: 'v3',
|
strapiCompatibility: 'v3',
|
||||||
|
strapiVersion: '^4.0.0',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -221,6 +222,7 @@ const handlers = [
|
|||||||
validated: false,
|
validated: false,
|
||||||
madeByStrapi: false,
|
madeByStrapi: false,
|
||||||
strapiCompatibility: 'v4',
|
strapiCompatibility: 'v4',
|
||||||
|
strapiVersion: '4.x.x',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -291,6 +293,7 @@ const handlers = [
|
|||||||
validated: true,
|
validated: true,
|
||||||
madeByStrapi: false,
|
madeByStrapi: false,
|
||||||
strapiCompatibility: 'v4',
|
strapiCompatibility: 'v4',
|
||||||
|
strapiVersion: 'Contact developer',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -362,6 +365,7 @@ const handlers = [
|
|||||||
validated: false,
|
validated: false,
|
||||||
madeByStrapi: false,
|
madeByStrapi: false,
|
||||||
strapiCompatibility: 'v4',
|
strapiCompatibility: 'v4',
|
||||||
|
strapiVersion: '^3.4.2',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -404,6 +408,7 @@ const handlers = [
|
|||||||
validated: true,
|
validated: true,
|
||||||
madeByStrapi: true,
|
madeByStrapi: true,
|
||||||
strapiCompatibility: 'v4',
|
strapiCompatibility: 'v4',
|
||||||
|
strapiVersion: '^4.0.7',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -446,6 +451,7 @@ const handlers = [
|
|||||||
validated: true,
|
validated: true,
|
||||||
madeByStrapi: false,
|
madeByStrapi: false,
|
||||||
strapiCompatibility: 'v3',
|
strapiCompatibility: 'v3',
|
||||||
|
strapiVersion: '^4.3.0',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -488,6 +494,7 @@ const handlers = [
|
|||||||
validated: false,
|
validated: false,
|
||||||
madeByStrapi: false,
|
madeByStrapi: false,
|
||||||
strapiCompatibility: 'v4',
|
strapiCompatibility: 'v4',
|
||||||
|
strapiVersion: '4.0.7',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -100,11 +100,11 @@
|
|||||||
"Settings.apiTokens.duration.30-days": "30 days",
|
"Settings.apiTokens.duration.30-days": "30 days",
|
||||||
"Settings.apiTokens.duration.90-days": "90 days",
|
"Settings.apiTokens.duration.90-days": "90 days",
|
||||||
"Settings.apiTokens.duration.unlimited": "Unlimited",
|
"Settings.apiTokens.duration.unlimited": "Unlimited",
|
||||||
"Settings.apiTokens.form.duration":"Token duration",
|
"Settings.apiTokens.form.duration": "Token duration",
|
||||||
"Settings.apiTokens.form.type":"Token type",
|
"Settings.apiTokens.form.type": "Token type",
|
||||||
"Settings.apiTokens.duration.expiration-date":"Expiration date",
|
"Settings.apiTokens.duration.expiration-date": "Expiration date",
|
||||||
"Settings.apiTokens.createPage.permissions.title":"Permissions",
|
"Settings.apiTokens.createPage.permissions.title": "Permissions",
|
||||||
"Settings.apiTokens.createPage.permissions.description":"Only actions bound by a route are listed below.",
|
"Settings.apiTokens.createPage.permissions.description": "Only actions bound by a route are listed below.",
|
||||||
"Settings.apiTokens.RegenerateDialog.title": "Regenerate token",
|
"Settings.apiTokens.RegenerateDialog.title": "Regenerate token",
|
||||||
"Settings.apiTokens.popUpWarning.message": "Are you sure you want to regenerate this token?",
|
"Settings.apiTokens.popUpWarning.message": "Are you sure you want to regenerate this token?",
|
||||||
"Settings.apiTokens.Button.cancel": "Cancel",
|
"Settings.apiTokens.Button.cancel": "Cancel",
|
||||||
@ -270,6 +270,8 @@
|
|||||||
"admin.pages.MarketPlacePage.plugin.installed": "Installed",
|
"admin.pages.MarketPlacePage.plugin.installed": "Installed",
|
||||||
"admin.pages.MarketPlacePage.plugin.tooltip.madeByStrapi": "Made by Strapi",
|
"admin.pages.MarketPlacePage.plugin.tooltip.madeByStrapi": "Made by Strapi",
|
||||||
"admin.pages.MarketPlacePage.plugin.tooltip.verified": "Plugin verified by Strapi",
|
"admin.pages.MarketPlacePage.plugin.tooltip.verified": "Plugin verified by Strapi",
|
||||||
|
"admin.pages.MarketPlacePage.plugin.version": "Update your Strapi version: \"{strapiAppVersion}\" to: \"{versionRange}\"",
|
||||||
|
"admin.pages.MarketPlacePage.plugin.version.null": "Unable to verify compatibility with your Strapi version: \"{strapiAppVersion}\"",
|
||||||
"admin.pages.MarketPlacePage.providers": "Providers",
|
"admin.pages.MarketPlacePage.providers": "Providers",
|
||||||
"admin.pages.MarketPlacePage.search.clear": "Clear the search",
|
"admin.pages.MarketPlacePage.search.clear": "Clear the search",
|
||||||
"admin.pages.MarketPlacePage.search.empty": "No result for \"{target}\"",
|
"admin.pages.MarketPlacePage.search.empty": "No result for \"{target}\"",
|
||||||
|
@ -110,5 +110,6 @@ coverage
|
|||||||
license.txt
|
license.txt
|
||||||
exports
|
exports
|
||||||
*.cache
|
*.cache
|
||||||
|
dist
|
||||||
build
|
build
|
||||||
.strapi-updater.json
|
.strapi-updater.json
|
||||||
|
Loading…
x
Reference in New Issue
Block a user