mirror of
https://github.com/oceanprotocol/market.git
synced 2024-12-02 05:57:29 +01:00
Merge pull request #101 from oceanprotocol/feature/history-compute
compute fix, compute history
This commit is contained in:
commit
28ad41218e
53
package-lock.json
generated
53
package-lock.json
generated
@ -4457,17 +4457,17 @@
|
||||
"integrity": "sha512-j4PEZSVtKSqxDYMVh/hd5vk088Bg6a6QkrUMTXN9Q6OIFAMfHM235f1AxaakNrEyK0FKMD908KuJEdfFLRn9Hw=="
|
||||
},
|
||||
"@oceanprotocol/contracts": {
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-0.5.6.tgz",
|
||||
"integrity": "sha512-LING+GvW37I0L40rZdPCZ1SvcZurDSGGhT0WOVPNO8oyh2C3bXModDBNE4+gCFa8pTbQBOc4ot1/Zoj9PfT/zA=="
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/contracts/-/contracts-0.5.7.tgz",
|
||||
"integrity": "sha512-p0oOHXr60hXZuLNsQ/PsOQtCfia79thm7MjPxTrnnBvD+csJoHzARYMB0IFj/KTw6U5vLXODgjJAn8x6QksLwg=="
|
||||
},
|
||||
"@oceanprotocol/lib": {
|
||||
"version": "0.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.7.3.tgz",
|
||||
"integrity": "sha512-P+ImSOtNz2iDmYXVWutviBwxfFSY/zql362K+FZz3NQt4wYaMrCIiPALR2IF3/9v2FA2g9itTC7eGvWO7bfxqw==",
|
||||
"version": "0.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@oceanprotocol/lib/-/lib-0.7.5.tgz",
|
||||
"integrity": "sha512-frqMwfsqhyQ7+wfY6ak7+vmrbMVXDd7DuYdXHL2gyzom9uqcLLWhmWFNWo/1hOh750GhZ5d8BT4iX0O9P1JPTw==",
|
||||
"requires": {
|
||||
"@ethereum-navigator/navigator": "^0.5.0",
|
||||
"@oceanprotocol/contracts": "^0.5.6",
|
||||
"@oceanprotocol/contracts": "^0.5.7",
|
||||
"decimal.js": "^10.2.0",
|
||||
"fs": "0.0.1-security",
|
||||
"lzma": "^2.3.2",
|
||||
@ -8134,6 +8134,15 @@
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-modal": {
|
||||
"version": "3.10.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.10.6.tgz",
|
||||
"integrity": "sha512-XpshhwVYir1TRZ2HS5EfmNotJjB8UEC2IkT3omNtiQzROOXSzVLz5xsjwEpACP8U+PctkpfZepX+WT5oDf0a9g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*"
|
||||
}
|
||||
},
|
||||
"@types/react-paginate": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-paginate/-/react-paginate-6.2.1.tgz",
|
||||
@ -16480,6 +16489,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"exenv": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
|
||||
"integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50="
|
||||
},
|
||||
"exif-parser": {
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz",
|
||||
@ -27781,11 +27795,6 @@
|
||||
"tslib": "^1.10.0"
|
||||
}
|
||||
},
|
||||
"no-scroll": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/no-scroll/-/no-scroll-2.1.1.tgz",
|
||||
"integrity": "sha512-YTzGAJOo/B6hkodeT5SKKHpOhAzjMfkUCCXjLJwjWk2F4/InIg+HbdH9kmT7bKpleDuqLZDTRy2OdNtAj0IVyQ=="
|
||||
},
|
||||
"node-abi": {
|
||||
"version": "2.19.1",
|
||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.1.tgz",
|
||||
@ -30997,6 +31006,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-modal": {
|
||||
"version": "3.11.2",
|
||||
"resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.11.2.tgz",
|
||||
"integrity": "sha512-o8gvvCOFaG1T7W6JUvsYjRjMVToLZgLIsi5kdhFIQCtHxDkA47LznX62j+l6YQkpXDbvQegsDyxe/+JJsFQN7w==",
|
||||
"requires": {
|
||||
"exenv": "^1.2.0",
|
||||
"prop-types": "^15.5.10",
|
||||
"react-lifecycles-compat": "^3.0.0",
|
||||
"warning": "^4.0.3"
|
||||
}
|
||||
},
|
||||
"react-onclickoutside": {
|
||||
"version": "6.9.0",
|
||||
"resolved": "https://registry.npmjs.org/react-onclickoutside/-/react-onclickoutside-6.9.0.tgz",
|
||||
@ -31071,15 +31091,6 @@
|
||||
"tslib": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"react-responsive-modal": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/react-responsive-modal/-/react-responsive-modal-5.1.1.tgz",
|
||||
"integrity": "sha512-DjNBoVWfiP+5KCvpqFKhjKPVpPUYjpieCU/F3nlBU4OPImiZyGdM7l8iDjTIEti0lAt02vbuwmAaVLf3z1Mrqw==",
|
||||
"requires": {
|
||||
"classnames": "^2.2.6",
|
||||
"no-scroll": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"react-side-effect": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.0.tgz",
|
||||
|
@ -22,7 +22,7 @@
|
||||
"@coingecko/cryptoformat": "^0.4.2",
|
||||
"@loadable/component": "5.13.1",
|
||||
"@oceanprotocol/art": "^3.0.0",
|
||||
"@oceanprotocol/lib": "^0.7.3",
|
||||
"@oceanprotocol/lib": "^0.7.5",
|
||||
"@oceanprotocol/react": "^0.3.5",
|
||||
"@oceanprotocol/typographies": "^0.1.0",
|
||||
"@sindresorhus/slugify": "^1.0.0",
|
||||
@ -66,8 +66,8 @@
|
||||
"react-dropzone": "^11.2.0",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-markdown": "^5.0.1",
|
||||
"react-modal": "^3.11.2",
|
||||
"react-paginate": "^6.5.0",
|
||||
"react-responsive-modal": "^5.1.1",
|
||||
"react-spring": "^8.0.27",
|
||||
"react-tabs": "^3.1.1",
|
||||
"react-toastify": "^6.0.9",
|
||||
@ -94,6 +94,7 @@
|
||||
"@types/react": "^16.9.53",
|
||||
"@types/react-datepicker": "^3.1.1",
|
||||
"@types/react-helmet": "^6.1.0",
|
||||
"@types/react-modal": "^3.10.6",
|
||||
"@types/react-paginate": "^6.2.1",
|
||||
"@types/react-tabs": "^2.3.2",
|
||||
"@types/remove-markdown": "^0.1.1",
|
||||
|
11
src/@types/ComputeJobMetaData.d.ts
vendored
Normal file
11
src/@types/ComputeJobMetaData.d.ts
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
export interface ComputeJobMetaData {
|
||||
jobId: string
|
||||
did: string
|
||||
dateCreated: string
|
||||
dateFinished: string
|
||||
assetName: string
|
||||
status: number
|
||||
statusText: string
|
||||
algorithmLogUrl: string
|
||||
resultsUrls: string[]
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
.customOverlay {
|
||||
}
|
||||
.customModal {
|
||||
border-radius: 15px;
|
||||
margin: auto;
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
import React, { ReactNode, ReactElement } from 'react'
|
||||
import styles from './BaseDialog.module.css'
|
||||
import { Modal } from 'react-responsive-modal'
|
||||
|
||||
export default function BaseDialog({
|
||||
open,
|
||||
title,
|
||||
onClose,
|
||||
children,
|
||||
disableClose,
|
||||
actions,
|
||||
...other
|
||||
}: {
|
||||
open: boolean
|
||||
title: string
|
||||
onClose: () => void
|
||||
children: ReactNode
|
||||
disableClose?: boolean
|
||||
actions?: any
|
||||
}): ReactElement {
|
||||
return (
|
||||
<Modal
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
classNames={{
|
||||
overlay: styles.customOverlay,
|
||||
modal: styles.customModal
|
||||
}}
|
||||
{...other}
|
||||
>
|
||||
<h2>{title}</h2>
|
||||
<div>{children}</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
96
src/components/atoms/Modal.module.css
Normal file
96
src/components/atoms/Modal.module.css
Normal file
@ -0,0 +1,96 @@
|
||||
/* prevent background scrolling */
|
||||
:global(.ReactModal__Body--open) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.modalOverlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
backdrop-filter: blur(3px);
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
animation: fadeIn 0.2s ease-out backwards;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.modal {
|
||||
composes: box from './Box.module.css';
|
||||
padding: var(--spacer);
|
||||
margin: var(--spacer) auto;
|
||||
max-width: var(--break-point--small);
|
||||
position: relative;
|
||||
animation: moveUp 0.2s ease-out backwards;
|
||||
}
|
||||
|
||||
.modal:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 40rem) {
|
||||
.modal {
|
||||
padding: calc(var(--spacer) * 2);
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
padding-bottom: var(--spacer);
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: var(--font-size-h3);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 40rem) {
|
||||
.title {
|
||||
font-size: var(--font-size-h2);
|
||||
}
|
||||
}
|
||||
|
||||
.description {
|
||||
margin: 0;
|
||||
margin-top: var(--spacer);
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
background: none;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
outline: 0;
|
||||
top: calc(var(--spacer) / 4);
|
||||
right: calc(var(--spacer) / 2);
|
||||
font-size: var(--font-size-h2);
|
||||
color: var(--brand-grey);
|
||||
}
|
||||
|
||||
.close:hover,
|
||||
.close:focus {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes moveUp {
|
||||
from {
|
||||
transform: translate3d(0, 1rem, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
17
src/components/atoms/Modal.test.tsx
Normal file
17
src/components/atoms/Modal.test.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import React from 'react'
|
||||
import { render } from '@testing-library/react'
|
||||
import Modal from './Modal'
|
||||
import ReactModal from 'react-modal'
|
||||
|
||||
describe('Modal', () => {
|
||||
it('renders without crashing', () => {
|
||||
ReactModal.setAppElement(document.createElement('div'))
|
||||
|
||||
render(
|
||||
<Modal title="Hello" isOpen onToggleModal={() => null}>
|
||||
Hello
|
||||
</Modal>
|
||||
)
|
||||
expect(document.querySelector('.ReactModalPortal')).toBeInTheDocument()
|
||||
})
|
||||
})
|
41
src/components/atoms/Modal.tsx
Normal file
41
src/components/atoms/Modal.tsx
Normal file
@ -0,0 +1,41 @@
|
||||
import React, { ReactElement, ReactNode } from 'react'
|
||||
import ReactModal from 'react-modal'
|
||||
import styles from './Modal.module.css'
|
||||
|
||||
if (process.env.NODE_ENV !== 'test') ReactModal.setAppElement('#___gatsby')
|
||||
|
||||
export interface ModalProps extends ReactModal.Props {
|
||||
title: string
|
||||
onToggleModal: () => void
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export default function Modal({
|
||||
title,
|
||||
onToggleModal,
|
||||
children,
|
||||
...props
|
||||
}: ModalProps): ReactElement {
|
||||
return (
|
||||
<ReactModal
|
||||
contentLabel={title}
|
||||
className={styles.modal}
|
||||
overlayClassName={styles.modalOverlay}
|
||||
{...props}
|
||||
>
|
||||
<button
|
||||
className={styles.close}
|
||||
onClick={onToggleModal}
|
||||
data-testid="closeModal"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
|
||||
<header className={styles.header}>
|
||||
<h2 className={styles.title}>{title}</h2>
|
||||
</header>
|
||||
|
||||
{children}
|
||||
</ReactModal>
|
||||
)
|
||||
}
|
32
src/components/atoms/Table.tsx
Normal file
32
src/components/atoms/Table.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import React, { ReactElement } from 'react'
|
||||
import DataTable, { IDataTableProps } from 'react-data-table-component'
|
||||
import Loader from './Loader'
|
||||
import styles from './Table.module.css'
|
||||
|
||||
interface TableProps extends IDataTableProps {
|
||||
isLoading?: boolean
|
||||
}
|
||||
|
||||
function Empty(): ReactElement {
|
||||
return <div className={styles.empty}>No results found</div>
|
||||
}
|
||||
|
||||
export default function Table({
|
||||
data,
|
||||
columns,
|
||||
isLoading
|
||||
}: TableProps): ReactElement {
|
||||
return (
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={data}
|
||||
className={styles.table}
|
||||
noHeader
|
||||
pagination={data?.length >= 9}
|
||||
paginationPerPage={10}
|
||||
noDataComponent={<Empty />}
|
||||
progressPending={isLoading}
|
||||
progressComponent={<Loader />}
|
||||
/>
|
||||
)
|
||||
}
|
@ -3,15 +3,19 @@ import { format, formatDistance } from 'date-fns'
|
||||
|
||||
export default function Time({
|
||||
date,
|
||||
relative
|
||||
relative,
|
||||
isUnix
|
||||
}: {
|
||||
date: string
|
||||
relative?: boolean
|
||||
isUnix?: boolean
|
||||
}): ReactElement {
|
||||
const dateNew = new Date(date)
|
||||
const dateNew = isUnix ? new Date(Number(date) * 1000) : new Date(date)
|
||||
const dateIso = dateNew.toISOString()
|
||||
|
||||
return (
|
||||
return !date ? (
|
||||
<></>
|
||||
) : (
|
||||
<time
|
||||
title={relative ? format(dateNew, 'MMMM d, yyyy') : undefined}
|
||||
dateTime={dateIso}
|
||||
|
@ -39,11 +39,9 @@ export default function Compute({
|
||||
const [isJobStarting, setIsJobStarting] = useState(false)
|
||||
const [, setError] = useState('')
|
||||
const [computeType, setComputeType] = useState('nodejs')
|
||||
const [computeContainer, setComputeContainer] = useState({
|
||||
entrypoint: '',
|
||||
image: '',
|
||||
tag: ''
|
||||
})
|
||||
const [computeContainer, setComputeContainer] = useState(
|
||||
computeOptions[0].value
|
||||
)
|
||||
const [algorithmRawCode, setAlgorithmRawCode] = useState('')
|
||||
const [isPublished, setIsPublished] = useState(false)
|
||||
const [file, setFile] = useState(null)
|
||||
@ -130,17 +128,20 @@ export default function Compute({
|
||||
<Dropzone multiple={false} handleOnDrop={onDrop} />
|
||||
|
||||
<div className={styles.actions}>
|
||||
<Button
|
||||
style="primary"
|
||||
onClick={() => startJob()}
|
||||
disabled={isComputeButtonDisabled}
|
||||
>
|
||||
{hasDatatoken ? 'Start job' : 'Buy'}
|
||||
</Button>
|
||||
{isLoading ? (
|
||||
<Loader message={computeStepText} />
|
||||
) : (
|
||||
<Button
|
||||
style="primary"
|
||||
onClick={() => startJob()}
|
||||
disabled={isComputeButtonDisabled}
|
||||
>
|
||||
{hasDatatoken ? 'Start job' : 'Buy'}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<footer className={styles.feedback}>
|
||||
{isLoading && <Loader message={computeStepText} />}
|
||||
{computeError !== undefined && (
|
||||
<Alert text={computeError} state="error" />
|
||||
)}
|
||||
|
3
src/components/pages/History/ComputeDetails.module.css
Normal file
3
src/components/pages/History/ComputeDetails.module.css
Normal file
@ -0,0 +1,3 @@
|
||||
.title {
|
||||
margin-bottom: calc(var(--spacer) / 4);
|
||||
}
|
99
src/components/pages/History/ComputeDetails.tsx
Normal file
99
src/components/pages/History/ComputeDetails.tsx
Normal file
@ -0,0 +1,99 @@
|
||||
import { Logger } from '@oceanprotocol/lib'
|
||||
import { useOcean } from '@oceanprotocol/react'
|
||||
import React, { ReactElement, useEffect, useState } from 'react'
|
||||
import Loader from '../../atoms/Loader'
|
||||
import Modal from '../../atoms/Modal'
|
||||
import { ComputeJobMetaData } from '../../../@types/ComputeJobMetaData'
|
||||
import Time from '../../atoms/Time'
|
||||
import shortid from 'shortid'
|
||||
import styles from './ComputeDetails.module.css'
|
||||
import { Status } from './ComputeJobs'
|
||||
import { ListItem } from '../../atoms/Lists'
|
||||
|
||||
export default function ComputeDetailsModal({
|
||||
computeJob,
|
||||
isOpen,
|
||||
onToggleModal
|
||||
}: {
|
||||
computeJob: ComputeJobMetaData
|
||||
isOpen: boolean
|
||||
onToggleModal: () => void
|
||||
}): ReactElement {
|
||||
const { ocean, status, account } = useOcean()
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
const isFinished = computeJob.dateFinished !== null
|
||||
|
||||
useEffect(() => {
|
||||
async function getDetails() {
|
||||
if (!account || !ocean || !computeJob || !isOpen || !isFinished) return
|
||||
|
||||
try {
|
||||
setIsLoading(true)
|
||||
const job = await ocean.compute.status(
|
||||
account,
|
||||
computeJob.did,
|
||||
computeJob.jobId
|
||||
)
|
||||
if (job && job.length > 0) {
|
||||
computeJob.algorithmLogUrl = job[0].algorithmLogUrl
|
||||
// hack because ComputeJob returns resultsUrl instead of resultsUrls, issue created already
|
||||
computeJob.resultsUrls =
|
||||
(job[0] as any).resultsUrl !== '' ? (job[0] as any).resultsUrl : []
|
||||
}
|
||||
} catch (error) {
|
||||
Logger.error(error.message)
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
getDetails()
|
||||
}, [ocean, status, account, isOpen, computeJob, isFinished])
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="Compute job details"
|
||||
isOpen={isOpen}
|
||||
onToggleModal={onToggleModal}
|
||||
>
|
||||
<h3 className={styles.title}>{computeJob.assetName}</h3>
|
||||
<p>
|
||||
Created on <Time date={computeJob.dateCreated} isUnix />
|
||||
{computeJob.dateFinished && (
|
||||
<>
|
||||
<br />
|
||||
Finished on <Time date={computeJob.dateFinished} isUnix />
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
<Status>{computeJob.statusText}</Status>
|
||||
|
||||
{isFinished &&
|
||||
(isLoading ? (
|
||||
<Loader />
|
||||
) : (
|
||||
<>
|
||||
<ul>
|
||||
<ListItem>
|
||||
<a
|
||||
href={computeJob.algorithmLogUrl}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
View Log
|
||||
</a>
|
||||
</ListItem>
|
||||
|
||||
{computeJob.resultsUrls?.map((url, i) => (
|
||||
<ListItem key={shortid.generate()}>
|
||||
<a href={url} target="_blank" rel="noreferrer">
|
||||
View Result {i}
|
||||
</a>
|
||||
</ListItem>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
))}
|
||||
</Modal>
|
||||
)
|
||||
}
|
4
src/components/pages/History/ComputeJobs.module.css
Normal file
4
src/components/pages/History/ComputeJobs.module.css
Normal file
@ -0,0 +1,4 @@
|
||||
.status {
|
||||
text-transform: uppercase;
|
||||
color: var(--color-secondary);
|
||||
}
|
141
src/components/pages/History/ComputeJobs.tsx
Normal file
141
src/components/pages/History/ComputeJobs.tsx
Normal file
@ -0,0 +1,141 @@
|
||||
import { useOcean } from '@oceanprotocol/react'
|
||||
import React, { ReactElement, useEffect, useState } from 'react'
|
||||
import Time from '../../atoms/Time'
|
||||
import styles from './ComputeJobs.module.css'
|
||||
import Button from '../../atoms/Button'
|
||||
import ComputeDetails from './ComputeDetails'
|
||||
import { ComputeJobMetaData } from '../../../@types/ComputeJobMetaData'
|
||||
import { Link } from 'gatsby'
|
||||
import { Logger } from '@oceanprotocol/lib'
|
||||
import Dotdotdot from 'react-dotdotdot'
|
||||
import Table from '../../atoms/Table'
|
||||
|
||||
function DetailsButton({ row }: { row: ComputeJobMetaData }): ReactElement {
|
||||
const [isDialogOpen, setIsDialogOpen] = useState(false)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button style="text" size="small" onClick={() => setIsDialogOpen(true)}>
|
||||
Show Details
|
||||
</Button>
|
||||
<ComputeDetails
|
||||
computeJob={row}
|
||||
isOpen={isDialogOpen}
|
||||
onToggleModal={() => setIsDialogOpen(false)}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export function Status({ children }: { children: string }): ReactElement {
|
||||
return <div className={styles.status}>{children}</div>
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{
|
||||
name: 'Data Set',
|
||||
selector: function getAssetRow(row: ComputeJobMetaData) {
|
||||
return (
|
||||
<Dotdotdot clamp={2}>
|
||||
<Link to={`/asset/${row.did}`}>{row.assetName}</Link>
|
||||
</Dotdotdot>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Created',
|
||||
selector: function getTimeRow(row: ComputeJobMetaData) {
|
||||
return <Time date={row.dateCreated} isUnix relative />
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Finished',
|
||||
selector: function getTimeRow(row: ComputeJobMetaData) {
|
||||
return <Time date={row.dateFinished} isUnix />
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Status',
|
||||
selector: function getStatus(row: ComputeJobMetaData) {
|
||||
return <Status>{row.statusText}</Status>
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Actions',
|
||||
selector: function getActions(row: ComputeJobMetaData) {
|
||||
return <DetailsButton row={row} />
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
export default function ComputeJobs(): ReactElement {
|
||||
const { ocean, account } = useOcean()
|
||||
const [jobs, setJobs] = useState<ComputeJobMetaData[]>()
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
async function getTitle(did: string) {
|
||||
const ddo = await ocean.metadatacache.retrieveDDO(did)
|
||||
const metadata = ddo.findServiceByType('metadata')
|
||||
return metadata.attributes.main.name
|
||||
}
|
||||
|
||||
async function getJobs() {
|
||||
if (!ocean || !account) return
|
||||
setIsLoading(true)
|
||||
try {
|
||||
const orderHistory = await ocean.assets.getOrderHistory(
|
||||
account,
|
||||
'compute',
|
||||
100
|
||||
)
|
||||
const jobs: ComputeJobMetaData[] = []
|
||||
|
||||
for (let i = 0; i < orderHistory.length; i++) {
|
||||
const assetName = await getTitle(orderHistory[i].did)
|
||||
const computeJob = await ocean.compute.status(
|
||||
account,
|
||||
orderHistory[i].did,
|
||||
undefined,
|
||||
orderHistory[i].transactionHash,
|
||||
false
|
||||
)
|
||||
computeJob.forEach((item) => {
|
||||
jobs.push({
|
||||
did: orderHistory[i].did,
|
||||
jobId: item.jobId,
|
||||
dateCreated: item.dateCreated,
|
||||
dateFinished: item.dateFinished,
|
||||
assetName: assetName,
|
||||
status: item.status,
|
||||
statusText: item.statusText,
|
||||
algorithmLogUrl: '',
|
||||
resultsUrls: []
|
||||
})
|
||||
})
|
||||
}
|
||||
const jobsSorted = jobs.sort((a, b) => {
|
||||
if (a.dateCreated > b.dateCreated) return -1
|
||||
if (a.dateCreated < b.dateCreated) return 1
|
||||
return 0
|
||||
})
|
||||
setJobs(jobsSorted)
|
||||
} catch (error) {
|
||||
Logger.log(error.message)
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
getJobs()
|
||||
}, [ocean, account])
|
||||
|
||||
return (
|
||||
<Table
|
||||
columns={columns}
|
||||
data={jobs}
|
||||
isLoading={isLoading}
|
||||
defaultSortField="row.dateCreated"
|
||||
defaultSortAsc={false}
|
||||
/>
|
||||
)
|
||||
}
|
@ -2,18 +2,18 @@ import { PoolTransaction } from '@oceanprotocol/lib/dist/node/balancer/OceanPool
|
||||
import { useMetadata, useOcean } from '@oceanprotocol/react'
|
||||
import { Link } from 'gatsby'
|
||||
import React, { ReactElement, useEffect, useState } from 'react'
|
||||
import DataTable from 'react-data-table-component'
|
||||
import EtherscanLink from '../../atoms/EtherscanLink'
|
||||
import Time from '../../atoms/Time'
|
||||
import styles from './PoolTransactions.module.css'
|
||||
import Dotdotdot from 'react-dotdotdot'
|
||||
import Table from '../../atoms/Table'
|
||||
|
||||
function AssetTitle({ did }: { did: string }): ReactElement {
|
||||
const { title } = useMetadata(did)
|
||||
return <Link to={`/asset/${did}`}>{title || did}</Link>
|
||||
}
|
||||
|
||||
function Empty() {
|
||||
return <div className={styles.empty}>No results found</div>
|
||||
return (
|
||||
<Dotdotdot clamp={2}>
|
||||
<Link to={`/asset/${did}`}>{title || did}</Link>
|
||||
</Dotdotdot>
|
||||
)
|
||||
}
|
||||
|
||||
function Title({ row }: { row: PoolTransaction }) {
|
||||
@ -60,9 +60,7 @@ const columns = [
|
||||
{
|
||||
name: 'Time',
|
||||
selector: function getTimeRow(row: PoolTransaction) {
|
||||
return (
|
||||
<Time date={new Date(row.timestamp * 1000).toUTCString()} relative />
|
||||
)
|
||||
return <Time date={row.timestamp.toString()} relative isUnix />
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -70,33 +68,24 @@ const columns = [
|
||||
export default function PoolTransactions(): ReactElement {
|
||||
const { ocean, accountId } = useOcean()
|
||||
const [logs, setLogs] = useState<PoolTransaction[]>()
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
async function getLogs() {
|
||||
if (!ocean || !accountId) return
|
||||
|
||||
setIsLoading(true)
|
||||
const logs = await ocean.pool.getAllPoolLogs(accountId)
|
||||
setLogs(
|
||||
// sort logs by date, newest first
|
||||
logs.sort((a, b) => {
|
||||
if (a.timestamp > b.timestamp) return -1
|
||||
if (a.timestamp < b.timestamp) return 1
|
||||
return 0
|
||||
})
|
||||
)
|
||||
// sort logs by date, newest first
|
||||
const logsSorted = logs.sort((a, b) => {
|
||||
if (a.timestamp > b.timestamp) return -1
|
||||
if (a.timestamp < b.timestamp) return 1
|
||||
return 0
|
||||
})
|
||||
setLogs(logsSorted)
|
||||
setIsLoading(false)
|
||||
}
|
||||
getLogs()
|
||||
}, [ocean, accountId])
|
||||
|
||||
return (
|
||||
<DataTable
|
||||
columns={columns}
|
||||
data={logs}
|
||||
className={styles.table}
|
||||
noHeader
|
||||
pagination={logs?.length >= 19}
|
||||
paginationPerPage={20}
|
||||
noDataComponent={<Empty />}
|
||||
/>
|
||||
)
|
||||
return <Table columns={columns} data={logs} isLoading={isLoading} />
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import React, { ReactElement, ReactNode } from 'react'
|
||||
import ComputeJobs from './ComputeJobs'
|
||||
import styles from './index.module.css'
|
||||
import PoolTransactions from './PoolTransactions'
|
||||
import PublishedList from './PublishedList'
|
||||
@ -14,7 +15,7 @@ const sections = [
|
||||
},
|
||||
{
|
||||
title: 'Compute Jobs',
|
||||
component: 'Coming Soon...'
|
||||
component: <ComputeJobs />
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -19,6 +19,15 @@ export function NetworkMonitor(): ReactElement {
|
||||
// add metadataCacheUri only when defined
|
||||
...(metadataCacheUri && { metadataCacheUri })
|
||||
}
|
||||
if (chainId === '8996') {
|
||||
newConfig.factoryAddress = '0x312213d6f6b5FCF9F56B7B8946A6C727Bf4Bc21f'
|
||||
newConfig.poolFactoryAddress =
|
||||
'0xF9E633CBeEB2A474D3Fe22261046C99e805beeC4'
|
||||
newConfig.fixedRateExchangeAddress =
|
||||
'0xefdcb16b16C7842ec27c6fdCf56adc316B9B29B8'
|
||||
newConfig.metadataContractAddress =
|
||||
'0xEBe77E16736359Bf0F9013F6017242a5971cAE76'
|
||||
}
|
||||
|
||||
try {
|
||||
await connect(newConfig)
|
||||
|
Loading…
Reference in New Issue
Block a user