mirror of
https://github.com/oceanprotocol/commons.git
synced 2023-03-15 18:03:00 +01:00
add default env vars into CONNECTIONS cofig
This commit is contained in:
parent
b4fc9883e2
commit
ab342b3fa6
@ -9,28 +9,28 @@ import './styles/global.scss'
|
|||||||
import styles from './App.module.scss'
|
import styles from './App.module.scss'
|
||||||
|
|
||||||
export default class App extends Component {
|
export default class App extends Component {
|
||||||
public render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<div className={styles.app}>
|
<div className={styles.app}>
|
||||||
<Router>
|
<Router>
|
||||||
<>
|
<>
|
||||||
<Header />
|
<Header />
|
||||||
|
|
||||||
<main className={styles.main}>
|
<main className={styles.main}>
|
||||||
{this.context.isLoading ? (
|
{this.context.isLoading ? (
|
||||||
<div className={styles.loader}>
|
<div className={styles.loader}>
|
||||||
<Spinner message={this.context.message} />
|
<Spinner message={this.context.message} />
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Routes />
|
<Routes />
|
||||||
)}
|
)}
|
||||||
</main>
|
</main>
|
||||||
<Footer />
|
<Footer />
|
||||||
</>
|
</>
|
||||||
</Router>
|
</Router>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
App.contextType = User
|
App.contextType = User
|
||||||
|
@ -8,34 +8,34 @@ import menu from '../../data/menu'
|
|||||||
import meta from '../../data/meta.json'
|
import meta from '../../data/meta.json'
|
||||||
|
|
||||||
const MenuItem = ({ item }: { item: any }) => (
|
const MenuItem = ({ item }: { item: any }) => (
|
||||||
<NavLink
|
<NavLink
|
||||||
to={item.link}
|
to={item.link}
|
||||||
className={styles.link}
|
className={styles.link}
|
||||||
activeClassName={styles.linkActive}
|
activeClassName={styles.linkActive}
|
||||||
exact
|
exact
|
||||||
>
|
>
|
||||||
{item.title}
|
{item.title}
|
||||||
</NavLink>
|
</NavLink>
|
||||||
)
|
)
|
||||||
|
|
||||||
export default class Header extends PureComponent {
|
export default class Header extends PureComponent {
|
||||||
public render() {
|
public render() {
|
||||||
return (
|
return (
|
||||||
<header className={styles.header}>
|
<header className={styles.header}>
|
||||||
<div className={styles.headerContent}>
|
<div className={styles.headerContent}>
|
||||||
<NavLink to="/" className={styles.headerLogo}>
|
<NavLink to="/" className={styles.headerLogo}>
|
||||||
<Logo className={styles.headerLogoImage} />
|
<Logo className={styles.headerLogoImage} />
|
||||||
<h1 className={styles.headerTitle}>{meta.title}</h1>
|
<h1 className={styles.headerTitle}>{meta.title}</h1>
|
||||||
</NavLink>
|
</NavLink>
|
||||||
|
|
||||||
<nav className={styles.headerMenu}>
|
<nav className={styles.headerMenu}>
|
||||||
{menu.map(item => (
|
{menu.map(item => (
|
||||||
<MenuItem key={item.title} item={item} />
|
<MenuItem key={item.title} item={item} />
|
||||||
))}
|
))}
|
||||||
<AccountStatus className={styles.accountStatus} />
|
<AccountStatus className={styles.accountStatus} />
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,151 +9,153 @@ import ReactGA from 'react-ga'
|
|||||||
import cleanupContentType from '../../../utils/cleanupContentType'
|
import cleanupContentType from '../../../utils/cleanupContentType'
|
||||||
|
|
||||||
export const messages: any = {
|
export const messages: any = {
|
||||||
99: 'Decrypting file URL...',
|
99: 'Decrypting file URL...',
|
||||||
0: '1/3<br />Asking for agreement signature...',
|
0: '1/3<br />Asking for agreement signature...',
|
||||||
1: '1/3<br />Agreement initialized.',
|
1: '1/3<br />Agreement initialized.',
|
||||||
2: '2/3<br />Asking for two payment confirmations...',
|
2: '2/3<br />Asking for two payment confirmations...',
|
||||||
3: '2/3<br />Payment confirmed. Requesting access...',
|
3: '2/3<br />Payment confirmed. Requesting access...',
|
||||||
4: '3/3<br /> Access granted. Consuming file...'
|
4: '3/3<br /> Access granted. Consuming file...'
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AssetFileProps {
|
interface AssetFileProps {
|
||||||
file: File
|
file: File
|
||||||
ddo: DDO
|
ddo: DDO
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AssetFileState {
|
interface AssetFileState {
|
||||||
isLoading: boolean
|
isLoading: boolean
|
||||||
error: string
|
error: string
|
||||||
step: number
|
step: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class AssetFile extends PureComponent<
|
export default class AssetFile extends PureComponent<
|
||||||
AssetFileProps,
|
AssetFileProps,
|
||||||
AssetFileState
|
AssetFileState
|
||||||
> {
|
> {
|
||||||
public static contextType = User
|
public static contextType = User
|
||||||
|
|
||||||
public state = {
|
public state = {
|
||||||
isLoading: false,
|
|
||||||
error: '',
|
|
||||||
step: 99
|
|
||||||
}
|
|
||||||
|
|
||||||
private resetState = () =>
|
|
||||||
this.setState({
|
|
||||||
isLoading: true,
|
|
||||||
error: '',
|
|
||||||
step: 99
|
|
||||||
})
|
|
||||||
|
|
||||||
private purchaseAsset = async (ddo: DDO, index: number) => {
|
|
||||||
this.resetState()
|
|
||||||
|
|
||||||
ReactGA.event({
|
|
||||||
category: 'Purchase',
|
|
||||||
action: 'purchaseAsset-start ' + ddo.id
|
|
||||||
})
|
|
||||||
|
|
||||||
const { ocean } = this.context
|
|
||||||
|
|
||||||
try {
|
|
||||||
const accounts = await ocean.accounts.list()
|
|
||||||
const service = ddo.findServiceByType('access')
|
|
||||||
|
|
||||||
const agreements = await ocean.keeper.conditions.accessSecretStoreCondition.getGrantedDidByConsumer(
|
|
||||||
accounts[0].id
|
|
||||||
)
|
|
||||||
const agreement = agreements.find((element: any) => {
|
|
||||||
return element.did === ddo.id
|
|
||||||
})
|
|
||||||
|
|
||||||
let agreementId
|
|
||||||
|
|
||||||
if (agreement) {
|
|
||||||
;({ agreementId } = agreement)
|
|
||||||
} else {
|
|
||||||
agreementId = await ocean.assets
|
|
||||||
.order(ddo.id, service.index, accounts[0])
|
|
||||||
.next((step: number) => this.setState({ step }))
|
|
||||||
}
|
|
||||||
|
|
||||||
// manually add another step here for better UX
|
|
||||||
this.setState({ step: 4 })
|
|
||||||
|
|
||||||
const path = await ocean.assets.consume(
|
|
||||||
agreementId,
|
|
||||||
ddo.id,
|
|
||||||
service.index,
|
|
||||||
accounts[0],
|
|
||||||
'',
|
|
||||||
index
|
|
||||||
)
|
|
||||||
Logger.log('path', path)
|
|
||||||
ReactGA.event({
|
|
||||||
category: 'Purchase',
|
|
||||||
action: 'purchaseAsset-end ' + ddo.id
|
|
||||||
})
|
|
||||||
this.setState({ isLoading: false })
|
|
||||||
} catch (error) {
|
|
||||||
Logger.error('error', error.message)
|
|
||||||
this.setState({
|
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
error: `${error.message}. Sorry about that, can you try again?`
|
error: '',
|
||||||
})
|
step: 99
|
||||||
ReactGA.event({
|
|
||||||
category: 'Purchase',
|
|
||||||
action: 'purchaseAsset-error ' + error.message
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public render() {
|
private resetState = () =>
|
||||||
const { ddo, file } = this.props
|
this.setState({
|
||||||
const { isLoading, error, step } = this.state
|
isLoading: true,
|
||||||
const { isLogged } = this.context
|
error: '',
|
||||||
const { index, contentType, contentLength } = file
|
step: 99
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
private purchaseAsset = async (ddo: DDO, index: number) => {
|
||||||
<div className={styles.fileWrap}>
|
this.resetState()
|
||||||
<ul key={index} className={styles.file}>
|
|
||||||
{contentType || contentLength ? (
|
|
||||||
<>
|
|
||||||
<li>{cleanupContentType(contentType)}</li>
|
|
||||||
<li>
|
|
||||||
{contentLength && contentLength !== '0'
|
|
||||||
? filesize(contentLength)
|
|
||||||
: ''}
|
|
||||||
</li>
|
|
||||||
{/* <li>{encoding}</li> */}
|
|
||||||
{/* <li>{compression}</li> */}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<li className={styles.empty}>No file info available</li>
|
|
||||||
)}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
{isLoading ? (
|
ReactGA.event({
|
||||||
<Spinner message={messages[step]} />
|
category: 'Purchase',
|
||||||
) : (
|
action: 'purchaseAsset-start ' + ddo.id
|
||||||
<Market.Consumer>
|
})
|
||||||
{market => (
|
|
||||||
<Button
|
|
||||||
primary
|
|
||||||
className={styles.buttonMain}
|
|
||||||
// weird 0 hack so TypeScript is happy
|
|
||||||
onClick={() => this.purchaseAsset(ddo, index || 0)}
|
|
||||||
disabled={!isLogged || !market.networkMatch}
|
|
||||||
name="Download"
|
|
||||||
>
|
|
||||||
Get file
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</Market.Consumer>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{error !== '' && <div className={styles.error}>{error}</div>}
|
const { ocean } = this.context
|
||||||
</div>
|
|
||||||
)
|
try {
|
||||||
}
|
const accounts = await ocean.accounts.list()
|
||||||
|
const service = ddo.findServiceByType('access')
|
||||||
|
|
||||||
|
const agreements = await ocean.keeper.conditions.accessSecretStoreCondition.getGrantedDidByConsumer(
|
||||||
|
accounts[0].id
|
||||||
|
)
|
||||||
|
const agreement = agreements.find((element: any) => {
|
||||||
|
return element.did === ddo.id
|
||||||
|
})
|
||||||
|
|
||||||
|
let agreementId
|
||||||
|
|
||||||
|
if (agreement) {
|
||||||
|
;({ agreementId } = agreement)
|
||||||
|
} else {
|
||||||
|
agreementId = await ocean.assets
|
||||||
|
.order(ddo.id, service.index, accounts[0])
|
||||||
|
.next((step: number) => this.setState({ step }))
|
||||||
|
}
|
||||||
|
|
||||||
|
// manually add another step here for better UX
|
||||||
|
this.setState({ step: 4 })
|
||||||
|
|
||||||
|
const path = await ocean.assets.consume(
|
||||||
|
agreementId,
|
||||||
|
ddo.id,
|
||||||
|
service.index,
|
||||||
|
accounts[0],
|
||||||
|
'',
|
||||||
|
index
|
||||||
|
)
|
||||||
|
Logger.log('path', path)
|
||||||
|
ReactGA.event({
|
||||||
|
category: 'Purchase',
|
||||||
|
action: 'purchaseAsset-end ' + ddo.id
|
||||||
|
})
|
||||||
|
this.setState({ isLoading: false })
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error('error', error.message)
|
||||||
|
this.setState({
|
||||||
|
isLoading: false,
|
||||||
|
error: `${error.message}. Sorry about that, can you try again?`
|
||||||
|
})
|
||||||
|
ReactGA.event({
|
||||||
|
category: 'Purchase',
|
||||||
|
action: 'purchaseAsset-error ' + error.message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
const { ddo, file } = this.props
|
||||||
|
const { isLoading, error, step } = this.state
|
||||||
|
const { isLogged } = this.context
|
||||||
|
const { index, contentType, contentLength } = file
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.fileWrap}>
|
||||||
|
<ul key={index} className={styles.file}>
|
||||||
|
{contentType || contentLength ? (
|
||||||
|
<>
|
||||||
|
<li>{cleanupContentType(contentType)}</li>
|
||||||
|
<li>
|
||||||
|
{contentLength && contentLength !== '0'
|
||||||
|
? filesize(contentLength)
|
||||||
|
: ''}
|
||||||
|
</li>
|
||||||
|
{/* <li>{encoding}</li> */}
|
||||||
|
{/* <li>{compression}</li> */}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<li className={styles.empty}>No file info available</li>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{isLoading ? (
|
||||||
|
<Spinner message={messages[step]} />
|
||||||
|
) : (
|
||||||
|
<Market.Consumer>
|
||||||
|
{market => (
|
||||||
|
<Button
|
||||||
|
primary
|
||||||
|
className={styles.buttonMain}
|
||||||
|
// weird 0 hack so TypeScript is happy
|
||||||
|
onClick={() =>
|
||||||
|
this.purchaseAsset(ddo, index || 0)
|
||||||
|
}
|
||||||
|
disabled={!isLogged || !market.networkMatch}
|
||||||
|
name="Download"
|
||||||
|
>
|
||||||
|
Get file
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Market.Consumer>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{error !== '' && <div className={styles.error}>{error}</div>}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,27 +27,60 @@ export const ipfsNodeUri =
|
|||||||
//
|
//
|
||||||
export const CONNECTIONS = {
|
export const CONNECTIONS = {
|
||||||
pacific: {
|
pacific: {
|
||||||
nodeUri: 'https://pacific.oceanprotocol.com',
|
nodeUri:
|
||||||
aquariusUri: 'https://aquarius.commons.oceanprotocol.com',
|
process.env.REACT_APP_NODE_URI ||
|
||||||
brizoUri: 'https://brizo.commons.oceanprotocol.com',
|
'https://pacific.oceanprotocol.com',
|
||||||
brizoAddress: '0x008c25ed3594e094db4592f4115d5fa74c4f41ea',
|
aquariusUri:
|
||||||
secretStoreUri: 'https://secret-store.oceanprotocol.com',
|
process.env.REACT_APP_AQUARIUS_URI ||
|
||||||
faucetUri: 'https://faucet.oceanprotocol.com'
|
'https://aquarius.commons.oceanprotocol.com',
|
||||||
|
brizoUri:
|
||||||
|
process.env.REACT_APP_BRIZO_URI ||
|
||||||
|
'https://brizo.commons.oceanprotocol.com',
|
||||||
|
brizoAddress:
|
||||||
|
process.env.REACT_APP_BRIZO_ADDRESS ||
|
||||||
|
'0x008c25ed3594e094db4592f4115d5fa74c4f41ea',
|
||||||
|
secretStoreUri:
|
||||||
|
process.env.REACT_APP_SECRET_STORE_URI ||
|
||||||
|
'https://secret-store.oceanprotocol.com',
|
||||||
|
faucetUri:
|
||||||
|
process.env.REACT_APP_FAUCET_URI ||
|
||||||
|
'https://faucet.oceanprotocol.com'
|
||||||
},
|
},
|
||||||
nile: {
|
nile: {
|
||||||
nodeUri: 'https://nile.dev-ocean.com',
|
nodeUri: process.env.REACT_APP_NODE_URI || 'https://nile.dev-ocean.com',
|
||||||
aquariusUri: 'https://aquarius.nile.dev-ocean.com',
|
aquariusUri:
|
||||||
brizoUri: 'https://brizo.nile.dev-ocean.com',
|
process.env.REACT_APP_AQUARIUS_URI ||
|
||||||
brizoAddress: '0x4aaab179035dc57b35e2ce066919048686f82972',
|
'https://aquarius.nile.dev-ocean.com',
|
||||||
secretStoreUri: 'https://secret-store.nile.dev-ocean.com',
|
brizoUri:
|
||||||
faucetUri: 'https://faucet.nile.dev-ocean.com'
|
process.env.REACT_APP_BRIZO_URI ||
|
||||||
|
'https://brizo.nile.dev-ocean.com',
|
||||||
|
brizoAddress:
|
||||||
|
process.env.REACT_APP_BRIZO_ADDRESS ||
|
||||||
|
'0x4aaab179035dc57b35e2ce066919048686f82972',
|
||||||
|
secretStoreUri:
|
||||||
|
process.env.REACT_APP_SECRET_STORE_URI ||
|
||||||
|
'https://secret-store.nile.dev-ocean.com',
|
||||||
|
faucetUri:
|
||||||
|
process.env.REACT_APP_FAUCET_URI ||
|
||||||
|
'https://faucet.nile.dev-ocean.com'
|
||||||
},
|
},
|
||||||
duero: {
|
duero: {
|
||||||
nodeUri: 'https://duero.dev-ocean.com',
|
nodeUri:
|
||||||
aquariusUri: 'https://aquarius.duero.dev-ocean.com',
|
process.env.REACT_APP_NODE_URI || 'https://duero.dev-ocean.com',
|
||||||
brizoUri: 'https://brizo.duero.dev-ocean.com',
|
aquariusUri:
|
||||||
brizoAddress: '0x9d4ed58293f71122ad6a733c1603927a150735d0',
|
process.env.REACT_APP_AQUARIUS_URI ||
|
||||||
secretStoreUri: 'https://secret-store.duero.dev-ocean.com',
|
'https://aquarius.duero.dev-ocean.com',
|
||||||
faucetUri: 'https://faucet.duero.dev-ocean.com'
|
brizoUri:
|
||||||
|
process.env.REACT_APP_BRIZO_URI ||
|
||||||
|
'https://brizo.duero.dev-ocean.com',
|
||||||
|
brizoAddress:
|
||||||
|
process.env.REACT_APP_BRIZO_ADDRESS ||
|
||||||
|
'0x9d4ed58293f71122ad6a733c1603927a150735d0',
|
||||||
|
secretStoreUri:
|
||||||
|
process.env.REACT_APP_SECRET_STORE_URI ||
|
||||||
|
'https://secret-store.duero.dev-ocean.com',
|
||||||
|
faucetUri:
|
||||||
|
process.env.REACT_APP_FAUCET_URI ||
|
||||||
|
'https://faucet.duero.dev-ocean.com'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,48 +1,48 @@
|
|||||||
import Web3 from 'web3'
|
import Web3 from 'web3'
|
||||||
|
|
||||||
export class MetamaskProvider {
|
export class MetamaskProvider {
|
||||||
private web3: Web3
|
private web3: Web3
|
||||||
|
|
||||||
public constructor() {
|
public constructor() {
|
||||||
// Default
|
// Default
|
||||||
this.web3 = null as any
|
this.web3 = null as any
|
||||||
// Modern dapp browsers
|
// Modern dapp browsers
|
||||||
if (window.ethereum) {
|
if (window.ethereum) {
|
||||||
this.web3 = new Web3(window.ethereum)
|
this.web3 = new Web3(window.ethereum)
|
||||||
|
}
|
||||||
|
// Legacy dapp browsers
|
||||||
|
else if (window.web3) {
|
||||||
|
this.web3 = new Web3(window.web3.currentProvider)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Legacy dapp browsers
|
|
||||||
else if (window.web3) {
|
public async isAvailable() {
|
||||||
this.web3 = new Web3(window.web3.currentProvider)
|
return this.web3 !== null
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public async isAvailable() {
|
public async isLogged() {
|
||||||
return this.web3 !== null
|
if (this.web3 === null) return false
|
||||||
}
|
if ((await this.web3.eth.getAccounts()).length > 0) {
|
||||||
|
return true
|
||||||
public async isLogged() {
|
}
|
||||||
if (this.web3 === null) return false
|
return false
|
||||||
if ((await this.web3.eth.getAccounts()).length > 0) {
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
public async startLogin() {
|
public async startLogin() {
|
||||||
try {
|
try {
|
||||||
await window.ethereum.enable()
|
await window.ethereum.enable()
|
||||||
localStorage.setItem('logType', 'Metamask')
|
localStorage.setItem('logType', 'Metamask')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return false
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public async logout() {
|
public async logout() {
|
||||||
localStorage.removeItem('logType')
|
localStorage.removeItem('logType')
|
||||||
// reload page?
|
// reload page?
|
||||||
}
|
}
|
||||||
|
|
||||||
public getProvider() {
|
public getProvider() {
|
||||||
return this.web3
|
return this.web3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,16 +5,16 @@ import App from './App'
|
|||||||
import * as serviceWorker from './serviceWorker'
|
import * as serviceWorker from './serviceWorker'
|
||||||
|
|
||||||
function renderToDOM() {
|
function renderToDOM() {
|
||||||
const root = document.getElementById('root')
|
const root = document.getElementById('root')
|
||||||
|
|
||||||
if (root !== null) {
|
if (root !== null) {
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<UserProvider>
|
<UserProvider>
|
||||||
<App />
|
<App />
|
||||||
</UserProvider>,
|
</UserProvider>,
|
||||||
root
|
root
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export { renderToDOM }
|
export { renderToDOM }
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
import { MetaData } from '@oceanprotocol/squid'
|
import { MetaData } from '@oceanprotocol/squid'
|
||||||
|
|
||||||
const AssetModel: MetaData = {
|
const AssetModel: MetaData = {
|
||||||
// OEP-08 Attributes
|
// OEP-08 Attributes
|
||||||
// https://github.com/oceanprotocol/OEPs/tree/master/8
|
// https://github.com/oceanprotocol/OEPs/tree/master/8
|
||||||
main: {
|
main: {
|
||||||
type: 'dataset',
|
type: 'dataset',
|
||||||
name: '',
|
name: '',
|
||||||
dateCreated: '',
|
dateCreated: '',
|
||||||
author: '',
|
author: '',
|
||||||
license: '',
|
license: '',
|
||||||
price: '',
|
price: '',
|
||||||
files: []
|
files: []
|
||||||
},
|
},
|
||||||
additionalInformation: {
|
additionalInformation: {
|
||||||
description: '',
|
description: '',
|
||||||
copyrightHolder: '',
|
copyrightHolder: '',
|
||||||
categories: []
|
categories: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default AssetModel
|
export default AssetModel
|
||||||
|
@ -10,48 +10,48 @@ const history = createMemoryHistory()
|
|||||||
const location = createLocation('/faucet')
|
const location = createLocation('/faucet')
|
||||||
|
|
||||||
const setup = () => {
|
const setup = () => {
|
||||||
const utils = render(
|
const utils = render(
|
||||||
<User.Provider value={userMockConnected}>
|
<User.Provider value={userMockConnected}>
|
||||||
<Market.Provider
|
<Market.Provider
|
||||||
value={{
|
value={{
|
||||||
network: 'pacific',
|
network: 'pacific',
|
||||||
totalAssets: 100,
|
totalAssets: 100,
|
||||||
categories: [''],
|
categories: [''],
|
||||||
networkMatch: true
|
networkMatch: true
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<Faucet
|
<Faucet
|
||||||
history={history}
|
history={history}
|
||||||
location={location}
|
location={location}
|
||||||
match={{ params: '', path: '', url: '', isExact: true }}
|
match={{ params: '', path: '', url: '', isExact: true }}
|
||||||
/>
|
/>
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
</Market.Provider>
|
</Market.Provider>
|
||||||
</User.Provider>
|
</User.Provider>
|
||||||
)
|
)
|
||||||
const button = utils.getByText('Request ETH')
|
const button = utils.getByText('Request ETH')
|
||||||
const { container } = utils
|
const { container } = utils
|
||||||
return { button, container, ...utils }
|
return { button, container, ...utils }
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Faucet', () => {
|
describe('Faucet', () => {
|
||||||
it('renders without crashing', () => {
|
it('renders without crashing', () => {
|
||||||
const { container } = setup()
|
const { container } = setup()
|
||||||
expect(container.firstChild).toBeInTheDocument()
|
expect(container.firstChild).toBeInTheDocument()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('shows actions when connected', () => {
|
it('shows actions when connected', () => {
|
||||||
const { button } = setup()
|
const { button } = setup()
|
||||||
expect(button).toBeInTheDocument()
|
expect(button).toBeInTheDocument()
|
||||||
expect(button).not.toHaveAttribute('disabled')
|
expect(button).not.toHaveAttribute('disabled')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('fires requestFromFaucet', async () => {
|
it('fires requestFromFaucet', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
const { button } = setup()
|
const { button } = setup()
|
||||||
fireEvent.click(button)
|
fireEvent.click(button)
|
||||||
|
})
|
||||||
|
expect(userMockConnected.requestFromFaucet).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
expect(userMockConnected.requestFromFaucet).toHaveBeenCalledTimes(1)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import React, {
|
import React, {
|
||||||
lazy,
|
lazy,
|
||||||
Suspense,
|
Suspense,
|
||||||
FormEvent,
|
FormEvent,
|
||||||
PureComponent,
|
PureComponent,
|
||||||
ChangeEvent
|
ChangeEvent
|
||||||
} from 'react'
|
} from 'react'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { Logger, File } from '@oceanprotocol/squid'
|
import { Logger, File } from '@oceanprotocol/squid'
|
||||||
@ -21,196 +21,202 @@ import Spinner from '../../../components/atoms/Spinner'
|
|||||||
const Ipfs = lazy(() => import('./Ipfs'))
|
const Ipfs = lazy(() => import('./Ipfs'))
|
||||||
|
|
||||||
export interface FilePublish extends File {
|
export interface FilePublish extends File {
|
||||||
found: boolean // non-standard
|
found: boolean // non-standard
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FilesProps {
|
interface FilesProps {
|
||||||
files: File[]
|
files: File[]
|
||||||
placeholder: string
|
placeholder: string
|
||||||
help?: string
|
help?: string
|
||||||
name: string
|
name: string
|
||||||
onChange(
|
onChange(
|
||||||
event:
|
event:
|
||||||
| ChangeEvent<HTMLInputElement>
|
| ChangeEvent<HTMLInputElement>
|
||||||
| FormEvent<HTMLInputElement>
|
| FormEvent<HTMLInputElement>
|
||||||
| ChangeEvent<HTMLSelectElement>
|
| ChangeEvent<HTMLSelectElement>
|
||||||
| ChangeEvent<HTMLTextAreaElement>
|
| ChangeEvent<HTMLTextAreaElement>
|
||||||
): void
|
): void
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FilesStates {
|
interface FilesStates {
|
||||||
isFormShown: boolean
|
isFormShown: boolean
|
||||||
isIpfsFormShown: boolean
|
isIpfsFormShown: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const buttons = [
|
const buttons = [
|
||||||
{
|
{
|
||||||
id: 'url',
|
id: 'url',
|
||||||
title: '+ From URL',
|
title: '+ From URL',
|
||||||
titleActive: '- Cancel'
|
titleActive: '- Cancel'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'ipfs',
|
id: 'ipfs',
|
||||||
title: '+ Add to IPFS',
|
title: '+ Add to IPFS',
|
||||||
titleActive: '- Cancel'
|
titleActive: '- Cancel'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
export default class Files extends PureComponent<FilesProps, FilesStates> {
|
export default class Files extends PureComponent<FilesProps, FilesStates> {
|
||||||
public state: FilesStates = {
|
public state: FilesStates = {
|
||||||
isFormShown: false,
|
|
||||||
isIpfsFormShown: false
|
|
||||||
}
|
|
||||||
|
|
||||||
// for canceling axios requests
|
|
||||||
public signal = axios.CancelToken.source()
|
|
||||||
|
|
||||||
public componentWillUnmount() {
|
|
||||||
this.signal.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
private toggleForm = (e: Event, form: string) => {
|
|
||||||
e.preventDefault()
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
isFormShown: form === 'url' ? !this.state.isFormShown : false,
|
|
||||||
isIpfsFormShown: form === 'ipfs' ? !this.state.isIpfsFormShown : false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private async getFile(url: string) {
|
|
||||||
const file: FilePublish = {
|
|
||||||
url,
|
|
||||||
contentType: '',
|
|
||||||
found: false // non-standard
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await axios({
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
url: `${serviceUri}/api/v1/urlcheck`,
|
|
||||||
data: { url },
|
|
||||||
cancelToken: this.signal.token
|
|
||||||
})
|
|
||||||
|
|
||||||
const { contentLength, contentType, found } = response.data.result
|
|
||||||
|
|
||||||
if (contentLength) file.contentLength = contentLength
|
|
||||||
if (contentType) {
|
|
||||||
file.contentType = contentType
|
|
||||||
file.compression = cleanupContentType(contentType)
|
|
||||||
}
|
|
||||||
|
|
||||||
file.found = found
|
|
||||||
|
|
||||||
return file
|
|
||||||
} catch (error) {
|
|
||||||
!axios.isCancel(error) && Logger.error(error.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private addFile = async (url: string) => {
|
|
||||||
// check for duplicate urls
|
|
||||||
const duplicateFiles = this.props.files.filter(props =>
|
|
||||||
url.includes(props.url)
|
|
||||||
)
|
|
||||||
|
|
||||||
if (duplicateFiles.length > 0) {
|
|
||||||
return this.setState({
|
|
||||||
isFormShown: false,
|
isFormShown: false,
|
||||||
isIpfsFormShown: false
|
isIpfsFormShown: false
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const file: FilePublish | undefined = await this.getFile(url)
|
// for canceling axios requests
|
||||||
file && this.props.files.push(file)
|
public signal = axios.CancelToken.source()
|
||||||
|
|
||||||
const event = {
|
public componentWillUnmount() {
|
||||||
currentTarget: {
|
this.signal.cancel()
|
||||||
name: 'files',
|
|
||||||
value: this.props.files
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.props.onChange(event as any)
|
|
||||||
|
|
||||||
this.setState({
|
private toggleForm = (e: Event, form: string) => {
|
||||||
isFormShown: false,
|
e.preventDefault()
|
||||||
isIpfsFormShown: false
|
|
||||||
})
|
|
||||||
|
|
||||||
this.forceUpdate()
|
this.setState({
|
||||||
}
|
isFormShown: form === 'url' ? !this.state.isFormShown : false,
|
||||||
|
isIpfsFormShown:
|
||||||
private removeFile = (index: number) => {
|
form === 'ipfs' ? !this.state.isIpfsFormShown : false
|
||||||
this.props.files.splice(index, 1)
|
})
|
||||||
const event = {
|
|
||||||
currentTarget: {
|
|
||||||
name: 'files',
|
|
||||||
value: this.props.files
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.props.onChange(event as any)
|
|
||||||
this.forceUpdate()
|
|
||||||
}
|
|
||||||
|
|
||||||
public render() {
|
private async getFile(url: string) {
|
||||||
const { files, help, placeholder, name, onChange } = this.props
|
const file: FilePublish = {
|
||||||
const { isFormShown, isIpfsFormShown } = this.state
|
url,
|
||||||
|
contentType: '',
|
||||||
|
found: false // non-standard
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
try {
|
||||||
<>
|
const response = await axios({
|
||||||
{help && <Help>{help}</Help>}
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
url: `${serviceUri}/api/v1/urlcheck`,
|
||||||
|
data: { url },
|
||||||
|
cancelToken: this.signal.token
|
||||||
|
})
|
||||||
|
|
||||||
{/* Use hidden input to collect files */}
|
const { contentLength, contentType, found } = response.data.result
|
||||||
<input
|
|
||||||
type="hidden"
|
|
||||||
name={name}
|
|
||||||
value={JSON.stringify(files)}
|
|
||||||
onChange={onChange}
|
|
||||||
data-testid="files"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className={styles.newItems}>
|
if (contentLength) file.contentLength = contentLength
|
||||||
{files.length > 0 && (
|
if (contentType) {
|
||||||
<ul className={styles.itemsList}>
|
file.contentType = contentType
|
||||||
{files.map((item: any, index: number) => (
|
file.compression = cleanupContentType(contentType)
|
||||||
<Item
|
}
|
||||||
key={shortid.generate()}
|
|
||||||
item={item}
|
file.found = found
|
||||||
removeFile={() => this.removeFile(index)}
|
|
||||||
|
return file
|
||||||
|
} catch (error) {
|
||||||
|
!axios.isCancel(error) && Logger.error(error.message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private addFile = async (url: string) => {
|
||||||
|
// check for duplicate urls
|
||||||
|
const duplicateFiles = this.props.files.filter(props =>
|
||||||
|
url.includes(props.url)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (duplicateFiles.length > 0) {
|
||||||
|
return this.setState({
|
||||||
|
isFormShown: false,
|
||||||
|
isIpfsFormShown: false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const file: FilePublish | undefined = await this.getFile(url)
|
||||||
|
file && this.props.files.push(file)
|
||||||
|
|
||||||
|
const event = {
|
||||||
|
currentTarget: {
|
||||||
|
name: 'files',
|
||||||
|
value: this.props.files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.props.onChange(event as any)
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
isFormShown: false,
|
||||||
|
isIpfsFormShown: false
|
||||||
|
})
|
||||||
|
|
||||||
|
this.forceUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
|
private removeFile = (index: number) => {
|
||||||
|
this.props.files.splice(index, 1)
|
||||||
|
const event = {
|
||||||
|
currentTarget: {
|
||||||
|
name: 'files',
|
||||||
|
value: this.props.files
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.props.onChange(event as any)
|
||||||
|
this.forceUpdate()
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
const { files, help, placeholder, name, onChange } = this.props
|
||||||
|
const { isFormShown, isIpfsFormShown } = this.state
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{help && <Help>{help}</Help>}
|
||||||
|
|
||||||
|
{/* Use hidden input to collect files */}
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
name={name}
|
||||||
|
value={JSON.stringify(files)}
|
||||||
|
onChange={onChange}
|
||||||
|
data-testid="files"
|
||||||
/>
|
/>
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{buttons.map(button => {
|
<div className={styles.newItems}>
|
||||||
const isActive =
|
{files.length > 0 && (
|
||||||
(button.id === 'url' && isFormShown) ||
|
<ul className={styles.itemsList}>
|
||||||
(button.id === 'ipfs' && isIpfsFormShown)
|
{files.map((item: any, index: number) => (
|
||||||
|
<Item
|
||||||
|
key={shortid.generate()}
|
||||||
|
item={item}
|
||||||
|
removeFile={() => this.removeFile(index)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
|
||||||
return (
|
{buttons.map(button => {
|
||||||
<Button
|
const isActive =
|
||||||
key={shortid.generate()}
|
(button.id === 'url' && isFormShown) ||
|
||||||
link
|
(button.id === 'ipfs' && isIpfsFormShown)
|
||||||
onClick={(e: Event) => this.toggleForm(e, button.id)}
|
|
||||||
>
|
|
||||||
{isActive ? button.titleActive : button.title}
|
|
||||||
</Button>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
|
|
||||||
{isFormShown && (
|
return (
|
||||||
<ItemForm placeholder={placeholder} addFile={this.addFile} />
|
<Button
|
||||||
)}
|
key={shortid.generate()}
|
||||||
|
link
|
||||||
|
onClick={(e: Event) =>
|
||||||
|
this.toggleForm(e, button.id)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{isActive ? button.titleActive : button.title}
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
|
||||||
{isIpfsFormShown && (
|
{isFormShown && (
|
||||||
<Suspense fallback={<Spinner message="Loading..." />}>
|
<ItemForm
|
||||||
<Ipfs addFile={this.addFile} />
|
placeholder={placeholder}
|
||||||
</Suspense>
|
addFile={this.addFile}
|
||||||
)}
|
/>
|
||||||
</div>
|
)}
|
||||||
</>
|
|
||||||
)
|
{isIpfsFormShown && (
|
||||||
}
|
<Suspense fallback={<Spinner message="Loading..." />}>
|
||||||
|
<Ipfs addFile={this.addFile} />
|
||||||
|
</Suspense>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user