diff --git a/package.json b/package.json index 987f4e10f0..e574b66d06 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,7 @@ "@gnosis.pm/safe-core-sdk": "^2.0.0", "@gnosis.pm/safe-deployments": "^1.8.0", "@gnosis.pm/safe-react-components": "^1.1.2", - "@gnosis.pm/safe-react-gateway-sdk": "^2.10.2", + "@gnosis.pm/safe-react-gateway-sdk": "^2.10.3", "@gnosis.pm/safe-web3-lib": "^1.0.0", "@material-ui/core": "^4.12.3", "@material-ui/icons": "^4.11.0", diff --git a/src/components/Dashboard/FeaturedApps/FeaturedApps.tsx b/src/components/Dashboard/FeaturedApps/FeaturedApps.tsx new file mode 100644 index 0000000000..0f3e4ede25 --- /dev/null +++ b/src/components/Dashboard/FeaturedApps/FeaturedApps.tsx @@ -0,0 +1,64 @@ +import { useAppList } from 'src/routes/safe/components/Apps/hooks/appList/useAppList' +import { Text } from '@gnosis.pm/safe-react-components' +import { Link } from 'react-router-dom' +import { getSafeAppUrl, SafeRouteParams } from 'src/routes/routes' +import { useSelector } from 'react-redux' +import { currentSafe } from 'src/logic/safe/store/selectors' +import { getShortName } from 'src/config' +import { ReactElement, useMemo } from 'react' +import Row from 'src/components/layout/Row' +import Col from 'src/components/layout/Col' +import styled from 'styled-components' + +const FEATURED_APPS_TAGS = 'dashboard-widgets' + +const StyledImage = styled.img` + max-width: 64px; + max-height: 64px; +` + +const StyledLink = styled(Link)` + margin-top: 10px; + text-decoration: none; +` + +const StyledRow = styled(Row)` + gap: 24px; + flex-wrap: inherit; +` + +export const FeaturedApps = (): ReactElement => { + const { allApps } = useAppList() + const { address } = useSelector(currentSafe) ?? {} + const featuredApps = useMemo(() => allApps.filter((app) => app.tags?.includes(FEATURED_APPS_TAGS)), [allApps]) + + const routesSlug: SafeRouteParams = { + shortName: getShortName(), + safeAddress: address, + } + + return ( + <> + {featuredApps.map((app) => { + const appRoute = getSafeAppUrl(app.url, routesSlug) + return ( + + + + + + + {app.description} + + + + Use {app.name} + + + + + ) + })} + + ) +} diff --git a/src/routes/Home/index.tsx b/src/routes/Home/index.tsx index 8df655ffe8..d61b2cbb15 100644 --- a/src/routes/Home/index.tsx +++ b/src/routes/Home/index.tsx @@ -8,6 +8,7 @@ import Overview from 'src/components/Dashboard/Overview/Overview' import { lg } from 'src/theme/variables' import SafeAppsGrid from 'src/components/Dashboard/SafeApps/Grid' import Row from 'src/components/layout/Row' +import { FeaturedApps } from 'src/components/Dashboard/FeaturedApps/FeaturedApps' const Card = styled.div` background: #fff; @@ -36,7 +37,8 @@ function Home(): ReactElement { -

Owned Safes

+

Safe Apps

+
diff --git a/src/routes/routes.ts b/src/routes/routes.ts index 71e53c971d..56a12545ed 100644 --- a/src/routes/routes.ts +++ b/src/routes/routes.ts @@ -126,3 +126,7 @@ export const generatePrefixedAddressRoutes = (params: SafeRouteParams): typeof S {} as typeof STANDARD_SAFE_ROUTES, ) } + +export const getSafeAppUrl = (appUrl: string, routesSlug: SafeRouteParams): string => { + return generateSafeRoute(SAFE_ROUTES.APPS, routesSlug) + `?appUrl=${appUrl}` +} diff --git a/src/routes/safe/components/Apps/components/AppsList.test.tsx b/src/routes/safe/components/Apps/components/AppsList.test.tsx index 8b3975cc8e..24b2227ad7 100644 --- a/src/routes/safe/components/Apps/components/AppsList.test.tsx +++ b/src/routes/safe/components/Apps/components/AppsList.test.tsx @@ -39,6 +39,7 @@ beforeEach(() => { accessControl: { type: safeAppsGatewaySDK.SafeAppAccessPolicyTypes.NoRestrictions, }, + tags: [], }), ) @@ -55,6 +56,7 @@ beforeEach(() => { accessControl: { type: safeAppsGatewaySDK.SafeAppAccessPolicyTypes.NoRestrictions, }, + tags: [], }, { id: 3, @@ -69,6 +71,7 @@ beforeEach(() => { type: safeAppsGatewaySDK.SafeAppAccessPolicyTypes.DomainAllowlist, value: ['https://gnosis-safe.io'], }, + tags: [], }, { id: 14, @@ -81,6 +84,7 @@ beforeEach(() => { accessControl: { type: safeAppsGatewaySDK.SafeAppAccessPolicyTypes.NoRestrictions, }, + tags: [], }, { id: 24, @@ -94,6 +98,7 @@ beforeEach(() => { type: safeAppsGatewaySDK.SafeAppAccessPolicyTypes.DomainAllowlist, value: ['https://gnosis-safe.io'], }, + tags: [], }, ]), ) diff --git a/src/routes/safe/components/Apps/utils.ts b/src/routes/safe/components/Apps/utils.ts index e0618d2844..975915021e 100644 --- a/src/routes/safe/components/Apps/utils.ts +++ b/src/routes/safe/components/Apps/utils.ts @@ -62,6 +62,7 @@ export const getEmptySafeApp = (url = ''): SafeApp => { accessControl: { type: SafeAppAccessPolicyTypes.NoRestrictions, }, + tags: [], } } diff --git a/yarn.lock b/yarn.lock index 2877c36864..c7fdcadff3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1887,10 +1887,10 @@ dependencies: cross-fetch "^3.1.5" -"@gnosis.pm/safe-react-gateway-sdk@^2.10.2": - version "2.10.2" - resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-react-gateway-sdk/-/safe-react-gateway-sdk-2.10.2.tgz#25d01ea5c947bc2701535c6cdf059b380276e0f5" - integrity sha512-9o0JiA3zS5s1fVQa61DB1gBdFgyqA9QxW3y8lTYzX/lWNbfpm2psonyLjBJkETp7RoMFSp30pM4wgPXXT9bjzQ== +"@gnosis.pm/safe-react-gateway-sdk@^2.10.3": + version "2.10.3" + resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-react-gateway-sdk/-/safe-react-gateway-sdk-2.10.3.tgz#4537442a78eb0508c483aabcac19296335a77ac3" + integrity sha512-ukaLACozdJQb2YGSAZgBUkF4CT9iKVjpnKFCKUnGGghXqp+Yyn9jpdcfFK0VYQJ6ZSwAm40tHtQaN3K9817Bcg== dependencies: cross-fetch "^3.1.5"