Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NFT Metadata form #2125

Merged
merged 45 commits into from
Jun 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
772add6
WIP
FSM1 Apr 26, 2022
3f823c2
fix reset of form
FSM1 Apr 26, 2022
5ddd522
more recursion for arrays
FSM1 Apr 28, 2022
1d310ad
handle single files elegantly
FSM1 May 5, 2022
433038d
wire up object handling
FSM1 May 6, 2022
b0c5d77
Merge remote-tracking branch 'origin/dev' into feat/nft-upload-form
FSM1 May 6, 2022
f4bda86
clean up recusion code
FSM1 May 9, 2022
3ebcc3b
add basic styling to the page
FSM1 May 10, 2022
c44d2cd
lingui extract
actions-user May 11, 2022
6f0858d
remove unnecessary conditionals
FSM1 May 11, 2022
a12fbe4
Merge branch 'feat/nft-upload-form' of https://github.com/ChainSafe/u…
FSM1 May 11, 2022
769a714
fix lint issues
FSM1 May 11, 2022
92896b4
Merge branch 'dev' into feat/nft-upload-form
FSM1 May 11, 2022
9e249dd
Merge branch 'dev' into feat/nft-upload-form
FSM1 May 12, 2022
a58e486
Merge branch 'dev' into feat/nft-upload-form
FSM1 May 13, 2022
02aef14
Merge branch 'dev' into feat/nft-upload-form
FSM1 May 16, 2022
ca8c1e5
Merge branch 'dev' into feat/nft-upload-form
FSM1 May 17, 2022
c4f2d21
Apply suggestions from code review
FSM1 May 17, 2022
7307ef4
fix missing bracket
FSM1 May 17, 2022
e2f32af
lingui extract
actions-user May 17, 2022
adff9a3
Extract component
FSM1 May 19, 2022
170bd6d
Merge remote-tracking branch 'origin/dev' into feat/nft-upload-form
FSM1 May 29, 2022
19bd12e
fix lint
FSM1 May 29, 2022
37d7977
Changes from review
FSM1 May 29, 2022
f187ebc
update api client
FSM1 May 29, 2022
30fad2a
Merge branch 'dev' into feat/nft-upload-form
FSM1 May 30, 2022
c227ec3
lingui extract
actions-user May 30, 2022
f067962
Merge branch 'dev' into feat/nft-upload-form
FSM1 May 31, 2022
16d553d
Merge branch 'dev' into feat/nft-upload-form
tanmoyAtb May 31, 2022
5b17ed5
fix file removal
Tbaut May 31, 2022
124b42c
Merge branch 'feat/nft-upload-form' of github.com:ChainSafe/ui-monore…
Tbaut May 31, 2022
55ee8de
without cache
Tbaut May 31, 2022
fc44305
git version
Tbaut May 31, 2022
caad52b
Merge branch 'dev' into feat/nft-upload-form
tanmoyAtb May 31, 2022
ea54bf4
pass locally
Tbaut May 31, 2022
817d9aa
Merge branch 'feat/nft-upload-form' of github.com:ChainSafe/ui-monore…
Tbaut May 31, 2022
46ba8f7
remove git version
Tbaut May 31, 2022
9bc7e2c
Merge branch 'dev' into feat/nft-upload-form
tanmoyAtb Jun 1, 2022
0396632
lingui extract
actions-user Jun 1, 2022
f9772e8
Merge branch 'dev' into feat/nft-upload-form
FSM1 Jun 3, 2022
fda11aa
Merge branch 'dev' into feat/nft-upload-form
FSM1 Jun 6, 2022
af922e7
nits and fix tests hopefully (#2172)
Tbaut Jun 8, 2022
43281f0
lingui extract
actions-user Jun 8, 2022
04bbdea
Experimental PR - fixing git binary not found (#2178)
Tbaut Jun 9, 2022
f353ae5
Merge branch 'dev' into feat/nft-upload-form
Tbaut Jun 9, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/test-files-on-demand.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ jobs:
key: ${{ runner.os }}-node_modules-files-build-${{ hashFiles('./yarn.lock') }}
restore-keys: |
${{ runner.os }}-node_modules-build-

- name: Install and show git version
run: apt-get -y install git && git --version
id: git-install
# Install NPM dependencies, cache them correctly
# and run all Cypress tests
- name: Cypress run
uses: cypress-io/github-action@v2
uses: cypress-io/github-action@v4
env:
REACT_APP_BLOCKNATIVE_ID: ${{ secrets.GH_REACT_APP_BLOCKNATIVE_ID }}
REACT_APP_FILES_VERIFIER_NAME: ${{ secrets.GH_REACT_APP_FILES_VERIFIER_NAME }}
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/test-files.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,19 @@ jobs:
key: ${{ runner.os }}-node_modules-files-build-${{ hashFiles('./yarn.lock') }}
restore-keys: |
${{ runner.os }}-node_modules-build-

- name: Install and show git version
run: apt-get -y install git && git --version
id: git-install
# Install NPM dependencies, cache them correctly
# and run all Cypress tests
- name: Cypress run
uses: cypress-io/github-action@v2
uses: cypress-io/github-action@v4
env:
REACT_APP_BLOCKNATIVE_ID: ${{ secrets.GH_REACT_APP_BLOCKNATIVE_ID }}
REACT_APP_FILES_VERIFIER_NAME: ${{ secrets.GH_REACT_APP_FILES_VERIFIER_NAME }}
REACT_APP_FILES_UUID_VERIFIER_NAME: 'chainsafe-uuid-testnet'
REACT_APP_TEST: 'true'
REACT_APP_STRIPE_PK: ${{secrets.GH_REACT_APP_STRIPE_PK}}
DEBUG: '@cypress/github-action'
with:
start: yarn start:files-ui
# wait for 10min for the server to be ready
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/test-storage-on-demand.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ jobs:
key: ${{ runner.os }}-node_modules-build-storage-${{ hashFiles('./yarn.lock') }}
restore-keys: |
${{ runner.os }}-node_modules-build-

- name: Install and show git version
run: apt-get -y install git && git --version
id: git-install
# Install NPM dependencies, cache them correctly
# and run all Cypress tests
- name: Cypress run
uses: cypress-io/github-action@v2
uses: cypress-io/github-action@v4
env:
REACT_APP_BLOCKNATIVE_ID: ${{ secrets.GH_REACT_APP_BLOCKNATIVE_ID }}
REACT_APP_FILES_VERIFIER_NAME: ${{ secrets.GH_REACT_APP_FILES_VERIFIER_NAME }}
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/test-storage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,13 @@ jobs:
key: ${{ runner.os }}-node_modules-build-storage-${{ hashFiles('./yarn.lock') }}
restore-keys: |
${{ runner.os }}-node_modules-build-

- name: Install and show git version
run: apt-get -y install git && git --version
id: git-install
# Install NPM dependencies, cache them correctly
# and run all Cypress tests
- name: Cypress run
uses: cypress-io/github-action@v2
uses: cypress-io/github-action@v4
env:
REACT_APP_BLOCKNATIVE_ID: ${{ secrets.GH_REACT_APP_BLOCKNATIVE_ID }}
REACT_APP_FILES_VERIFIER_NAME: ${{ secrets.GH_REACT_APP_FILES_VERIFIER_NAME }}
Expand Down
105 changes: 71 additions & 34 deletions packages/common-components/src/FileInput/FileInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,41 @@ interface IFileInputProps extends DropzoneOptions {
closeIcon?: string
error?: string
}
onFileNumberChange: (filesNumber: number) => void
onFileNumberChange?: (filesNumber: number) => void
moreFilesLabel: string
testId?: string
}

interface FileItemProps {
index?: number
fullPath: string
removeItem: (index: number) => void
itemClassName?: string
closeIconClassName?: string
}

const FileItem = ({ index = 0, fullPath, removeItem, itemClassName, closeIconClassName }: FileItemProps) => {
const classes = useStyles()
return <li
className={clsx(classes.item, itemClassName)}
key={index}
>
<span className={classes.itemText}>{fullPath}</span>
<Button
testId="remove-from-file-list"
className={clsx(classes.crossIcon, closeIconClassName)}
type="button"
onClick={(e) => {
e.stopPropagation()
removeItem(index)
}}
size="small"
>
<CrossIcon fontSize="small" />
</Button>
</li>
}

const FileInput = ({
className,
variant = "dropzone",
Expand All @@ -139,11 +169,15 @@ const FileInput = ({
const classes = useStyles()
const [previews, setPreviews] = useState<any[]>([])
const [errors, setErrors] = useState<any[]>([])
const [{ value }, meta, helpers] = useField<FileWithPath[]>(name)
const [{ value }, meta, helpers] = useField<FileWithPath[] | FileWithPath | null>(name)
FSM1 marked this conversation as resolved.
Show resolved Hide resolved

useEffect(() => {
onFileNumberChange && onFileNumberChange(value.length)
}, [onFileNumberChange, value.length])
if(Array.isArray(value)){
onFileNumberChange && onFileNumberChange(value.length)
} else {
onFileNumberChange && onFileNumberChange(value ? 1 : 0)
}
}, [onFileNumberChange, value])

const onDrop = useCallback(
async (acceptedFiles: FileWithPath[], fileRejections: FileRejection[]) => {
Expand All @@ -161,8 +195,9 @@ const FileInput = ({
)
)
}

helpers.setValue([...value, ...filtered])
Array.isArray(value)
? helpers.setValue([...value, ...filtered])
: helpers.setValue(filtered[0])

if (fileRejections.length > 0) {
const fileDropRejectionErrors = fileRejections.map((fr) =>
Expand Down Expand Up @@ -191,11 +226,15 @@ const FileInput = ({
...dropZoneProps
})

const removeItem = (i: number) => {
const items = value
items.splice(i, 1)
const removeItem = useCallback((i: number) => {
let items = value

Array.isArray(items)
? items.splice(i, 1)
: items = null

helpers.setValue(items)
}
}, [helpers, value])

return (
<div
Expand All @@ -205,7 +244,7 @@ const FileInput = ({
>
<input {...getInputProps()} />
{variant === "dropzone" ? (
value?.length === 0 ? (
value === null || (Array.isArray(value) && value.length === 0) ? (
<div className={clsx(classes.pending, classNames?.pending)}>
{pending || (
<>
Expand All @@ -224,35 +263,33 @@ const FileInput = ({
>
<ScrollbarWrapper className={clsx("scrollbar")}>
<ul>
{value.map((file: any, i: number) => (
<li
className={clsx(classes.item, classNames?.item)}
key={i}
>
<span className={classes.itemText}>{file.path}</span>
<Button
testId="remove-from-file-list"
className={clsx(classes.crossIcon, classNames?.closeIcon)}
type="button"
onClick={(e) => {
e.stopPropagation()
removeItem(i)
}}
size="small"
>
<CrossIcon fontSize="small" />
</Button>
</li>
))}
{Array.isArray(value)
? value.map((file, i) => (
<FileItem
key={i}
index={i}
fullPath={file.path || ""}
removeItem={removeItem}
closeIconClassName={classNames?.closeIcon}
itemClassName={classNames?.item}
/>
))
: <FileItem
fullPath={value.path || ""}
removeItem={removeItem}
closeIconClassName={classNames?.closeIcon}
itemClassName={classNames?.item}
/>
}
</ul>
</ScrollbarWrapper>
</div>
)
) : (
<>
{value?.length === 0
{value === null || (Array.isArray(value) && value?.length === 0)
? "No files selected"
: `${value?.length} file(s) selected`}
: `${Array.isArray(value) ? value?.length : 1} file(s) selected`}
<Button
onClick={open}
size="small"
Expand All @@ -261,7 +298,7 @@ const FileInput = ({
</Button>
</>
)}
{value?.length > 0 && (
{Array.isArray(value) && value.length > 0 && (
<div
className={clsx(classes.addFiles, classNames?.addFiles)}
>
Expand Down
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 UploadRoundSvg } from "../svgs/upload-round.svg"

export { UploadRoundSvg }

export default createSvgIcon(<UploadRoundSvg />)
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 @@ -84,6 +84,7 @@ export { default as SubscriptionPlanIcon, SubscriptionSvg } from "./icons/Subscr
export { default as TableIcon, TableSvg } from "./icons/Table.icon"
export { default as UpdateIcon, UpdateSvg } from "./icons/Update.icon"
export { default as UploadIcon, UploadSvg } from "./icons/Upload.icon"
export { default as UploadRoundIcon, UploadRoundSvg } from "./icons/UploadRound.icon"
export { default as UnionpayCardIcon, UnionpayCardSvg } from "./icons/UnionpayCard.icon"
export { default as UsdcIcon, UsdcSvg } from "./icons/Usdc.icon"
export { default as UserIcon, UserSvg } from "./icons/User.icon"
Expand Down
12 changes: 12 additions & 0 deletions packages/common-components/src/Icons/svgs/upload-round.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/files-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.35",
"@chainsafe/files-api-client": "1.18.37",
"@chainsafe/web3-context": "1.3.1",
"@emeraldpay/hashicon-react": "^0.5.1",
"@lingui/core": "^3.7.2",
Expand Down
1 change: 1 addition & 0 deletions packages/files-ui/src/Components/FilesRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const ROUTE_LINKS = {
// bucketId should not have a / at the end
// rawCurrentPath can be empty, or /
const adjustedRawCurrentPath = !rawCurrentPath ? "/" : rawCurrentPath

return `/shared/${bucketId}${adjustedRawCurrentPath}`
},
DiscordInvite: "https://discord.gg/zAEY37fNb2",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { Button, FileInput } from "@chainsafe/common-components"
import { useFiles } from "../../../Contexts/FilesContext"
import { createStyles, makeStyles } from "@chainsafe/common-theme"
import React, { useCallback, useMemo, useState } from "react"
import React, { useCallback, useState } from "react"
import { Form, useFormik, FormikProvider } from "formik"
import { array, object } from "yup"
import CustomModal from "../../Elements/CustomModal"
import { Trans, t } from "@lingui/macro"
import clsx from "clsx"
Expand Down Expand Up @@ -77,31 +76,21 @@ interface IUploadFileModuleProps {
close: () => void
}

interface UploadedFiles {
files: Array<File & {path: string}>
}

const UploadFileModule = ({ modalOpen, close }: IUploadFileModuleProps) => {
const classes = useStyles()
const [isDoneDisabled, setIsDoneDisabled] = useState(true)
const { currentPath, refreshContents, bucket } = useFileBrowser()
const { storageSummary, uploadFiles } = useFiles()

const UploadSchema = useMemo(() => object().shape({
files: array().required(t`Please select a file to upload`)
.test("Upload Size",
t`Upload size exceeds plan capacity`,
(files) => {
// no validation if the user isn't the owner
if(bucket?.permission !== "owner") return true

const availableStorage = storageSummary?.available_storage || 0
const uploadSize = files?.reduce((total: number, file: File) => total += file.size, 0) || 0
return uploadSize < availableStorage
})
}), [bucket, storageSummary])
const { currentPath, refreshContents, bucket } = useFileBrowser()
const { uploadFiles, storageSummary } = useFiles()

const onFileNumberChange = useCallback((filesNumber: number) => {
setIsDoneDisabled(filesNumber === 0)
}, [])

const onSubmit = useCallback(async (values: {files: Array<File & {path: string}>}, helpers) => {
const onSubmit = useCallback(async (values: UploadedFiles, helpers) => {
if (!bucket) return

helpers.setSubmitting(true)
Expand All @@ -116,9 +105,23 @@ const UploadFileModule = ({ modalOpen, close }: IUploadFileModuleProps) => {
helpers.setSubmitting(false)
}, [bucket, close, refreshContents, uploadFiles, currentPath])

const onFormikValidate = useCallback(({ files }: UploadedFiles) => {

if (files.length === 0) {
return { files: t`Please select a file to upload` }
}

const availableStorage = storageSummary?.available_storage || 0
const uploadSize = files?.reduce((total: number, file: File) => total += file.size, 0) || 0

if(uploadSize > availableStorage)
return { files: t`Upload size exceeds plan capacity` }
},
[storageSummary])

const formik = useFormik({
initialValues: { files: [] },
validationSchema: UploadSchema,
validate: onFormikValidate,
onSubmit
})

Expand Down
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.35",
"@chainsafe/files-api-client": "1.18.37",
"@chainsafe/web3-context": "1.3.0",
"@emeraldpay/hashicon-react": "0.5.2",
"@lingui/core": "^3.7.2",
Expand Down
Loading