mirror of
https://github.com/oceanprotocol/commons.git
synced 2023-03-15 18:03:00 +01:00
add job on compute asset
This commit is contained in:
parent
f63077181e
commit
d234717a6a
@ -47,7 +47,7 @@
|
||||
display: inline-block;
|
||||
fill: currentColor;
|
||||
margin-right: $spacer / 8;
|
||||
transition: .2s ease-out;
|
||||
transition: 0.2s ease-out;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
.header {
|
||||
// stylelint-disable value-keyword-case
|
||||
composes: categoryImage;
|
||||
composes: categoryimage;
|
||||
// stylelint-enable value-keyword-case
|
||||
height: 8rem;
|
||||
margin-top: $spacer / $line-height;
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
.dimmed {
|
||||
// stylelint-disable value-keyword-case
|
||||
composes: categoryImage;
|
||||
composes: categoryimage;
|
||||
// stylelint-enable value-keyword-case
|
||||
opacity: .6;
|
||||
}
|
||||
|
@ -33,8 +33,8 @@
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
top: 50%;
|
||||
margin-top: -.6rem;
|
||||
fill: rgba($brand-grey-light, .7);
|
||||
margin-top: -0.6rem;
|
||||
fill: rgba($brand-grey-light, 0.7);
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@
|
||||
padding: $spacer / 3;
|
||||
margin: 0;
|
||||
border-radius: $border-radius;
|
||||
transition: .2s ease-out;
|
||||
transition: 0.2s ease-out;
|
||||
min-height: 43px;
|
||||
appearance: none;
|
||||
|
||||
@ -65,8 +65,8 @@
|
||||
font-size: $font-size-base;
|
||||
color: $brand-grey-light;
|
||||
font-weight: $font-weight-base;
|
||||
transition: .2s ease-out;
|
||||
opacity: .7;
|
||||
transition: 0.2s ease-out;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
&[readonly],
|
||||
@ -155,7 +155,7 @@
|
||||
font-size: $font-size-small;
|
||||
line-height: 1.2;
|
||||
border: 2px solid $brand-grey-lighter;
|
||||
border-radius: .2rem;
|
||||
border-radius: 0.2rem;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
|
@ -18,7 +18,7 @@
|
||||
/* yellow triangle */
|
||||
.statusIndicatorCloseEnough {
|
||||
// stylelint-disable value-keyword-case
|
||||
composes: statusIndicator;
|
||||
composes: statusindicator;
|
||||
// stylelint-enable value-keyword-case
|
||||
background: none;
|
||||
width: 0;
|
||||
@ -31,7 +31,7 @@
|
||||
/* green circle */
|
||||
.statusIndicatorActive {
|
||||
// stylelint-disable value-keyword-case
|
||||
composes: statusIndicator;
|
||||
composes: statusindicator;
|
||||
// stylelint-enable value-keyword-case
|
||||
border-radius: 50%;
|
||||
background: $green;
|
||||
|
@ -7,12 +7,12 @@ $popoverWidth: 18rem;
|
||||
width: $popoverWidth;
|
||||
padding: $spacer / 2;
|
||||
background: $brand-black;
|
||||
border-radius: .1rem;
|
||||
border: .1rem solid $brand-grey-light;
|
||||
box-shadow: 0 6px 16px 0 rgba($brand-black, .3);
|
||||
border-radius: 0.1rem;
|
||||
border: 0.1rem solid $brand-grey-light;
|
||||
box-shadow: 0 6px 16px 0 rgba($brand-black, 0.3);
|
||||
color: $brand-grey-light;
|
||||
font-size: $font-size-small;
|
||||
animation: showPopup .2s ease-in forwards;
|
||||
animation: showPopup 0.2s ease-in forwards;
|
||||
white-space: initial;
|
||||
text-align: left;
|
||||
}
|
||||
@ -28,7 +28,7 @@ $popoverWidth: 18rem;
|
||||
}
|
||||
|
||||
.popoverInfoline {
|
||||
border-bottom: .05rem solid $brand-grey;
|
||||
border-bottom: 0.05rem solid $brand-grey;
|
||||
padding: $spacer / 3 0;
|
||||
|
||||
&:first-child {
|
||||
|
@ -24,11 +24,11 @@
|
||||
|
||||
// stylelint-disable value-keyword-case
|
||||
.indicator {
|
||||
composes: statusIndicator from '../AccountStatus/Indicator.module.scss';
|
||||
composes: statusindicator from '../AccountStatus/Indicator.module.scss';
|
||||
}
|
||||
|
||||
.indicatorActive {
|
||||
composes: statusIndicatorActive from '../AccountStatus/Indicator.module.scss';
|
||||
composes: statusindicatoractive from '../AccountStatus/Indicator.module.scss';
|
||||
}
|
||||
// stylelint-enable value-keyword-case
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
align-items: flex-start;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
transition: border .2s ease-out;
|
||||
transition: border 0.2s ease-out;
|
||||
margin-bottom: $spacer;
|
||||
position: relative;
|
||||
|
||||
|
@ -8,9 +8,12 @@ import styles from './AssetDetails.module.scss'
|
||||
import AssetFilesDetails from './AssetFilesDetails'
|
||||
import Report from './Report'
|
||||
import Web3 from 'web3'
|
||||
import AssetsJob from './AssetJob'
|
||||
|
||||
interface AssetDetailsProps {
|
||||
ocean: any
|
||||
metadata: MetaData
|
||||
computeMetadata?: MetaData
|
||||
ddo: DDO
|
||||
}
|
||||
|
||||
@ -30,10 +33,19 @@ const MetaFixedItem = ({ name, value }: { name: string; value: string }) => (
|
||||
</li>
|
||||
)
|
||||
|
||||
export default function AssetDetails({ metadata, ddo }: AssetDetailsProps) {
|
||||
export default function AssetDetails({
|
||||
metadata,
|
||||
ddo,
|
||||
computeMetadata,
|
||||
ocean
|
||||
}: AssetDetailsProps) {
|
||||
const { main, additionalInformation } = metadata
|
||||
const price = main.price && Web3.utils.fromWei(main.price.toString())
|
||||
|
||||
console.log(computeMetadata)
|
||||
const isCompute = computeMetadata ? true : false
|
||||
console.log(isCompute)
|
||||
|
||||
const metaFixed = [
|
||||
{
|
||||
name: 'Author',
|
||||
@ -120,7 +132,18 @@ export default function AssetDetails({ metadata, ddo }: AssetDetailsProps) {
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<AssetFilesDetails files={main.files ? main.files : []} ddo={ddo} />
|
||||
{isCompute ? (
|
||||
<AssetsJob
|
||||
ddo={ddo}
|
||||
ocean={ocean}
|
||||
computeMetadata={computeMetadata}
|
||||
/>
|
||||
) : (
|
||||
<AssetFilesDetails
|
||||
files={main.files ? main.files : []}
|
||||
ddo={ddo}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
100
client/src/components/templates/Asset/AssetJob.module.scss
Normal file
100
client/src/components/templates/Asset/AssetJob.module.scss
Normal file
@ -0,0 +1,100 @@
|
||||
@import '../../../styles/variables';
|
||||
|
||||
.box {
|
||||
margin-bottom: $spacer / 2;
|
||||
background: $brand-white;
|
||||
border-radius: $border-radius;
|
||||
border: 1px solid $brand-grey-lighter;
|
||||
padding: $spacer / 2;
|
||||
}
|
||||
|
||||
.dataType {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.buttonWrapper {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: $red;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.bold {
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.expiry {
|
||||
color: $brand-grey-light;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.job {
|
||||
border-top: 1px solid #e2e2e2;
|
||||
}
|
||||
|
||||
.dragndrop {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
height: 90px;
|
||||
color: $brand-grey-light;
|
||||
background-color: $brand-white;
|
||||
}
|
||||
|
||||
.filleddragndrop {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
font-weight: 900;
|
||||
height: 90px;
|
||||
color: $brand-grey;
|
||||
background-color: $brand-white;
|
||||
}
|
||||
|
||||
.inputWrap {
|
||||
margin-top: $spacer / 4;
|
||||
background: $brand-gradient;
|
||||
border-radius: $border-radius;
|
||||
padding: 2px;
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
&.isFocused {
|
||||
background: $brand-black;
|
||||
}
|
||||
|
||||
> div,
|
||||
> div > div {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.jobButtonWrapper {
|
||||
text-align: right;
|
||||
margin-top: $spacer / 4;
|
||||
}
|
||||
|
||||
.table {
|
||||
margin-top: $spacer / 2;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
||||
.jobloading {
|
||||
padding-left: 23px;
|
||||
}
|
159
client/src/components/templates/Asset/AssetJob.tsx
Normal file
159
client/src/components/templates/Asset/AssetJob.tsx
Normal file
@ -0,0 +1,159 @@
|
||||
import React, { ChangeEvent, useState } from 'react'
|
||||
import { DDO, MetaData } from '@oceanprotocol/squid'
|
||||
import Input from '../../atoms/Form/Input'
|
||||
import computeOptions from '../../../data/computeOptions.json'
|
||||
import styles from './AssetJob.module.scss'
|
||||
import Spinner from '../../atoms/Spinner'
|
||||
import Button from '../../atoms/Button'
|
||||
import { messages } from './AssetFile'
|
||||
import ReactDropzone from 'react-dropzone'
|
||||
|
||||
interface JobsProps {
|
||||
ocean: any
|
||||
computeMetadata?: MetaData
|
||||
ddo: DDO
|
||||
}
|
||||
|
||||
export default function AssetsJobs({ ddo, computeMetadata, ocean }: JobsProps) {
|
||||
let rawAlgorithmMeta = {
|
||||
rawcode: `console.log('Hello world'!)`,
|
||||
format: 'docker-image',
|
||||
version: '0.1',
|
||||
container: {}
|
||||
}
|
||||
|
||||
const [isJobStarting, setIsJobStarting] = useState(false)
|
||||
const [step, setStep] = useState(99)
|
||||
|
||||
const [computeType, setComputeType] = useState('')
|
||||
const [computeValue, setComputeValue] = useState({})
|
||||
const [algorithmRawCode, setAlgorithmRawCode] = useState('')
|
||||
|
||||
const [file, setFile] = useState(null)
|
||||
|
||||
const onDrop = async (files: any) => {
|
||||
setFile(files[0])
|
||||
const fileText = await readFileContent(files[0])
|
||||
setAlgorithmRawCode(fileText)
|
||||
}
|
||||
const handleSelectChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
const comType = event.target.value
|
||||
setComputeType(comType)
|
||||
|
||||
const selectedComputeOption = computeOptions.find(
|
||||
x => x.name === comType
|
||||
)
|
||||
if (selectedComputeOption !== undefined)
|
||||
setComputeValue(selectedComputeOption.value)
|
||||
}
|
||||
const readFileContent = (file: File): Promise<string> => {
|
||||
return new Promise(resolve => {
|
||||
const reader = new FileReader()
|
||||
reader.onload = function(e) {
|
||||
resolve(reader.result as string)
|
||||
}
|
||||
reader.readAsText(file)
|
||||
})
|
||||
}
|
||||
|
||||
const startJob = async () => {
|
||||
try {
|
||||
setIsJobStarting(true)
|
||||
const accounts = await ocean.accounts.list()
|
||||
const ComputeOutput = {
|
||||
publishAlgorithmLog: false,
|
||||
publishOutput: false,
|
||||
brizoAddress: ocean.config.brizoAddress,
|
||||
brizoUri: ocean.config.brizoUri,
|
||||
metadataUri: ocean.config.aquariusUri,
|
||||
nodeUri: ocean.config.nodeUri,
|
||||
owner: accounts[0].getId(),
|
||||
secretStoreUri: ocean.config.secretStoreUri
|
||||
}
|
||||
|
||||
const agreement = await ocean.compute
|
||||
.order(accounts[0], ddo.id)
|
||||
.next((step: number) => setStep(step))
|
||||
|
||||
rawAlgorithmMeta.container = computeValue
|
||||
rawAlgorithmMeta.rawcode = algorithmRawCode
|
||||
|
||||
const status = await ocean.compute.start(
|
||||
accounts[0],
|
||||
agreement,
|
||||
undefined,
|
||||
encodeURIComponent(JSON.stringify(rawAlgorithmMeta)),
|
||||
ComputeOutput
|
||||
)
|
||||
|
||||
console.log(status)
|
||||
} catch (error) {
|
||||
console.error(error.message)
|
||||
}
|
||||
setIsJobStarting(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<div>
|
||||
<span className={styles.bold}>New job</span>
|
||||
<div className={styles.dataType}>
|
||||
<Input
|
||||
type="select"
|
||||
name="select"
|
||||
label="Select data type"
|
||||
placeholder=""
|
||||
value={computeType}
|
||||
options={computeOptions.map(x => x.name)}
|
||||
onChange={handleSelectChange}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div className={styles.inputWrap}>
|
||||
<ReactDropzone
|
||||
onDrop={acceptedFiles => onDrop(acceptedFiles)}
|
||||
>
|
||||
{({ getRootProps, getInputProps }) => (
|
||||
<div {...getRootProps()}>
|
||||
<input {...getInputProps()} />
|
||||
{file === null && (
|
||||
<div className={styles.dragndrop}>
|
||||
Click or drop your notebook here
|
||||
</div>
|
||||
)}
|
||||
{file !== null && (
|
||||
<div
|
||||
className={
|
||||
styles.filleddragndrop
|
||||
}
|
||||
>
|
||||
You selected:{' '}
|
||||
{(file as any).path}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</ReactDropzone>
|
||||
</div>
|
||||
<div className={styles.jobButtonWrapper}>
|
||||
<Button
|
||||
primary
|
||||
onClick={() => startJob()}
|
||||
disabled={
|
||||
isJobStarting ||
|
||||
file === null ||
|
||||
computeType === ''
|
||||
}
|
||||
name="Purchase access"
|
||||
>
|
||||
Start job
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{isJobStarting ? <Spinner message={messages[step]} /> : ''}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
@ -20,8 +20,10 @@ interface AssetProps {
|
||||
}
|
||||
|
||||
interface AssetState {
|
||||
ocean: any
|
||||
ddo: DDO
|
||||
metadata: MetaData
|
||||
computeMetadata?: MetaData
|
||||
error: string
|
||||
isLoading: boolean
|
||||
}
|
||||
@ -30,8 +32,10 @@ class Asset extends Component<AssetProps, AssetState> {
|
||||
public static contextType = User
|
||||
|
||||
public state = {
|
||||
ocean: undefined,
|
||||
ddo: ({} as any) as DDO,
|
||||
metadata: ({ main: { name: '' } } as any) as MetaData,
|
||||
computeMetadata: undefined,
|
||||
error: '',
|
||||
isLoading: true
|
||||
}
|
||||
@ -44,10 +48,19 @@ class Asset extends Component<AssetProps, AssetState> {
|
||||
try {
|
||||
const { ocean } = this.context
|
||||
const ddo = await ocean.assets.resolve(this.props.match.params.did)
|
||||
|
||||
const { attributes } = ddo.findServiceByType('metadata')
|
||||
let computeAttributes
|
||||
|
||||
try {
|
||||
computeAttributes = ddo.findServiceByType('compute')
|
||||
} catch (error) {}
|
||||
|
||||
this.setState({
|
||||
ocean,
|
||||
ddo,
|
||||
metadata: attributes,
|
||||
computeMetadata: computeAttributes,
|
||||
isLoading: false
|
||||
})
|
||||
} catch (error) {
|
||||
@ -59,7 +72,14 @@ class Asset extends Component<AssetProps, AssetState> {
|
||||
}
|
||||
|
||||
public render() {
|
||||
const { metadata, ddo, error, isLoading } = this.state
|
||||
const {
|
||||
metadata,
|
||||
ddo,
|
||||
error,
|
||||
isLoading,
|
||||
computeMetadata,
|
||||
ocean
|
||||
} = this.state
|
||||
const { main, additionalInformation } = metadata
|
||||
|
||||
const hasError = error !== ''
|
||||
@ -88,7 +108,12 @@ class Asset extends Component<AssetProps, AssetState> {
|
||||
}
|
||||
>
|
||||
<Content>
|
||||
<AssetDetails metadata={metadata} ddo={ddo} />
|
||||
<AssetDetails
|
||||
metadata={metadata}
|
||||
ddo={ddo}
|
||||
computeMetadata={computeMetadata}
|
||||
ocean={ocean}
|
||||
/>
|
||||
</Content>
|
||||
</Route>
|
||||
)
|
||||
|
18
client/src/data/computeOptions.json
Normal file
18
client/src/data/computeOptions.json
Normal file
@ -0,0 +1,18 @@
|
||||
[
|
||||
{
|
||||
"name": "nodejs",
|
||||
"value": {
|
||||
"entrypoint": "node $ALGO",
|
||||
"image": "node",
|
||||
"tag": "10"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "pyhton3.6",
|
||||
"value": {
|
||||
"entrypoint": "python3.6 $ALGO",
|
||||
"image": "python",
|
||||
"tag": "3.6"
|
||||
}
|
||||
}
|
||||
]
|
@ -11,6 +11,16 @@
|
||||
"required": true,
|
||||
"help": "Enter a concise title. You will be able to enter a more thorough description in the next step."
|
||||
},
|
||||
"datasetType":{
|
||||
"label": "Dataset type",
|
||||
"help": "Pick the type which best fits your data set.",
|
||||
"type": "select",
|
||||
"required": true,
|
||||
"options": [
|
||||
"access",
|
||||
"compute"
|
||||
]
|
||||
},
|
||||
"files": {
|
||||
"label": "Files",
|
||||
"placeholder": "e.g. https://file.com/file.json",
|
||||
|
@ -14,7 +14,7 @@ import Content from '../../components/atoms/Content'
|
||||
import withTracker from '../../hoc/withTracker'
|
||||
|
||||
type AssetType = 'dataset' | 'algorithm' | 'container' | 'workflow' | 'other'
|
||||
|
||||
type DatasetType = 'compute' | 'access'
|
||||
interface PublishState {
|
||||
name?: string
|
||||
dateCreated?: string
|
||||
@ -26,6 +26,7 @@ interface PublishState {
|
||||
type?: AssetType
|
||||
copyrightHolder?: string
|
||||
categories?: string
|
||||
datasetType?: DatasetType
|
||||
|
||||
currentStep?: number
|
||||
publishingStep?: number
|
||||
@ -60,6 +61,7 @@ class Publish extends Component<{}, PublishState> {
|
||||
license: '',
|
||||
copyrightHolder: '',
|
||||
categories: '',
|
||||
datasetType: 'access' as DatasetType,
|
||||
|
||||
currentStep: 1,
|
||||
isPublishing: false,
|
||||
@ -133,7 +135,8 @@ class Publish extends Component<{}, PublishState> {
|
||||
isPublishing: false,
|
||||
isPublished: false,
|
||||
publishingStep: 0,
|
||||
currentStep: 1
|
||||
currentStep: 1,
|
||||
datasetType: 'access' as DatasetType
|
||||
})
|
||||
}
|
||||
|
||||
@ -256,6 +259,32 @@ class Publish extends Component<{}, PublishState> {
|
||||
}
|
||||
}
|
||||
|
||||
private async createComputeService(
|
||||
ocean: any,
|
||||
publisher: any,
|
||||
price: string,
|
||||
datePublished: string
|
||||
) {
|
||||
const { templates } = ocean.keeper
|
||||
const serviceAgreementTemplate = await templates.escrowComputeExecutionTemplate.getServiceAgreementTemplate()
|
||||
const name = 'dataAssetComputingServiceAgreement'
|
||||
return {
|
||||
type: 'compute',
|
||||
serviceEndpoint: ocean.brizo.getComputeEndpoint(),
|
||||
templateId: templates.escrowComputeExecutionTemplate.getId(),
|
||||
attributes: {
|
||||
main: {
|
||||
creator: publisher.getId(),
|
||||
datePublished,
|
||||
price,
|
||||
timeout: 3600,
|
||||
name
|
||||
},
|
||||
serviceAgreementTemplate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private handleRegisterAsset = async (event: FormEvent<HTMLFormElement>) => {
|
||||
event.preventDefault()
|
||||
|
||||
@ -305,8 +334,21 @@ class Publish extends Component<{}, PublishState> {
|
||||
}
|
||||
|
||||
try {
|
||||
let computeService: any[] = []
|
||||
console.log('dataset type ', this.state.datasetType)
|
||||
if (this.state.datasetType === 'compute') {
|
||||
const service = await this.createComputeService(
|
||||
ocean,
|
||||
account[0],
|
||||
this.state.price,
|
||||
this.state.dateCreated
|
||||
)
|
||||
computeService = [service]
|
||||
console.log('compute ', computeService)
|
||||
}
|
||||
|
||||
const asset = await this.context.ocean.assets
|
||||
.create(newAsset, account[0])
|
||||
.create(newAsset, account[0], computeService)
|
||||
.next((publishingStep: number) =>
|
||||
this.setState({ publishingStep })
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user