react-dropzone#useDropzone JavaScript Examples

The following examples show how to use react-dropzone#useDropzone. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: DragNDrop.jsx    From ResoBin with MIT License 6 votes vote down vote up
DragNDrop = ({ onDrop, children }) => {
  const { getRootProps, getInputProps, isDragActive, isDragReject } =
    useDropzone({ onDrop, ...dropzoneProps })

  let message = null
  if (!isDragActive)
    message = (
      <h2>
        Drag & drop to upload
        <br />
        or click to browse files
      </h2>
    )
  else if (isDragReject) message = <h2>Invalid upload format</h2>
  else message = <h2>Drop files here</h2>

  return (
    <UploadBox {...getRootProps()} error={isDragReject}>
      <input {...getInputProps()} />
      <CloudUpload size="60" />
      {message}
      <span>
        Accepted formats: .pdf, .doc, .ppt
        <br />
        Maximum upload file size: 30MB
      </span>
    </UploadBox>
  )
}
Example #2
Source File: index.js    From NFT-Marketplace with MIT License 6 votes vote down vote up
DropZone = ({ onFileUploaded })  => {
  const classes = useStyles();
  const [selectedFileUrl, setSelectedFileUrl] = useState('');

  const onDrop = useCallback(acceptedFiles => {
    const file = acceptedFiles[0];
     
    const fileUrl = URL.createObjectURL(file);
    
    setSelectedFileUrl(fileUrl);
    onFileUploaded(file);
  }, [onFileUploaded]);

  const { getRootProps, getInputProps } = useDropzone({
    onDrop, 
    accept: 'image/*'
  });

  return (
    <div className={classes.dropzone} {...getRootProps()}>
      <input {...getInputProps()} accept='image/*' />

      { selectedFileUrl 
        ? <img src={selectedFileUrl} alt="Point thumbnail"/>
        : (
          <p>
            <CloudUploadIcon />
            NFT image
          </p>
        )
      }
    </div>
  );
}
Example #3
Source File: image-upload-previewContainer.js    From horondi_admin with MIT License 6 votes vote down vote up
ImageUploadPreviewContainer = ({ handler, src, id }) => {
  const style = useStyles();
  const { getRootProps, getInputProps } = useDropzone({
    accept: 'image/*',
    onDrop: (acceptedFiles) => {
      handler(
        acceptedFiles.map((file) =>
          Object.assign(file, {
            preview: URL.createObjectURL(file)
          })
        )
      );
    }
  });

  return (
    <section className='container'>
      <div {...getRootProps({ className: 'dropzone' })}>
        <input
          style={{ height: '300px', width: '200px' }}
          {...getInputProps()}
        />
        <label
          className={src ? style.labelWithoutBack : style.labelWithBack}
          htmlFor={id}
          data-cy={utils.dataCy.preview}
        >
          {src && (
            <img className={style.image} src={src} alt={utils.alt.preview} />
          )}
        </label>
      </div>
    </section>
  );
}
Example #4
Source File: image-upload-container.js    From horondi_admin with MIT License 6 votes vote down vote up
ImageUploadContainer = ({ handler, src, id }) => {
  const style = useStyles();
  const { getRootProps, getInputProps } = useDropzone({
    accept: 'image/*',
    onDrop: (acceptedFiles) => {
      handler(
        acceptedFiles.map((file) =>
          Object.assign(file, {
            preview: URL.createObjectURL(file)
          })
        )
      );
    }
  });

  return (
    <section className='container'>
      <div {...getRootProps({ className: 'dropzone' })}>
        <input
          style={{ height: '300px', width: '200px' }}
          {...getInputProps()}
        />
        <label
          className={src ? style.labelWithoutBack : style.labelWithBack}
          htmlFor={id}
          data-cy={utils.dataCy.preview}
        >
          {src && (
            <img className={style.image} src={src} alt={utils.alt.preview} />
          )}
        </label>
      </div>
    </section>
  );
}
Example #5
Source File: BoxDropzone.js    From eosio-components with MIT License 6 votes vote down vote up
Dropzone = ({ onSubmit }) => {
  const classes = useStyles()
  const { acceptedFiles, getRootProps, getInputProps } = useDropzone({
    maxFiles: 1,
    accept: 'application/json'
  })

  useEffect(() => {
    if (!!!acceptedFiles.length) return

    const reader = new FileReader()

    reader.onload = (e) => {
      onSubmit(JSON.parse(e.target.result))
    }
    reader.readAsText(acceptedFiles[0])
  }, [acceptedFiles, onSubmit])

  return (
    <section>
      <div {...getRootProps({ className: classes.dropzoneArea })}>
        <input {...getInputProps()} />
        <p>Drop your BP json file here</p>
      </div>
    </section>
  )
}
Example #6
Source File: Dropzone.js    From react-saas-template with MIT License 6 votes vote down vote up
function Dropzone(props) {
  const { onDrop, accept, fullHeight, children, classes, style, theme } = props;
  const {
    getRootProps,
    getInputProps,
    isDragAccept,
    isDragReject
  } = useDropzone({
    accept: accept,
    onDrop: onDrop
  });
  return (
    <Box {...getRootProps()} height="100%">
      <input {...getInputProps()} />
      <ColoredButton
        fullWidth
        className={classNames(
          fullHeight ? classes.fullHeight : null,
          classes.button
        )}
        variant="outlined"
        color={getColor(isDragAccept, isDragReject, theme)}
        style={style}
      >
        {children}
      </ColoredButton>
    </Box>
  );
}
Example #7
Source File: UploadDragAndDrop.js    From EDAViewer with MIT License 6 votes vote down vote up
export default function UploadDragAndDrop(props) {
	const classes = useStyles();
	const { onFilesAdded } = props;
	const onDrop = React.useCallback(onFilesAdded, []);
	const { getRootProps, getInputProps } = useDropzone({
		onDrop,
		maxSize: 100 * 1024 * 1024, //100MBs
	});
	return (
		<div className={classes.dropzone} {...getRootProps()} style={{}}>
			<input {...getInputProps()} />
			<CloudUpload
				className={classes.dropzoneIcon}
				style={{
					fontSize: "8rem",
				}}
			/>
			<div className={classes.dropzoneText}>
				Drag and drop design LEF/DEF files or <br />{" "}
				<b>click to choose from your computer</b>
			</div>
		</div>
	);
}
Example #8
Source File: Dropzone.js    From verapdf-webapp-gui with GNU General Public License v3.0 6 votes vote down vote up
function Dropzone(props) {
    const { files, onFileDrop } = props;

    // NOTE: will be adjusted with multiple files in future
    const onDrop = useCallback(
        acceptedFiles => {
            if (!acceptedFiles.length) return;

            onFileDrop(acceptedFiles[0]);
        },
        [onFileDrop]
    );

    const { getRootProps, getInputProps, isDragActive } = useDropzone({
        onDrop,
        ...DROPZONE_OPTIONS,
    });

    return (
        <section className="dropzone">
            <div
                {...getRootProps({
                    className: classNames('dropzone__container', {
                        _focused: isDragActive,
                        _filled: files.length,
                    }),
                })}
            >
                <input {...getInputProps()} />
                <DropzoneText files={files} />
            </div>
        </section>
    );
}
Example #9
Source File: DropzoneWrapper.js    From verapdf-webapp-gui with GNU General Public License v3.0 6 votes vote down vote up
function DropzoneWrapper(props) {
    const { onFileDrop, children } = props;

    // NOTE: will be adjusted with multiple files in future
    const onDrop = useCallback(
        acceptedFiles => {
            if (!acceptedFiles.length) return;

            onFileDrop(acceptedFiles);
        },
        [onFileDrop]
    );

    const { getRootProps, getInputProps, isDragActive } = useDropzone({
        onDrop,
        ...DROPZONE_OPTIONS,
        noClick: true,
    });

    return (
        <section
            {...getRootProps({
                className: 'dropzone-wrapper',
            })}
        >
            {children}
            <input {...getInputProps()} />
            <div
                className={classNames('dropzone-wrapper__fade', {
                    _visible: isDragActive,
                })}
            >
                {DROPZONE_TEXT}
            </div>
        </section>
    );
}
Example #10
Source File: DragNDrop.jsx    From ResoBin with MIT License 6 votes vote down vote up
DragNDropSub = ({ onDrop, children }) => {
  const { getRootProps, getInputProps, isDragActive, isDragReject } =
    useDropzone({ maxFiles: 1, onDrop, ...dropzoneProps })

  let message = children
  if (isDragActive) {
    if (isDragReject) message = <h2>File too large or invalid upload format</h2>
    else message = <h2>Drop files here</h2>
  }

  return (
    <UploadBoxSub {...getRootProps()} error={isDragReject}>
      <input {...getInputProps()} />

      {message}
    </UploadBoxSub>
  )
}
Example #11
Source File: GraphImporter.js    From aws-perspective with Apache License 2.0 5 votes vote down vote up
export function GraphImporter({setImportedGraph}) {

  const onDrop = useCallback(acceptedFiles => {
    acceptedFiles.forEach(file => {
      const reader = new FileReader();

      reader.onabort = () => console.error('file reading was aborted');
      reader.onerror = () => console.error('file reading has failed');
      reader.onload = () => {
        const binaryStr = reader.result;
        setImportedGraph({name: file.name, graph: JSON.parse(binaryStr)})
      };
      reader.readAsText(file);
    });
  }, [setImportedGraph]);

  const { getRootProps, getInputProps } = useDropzone({ onDrop });
  const { ref, ...rootProps } = getRootProps();

  const useStyles = makeStyles(theme => ({
    root: {
      width: '100%',
      textAlign: 'center',
      border: '2px dashed #fafafa',
      marginBottom: '2%',
      '&:focus': {
        outline: 'none'
    },
    },
    text: {
      fontFamily: 'Amazon Ember, Helvetica, Arial, sans-serif',
      fontSize: '1rem',
      padding: '5%',
      color: '#AAB7B8'
    }
  }));

  const classes = useStyles();

  return (
    <div>
      <RootRef rootRef={ref}>
        <Paper className={classes.root} {...rootProps}>
          <input {...getInputProps()} />
          <Typography className={classes.text}>
            Drop JSON graph files here, or click to select files
          </Typography>
        </Paper>
      </RootRef>
      
    </div>
  );
}
Example #12
Source File: Dropzone.js    From web-client with Apache License 2.0 5 votes vote down vote up
AttachmentsDropzone = ({ parentType, parentId, onUploadFinished = null, attachmentId = null }) => {
    const onFileDrop = (newFiles) => {
        setAcceptedFiles(newFiles);
    };

    const {
        getRootProps, getInputProps,
        isDragActive, isDragAccept, isDragReject
    } = useDropzone({ onDrop: onFileDrop });

    const [acceptedFiles, setAcceptedFiles] = useState([]);

    const onUploadButtonClick = ev => {
        const formData = new FormData();
        formData.append('parentType', parentType);
        formData.append('parentId', parentId);
        acceptedFiles.forEach(file => {
            formData.append('attachment[]', file);
        })

        let uri = '/attachments';
        if (attachmentId) {
            formData.append('attachmentId', attachmentId);
            uri = `/attachments/${attachmentId}`;
        }

        secureApiFetch(uri, {
            method: 'POST',
            body: formData
        })
            .then(() => {
                setAcceptedFiles([]);
                if (onUploadFinished) onUploadFinished();
            })
            .catch(err => console.error(err));
    }

    const style = useMemo(() => ({
        ...baseStyle,
        ...(isDragActive ? activeStyle : {}),
        ...(isDragAccept ? acceptStyle : {}),
        ...(isDragReject ? rejectStyle : {})
    }), [
        isDragActive,
        isDragAccept,
        isDragReject
    ]);

    return (
        <div className="container">
            <div {...getRootProps({ style })}>
                <input {...getInputProps()} />
                <p>Drag and drop some files here, or click to select files</p>
            </div>
            <aside>
                {acceptedFiles.length === 0 && <div>(upload list empty)</div>}
                {acceptedFiles.length > 0 && <List spacing={3}>{acceptedFiles.map(file => (
                    <ListItem key={file.path}>
                        <FontAwesomeIcon color='var(--primary-color)' icon={faUpload} /> {file.path} - {file.size} bytes
                    </ListItem>
                ))}</List>}
            </aside>
            <hr />
            <PrimaryButton onClick={onUploadButtonClick} disabled={acceptedFiles.length === 0}>Upload file(s)</PrimaryButton>
        </div>
    );
}
Example #13
Source File: LibraryBlockAssets.jsx    From frontend-app-library-authoring with GNU Affero General Public License v3.0 5 votes vote down vote up
LibraryBlockAssets = (props) => {
  const onDrop = useCallback(props.onDropFiles, []);
  const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });
  if (props.assets.value === null) {
    return <LoadingPage loadingMessage="Loading..." />;
  }
  const assets = props.assets.value || [];

  return (
    <>
      <h1 className="float-right"><span className="sr-only">Static Assets</span></h1>
      <p>There are {assets.length} static asset files for this XBlock:</p>
      <ul>
        {
          assets.map(assetFile => (
            <li key={assetFile.path}>
              <a href={assetFile.url}>/static/{assetFile.path}</a> {' '}
              ({Math.round(assetFile.size / 1024.0)} KB)
              (<Button variant="link" onClick={() => props.onDeleteFile(assetFile.path)} className="p-0" title="Delete this file">x</Button>)
            </li>
          ))
        }
      </ul>
      <div
        {...getRootProps()}
        style={{
          lineHeight: '150px',
          border: '3px solid #ddd',
          textAlign: 'center',
          backgroundColor: isDragActive ? '#90ee90' : '#fbfbfb',
          marginBottom: '1em',
        }}
      >
        <input {...getInputProps()} />
        {
          isDragActive
            ? <span> Drop the files here ...</span>
            : <span> Drag and drop some files here to upload them, or click here to select files.</span>
        }
      </div>
      <p>Tip: set the filenames carefully <em>before</em> uploading, as there is no rename tool.</p>
      <p>
        Within OLX or when using the &quot;Edit&quot; tab, always reference assets using /static/filename, e.g.
        <code>&lt;img src=&quot;/static/jamie.jpg&quot; alt=&quot;Picture of Jamie&quot;/&gt;</code>
      </p>
    </>
  );
}
Example #14
Source File: index.js    From dashboard-reactjs with MIT License 5 votes vote down vote up
Dropzone = ({file, onFileUploaded }) => {

    const [selectedFiles, setSelectedFiles] = useState('');
    const onDrop = useCallback(acceptedFiles => {
        const file = acceptedFiles[0];

        const fileUrl = URL.createObjectURL(file);

        setSelectedFiles(fileUrl);
        onFileUploaded(file);

    }, [onFileUploaded])

    const {getRootProps, getInputProps, isDragActive} = useDropzone({
        onDrop,
        accept: 'image/*'
    })

    return (
        <DropBackground  {...getRootProps()}>
            <input {...getInputProps()} accept="image/*" />
        {/* {
            isDragActive ?
            <p>Drop the files here ...</p> :
            <p>Drag 'n' drop some files here, or click to select files</p>
        } */}
            { selectedFiles || file
                ?
                <div className="image">
                    <img src={!selectedFiles ? `${process.env.REACT_APP_API_URL}/uploads/business/${file}` : selectedFiles
                    } alt="Point File" />
                    <span><FontAwesomeIcon icon={faPencilAlt} /> Alterar</span>
                </div>
                :
                <div className="image-default">
                    <img src={Profile} alt="Point File" />
                    <span><FontAwesomeIcon icon={faUpload} /> Carregar</span>
                </div>
            }

        </DropBackground>
    )
}
Example #15
Source File: index.js    From conectadev with MIT License 5 votes vote down vote up
function PostEditor() {
  const classes = useStyles();
  const ctx = usePost();

  const { image, setImage, tags, setTags, markdownText, setMarkdownText } = ctx;

  const onDrop = useCallback(
    (acceptedFiles) => {
      const file = acceptedFiles[0];
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onloadend = () => {
        const base64data = reader.result;
        setImage(base64data);
      };
    },
    [setImage],
  );

  const { getRootProps, getInputProps } = useDropzone({
    onDrop,
    multiple: false,
    accept: 'image/*',
  });

  return (
    <>
      <Box {...getRootProps()} mb={1}>
        <input {...getInputProps()} />
        <Button>Carregar imagem</Button>
      </Box>

      {image && (
        <Box mb={2}>
          <img className={classes.image} src={image} alt="background" />
        </Box>
      )}
      <Box mb={2}>
        <Title />
      </Box>
      <Box mb={2}>
        <Autocomplete
          multiple
          id="tags-standard"
          options={arrayTags}
          getOptionLabel={(option) => option.title}
          value={tags}
          onChange={setTags}
          renderInput={(params) => (
            <TextField {...params} variant="standard" placeholder="tags" />
          )}
        />
      </Box>
      <textarea
        onChange={setMarkdownText}
        value={markdownText}
        className={classes.textArea}
      >
        editor markdown
      </textarea>
    </>
  );
}
Example #16
Source File: VidDropzone.js    From youtube-clone with MIT License 5 votes vote down vote up
function StyledDropzone() {
  const dispatch = useDispatch();

  const classes = useStyles();
  const onDrop = ([videoFile]) => {
    if (videoFile) {
      dispatch(uploadVideo(videoFile));
    }
  };
  const {
    getRootProps,
    getInputProps,
    open,
    isDragAccept,
    isDragReject,
  } = useDropzone({
    noClick: true,
    noKeyboard: true,
    accept: "video/mp4",
    maxSize: 25 * 1024 * 1024,
    onDrop,
  });

  return (
    <div className={classes.root}>
      <div
        {...getRootProps({
          className: clsx(classes.content, {
            [classes.acceptStyle]: isDragAccept,
            [classes.rejectStyle]: isDragReject,
          }),
        })}
      >
        <input {...getInputProps()} />

        <Fab className={clsx(classes.button, classes.uploadBtn)} onClick={open}>
          <PublishIcon className={classes.uploadIcon} />
        </Fab>
        <Typography variant="body1">
          Drag and drop a <strong>.mp4 </strong> file to upload
        </Typography>
        <Typography variant="body2" gutterBottom>
          Your videos will be private until you publish them.
        </Typography>
        <Typography variant="caption" gutterBottom>
          * Video Uploads are limited to 25 MB.
        </Typography>

        <Button
          className={classes.button}
          variant="contained"
          color="primary"
          onClick={open}
        >
          Select File
        </Button>
      </div>
    </div>
  );
}
Example #17
Source File: LoadData.jsx    From airboardgame with MIT License 5 votes vote down vote up
LoadGame = ({ onLoad = () => {} }) => {
  const { t } = useTranslation();

  const onDrop = React.useCallback(
    (acceptedFiles) => {
      acceptedFiles.forEach((file) => {
        const reader = new FileReader();

        reader.onabort = () => console.log("file reading was aborted");
        reader.onerror = () => console.log("file reading has failed");
        reader.onload = () => {
          try {
            const result = JSON.parse(reader.result);
            onLoad(result);
          } catch (e) {
            console.log("File parsing failed", e);
          }
        };
        reader.readAsText(file);
      });
    },
    [onLoad]
  );

  const { getRootProps, getInputProps } = useDropzone({ onDrop });

  return (
    <div
      {...getRootProps()}
      style={{
        border: "1px dashed white",
        padding: "0.5em",
        cursor: "pointer",
        fontSize: "1.5em",
      }}
    >
      <input {...getInputProps()} />
      <p style={{ textAlign: "center", margin: "1em" }}>
        {t("Dragn drop file here")}
      </p>
    </div>
  );
}
Example #18
Source File: ImageDropNPaste.jsx    From airboardgame with MIT License 5 votes vote down vote up
ImageDropNPaste = ({ children }) => {
  const { t } = useTranslation();
  const [uploading, setUploading] = React.useState(false);
  const { pushItem } = useItemActions();

  const { addMedia, libraries } = useMediaLibrary();

  const addImageItem = React.useCallback(
    async (media) => {
      pushItem({
        type: "image",
        id: uid(),
        content: media,
      });
    },
    [pushItem]
  );

  const onDrop = React.useCallback(
    async (acceptedFiles) => {
      setUploading(true);
      await Promise.all(
        acceptedFiles.map(async (file) => {
          const media = await addMedia(libraries[0], file);
          await addImageItem(media);
        })
      );
      setUploading(false);
    },
    [addImageItem, addMedia, libraries]
  );

  const { getRootProps } = useDropzone({ onDrop });

  const onPaste = React.useCallback(
    async (e) => {
      const { items } = e.clipboardData;
      setUploading(true);
      // eslint-disable-next-line no-plusplus
      for (let i = 0; i < items.length; i++) {
        const item = items[i];
        if (item.type.indexOf("image") !== -1) {
          const file = item.getAsFile();
          // eslint-disable-next-line no-await-in-loop
          const location = await addMedia(libraries[0], file);
          // eslint-disable-next-line no-await-in-loop
          await addImageItem(location);
        }
      }
      setUploading(false);
    },
    [addImageItem, addMedia, libraries]
  );

  React.useEffect(() => {
    window.addEventListener("paste", onPaste, false);

    return () => {
      window.removeEventListener("paste", onPaste);
    };
  }, [onPaste]);

  return (
    <div {...getRootProps()}>
      {children}
      {uploading && <Waiter message={t("Uploading image(s)...")} />}
    </div>
  );
}
Example #19
Source File: index.js    From website with MIT License 5 votes vote down vote up
ChatImageUpload = ({ postType, postId, setAlertMessage, onCloseAlert }) => {
  const router = useRouter();

  const { state, dispatch } = useContext(ChatContext);
  const isNewChat = getIsNewChat(state);
  const selectedChatId = getSelectedChatId(state);

  const sendFirstImageMessages = async (images) => {
    const method = postType === donations ? 'sendInitialImageMessagesForDonation' : 'sendInitialImageMessagesForWish';
    const [rawChat, rawFirstMessage] = await api.chats[method](postId, images);
    const chatId = rawChat.data().chatId;
    dispatch(setIsNewChat(false));
    dispatch(setSelectedChatId(chatId));
    router.push(`/chat`, `/chat?chatId=${chatId}`, { shallow: true });
  };

  const handleImageUploadError = (err) => {
    if (err instanceof ChatError) {
      setAlertMessage(err.message);
      setTimeout(() => {
        onCloseAlert(); // hide alert message after 5 seconds
      }, 5000);
    }
  };

  const handleImageExceedSizeLimitError = (message) => {
    setAlertMessage(message);
    setTimeout(() => {
      onCloseAlert(); // hide alert message after 5 seconds
    }, 5000);
  };

  const onUpload = useCallback((uploadedFiles, isNewChat, selectedChatId) => {
    // check if file is more than 25 mb
    if (uploadedFiles.some((file) => file.size > MAXIMUM_FILE_SIZE_LIMIT)) {
      handleImageExceedSizeLimitError('Unable to upload files that are more than 25mb');
      uploadedFiles = uploadedFiles.filter((file) => file.size <= MAXIMUM_FILE_SIZE_LIMIT);
    }

    if (uploadedFiles.length === 0) {
      return;
    }

    if (isNewChat) {
      sendFirstImageMessages(uploadedFiles)
        .then(() => {
          uploadedFiles = [];
        })
        .catch((err) => handleImageUploadError(err));
    } else {
      api.chats.sendImageMessages(selectedChatId, uploadedFiles).catch((err) => handleImageUploadError(err));
    }
  }, []);

  const { getRootProps, getInputProps } = useDropzone({
    onDrop: (files) => onUpload(files, isNewChat, selectedChatId),
    accept: '.jpeg, .png, .jpg',
  });
  return (
    <div {...getRootProps()}>
      <input {...getInputProps()} />
      <Gallery size="normal" />
    </div>
  );
}
Example #20
Source File: ImageSection.js    From nextjs-ic-starter with MIT License 5 votes vote down vote up
ImageSection = () => {
  const [imageId, setImageId] = useState(null)
  const [loading, setLoading] = useState("")
  const [file, setFile] = useState(null)

  const imgSrc = useImageObject(imageId)

  const { getRootProps, getInputProps } = useDropzone({
    maxFiles: 1,
    accept: "image/*",
    onDrop: async acceptedFiles => {
      if (acceptedFiles.length > 0) {
        try {
          const firstFile = acceptedFiles[0]
          const newFile = await resizeImage(firstFile, ImageMaxWidth)
          setFile(newFile)
        } catch (error) {
          console.error(error)
        }
      }
    }
  })

  async function submitImage() {
    if (file == null) {
      return
    }

    setLoading("Submitting...")
    setImageId(null)

    const fileArray = await fileToCanisterBinaryStoreFormat(file)
    const imageActor = makeImageActor()
    const newImageId = await imageActor.create(fileArray)
    setImageId(newImageId)

    setLoading("")
  }

  return (
    <div>
      <section>
        <h2>Image</h2>
        <label htmlFor="name">Upload Image: &nbsp;</label>
        <button {...getRootProps({ className: "dropzone" })}>
          Pick a Image
          <input {...getInputProps()} />
        </button>
        <button onClick={submitImage}>Submit</button>
      </section>
      <section>
        <div>{loading}</div>
        <label>Image loaded from canister: &nbsp;</label>
        {imgSrc && <img src={imgSrc} alt="canister-image" />}
      </section>
    </div>
  )
}
Example #21
Source File: DropZone.js    From sailplane-web with GNU General Public License v3.0 5 votes vote down vote up
export function DropZone({children, sharedFs, currentDirectory}, ref) {
  const styles = {
    container: {
      cursor: 'pointer',
      textAlign: 'center',
      color: primary5,
      fontSize: 16,
      fontWeight: 200,
      fontFamily: 'Open Sans',
      outline: 0,
      userSelect: 'none',
      height: '100%',
    },
  };

  const dispatch = useDispatch();

  const onDrop = useCallback(
    async (acceptedFiles) => {
      dispatch(setStatus({message: 'Uploading'}));
      const listSource = fileListSource(acceptedFiles, {preserveMtime: true});
      const totalSize = acceptedFiles.reduce((prev, cur) => cur.size + prev, 0);

      try {
        await sharedFs.current.upload(currentDirectory, listSource, {
          progress: (length) => {
            dispatch(
              setStatus({
                message: `[${getPercent(length, totalSize)}%] Uploading files`,
              }),
            );
          },
        });
        dispatch(setStatus({}));
      } catch (e) {
        // will add sharedFs.canWrite method later for richer ux
        dispatch(
          setStatus({
            message: `Missing write permissions.`,
            isError: true,
          }),
        );
        delay(4000).then(() => dispatch(setStatus({})));
      }
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [currentDirectory],
  );

  const {getRootProps, getInputProps, isDragActive, open} = useDropzone({
    onDrop,
    noClick: true,
  });

  useImperativeHandle(ref, () => ({
    openUpload: () => {
      open();
    },
  }));

  return (
    <div {...getRootProps()} style={styles.container} id={'dropZone'}>
      <input {...getInputProps()} id={'fileUpload'} />
      {isDragActive ? <FileDragBlock isActive={true} /> : <div>{children}</div>}
    </div>
  );
}
Example #22
Source File: images-upload-container.js    From horondi_admin with MIT License 5 votes vote down vote up
ImagesUploadContainer = ({ handler, multiple, maxFiles, length }) => {
  const style = useStyles();
  const dispatch = useDispatch();
  const availableCount = length ? maxFiles - length : maxFiles;

  const validate = (file) => {
    if (file.size > 15000000)
      return {
        code: 'size-too-large',
        message: 'Максимальний розмір фото 15Mb'
      };
    if (length >= maxFiles)
      return {
        code: 'max files',
        message: `Завантажте до ${maxFiles} фотографій`
      };
    return null;
  };

  const options = {
    accept: 'image/*',
    multiple,
    maxFiles: availableCount,
    noClick: true,
    noKeyboard: true,
    validator: validate,
    onDrop: (acceptedFiles, fileRejections) => {
      const files = acceptedFiles.map((file) =>
        Object.assign(file, {
          preview: URL.createObjectURL(file)
        })
      );
      handler(files);

      if (fileRejections.length) {
        const { message } = fileRejections[0].errors[0];
        dispatch(showErrorSnackbar(message));
      }
    }
  };

  const { getRootProps, getInputProps, open } = useDropzone(options);

  return (
    <Grid container>
      <div {...getRootProps({ className: style.dropzone })}>
        <input {...getInputProps()} />
        <span>
          <CloudUploadRounded />
        </span>
        <p>Перетягніть фото сюди або</p>
        <button type='button' className={style.dropButton} onClick={open}>
          Обрати
        </button>
      </div>
      <p className={style.description}>
        Завантажте до {maxFiles} зображень. Максимальний розмір фото - 15MB.
        Дозволені формати: jpeg, jpg, png.
      </p>
    </Grid>
  );
}
Example #23
Source File: dropSection.js    From open-jobboard with Apache License 2.0 4 votes vote down vote up
DropSection = (props) => {
  const [isShownRight, setIsShownRight] = useState(true)
  const [isShownLeft, setIsShownLeft] = useState(true)
  const [modalIsOpen, setModalIsOpen] = useState(false)
  const [profileFile, setProfileFile] = useState("");
  const [device, setDevice] = useState("mobile")

  useEffect(() => {
    if(props.profile?.s) {
      setModalIsOpen(false)
      swal({
        title: "Title success",
        text: "Message success!",
        icon: "success",
      });
      // Swal.fire({
      //   title: 'Vérifie ta boite mail.',
      //   html: 'Tu viens de recevoir un message de la part d\'ENGIE.',
      //   type: 'success',
      //   confirmButtonColor: '#00aaff',
      // });
    }
    if(props.profile.f) {
      swal(
        {
         type: 'error',
         title: 'Oops...',
         text: 'Message error',
        }
       )
    }
  }, [props.profile])
  const onDrop = useCallback((acceptedFiles) => {
    acceptedFiles.forEach((file) => {
      setModalIsOpen(true)
      const reader = new FileReader()

      reader.onabort = () => console.log('file reading was aborted')
      reader.onerror = () => console.log('file reading has failed')
      reader.onload = () => {
      // Do whatever you want with the file contents
        const binaryStr = reader.result
        console.log(binaryStr)
      }
      reader.readAsArrayBuffer(file)
      setProfileFile(file)
    })
    
  }, [])

  const {getRootProps, getInputProps} = useDropzone({onDrop})
  const postProfile = (consentController) => {
    props.addProfile({file: profileFile, consent: consentController, redirect: true})
  }

  const leftClassContent = isShownLeft ? [clippedStyles.left__content, clippedStyles.content__shown] : [clippedStyles.left__content]
  const leftClassHover = isShownLeft ? [clippedStyles.left__content] : [clippedStyles.left__content_hovered, clippedStyles.hover__shown]

  return (
    <>
      <section className={clippedStyles.clipped}>
        <Media
          queries={{ large: "(min-width: 1200px)" }}
          defaultMatches={{ large: device === 'desktop' && props.isDesktopOrLaptop === 'desktop' }}
          render={() => 
            <div className={clippedStyles.bridge}>
              <img src={bridgeImg} />
            </div>
          }
        />
        <Media
          queries={{ mobile: "(max-width: 1200px)" }}
          defaultMatches={{ mobile: device === 'mobile' && props.isDesktopOrLaptop === 'mobile' }}
          render={() => 
            <div className={clippedStyles.heading_mobile}>
              <div className="text-extra-large"><span className="text-bold-600">BPI group</span> vous accompagne</div>
              <div className="text-extra-large text-bold-600">vers un nouvel avenir professionnel</div>
              <div className={clippedStyles.bridge_mobile}>
                <img src={bridgeImg} className={clippedStyles.bridge_mobile_img} />
              </div>
            </div>
          }
        />

        <Media
          queries={{ large: "(min-width: 1200px)" }}
          defaultMatches={{ large: device === 'desktop' && props.isDesktopOrLaptop === 'desktop' }}
          render={() => 
            <div className={clippedStyles.left}
            onMouseEnter={() => setIsShownLeft(false)}
            onMouseLeave={() => setIsShownLeft(true)}
            role="textbox"
            tabIndex="-1"
          >
            <div className={leftClassContent.join(' ')}>
              <div className={clippedStyles.heading}>
                <div className="text-extra-large">Dolore occaecat dolore consequat deserunt mollit deserunt laboris </div>
                <div className="text-medium">Ut Lorem anim minim consectetur aliquip nulla est anim </div>
              </div>
              <div className={[clippedStyles.shape,clippedStyles.shape__justified].join(' ')}>
                <img src={girlImg} alt="Jumping girl" />
                <span className={clippedStyles.shape__text}>With Resume</span>
              </div>
            </div>
            <div className={leftClassHover.join(' ')} {...getRootProps()}>
              <input {...getInputProps()} />
              <div className={clippedStyles.dropping}>
                <div className={clippedStyles.cloud_row}>
                    <img src={cloudLogo} />
                    <img src={cloudLogo} />
                    <img src={cloudLogo} />
                    <img src={cloudLogo} />
                </div>
                <div className={clippedStyles.cloud_row}>
                  <div className={clippedStyles.cloud_col}>
                      <img src={cloudLogo} />
                      <img src={cloudLogo} />
                  </div>
                  
                    <div className={clippedStyles.dropzone} >
                      <span className="text-large bold">
                          Glisse ton CV
                      </span>
                      <div id="dropzone">
                      
                      </div>
                      <div className={clippedStyles.dashed}>
                        <div className={clippedStyles.logo_wrapper}>
                          <img src={plusLogo} alt="plus" />
                        </div>
                      </div>
                    </div>
                    <img src={cloudLogo} />
                </div>
                <div className="drop-message">et laisse la magie opérer</div>
                <div className={clippedStyles.cloud_row}>
                  <img src={cloudLogo} />
                  <img src={cloudLogo} />
                  <img src={cloudLogo} />
                </div>
              </div>
            </div>
          </div>
        }/>

        <Media
          queries={{ mobile: "(max-width: 1200px)" }}
          defaultMatches={{ mobile: device === 'mobile' && props.isDesktopOrLaptop === 'mobile' }}
          render={() => 
            <div className={clippedStyles.left}
              onMouseEnter={() => setIsShownLeft(false)}
              onMouseLeave={() => setIsShownLeft(true)}
              role="textbox"
              tabIndex="-1"
            >
              <div className={[clippedStyles.left__content_hovered, clippedStyles.hover__shown].join(' ')} {...getRootProps()}>
                <input {...getInputProps()} />
                <div className={clippedStyles.dropping}>
                  <div className={clippedStyles.cloud_row_mobile}>
                      <div className={clippedStyles.dropzone} >
                        <span className="text-large text-bold-600">
                          Glissez votre CV
                        </span>
                        <div id="dropzone">
                        
                        </div>
                        <div className={clippedStyles.dashed}>
                          <div className={clippedStyles.logo_wrapper}>
                            <img src={plusLogo} alt="plus" />
                          </div>
                        </div>
                      </div>
                  </div>
                  <div className="drop-message text-large text-bold-600">et le tour est joué</div>
                </div>
              </div>
            </div>
          }
        />

          <Media
            queries={{ large: "(min-width: 1200px)" }}
            defaultMatches={{ large: device === 'desktop' && props.isDesktopOrLaptop === 'desktop'}}
            render={() => 
            <div
              className={clippedStyles.right}
              onMouseEnter={() => setIsShownRight(false)}
              onMouseLeave={() => setIsShownRight(true)}
              role="textbox"
              tabIndex="-2"
            >
              { isShownRight ? (
                  <div className={clippedStyles.right__content}>
                    <div className={clippedStyles.heading}>
                    </div>
                    <div className={clippedStyles.shape}>
                      <img src={boyImg} alt="Jumping boy" />
                      <span className={clippedStyles.shape__text}>Without Resume</span>
                    </div>
                  </div>
                )
                :
                (
                  <Link to="/jobs" className={clippedStyles.right__content_hovered}>
                    <span className={clippedStyles.row}>
                      <img src={times} alt="times 1" />
                      <img src={times} alt="times 2" />
                      <img src={times} alt="times 3" />
                    </span>
                    <span className={`${clippedStyles.row} text-large text-bold-700 text-right`}>
                      Trop pressé
                    </span>
                    <span className={clippedStyles.row}>
                      <img src={times} alt="times 4" />
                      <img src={times} alt="times 5" />
                      <img src={times} alt="times 6" />
                      <img src={times} alt="times 7" />
                    </span>
                    <span className={`${clippedStyles.row} text-large text-right`}>
                      Accède à nos offres <FontAwesomeIcon className="icon-right" icon={faLongArrowAltRight} />
                    </span>
                    <span className={clippedStyles.row}>
                      <img src={times} alt="times 8" />
                      <img src={times} alt="times 9" />
                      <img src={times} alt="times 10" />
                      <img src={times} alt="times 11" />
                    </span>
                  </Link>
                )
              }
            </div>
            } 
          />
          <Media
            queries={{ mobile: "(max-width: 1200px)" }}
            defaultMatches={{ mobile: device === 'mobile' && props.isDesktopOrLaptop === 'mobile' }}
            render={() => 
              <div className={clippedStyles.content_mobile}>
                <div className="text-extra-large"><span className="text-bold-600">Trop pressé</span></div>
                <Link to="/jobs" className="button button-large">Accédez à nos offres <FontAwesomeIcon className="icon-right" icon={faLongArrowAltRight} /></Link>
              </div>
            }
          />      
        <Modal 
          toggleModal={setModalIsOpen}
          modalIsOpen={modalIsOpen}
          postProfile={postProfile}
          profile={props.profile}
        />
      </section>
    </>
  )
}
Example #24
Source File: index.js    From Artion-Client with GNU General Public License v3.0 4 votes vote down vote up
PaintBoard = () => {
  const dispatch = useDispatch();
  const history = useHistory();

  const {
    explorerUrl,
    apiUrl,
    fetchMintableCollections,
    getNonce,
    addUnlockableContent,
    checkBan,
  } = useApi();

  const { registerRoyalty } = useSalesContract();
  const { loadContract } = useContract();

  const { account, chainId } = useWeb3React();

  const imageRef = useRef();

  const [selected, setSelected] = useState([]);
  const [collections, setCollections] = useState([]);
  const [nft, setNft] = useState();
  const [type, setType] = useState();
  const [image, setImage] = useState(null);
  const [fee, setFee] = useState(null);

  const [name, setName] = useState('');
  const [symbol, setSymbol] = useState('');
  const [description, setDescription] = useState('');
  const [royalty, setRoyalty] = useState('');
  const [xtra, setXtra] = useState('');
  const [supply, setSupply] = useState(0);
  const [hasUnlockableContent, setHasUnlockableContent] = useState(false);
  const [unlockableContent, setUnlockableContent] = useState('');

  const [currentMintingStep, setCurrentMintingStep] = useState(0);
  const [isMinting, setIsMinting] = useState(false);

  const [lastMintedTnxId, setLastMintedTnxId] = useState('');

  const authToken = useSelector(state => state.ConnectWallet.authToken);

  const getFee = async () => {
    setFee(null);

    try {
      const contract = await loadContract(nft, FEE_ABI);
      const _fee = await contract.platformFee();
      setFee(parseFloat(_fee.toString()) / 10 ** 18);
    } catch {
      setFee(0);
    }
  };

  const getCollections = async () => {
    try {
      const { data } = await fetchMintableCollections(authToken);
      setCollections(data);
      if (data.length) {
        setSelected([data[0]]);
      }
    } catch (err) {
      console.log(err);
    }
  };

  useEffect(() => {
    if (authToken) {
      getCollections();
    }
  }, [authToken]);

  useEffect(() => {
    if (!nft) return;

    getFee();
  }, [nft]);

  useEffect(() => {
    dispatch(HeaderActions.toggleSearchbar(true));
  }, []);

  const onDrop = useCallback(acceptedFiles => {
    setImage(acceptedFiles[0]);
  }, []);

  const { getRootProps, getInputProps } = useDropzone({
    accept: accept.join(', '),
    multiple: false,
    onDrop,
    maxSize: 15728640,
  });

  const removeImage = () => {
    setImage(null);
    if (imageRef.current) {
      imageRef.current.value = '';
    }
  };

  const imageToBase64 = () => {
    return new Promise((resolve, reject) => {
      let reader = new FileReader();
      reader.readAsDataURL(image);
      reader.onload = () => {
        resolve(reader.result);
      };
      reader.onerror = err => {
        reject(err);
      };
    });
  };

  const validateMetadata = () => {
    return name !== '' && account !== '' && image;
  };

  const resetMintingStatus = () => {
    setTimeout(() => {
      setIsMinting(false);
      setCurrentMintingStep(0);
    }, 1000);
  };

  const mintNFT = async () => {
    if (!account) {
      showToast('info', 'Connect your wallet first');
      return;
    }
    if (chainId !== ChainId.FANTOM && chainId !== ChainId.FANTOM_TESTNET) {
      showToast('info', 'You are not connected to Fantom Opera Network');
      return;
    }
    const balance = await WalletUtils.checkBalance(account);

    if (balance < fee) {
      showToast(
        'custom',
        `Your balance should be at least ${fee} FTM to mint an NFT`
      );
      return;
    }

    let isBanned = await checkBan(account, authToken);

    if (isBanned) {
      showToast('error', 'You are banned from minting');
      return;
    }

    setLastMintedTnxId('');
    // show stepper
    setIsMinting(true);
    console.log('created from ', account);
    if (!validateMetadata()) {
      resetMintingStatus();
      return;
    }

    let signature;
    let addr;

    if (hasUnlockableContent && unlockableContent.length > 0) {
      const { data: nonce } = await getNonce(account, authToken);
      try {
        const signer = await getSigner();
        const msg = `Approve Signature on Artion.io with nonce ${nonce}`;
        signature = await signer.signMessage(msg);
        addr = ethers.utils.verifyMessage(msg, signature);
      } catch (err) {
        showToast(
          'error',
          'You need to sign the message to be able to update account settings.'
        );
        resetMintingStatus();
        return;
      }
    }

    let formData = new FormData();
    const base64 = await imageToBase64();
    formData.append('image', base64);
    formData.append('name', name);
    formData.append('account', account);
    formData.append('description', description);
    formData.append('symbol', symbol);
    formData.append('xtra', xtra);
    const _royalty = parseInt(royalty) * 100;
    formData.append('royalty', isNaN(_royalty) ? 0 : _royalty);
    try {
      let result = await axios({
        method: 'post',
        url: `${apiUrl}/ipfs/uploadImage2Server`,
        data: formData,
        headers: {
          'Content-Type': 'multipart/form-data',
          Authorization: 'Bearer ' + authToken,
        },
      });

      console.log('upload image result is ');

      const jsonHash = result.data.jsonHash;

      const contract = await loadContract(
        nft,
        type === 721 ? SINGLE_NFT_ABI : MULTI_NFT_ABI
      );
      try {
        const args =
          type === 721 ? [account, jsonHash] : [account, supply, jsonHash];

        let tx;

        if (!fee) {
          tx = await contract.mint(...args);
        } else {
          const options = {
            value: ethers.utils.parseEther(fee.toString()),
            gasPrice: getHigherGWEI(),
          };
          const gasEstimate = await contract.estimateGas.mint(...args, options);
          options.gasLimit = calculateGasMargin(gasEstimate);
          tx = await contract.mint(...args, options);
        }
        setCurrentMintingStep(1);
        setLastMintedTnxId(tx.hash);

        setCurrentMintingStep(2);
        const confirmedTnx = await tx.wait();
        setCurrentMintingStep(3);
        let mintedTkId;
        if (type === 721) {
          const evtCaught = confirmedTnx.logs[0].topics;
          mintedTkId = BigNumber.from(evtCaught[3]);
        } else {
          mintedTkId = BigNumber.from(
            ethers.utils.hexDataSlice(confirmedTnx.logs[1].data, 0, 32)
          );
        }

        const royaltyTx = await registerRoyalty(
          nft,
          mintedTkId.toNumber(),
          isNaN(_royalty) ? 0 : _royalty
        );
        await royaltyTx.wait();

        // save unlockable content
        if (hasUnlockableContent && unlockableContent.length > 0) {
          await addUnlockableContent(
            nft,
            mintedTkId.toNumber(),
            unlockableContent,
            signature,
            addr,
            authToken
          );
        }

        showToast('success', 'New NFT item minted!');
        removeImage();
        setName('');
        setSymbol('');
        setDescription('');

        setTimeout(() => {
          history.push(`/explore/${nft}/${mintedTkId.toNumber()}`);
        }, 1000 + Math.random() * 2000);
      } catch (error) {
        showToast('error', formatError(error));
      }
    } catch (error) {
      showToast('error', error.message);
    }
    resetMintingStatus();
  };

  return (
    <div className={styles.container}>
      <Header border />
      <div className={styles.body}>
        <div className={styles.board}>
          <div {...getRootProps({ className: styles.uploadCont })}>
            <input {...getInputProps()} ref={imageRef} />
            {image ? (
              <>
                <img
                  className={styles.image}
                  src={URL.createObjectURL(image)}
                />
                <div className={styles.overlay}>
                  <CloseIcon className={styles.remove} onClick={removeImage} />
                </div>
              </>
            ) : (
              <>
                <div className={styles.uploadtitle}>
                  Drop files here or&nbsp;
                  <span
                    className={styles.browse}
                    onClick={() => imageRef.current?.click()}
                  >
                    browse
                  </span>
                </div>
                <div className={styles.uploadsubtitle}>
                  JPG, PNG, BMP, GIF Max 15mb.
                </div>
              </>
            )}
          </div>
        </div>
        <div className={styles.panel}>
          <div className={styles.panelInputs}>
            <div className={styles.panelLeft}>
              <div className={styles.formGroup}>
                <p className={styles.formLabel}>Collection</p>
                <Select
                  options={collections}
                  disabled={isMinting}
                  values={selected}
                  onChange={([col]) => {
                    setSelected([col]);
                    setNft(col.erc721Address);
                    setType(col.type);
                  }}
                  className={styles.select}
                  placeholder="Choose Collection"
                  itemRenderer={({ item, methods }) => (
                    <div
                      key={item.erc721Address}
                      className={styles.collection}
                      onClick={() => {
                        methods.clearAll();
                        methods.addItem(item);
                      }}
                    >
                      <img
                        src={`https://cloudflare-ipfs.com/ipfs/${item.logoImageHash}`}
                        className={styles.collectionLogo}
                      />
                      <div className={styles.collectionName}>
                        {item.collectionName}
                      </div>
                    </div>
                  )}
                  contentRenderer={({ props: { values } }) =>
                    values.length > 0 ? (
                      <div className={styles.collection}>
                        <img
                          src={`https://cloudflare-ipfs.com/ipfs/${values[0].logoImageHash}`}
                          className={styles.collectionLogo}
                        />
                        <div className={styles.collectionName}>
                          {values[0].collectionName}
                        </div>
                      </div>
                    ) : (
                      <div className={styles.collection} />
                    )
                  }
                />
              </div>
              <div className={styles.formGroup}>
                <p className={styles.formLabel}>Name</p>
                <input
                  className={styles.formInput}
                  maxLength={40}
                  placeholder="Name"
                  value={name}
                  onChange={e => setName(e.target.value)}
                  disabled={isMinting}
                />
                <div className={styles.lengthIndicator}>{name.length}/40</div>
              </div>
              <div className={styles.formGroup}>
                <p className={styles.formLabel}>Symbol</p>
                <input
                  className={styles.formInput}
                  maxLength={20}
                  placeholder="Symbol"
                  value={symbol}
                  onChange={e => setSymbol(e.target.value)}
                  disabled={isMinting}
                />
                <div className={styles.lengthIndicator}>{symbol.length}/20</div>
              </div>
              <div className={styles.formGroup}>
                <p className={styles.formLabel}>Description</p>
                <textarea
                  className={cx(styles.formInput, styles.longInput)}
                  maxLength={120}
                  placeholder="Description"
                  value={description}
                  onChange={e => setDescription(e.target.value)}
                  disabled={isMinting}
                />
                <div className={styles.lengthIndicator}>
                  {description.length}/120
                </div>
              </div>
            </div>
            <div className={styles.panelRight}>
              {type === 1155 && (
                <div className={styles.formGroup}>
                  <p className={styles.formLabel}>Supply</p>
                  <PriceInput
                    className={styles.formInput}
                    placeholder="Supply"
                    decimals={0}
                    value={'' + supply}
                    onChange={setSupply}
                    disabled={isMinting}
                  />
                </div>
              )}
              <div className={styles.formGroup}>
                <p className={styles.formLabel}>
                  Royalty (%)&nbsp;
                  <BootstrapTooltip
                    title="If you set a royalty here, you will get X percent of sales price each time an NFT is sold on our platform."
                    placement="top"
                  >
                    <HelpOutlineIcon />
                  </BootstrapTooltip>
                </p>
                <PriceInput
                  className={styles.formInput}
                  placeholder="Royalty"
                  decimals={2}
                  value={'' + royalty}
                  onChange={val =>
                    val[val.length - 1] === '.'
                      ? setRoyalty(val)
                      : setRoyalty(Math.min(100, +val))
                  }
                  disabled={isMinting}
                />
              </div>
              <div className={styles.formGroup}>
                <p className={styles.formLabel}>
                  Link to IP Rights Document (Optional)&nbsp;
                  <BootstrapTooltip
                    title="Link to the document which proves your ownership of this image."
                    placement="top"
                  >
                    <HelpOutlineIcon />
                  </BootstrapTooltip>
                </p>
                <input
                  className={styles.formInput}
                  placeholder="Enter Link"
                  value={xtra}
                  onChange={e => setXtra(e.target.value)}
                  disabled={isMinting}
                />
              </div>
              <div className={styles.formGroup}>
                <p className={styles.formLabel}>
                  Unlockable Content&nbsp;
                  <PurpleSwitch
                    checked={hasUnlockableContent}
                    onChange={e => {
                      setHasUnlockableContent(e.target.checked);
                      setUnlockableContent('');
                    }}
                    name="unlockableContent"
                  />
                </p>
                {hasUnlockableContent && (
                  <textarea
                    className={cx(styles.formInput, styles.longInput)}
                    maxLength={500}
                    placeholder="Unlockable Content"
                    value={unlockableContent}
                    onChange={e => setUnlockableContent(e.target.value)}
                    disabled={isMinting}
                  />
                )}
              </div>
            </div>
          </div>

          {isMinting && (
            <div>
              <Stepper activeStep={currentMintingStep} alternativeLabel>
                {mintSteps.map(label => (
                  <Step key={label}>
                    <StepLabel>{label}</StepLabel>
                  </Step>
                ))}
              </Stepper>
            </div>
          )}
          <div
            className={cx(
              styles.button,
              (isMinting || !account || !validateMetadata()) && styles.disabled
            )}
            onClick={
              isMinting || !account || !validateMetadata() ? null : mintNFT
            }
          >
            {isMinting ? (
              <ClipLoader size="16" color="white"></ClipLoader>
            ) : (
              'Mint'
            )}
          </div>
          <div className={styles.fee}>
            {fee !== null ? (
              <>
                <InfoIcon />
                &nbsp;{fee} FTM are charged to create a new NFT.
              </>
            ) : (
              <Skeleton width={330} height={22} />
            )}
          </div>
          <div className={styles.mintStatusContainer}>
            {lastMintedTnxId !== '' && (
              <a
                className={styles.tnxAnchor}
                target="_blank"
                rel="noopener noreferrer"
                href={`${explorerUrl}/tx/${lastMintedTnxId}`}
              >
                You can track the last transaction here ...
              </a>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}
Example #25
Source File: Data.js    From vria with MIT License 4 votes vote down vote up
function FileUploader(props) {
  const { editorConfig, actions } = props;
  const [currentFile, setCurrentFile] = useState(null);
  const [readError, setReadError] = useState(null);
  const onDrop = useCallback((acceptedFiles) => {
    acceptedFiles.forEach((file) => {
      const reader = new FileReader();
      reader.onabort = () => setReadError('File read was aborted');
      reader.onerror = () => setReadError('File read has failed');
      reader.onload = () => setCurrentFile(reader.result);
      reader.readAsText(file);
    });
  }, []);
  const history = useHistory();

  const {
    acceptedFiles,
    fileRejections,
    isDragActive,
    isDragAccept,
    isDragReject,
    getRootProps,
    getInputProps
  } = useDropzone({
    onDrop,
    accept: 'text/csv, application/json',
    multiple: false
  });

  const importDataset = () => {
    console.log('editorConfig', editorConfig);

    try {
      let c = JSON.parse(editorConfig);
      console.log(c);

      if (currentFile !== null) {
        if (isJSON(currentFile)) {
          // File is JSON
          c.data = {
            values: JSON.parse(currentFile)
          };
        } else {
          // File is CSV
          c.data = {
            values: Papa.parse(currentFile, {
              header: true,
              dynamicTyping: true,
              skipEmptyLines: true
            }).data
          };
        }
        actions.setEditorConfig(JSON.stringify(c, null, 2));
        history.push('/editor');
      }
    } catch {
      setReadError('Cannot import dataset: Vis-config contains invalid JSON');
    }
  };

  const files = acceptedFiles.map((file) => (
    <li key={file.path}>
      {file.path} - {(file.size / 1000).toFixed(2)} KB -{' '}
      <button onClick={importDataset}>Use Dataset</button>
    </li>
  ));

  return (
    <section className='container'>
      <DropArea {...getRootProps({ isDragActive, isDragAccept, isDragReject })}>
        <input {...getInputProps()} />
        <p>Drag a CSV or JSON file here or click to upload.</p>
      </DropArea>
      {files.length !== 0 ? (
        <aside>
          <h3>Uploaded file:</h3>
          <ul>{files}</ul>
        </aside>
      ) : null}
      {fileRejections.length !== 0 ? (
        <aside>
          <p>{fileRejections[0].errors[0].message}</p>
        </aside>
      ) : null}
      <div>{readError}</div>
    </section>
  );
}
Example #26
Source File: index.js    From website with MIT License 4 votes vote down vote up
DragNDropInputField = ({ onChange, error, initialImages = null }) => {
  const [selectedImages, setSelectedImages] = useState([]);
  const [alertMessage, setAlertMessage] = useState('');
  const { getRootProps, getInputProps, isDragActive, isDragAccept, isDragReject } = useDropzone({
    onDrop: (files) => onUpload(files, selectedImages),
    accept: '.jpeg, .png, .jpg',
  });

  const onCloseAlert = () => setAlertMessage('');

  const displayUploadFileAlert = (message) => {
    setAlertMessage(message);
    setTimeout(() => {
      onCloseAlert(); // hide alert message after 5 seconds
    }, 5000);
  };

  const onUpload = useCallback((acceptedFiles, selectedImages) => {
    if (acceptedFiles.some((file) => file.size > MAXIMUM_FILE_SIZE_LIMIT)) {
      displayUploadFileAlert('Unable to upload images that are more than 25mb');
      acceptedFiles = acceptedFiles.filter((file) => file.size <= MAXIMUM_FILE_SIZE_LIMIT);
    }

    const allowedRemainingImages = MAXIMUM_ALLOWED_PHOTOS - selectedImages.length;
    if (allowedRemainingImages < acceptedFiles.length) {
      displayUploadFileAlert('Unable to upload more than 4 images');
    }

    // Only take maximum 4 images.
    if (acceptedFiles.length > 0 && selectedImages.length <= MAXIMUM_ALLOWED_PHOTOS - 1) {
      const acceptedImages = acceptedFiles.map((file) => {
        return Object.assign(file, {
          preview: URL.createObjectURL(file),
          id: uuidv4(),
        });
      });

      if (allowedRemainingImages > 0) {
        const allowedImages = acceptedImages.splice(0, allowedRemainingImages);
        setSelectedImages((prevSelectedImages) => [...prevSelectedImages, ...allowedImages]);
      }
    }
  }, []);

  useEffect(() => {
    onChange(selectedImages);
  }, [selectedImages]);

  useEffect(() => {
    if (initialImages) {
      let initial = initialImages.map((imageUrl) => ({
        preview: imageUrl,
        id: uuidv4(),
      }));
      setSelectedImages(initial);
    }
  }, [initialImages]);

  const onDragEnd = (result) => {
    if (!result.destination) {
      // dropped outside the list
      return;
    }
    const items = reorder(selectedImages, result.source.index, result.destination.index);
    setSelectedImages(items);
  };

  // a little function to help us with reordering the result
  const reorder = (list, startIndex, endIndex) => {
    const result = Array.from(list);
    const [removed] = result.splice(startIndex, 1);
    result.splice(endIndex, 0, removed);
    return result;
  };

  const onDeleteClick = (index) => {
    let cloneSelectedImages = [...selectedImages];
    cloneSelectedImages.splice(index, 1);
    setSelectedImages(cloneSelectedImages);
  };

  return (
    <Container>
      <DragNDropContainer {...getRootProps({ isDragActive, isDragAccept, isDragReject })}>
        <input {...getInputProps()} />
        <p>Drag 'n' drop up to {MAXIMUM_ALLOWED_PHOTOS} photos, or click to select photos</p>
      </DragNDropContainer>
      {error && <Error>{error}</Error>}

      <DragDropContext onDragEnd={onDragEnd}>
        <Droppable droppableId="droppable" direction="horizontal">
          {(provided, snapshot) => (
            <HorizontalImagesContainer ref={provided.innerRef} {...provided.droppableProps}>
              {selectedImages.map((item, index) => (
                <Draggable key={item.id} draggableId={item.id} index={index}>
                  {(provided, snapshot) => (
                    <DraggableImageContainer
                      ref={provided.innerRef}
                      {...provided.draggableProps}
                      {...provided.dragHandleProps}
                      isDragging={snapshot.isDragging}
                      draggableStyle={provided.draggableProps.style}
                    >
                      <Image src={item.preview} onDeleteClick={() => onDeleteClick(index)} />
                    </DraggableImageContainer>
                  )}
                </Draggable>
              ))}
              {provided.placeholder}
            </HorizontalImagesContainer>
          )}
        </Droppable>
      </DragDropContext>

      {selectedImages.length > 0 ? (
        <CoverTextWrapper>
          <Text type="white" align="center">
            Cover
          </Text>
        </CoverTextWrapper>
      ) : null}
      {alertMessage.length > 0 && (
        <AlertContainer>
          <Alert icon type="critical" title="Something has gone wrong" closable onClose={onCloseAlert}>
            {alertMessage}
          </Alert>
        </AlertContainer>
      )}
    </Container>
  );
}
Example #27
Source File: file-upload.js    From proof-of-humanity-web with MIT License 4 votes vote down vote up
export default function FileUpload({
  value,
  onChange: _onChange,
  name,
  accept,
  acceptLabel,
  maxSize,
  maxSizeLabel,
  multiple = false,
  onBlur,
  placeholder = `Drag your file${multiple ? "s" : ""}`,
  photo = false,
  video = false,
  ...rest
}) {
  const [files, setFiles] = useState(value);
  const [popupOpen, setPopupOpen] = useState(false);

  const onChange = (_files, ...args) => {
    if (_files)
      for (const file of Array.isArray(_files) ? _files : [_files])
        file.toJSON = () => ({
          isSerializedFile: true,
          type: file.type,
          name: file.name,
          content: bufferToString(file.content),
        });
    return _onChange
      ? _onChange({ target: { name, value: _files } })
      : setFiles(_files, ...args);
  };

  const { getRootProps, getInputProps, open } = useDropzone({
    noClick: true,
    async onDrop(acceptedFiles) {
      const readFiles = await Promise.all(
        acceptedFiles.map(async (file) => {
          const buffer = await file.arrayBuffer();
          file.preview = URL.createObjectURL(file);
          file.content = buffer;
          return file;
        })
      );
      const _files = readFiles.length === 1 ? readFiles[0] : readFiles;
      onChange(_files);
    },
    multiple,
    accept,
    maxSize,
    ...rest,
  });

  useEffect(() => {
    if (value) {
      const _files = Array.isArray(value) ? value : [value];
      if (_files.some((file) => file.isSerializedFile)) {
        const parsedFiles = _files.map((file) => {
          if (!file.isSerializedFile) return file;

          const buffer = stringToBuffer(file.content);
          file = new File([buffer], file.name, { type: file.type });
          file.preview = URL.createObjectURL(file);
          file.content = buffer;
          file.toJSON = () => ({
            isSerializedFile: true,
            type: file.type,
            name: file.name,
            content: bufferToString(file.content),
          });
          return file;
        });
        _onChange({ target: { name, value: parsedFiles } });
      }
    }
  }, [value, _onChange, name]);

  useEffect(() => {
    if (value !== undefined && value !== files) setFiles(value);
  }, [value, files]);

  useEffect(
    () => () => {
      if (files)
        (Array.isArray(files) ? files : [files]).forEach((file) =>
          URL.revokeObjectURL(file.preview)
        );
    },
    [files]
  );
  return (
    <Box
      sx={{ position: "relative" }}
      onClick={(event) => {
        event.stopPropagation();
        event.preventDefault();
      }}
    >
      <Box
        {...getRootProps({
          onClick: (event) => {
            event.preventDefault();
            event.stopPropagation();
          },
          variant: "forms.fileUpload",
          onBlur() {
            if (onBlur) onBlur({ target: { name } });
          },
          ...rest,
        })}
      >
        <Input {...getInputProps({ name })} />
        {maxSizeLabel && acceptLabel ? (
          <Text sx={{ fontStyle: "italic" }}>
            (Max Size: {maxSizeLabel} | {acceptLabel})
          </Text>
        ) : maxSizeLabel ? (
          <Text sx={{ fontStyle: "italic" }}>(Max Size: {maxSizeLabel})</Text>
        ) : acceptLabel ? (
          <Text sx={{ fontStyle: "italic" }}>{acceptLabel}</Text>
        ) : null}
        <Text>
          {placeholder}
          {photo || video ? ", " : " or "}
          <Button variant="secondary" onClick={open}>
            click here to browse files
          </Button>
          {photo || video ? (
            <>
              {" or "}
              <Button
                variant="secondary"
                onClick={(event) => {
                  event.stopPropagation();
                  event.preventDefault();
                  setPopupOpen(true);
                }}
              >
                click here to use your webcam
              </Button>
              <Webcam
                open={popupOpen}
                setPopupOpen={setPopupOpen}
                photo={photo}
                video={video}
                onChange={(file) =>
                  onChange(multiple ? [...files, file] : file)
                }
                mirrored={false}
              />
            </>
          ) : null}
        </Text>
      </Box>
      <Flex sx={{ marginTop: 1 }}>
        {files &&
          (Array.isArray(files) ? files : [files])
            .filter((file) => !file.isSerializedFile)
            .map((file) => (
              <Box
                key={file.path || file.name}
                sx={{
                  marginTop: 1,
                  position: "relative",
                  width: "fit-content",
                }}
              >
                {file.type.startsWith("video") ? (
                  <Video variant="thumbnail" url={file.preview} />
                ) : file.type.startsWith("image") ? (
                  <Image variant="thumbnail" src={file.preview} />
                ) : (
                  <Text>{file.name}</Text>
                )}
                <Trash
                  sx={{
                    fill: "text",
                    position: "absolute",
                    right: -1,
                    top: -1,
                  }}
                  onClick={(event) => {
                    event.stopPropagation();
                    event.preventDefault();
                    onChange(
                      multiple ? files.filter((_file) => _file !== file) : null
                    );
                  }}
                />
              </Box>
            ))}
      </Flex>
    </Box>
  );
}
Example #28
Source File: Editor.jsx    From locked.fyi with MIT License 4 votes vote down vote up
Editor = ({ thread: threadId, note: noteId }) => {
  const { account } = useWeb3React()

  const {
    setNoteAttribute,
    setNoteBody,
    note,
    noteThread,
    loading,
    save,
    destroy,
    uploadFile,
  } = useOwnerThread(account, threadId, noteId)

  const onDrop = async (acceptedFiles) => {
    const { body } = note // keeping track of body, as-is

    // TODO: support multiple file uploads at once!
    const file = acceptedFiles[0]
    const textArea = document.querySelector(".mde-text")
    const insertAt = textArea.selectionStart
    const uploadPlaceholder = "\nUploading file..."

    setNoteBody(
      body.slice(0, insertAt) + uploadPlaceholder + body.slice(insertAt)
    )

    const url = await uploadFile(file)

    // We should look at the mimetype for files an respond accordingly
    // If it is an image, embed as is
    // if it is an mp3 use an audio player
    // if it is an mp4, use a video player...
    let markdown = `\n${url}\n`
    if (file.type.match("image/*")) {
      markdown = `![](${url})`
    } else {
      // Link to the file
      markdown = `\n[${file.name}](${url})\n`
    }

    setNoteBody(`${body.slice(0, insertAt)}${markdown}${body.slice(insertAt)}`)
    // WARNING: what happens if the body was changed?

    // Restore the position
    textArea.setSelectionRange(
      insertAt + markdown.length + 1,
      insertAt + markdown.length + 1
    )
  }
  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    onDrop,
    noClick: true,
    noKeyboard: true,
  })

  const history = useHistory()
  const [selectedTab, setSelectedTab] = useState("write")
  const [saving, setSaving] = useState(false)

  if (loading) {
    return <Loading />
  }

  const onSave = async (event) => {
    event.preventDefault()
    setSaving(true)
    await save()
    setSaving(false)
    return false
  }

  const onDestroy = async () => {
    setSaving(true)
    await destroy()
    setSaving(false)
    history.push(writePath())
    return false
  }

  const onLockChange = (selected) => {
    setNoteAttribute(
      "locks",
      (selected || []).map((option) => option.value)
    )
  }

  const draftToggle = () => {
    setNoteAttribute("draft", !note.attributes.draft)
  }

  const isDraft = note.attributes.draft
  return (
    <form className="container" onSubmit={onSave}>
      <LockPicker
        identity={account}
        onLockChange={onLockChange}
        currentLocks={note.attributes.locks}
      >
        <p>
          Your note will use the{" "}
          <a target="_blank" rel="noopener noreferrer" href="/#community-lock">
            community lock
          </a>
          ... but you can also{" "}
          <a
            target="_blank"
            rel="noopener noreferrer"
            href="https://app.unlock-protocol.com/dashboard"
          >
            deploy your own lock
          </a>{" "}
          if you want to monetize your own notes.
        </p>
      </LockPicker>
      <div {...getRootProps()}>
        <input {...getInputProps()} />
        {/* Source: https://github.com/andrerpena/react-mde */}
        <MarkDownEditor
          isDragActive={isDragActive}
          value={note.body}
          onChange={setNoteBody}
          selectedTab={selectedTab}
          onTabChange={setSelectedTab}
          generateMarkdownPreview={(markdown) =>
            Promise.resolve(converter.makeHtml(markdown))
          }
        />
      </div>
      <Checkbox
        name="draft"
        checked={isDraft}
        onChange={draftToggle}
        label="Draft"
      />
      <Actions>
        <nav>
          <Button type="submit" disabled={saving}>
            Save
          </Button>
        </nav>
        <nav>
          <Button type="button" disabled={saving} onClick={onDestroy}>
            Destroy
          </Button>
        </nav>
        {saving && <Loading />}
      </Actions>
      <div>
        {note.attributes.id && note.attributes.id > 0 && (
          <>
            ➡{" "}
            <Link to={notePath(account, noteThread, note.attributes.id)}>
              {note.attributes.title}
            </Link>
          </>
        )}
      </div>
    </form>
  )
}
Example #29
Source File: index.js    From plataforma-sabia with MIT License 4 votes vote down vote up
EditServiceModal = ({
	closeModal,
	id,
	name,
	thumbnail,
	keywords,
	description,
	measure_unit,
	price,
	type,
	revalidateServices,
	revalidateKeywords,
	keywordsOptions,
}) => {
	const [isSubmitting, setIsSubmitting] = useState(false);
	const [uploadError, setUploadError] = useState(null);

	const form = useForm({
		defaultValues: {
			name,
			keywords,
			thumbnail: { id: thumbnail?.id, url: thumbnail?.url },
			description,
			measure_unit,
			price,
			type,
		},
	});
	const formThumbnail = form.watch('thumbnail');

	const onSubmit = async (values) => {
		setIsSubmitting(true);

		const serviceToEdit = {
			...values,
			measure_unit: values.measure_unit.value,
			thumbnail_id: values.thumbnail.id,
			type: values.type.value,
			keywords: values.keywords?.map((item) => item.value) ?? [],
			price: formatCurrencyToInt(values.price),
		};

		const result = await updateService(id, serviceToEdit);

		if (result.success) {
			toast.success('Serviço atualizado com sucesso');
			revalidateServices();
			revalidateKeywords();
			closeModal();
		} else {
			toast.error(result.error);
		}

		setIsSubmitting(false);
	};

	const onDropAttachment = async (acceptedFiles) => {
		if (!acceptedFiles) return null;

		setUploadError(false);

		const formData = new FormData();
		if (acceptedFiles.length !== 0) {
			formData.append(`files[0]`, acceptedFiles[0], acceptedFiles[0].name);
		}

		const response = await upload(formData);

		if (response.status === 200) {
			const { id: uploadId, url } = response.data[0];
			form.setValue('thumbnail.id', uploadId);
			form.setValue('thumbnail.url', url);
		} else {
			setUploadError(response.data?.error?.message[0]?.message);
		}

		return true;
	};

	const handleRemoveAttachment = async () => {
		const response = await deleteUpload(formThumbnail.id);

		if (response?.success) {
			form.setValue('thumbnail.id', '');
			form.setValue('thumbnail.url', '');
		} else {
			toast.error(response.data?.error?.message[0]?.message);
		}
	};

	const { getRootProps, getInputProps } = useDropzone({
		accept: 'image/*',
		onDrop: onDropAttachment,
	});

	const onCreateTerm = async (inputValue) => {
		const term = await createTerm(inputValue, 'KEYWORDS');
		revalidateKeywords();
		return { label: term.term, value: `${term.id}` };
	};

	return (
		<S.Modal onSubmit={form.handleSubmit(onSubmit)} noValidate>
			<Title>Editar serviço</Title>

			<Row>
				<S.Column noPadding mr={1.2} noMarginMobile>
					<InputField
						form={form}
						name="name"
						label="Nome do serviço"
						variant="gray"
						fullWidth
					/>

					<SelectField
						form={form}
						name="keywords"
						placeholder="Busque por palavras chaves (pode adicionar mais de um)"
						label="Palavras-chave"
						isMulti
						creatable
						onCreate={(inputValue) => onCreateTerm(inputValue)}
						options={mapArrayOfObjectToSelect(keywordsOptions, 'term', 'id')}
						variant="gray"
					/>

					<TextField
						form={form}
						name="description"
						label="Descrição do serviço"
						resize="none"
						variant="gray"
					/>
				</S.Column>
				<Column noPadding ml={1.2} noMarginMobile>
					<S.Row mb={1.6}>
						<InputHiddenField form={form} name="thumbnail.id" />
						<InputHiddenField form={form} name="thumbnail.url" />
						<S.ImageContainer>
							<Image
								src={formThumbnail?.url || '/card-image.jpg'}
								alt={name}
								layout="fill"
								objectFit="cover"
							/>
						</S.ImageContainer>
						<S.ImageActions>
							<S.UploadBox {...getRootProps()}>
								<input {...getInputProps()} />
								<RectangularButton colorVariant="green">
									<FiUpload fontSize={14} strokeWidth={4} />
									Alterar imagem
								</RectangularButton>
							</S.UploadBox>

							<RectangularButton
								colorVariant="red"
								onClick={handleRemoveAttachment}
								disabled={!formThumbnail?.id}
							>
								<FiTrash2 fontSize={14} strokeWidth={3} />
								Remover
							</RectangularButton>
						</S.ImageActions>
					</S.Row>
					{!!uploadError && (
						<Row>
							<S.UploadError>{uploadError}</S.UploadError>
						</Row>
					)}

					<S.Row mb={1.6}>
						<SelectField
							form={form}
							name="measure_unit"
							label="Unidade de medida"
							placeholder="Escolha a unidade de medida"
							options={measureUnitOptions}
							variant="rounded"
						/>
						<CurrencyInputField form={form} name="price" label="Preço" variant="gray" />
					</S.Row>
					<SelectField
						form={form}
						name="type"
						label="Tipo"
						placeholder="Escolha um tipo"
						options={typeOptions}
						variant="rounded"
					/>
				</Column>
			</Row>
			<S.Actions>
				<RectangularButton variant="outlined" colorVariant="red" onClick={closeModal}>
					Cancelar
				</RectangularButton>
				<RectangularButton
					type="submit"
					variant="filled"
					colorVariant="green"
					disabled={isSubmitting}
				>
					Editar Serviço
				</RectangularButton>
			</S.Actions>
		</S.Modal>
	);
}