From 0972944e03a12e72da7b80254be2ed14c590de43 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Wed, 28 Oct 2020 23:59:14 +0100 Subject: [PATCH] Bookmarks (#159) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * handle pinned items in UserPreferencesProvider * prototype add/remove pins * output pins * pins → bookmarks * styling * output datatoken info --- src/components/atoms/Table.tsx | 4 +- .../molecules/AssetTeaser.module.css | 2 +- src/components/molecules/AssetTeaser.tsx | 9 +- src/components/molecules/Bookmarks.module.css | 16 ++++ src/components/molecules/Bookmarks.tsx | 87 +++++++++++++++++++ .../AssetContent/Bookmark.module.css | 28 ++++++ .../organisms/AssetContent/Bookmark.tsx | 23 +++++ .../organisms/AssetContent/index.module.css | 1 + .../organisms/AssetContent/index.tsx | 5 +- src/components/pages/Home.tsx | 7 ++ src/images/bookmark.svg | 3 + src/providers/UserPreferences.tsx | 25 +++++- 12 files changed, 201 insertions(+), 9 deletions(-) create mode 100644 src/components/molecules/Bookmarks.module.css create mode 100644 src/components/molecules/Bookmarks.tsx create mode 100644 src/components/organisms/AssetContent/Bookmark.module.css create mode 100644 src/components/organisms/AssetContent/Bookmark.tsx create mode 100644 src/images/bookmark.svg diff --git a/src/components/atoms/Table.tsx b/src/components/atoms/Table.tsx index 62194560d..6ab1a1bc6 100644 --- a/src/components/atoms/Table.tsx +++ b/src/components/atoms/Table.tsx @@ -14,7 +14,8 @@ function Empty(): ReactElement { export default function Table({ data, columns, - isLoading + isLoading, + ...props }: TableProps): ReactElement { return ( } progressPending={isLoading} progressComponent={} + {...props} /> ) } diff --git a/src/components/molecules/AssetTeaser.module.css b/src/components/molecules/AssetTeaser.module.css index 995b99e05..14c7a8c94 100644 --- a/src/components/molecules/AssetTeaser.module.css +++ b/src/components/molecules/AssetTeaser.module.css @@ -53,5 +53,5 @@ } .symbol { - margin-bottom: 0; + display: inline-block; } diff --git a/src/components/molecules/AssetTeaser.tsx b/src/components/molecules/AssetTeaser.tsx index b054578d4..38851155e 100644 --- a/src/components/molecules/AssetTeaser.tsx +++ b/src/components/molecules/AssetTeaser.tsx @@ -6,6 +6,7 @@ import Price from '../atoms/Price' import styles from './AssetTeaser.module.css' import { DDO } from '@oceanprotocol/lib' import removeMarkdown from 'remove-markdown' +import Tooltip from '../atoms/Tooltip' declare type AssetTeaserProps = { ddo: DDO @@ -23,7 +24,13 @@ const AssetTeaser: React.FC = ({ return (
-

{dataTokenInfo?.symbol}

+ + {dataTokenInfo?.symbol} +

{name}

{isCompute &&
Compute
} diff --git a/src/components/molecules/Bookmarks.module.css b/src/components/molecules/Bookmarks.module.css new file mode 100644 index 000000000..073a6dac8 --- /dev/null +++ b/src/components/molecules/Bookmarks.module.css @@ -0,0 +1,16 @@ +.title { + line-height: var(--line-height); + margin: 0; + display: inline; +} + +.title a { + font-size: var(--font-size-base); + color: var(--brand-black); +} + +.empty { + font-size: var(--font-size-small); + color: var(--color-secondary); + font-style: italic; +} diff --git a/src/components/molecules/Bookmarks.tsx b/src/components/molecules/Bookmarks.tsx new file mode 100644 index 000000000..f970c974b --- /dev/null +++ b/src/components/molecules/Bookmarks.tsx @@ -0,0 +1,87 @@ +import { useUserPreferences } from '../../providers/UserPreferences' +import React, { ReactElement, useEffect, useState } from 'react' +import Table from '../atoms/Table' +import { DDO, Logger, MetadataCache } from '@oceanprotocol/lib' +import { useOcean } from '@oceanprotocol/react' +import { Link } from 'gatsby' +import styles from './Bookmarks.module.css' +import Price from '../atoms/Price' +import Tooltip from '../atoms/Tooltip' + +async function getAssetsBookmarked(pins: string[], metadataCacheUri: string) { + try { + const metadataCache = new MetadataCache(metadataCacheUri, Logger) + const result: DDO[] = [] + + for (const pin of pins) { + result.push(await metadataCache.retrieveDDO(pin)) + } + + return result + } catch (error) { + Logger.error(error.message) + } +} + +const columns = [ + { + name: 'Data Set', + selector: function getAssetRow(row: DDO) { + const { attributes } = row.findServiceByType('metadata') + return ( +

+ {attributes.main.name} +

+ ) + }, + grow: 2 + }, + { + name: 'Datatoken Symbol', + selector: function getAssetRow(row: DDO) { + return ( + + {row.dataTokenInfo.symbol} + + ) + } + }, + { + name: 'Price', + selector: function getAssetRow(row: DDO) { + return + }, + right: true + } +] + +export default function Bookmarks(): ReactElement { + const { config } = useOcean() + const { bookmarks } = useUserPreferences() + + const [pinned, setPinned] = useState() + const [isLoading, setIsLoading] = useState() + + const noBookmarks = !bookmarks || !bookmarks.length + + useEffect(() => { + if (noBookmarks) return + + async function init() { + setIsLoading(true) + const resultPinned = await getAssetsBookmarked( + bookmarks, + config.metadataCacheUri + ) + setPinned(resultPinned) + setIsLoading(false) + } + init() + }, [bookmarks, config.metadataCacheUri, noBookmarks]) + + return noBookmarks ? ( +
Your bookmarks will appear here.
+ ) : ( + + ) +} diff --git a/src/components/organisms/AssetContent/Bookmark.module.css b/src/components/organisms/AssetContent/Bookmark.module.css new file mode 100644 index 000000000..19b19db0a --- /dev/null +++ b/src/components/organisms/AssetContent/Bookmark.module.css @@ -0,0 +1,28 @@ +.bookmark { + position: absolute; + top: -10px; + right: calc(var(--spacer) / 4); + appearance: none; + background: none; + border: none; + box-shadow: none; + outline: 0; + cursor: pointer; + transition: 0.2s ease-out; +} + +.bookmark svg { + fill: var(--brand-grey-light); + height: 40px; + width: 40px; + filter: drop-shadow(0 4px 6px rgba(0, 0, 0, 0.2)); +} + +.bookmark:hover, +.bookmark:focus { + transform: translate3d(0, 6px, 0); +} + +.bookmark.active svg { + fill: var(--brand-violet); +} diff --git a/src/components/organisms/AssetContent/Bookmark.tsx b/src/components/organisms/AssetContent/Bookmark.tsx new file mode 100644 index 000000000..9914818fb --- /dev/null +++ b/src/components/organisms/AssetContent/Bookmark.tsx @@ -0,0 +1,23 @@ +import { useUserPreferences } from '../../../providers/UserPreferences' +import React, { ReactElement } from 'react' +import styles from './Bookmark.module.css' +import { ReactComponent as BookmarkIcon } from '../../../images/bookmark.svg' + +export default function Bookmark({ did }: { did: string }): ReactElement { + const { bookmarks, addBookmark, removeBookmark } = useUserPreferences() + const isBookmarked = bookmarks?.includes(did) + + function handleBookmark() { + isBookmarked ? removeBookmark(did) : addBookmark(did) + } + + return ( + + ) +} diff --git a/src/components/organisms/AssetContent/index.module.css b/src/components/organisms/AssetContent/index.module.css index fd6784518..471f4091b 100644 --- a/src/components/organisms/AssetContent/index.module.css +++ b/src/components/organisms/AssetContent/index.module.css @@ -12,6 +12,7 @@ .content { composes: box from '../../atoms/Box.module.css'; margin-top: var(--spacer); + position: relative; } @media (min-width: 60rem) { diff --git a/src/components/organisms/AssetContent/index.tsx b/src/components/organisms/AssetContent/index.tsx index 63e4bffac..7b25c03f4 100644 --- a/src/components/organisms/AssetContent/index.tsx +++ b/src/components/organisms/AssetContent/index.tsx @@ -1,6 +1,5 @@ import { MetadataMarket } from '../../../@types/MetaData' import React, { ReactElement } from 'react' -import Time from '../../atoms/Time' import { Link } from 'gatsby' import Markdown from '../../atoms/Markdown' import MetaFull from './MetaFull' @@ -12,7 +11,7 @@ import { useUserPreferences } from '../../../providers/UserPreferences' import Pricing from './Pricing' import { useOcean, usePricing } from '@oceanprotocol/react' import EtherscanLink from '../../atoms/EtherscanLink' -import MetaItem from './MetaItem' +import Bookmark from './Bookmark' export interface AssetContentProps { metadata: MetadataMarket @@ -89,6 +88,8 @@ export default function AssetContent({ {JSON.stringify(ddo, null, 2)} )} + + diff --git a/src/components/pages/Home.tsx b/src/components/pages/Home.tsx index b8d8ab4a5..edb9e7f3d 100644 --- a/src/components/pages/Home.tsx +++ b/src/components/pages/Home.tsx @@ -11,6 +11,7 @@ import Container from '../atoms/Container' import Loader from '../atoms/Loader' import { useOcean } from '@oceanprotocol/react' import Button from '../atoms/Button' +import Bookmarks from '../molecules/Bookmarks' const queryHighest = { page: 1, @@ -46,6 +47,7 @@ async function getAssets(query: SearchQuery, metadataCacheUri: string) { export default function HomePage(): ReactElement { const { config } = useOcean() + const [queryResultLatest, setQueryResultLatest] = useState() const [queryResultPoolsLatest, setQueryResultPoolsLatest] = useState< QueryResult @@ -83,6 +85,11 @@ export default function HomePage(): ReactElement { +
+

Bookmarks

+ +
+

Highest Liquidity Pools

{loading ? ( diff --git a/src/images/bookmark.svg b/src/images/bookmark.svg new file mode 100644 index 000000000..95ed52f19 --- /dev/null +++ b/src/images/bookmark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/providers/UserPreferences.tsx b/src/providers/UserPreferences.tsx index ce5db4463..b4201dee7 100644 --- a/src/providers/UserPreferences.tsx +++ b/src/providers/UserPreferences.tsx @@ -13,8 +13,11 @@ interface UserPreferencesValue { debug: boolean currency: string locale: string + bookmarks: string[] setDebug: (value: boolean) => void setCurrency: (value: string) => void + addBookmark: (did: string) => void + removeBookmark: (did: string) => void } const UserPreferencesContext = createContext(null) @@ -48,13 +51,14 @@ function UserPreferencesProvider({ localStorage?.currency || 'EUR' ) const [locale, setLocale] = useState() + const [bookmarks, setBookmarks] = useState(localStorage?.bookmarks || []) // Write values to localStorage on change useEffect(() => { - setLocalStorage({ debug, currency }) - }, [debug, currency]) + setLocalStorage({ debug, currency, bookmarks }) + }, [debug, currency, bookmarks]) - // Set ocean-lib-js log levels, default: Error + // Set ocean.js log levels, default: Error useEffect(() => { debug === true ? Logger.setLevel(LogLevel.Verbose) @@ -67,6 +71,16 @@ function UserPreferencesProvider({ setLocale(window.navigator.language) }, []) + function addBookmark(didToAdd: string): void { + const newPinned = bookmarks.concat(didToAdd) + setBookmarks(newPinned) + } + + function removeBookmark(didToAdd: string): void { + const newPinned = bookmarks.filter((did: string) => did !== didToAdd) + setBookmarks(newPinned) + } + return (