Commit 878cb938 authored by Max Alekseenko's avatar Max Alekseenko Committed by GitHub

Merge pull request #1528 from blockscout/integration-mark

Add the integration mark
parents 0e0952c0 cac9198b
......@@ -71,6 +71,7 @@ const marketplaceAppSchema: yup.ObjectSchema<MarketplaceAppOverview> = yup
twitter: yup.string().test(urlTest),
telegram: yup.string().test(urlTest),
github: yup.string().test(urlTest),
internalWallet: yup.boolean(),
});
const marketplaceSchema = yup
......
<svg viewBox="-1 -1 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.24.661a.964.964 0 1 0-1.831.607l.426 1.285a.964.964 0 0 0 1.83-.606L7.24.661Zm10.478.985A.964.964 0 0 0 16.354.283l-3.495 3.495-.204-.204a2.893 2.893 0 0 0-4.091 0L6.75 5.388A.964.964 0 0 0 5.388 6.75L3.575 8.562a2.893 2.893 0 0 0 0 4.091l.204.204-3.496 3.497a.964.964 0 1 0 1.364 1.363l3.496-3.496.205.205a2.893 2.893 0 0 0 4.091 0l1.813-1.813a.964.964 0 0 0 1.361-1.361l1.815-1.814a2.893 2.893 0 0 0 0-4.091l-.206-.206 3.496-3.495ZM11.25 9.887l1.813-1.813a.964.964 0 0 0 0-1.364l-.839-.839a.996.996 0 0 1-.096-.096l-.838-.838a.964.964 0 0 0-1.363 0L8.114 6.751l3.137 3.136Zm-4.5-1.773L4.939 9.926a.964.964 0 0 0 0 1.364l.864.864a1.193 1.193 0 0 1 .044.043l.865.866a.964.964 0 0 0 1.363 0l1.812-1.812-3.136-3.137Zm4.196 6.72a.964.964 0 0 1 1.218.613l.426 1.285a.964.964 0 1 1-1.83.607l-.426-1.286a.964.964 0 0 1 .612-1.219Zm3.888-3.887a.964.964 0 0 1 1.218-.612l1.286.425a.964.964 0 1 1-.607 1.831l-1.285-.426a.964.964 0 0 1-.612-1.218ZM1.268 5.409a.964.964 0 1 0-.607 1.83l1.286.426a.964.964 0 1 0 .606-1.83l-1.285-.426Z" fill="currentColor"/>
</svg>
<svg viewBox="0 -1 19 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.394.273a.931.931 0 0 1 0 1.316l-1.825 1.825.194.194h.001a2.795 2.795 0 0 1 0 3.956l-1.747 1.747a.931.931 0 0 1-1.354 1.278l-.609-.61-.011-.01-.012-.012L8.71 5.635l-.011-.011-.011-.012-.61-.609A.931.931 0 0 1 9.355 3.65l1.747-1.747a2.794 2.794 0 0 1 3.956 0l.195.194L17.077.273a.931.931 0 0 1 1.317 0Zm-2.945 5.973L13.7 7.994l-3.028-3.029 1.748-1.747a.93.93 0 0 1 1.319 0l1.708 1.708a.93.93 0 0 1 0 1.32ZM6.563 8.304l-.893-.893a.931.931 0 0 0-1.354 1.278L2.57 10.435l-.001.001a2.793 2.793 0 0 0 0 3.956l.195.194-1.825 1.825a.931.931 0 0 0 1.317 1.316l1.824-1.824.194.194a2.793 2.793 0 0 0 3.956 0h.001l1.747-1.747a.931.931 0 0 0 1.278-1.353l-.894-.893.894-.894a.931.931 0 0 0-1.317-1.317l-.893.894L7.88 9.62l.893-.894A.931.931 0 1 0 7.456 7.41l-.893.893Zm-.655 1.978-.003-.003-.004-.003-.27-.27-1.747 1.748a.931.931 0 0 0 0 1.32l.845.844.01.01.01.01.843.843.001.002a.93.93 0 0 0 1.319 0l1.748-1.748-2.752-2.753Z" fill="currentColor"/>
</svg>
......@@ -7,6 +7,7 @@ import { STORAGE_KEY, STORAGE_LIMIT } from './consts';
export interface GrowthBookFeatures {
test_value: string;
marketplace_exp: boolean;
}
export const growthBook = (() => {
......
......@@ -55,6 +55,8 @@
| "globe"
| "graphQL"
| "info"
| "integration/full"
| "integration/partial"
| "key"
| "lightning"
| "link"
......
......@@ -7,6 +7,7 @@ export type MarketplaceAppPreview = {
shortDescription: string;
categories: Array<string>;
url: string;
internalWallet?: boolean;
}
export type MarketplaceAppOverview = MarketplaceAppPreview & {
......
import { Box, IconButton, Image, Link, LinkBox, Skeleton, useColorModeValue } from '@chakra-ui/react';
import { Box, IconButton, Image, Link, LinkBox, Skeleton, useColorModeValue, Tooltip } from '@chakra-ui/react';
import type { MouseEvent } from 'react';
import React, { useCallback } from 'react';
import type { MarketplaceAppPreview } from 'types/client/marketplace';
import useFeatureValue from 'lib/growthbook/useFeatureValue';
import * as mixpanel from 'lib/mixpanel/index';
import type { IconName } from 'ui/shared/IconSvg';
import IconSvg from 'ui/shared/IconSvg';
import MarketplaceAppCardLink from './MarketplaceAppCardLink';
......@@ -29,9 +31,13 @@ const MarketplaceAppCard = ({
onInfoClick,
isFavorite,
onFavoriteClick,
isLoading,
isLoading: isDataLoading,
showDisclaimer,
internalWallet,
}: Props) => {
const { value: isExperiment, isLoading: isExperimentLoading } = useFeatureValue('marketplace_exp', false);
const isLoading = isDataLoading || isExperimentLoading;
const categoriesLabel = categories.join(', ');
const handleClick = useCallback((event: MouseEvent) => {
......@@ -55,6 +61,23 @@ const MarketplaceAppCard = ({
const logoUrl = useColorModeValue(logo, logoDarkMode || logo);
const moreButtonBgGradient = `linear(to-r, ${ useColorModeValue('whiteAlpha.50', 'blackAlpha.50') }, ${ useColorModeValue('white', 'black') } 20%)`;
const [ integrationIcon, integrationIconColor, integrationText ] = React.useMemo(() => {
let icon: IconName = 'integration/partial';
let color = 'gray.400';
let text = 'This app opens in Blockscout without Blockscout wallet functionality. Use your external web3 wallet to connect directly to this application';
if (external) {
icon = 'arrows/north-east';
text = 'This app opens in a separate tab';
} else if (internalWallet) {
icon = 'integration/full';
color = 'green.500';
text = 'This app opens in Blockscout and your Blockscout wallet connects automatically';
}
return [ icon, color, text ];
}, [ external, internalWallet ]);
return (
<LinkBox
_hover={{
......@@ -71,12 +94,14 @@ const MarketplaceAppCard = ({
role="group"
>
<Box
display={{ base: 'grid', sm: 'block' }}
display={{ base: 'grid', sm: isExperiment ? 'flex' : 'block' }}
flexDirection={ isExperiment ? 'column' : undefined }
gridTemplateColumns={{ base: '64px 1fr', sm: '1fr' }}
gridTemplateRows={{ base: 'none', sm: 'none' }}
gridRowGap={{ base: 2, sm: 'none' }}
gridColumnGap={{ base: 4, sm: 'none' }}
gridRowGap={{ base: 2, sm: 0 }}
gridColumnGap={{ base: 4, sm: 0 }}
height="100%"
alignContent={ isExperiment ? 'start' : undefined }
>
<Skeleton
isLoaded={ !isLoading }
......@@ -112,6 +137,25 @@ const MarketplaceAppCard = ({
title={ title }
onClick={ handleClick }
/>
{ isExperiment && (
<Tooltip
label={ integrationText }
textAlign="center"
padding={ 2 }
openDelay={ 300 }
maxW={ 400 }
>
<IconSvg
name={ integrationIcon }
boxSize={ 5 }
color={ integrationIconColor }
position="relative"
cursor="pointer"
verticalAlign="middle"
marginBottom={ 1 }
/>
</Tooltip>
) }
</Skeleton>
<Skeleton
......@@ -127,43 +171,63 @@ const MarketplaceAppCard = ({
isLoaded={ !isLoading }
fontSize={{ base: 'xs', sm: 'sm' }}
lineHeight="20px"
noOfLines={ 4 }
noOfLines={ isExperiment ? 3 : 4 }
>
{ shortDescription }
</Skeleton>
{ !isLoading && (
<Box
position="absolute"
right={{ base: 3, sm: '20px' }}
bottom={{ base: 3, sm: '20px' }}
paddingLeft={ 8 }
bgGradient={ moreButtonBgGradient }
>
<Link
fontSize={{ base: 'xs', sm: 'sm' }}
isExperiment ? (
<Box
display="flex"
alignItems="center"
paddingRight={{ sm: 2 }}
maxW="100%"
overflow="hidden"
href="#"
onClick={ handleInfoClick }
position={{ base: 'absolute', sm: 'relative' }}
bottom={{ base: 3, sm: 0 }}
left={{ base: 3, sm: 0 }}
marginTop={{ base: 0, sm: 'auto' }}
paddingTop={{ base: 0, sm: 4 }}
>
More
<IconSvg
name="arrows/north-east"
marginLeft={ 1 }
boxSize={ 4 }
/>
</Link>
</Box>
<Link
fontSize={{ base: 'xs', sm: 'sm' }}
paddingRight={{ sm: 2 }}
href="#"
onClick={ handleInfoClick }
>
More info
</Link>
</Box>
) : (
<Box
position="absolute"
right={{ base: 3, sm: '20px' }}
bottom={{ base: 3, sm: '20px' }}
paddingLeft={ 8 }
bgGradient={ moreButtonBgGradient }
>
<Link
fontSize={{ base: 'xs', sm: 'sm' }}
display="flex"
alignItems="center"
paddingRight={{ sm: 2 }}
maxW="100%"
overflow="hidden"
href="#"
onClick={ handleInfoClick }
>
More
<IconSvg
name="arrows/north-east"
marginLeft={ 1 }
boxSize={ 4 }
/>
</Link>
</Box>
)
) }
{ !isLoading && (
<IconButton
display={{ base: 'block', sm: isFavorite ? 'block' : 'none' }}
display={{ base: 'block', sm: isFavorite || isExperiment ? 'block' : 'none' }}
_groupHover={{ display: 'block' }}
position="absolute"
right={{ base: 3, sm: '10px' }}
......
......@@ -13,12 +13,12 @@ type Props = {
const MarketplaceAppCardLink = ({ url, external, id, title, onClick }: Props) => {
return external ? (
<LinkOverlay href={ url } isExternal={ true }>
<LinkOverlay href={ url } isExternal={ true } marginRight={ 2 }>
{ title }
</LinkOverlay>
) : (
<NextLink href={{ pathname: '/apps/[id]', query: { id } }} passHref legacyBehavior>
<LinkOverlay onClick={ onClick }>
<LinkOverlay onClick={ onClick } marginRight={ 2 }>
{ title }
</LinkOverlay>
</NextLink>
......
......@@ -43,6 +43,7 @@ const MarketplaceList = ({ apps, onAppClick, favoriteApps, onFavoriteClick, isLo
onFavoriteClick={ onFavoriteClick }
isLoading={ isLoading }
showDisclaimer={ showDisclaimer }
internalWallet={ app.internalWallet }
/>
)) }
</Grid>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment