Skip to content

Commit

Permalink
Feat/nft grid view 2206 (#2213)
Browse files Browse the repository at this point in the history
* nft page

* icons

* NFTs page is ready

* making grid

* grid ready

* copy system

* nft grid ready

* lingui extract

* spacings

* lingui extract

* reading NFTs

* NFT async load

* NFTs grid

* spacings

* no loader system

* type cleanings

* api client update

* gateway and asyncs

* undefined in state

* update api-client

* updates

* no nfts show

* lingui extract

* package update

* lock file

* loaders

* lingui extract

Co-authored-by: GitHub Actions <actions@github.com>
Co-authored-by: Thibaut Sardan <33178835+Tbaut@users.noreply.github.com>
Co-authored-by: Michael Yankelev <myankelev@gmail.com>
  • Loading branch information
4 people committed Jul 26, 2022
1 parent d3a6ad1 commit 3c43b95
Show file tree
Hide file tree
Showing 16 changed files with 490 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as React from "react"
import createSvgIcon from "../createSvgIcon"
import { ReactComponent as FileWithImageSvg } from "../svgs/file-with-image.svg"

export { FileWithImageSvg }

export default createSvgIcon(<FileWithImageSvg />)
1 change: 1 addition & 0 deletions packages/common-components/src/Icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export { default as FileImageIcon, FileImageSvg } from "./icons/FileImage.icon"
export { default as FilePdfIcon, FilePdfSvg } from "./icons/FilePdf.icon"
export { default as FileTextIcon, FileTextSvg } from "./icons/FileText.icon"
export { default as FileVideoIcon, FileVideoSvg } from "./icons/FileVideo.icon"
export { default as FileWithImageIcon, FileWithImageSvg } from "./icons/FileWithImage.icon"
export { default as FolderIcon, FolderSvg } from "./icons/Folder.icon"
export { default as FolderFilledIcon, FolderFilledSvg } from "./icons/FolderFilled.icon"
export { default as FullscreenIcon, FullscreenSvg } from "./icons/Fullscreen.icon"
Expand Down
5 changes: 5 additions & 0 deletions packages/common-components/src/Icons/svgs/file-with-image.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion packages/storage-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"@babel/core": "^7.12.10",
"@babel/runtime": "^7.0.0",
"@chainsafe/browser-storage-hooks": "^1.0.1",
"@chainsafe/files-api-client": "1.18.37",
"@chainsafe/files-api-client": "1.18.42",
"@chainsafe/web3-context": "1.3.0",
"@emeraldpay/hashicon-react": "0.5.2",
"@lingui/core": "^3.7.2",
Expand Down
3 changes: 1 addition & 2 deletions packages/storage-ui/src/Components/Elements/CidRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { CSSTheme } from "../../Themes/types"
import { useStorage } from "../../Contexts/StorageContext"
import { desktopGridSettings, mobileGridSettings } from "../Pages/CidsPage"
import { trimChar } from "../../Utils/pathUtils"
import { IPFS_GATEWAY } from "../../Utils/Constants"

const useStyles = makeStyles(({ animation, constants, breakpoints, palette }: CSSTheme) =>
createStyles({
Expand Down Expand Up @@ -66,8 +67,6 @@ interface Props {
pinStatus: PinStatus
}

const IPFS_GATEWAY = process.env.REACT_APP_IPFS_GATEWAY || "https://ipfs.io/ipfs/"

const CidRow = ({ pinStatus }: Props) => {
const classes = useStyles()
const { unpin } = useStorage()
Expand Down
19 changes: 17 additions & 2 deletions packages/storage-ui/src/Components/Layouts/AppNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import {
PowerDownIcon,
useLocation,
KeySvg,
CreditCardOutlinedSvg
CreditCardOutlinedSvg,
FileWithImageSvg
} from "@chainsafe/common-components"
import { ROUTE_LINKS } from "../StorageRoutes"
import { Trans } from "@lingui/macro"
Expand Down Expand Up @@ -257,7 +258,7 @@ interface IAppNav {
setNavOpen: (state: boolean) => void
}

type AppNavTab = "buckets" | "cids" | "settings" | "api-keys" | "subscription"
type AppNavTab = "buckets" | "cids" | "nfts" | "settings" | "api-keys" | "subscription"

const AppNav: React.FC<IAppNav> = ({ navOpen, setNavOpen }: IAppNav) => {
const { desktop } = useThemeSwitcher()
Expand All @@ -283,6 +284,7 @@ const AppNav: React.FC<IAppNav> = ({ navOpen, setNavOpen }: IAppNav) => {
case "cids": return "cids"
case "buckets": return "buckets"
case "bucket": return "buckets"
case "nfts": return "nfts"
case "api-keys": return "api-keys"
case "subscription": return "subscription"
case "settings": return "settings"
Expand Down Expand Up @@ -342,6 +344,19 @@ const AppNav: React.FC<IAppNav> = ({ navOpen, setNavOpen }: IAppNav) => {
<Trans>CIDs</Trans>
</Typography>
</Link>
<Link
data-cy="nfts-nav"
onClick={handleOnClick}
className={clsx(classes.navItem, classes.navItemIconStroke, appNavTab === "nfts" && "selected")}
to={ROUTE_LINKS.NFTs}
>
<FileWithImageSvg />
<Typography
variant="h5"
>
<Trans>NFTs</Trans>
</Typography>
</Link>
<Link
data-cy="api-keys-nav"
onClick={handleOnClick}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,7 @@ const FilesList = () => {

const getItemOperations = useCallback(
(contentType: string) => {
if (!itemOperations) return []
const result = Object.keys(itemOperations).reduce(
(acc: FileOperation[], item: string) => {
const matcher = new MimeMatcher(item)
Expand Down
149 changes: 149 additions & 0 deletions packages/storage-ui/src/Components/Modules/NFTsList/NFTItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import React, { useEffect, useState } from "react"
import { makeStyles, createStyles } from "@chainsafe/common-theme"
import {
Typography,
Button
} from "@chainsafe/common-components"
import { CSSTheme } from "../../../Themes/types"
import { Trans } from "@lingui/macro"
import clsx from "clsx"
import axios from "axios"
import { trimChar } from "../../../Utils/pathUtils"
import { IPFS_GATEWAY } from "../../../Utils/Constants"

const useStyles = makeStyles(({ constants, palette }: CSSTheme) =>
createStyles({
root: {
maxWidth: "100%"
},
imageBox: {
width: "100%",
objectFit: "cover",
marginBottom: constants.generalUnit
},
nameTitle: {
marginBottom: constants.generalUnit * 0.5
},
nameContainer: {
borderBottom: `1px solid ${palette.additional["gray"][6]}`,
marginBottom: constants.generalUnit * 0.5
},
cidRow: {
display: "flex",
alignItems: "center",
justifyContent: "space-between",
"&.clickable": {
cursor: "pointer"
}
},
cidStartSection: {
display: "table",
tableLayout: "fixed",
width: "100%",
whiteSpace: "nowrap"
},
cidSubtitle: {
width: "35px",
display: "table-cell",
color: palette.additional["gray"][7]
},
cid: {
display: "table-cell",
overflow: "hidden",
textOverflow: "ellipsis"
},
copyButton: {
marginLeft: constants.generalUnit,
color: palette.primary.main,
padding: `${constants.generalUnit * 0.5}px 0 !important`
},
copiedText: {
marginLeft: constants.generalUnit,
padding: `${constants.generalUnit * 0.5}px 0 !important`
}
})
)

interface NFTData {
name: string
CID: string
image?: string
}

const NFTItem = ({ CID }: {CID: string}) => {
const classes = useStyles()
const [isCopied, setIsCopied] = useState(false)
const [NFTData, setNFTData] = useState<NFTData | undefined>()

useEffect(() => {
axios.get(`${trimChar(IPFS_GATEWAY, "/")}/${CID}`)
.then(({ data }) => { setNFTData({
CID,
name: data.name,
image: data.image?.replace("ipfs://", `${trimChar(IPFS_GATEWAY, "/")}/`)
}) })
.catch(console.error)
}, [CID])

if (!NFTData) return null

return (
<div className={classes.root}>
<img
src={NFTData.image}
alt={NFTData.name}
className={classes.imageBox}
/>
<div className={classes.nameContainer}>
<Typography
variant="h5"
component="p"
className={classes.nameTitle}
>
{NFTData.name}
</Typography>
</div>
<div
className={clsx(classes.cidRow, !isCopied && "clickable")}
onClick={() => {
navigator.clipboard.writeText(CID)
setIsCopied(true)
setInterval(() => setIsCopied(false), 3000)
}}
>
<div className={classes.cidStartSection}>
<Typography
variant="body1"
component="p"
className={classes.cidSubtitle}
>
<Trans>CID</Trans> :&nbsp;
</Typography>
<Typography
variant="body1"
component="p"
className={classes.cid}
>
{CID}
</Typography>
</div>
{isCopied
? <Typography
className={classes.copiedText}
variant="body1"
>
<Trans>Copied!</Trans>
</Typography>
: <Button
className={classes.copyButton}
variant="text"
>
<Trans>Copy</Trans>
</Button>
}
</div>
</div>
)
}

export default NFTItem
Loading

0 comments on commit 3c43b95

Please sign in to comment.