diff --git a/_redirects b/_redirects
index b810c2224..db198413a 100644
--- a/_redirects
+++ b/_redirects
@@ -1,2 +1,2 @@
/asset/* /asset/index.html 200
-/account/* /account/index.html 200
\ No newline at end of file
+/profile/* /profile/index.html 200
\ No newline at end of file
diff --git a/content/pages/account.json b/content/pages/profile.json
similarity index 100%
rename from content/pages/account.json
rename to content/pages/profile.json
diff --git a/content/site.json b/content/site.json
index 84e2ede5c..7cef28e78 100644
--- a/content/site.json
+++ b/content/site.json
@@ -12,8 +12,8 @@
"link": "/publish"
},
{
- "name": "My Account",
- "link": "/account"
+ "name": "Profile",
+ "link": "/profile"
}
],
"warning": {
diff --git a/gatsby-node.js b/gatsby-node.js
index cc88386ba..cb611c715 100644
--- a/gatsby-node.js
+++ b/gatsby-node.js
@@ -34,14 +34,14 @@ exports.onCreatePage = async ({ page, actions }) => {
// page.matchPath is a special key that's used for matching pages
// only on the client.
const handleClientSideOnlyAsset = page.path.match(/^\/asset/)
- const handleClientSideOnlyAccount = page.path.match(/^\/account/)
+ const handleClientSideOnlyAccount = page.path.match(/^\/profile/)
if (handleClientSideOnlyAsset) {
page.matchPath = '/asset/*'
// Update the page.
createPage(page)
} else if (handleClientSideOnlyAccount) {
- page.matchPath = '/account/*'
+ page.matchPath = '/profile/*'
createPage(page)
}
}
diff --git a/package-lock.json b/package-lock.json
index 4574eb4f3..94e78b378 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -55,6 +55,7 @@
"query-string": "^7.0.0",
"react": "^17.0.2",
"react-chartjs-2": "^2.11.2",
+ "react-clipboard.js": "^2.0.16",
"react-data-table-component": "^6.11.7",
"react-dom": "^17.0.2",
"react-dotdotdot": "^1.3.1",
@@ -10524,6 +10525,15 @@
"classnames": "*"
}
},
+ "node_modules/@types/clipboard": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/clipboard/-/clipboard-2.0.7.tgz",
+ "integrity": "sha512-VwVFUHlneOsWfv/GaaY7Kwk4XasDqkAlyFQtsHxnOw0yyBYWTrlEXtmb9RtC+VFBCdtuOeIXECmELNd5RrKp/g==",
+ "deprecated": "This is a stub types definition. clipboard provides its own type definitions, so you do not need this installed.",
+ "dependencies": {
+ "clipboard": "*"
+ }
+ },
"node_modules/@types/common-tags": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@types/common-tags/-/common-tags-1.8.0.tgz",
@@ -16998,6 +17008,16 @@
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz",
"integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw=="
},
+ "node_modules/clipboard": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.8.tgz",
+ "integrity": "sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==",
+ "dependencies": {
+ "good-listener": "^1.2.2",
+ "select": "^1.1.2",
+ "tiny-emitter": "^2.0.0"
+ }
+ },
"node_modules/clipboardy": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz",
@@ -19004,6 +19024,11 @@
"node": ">=0.4.0"
}
},
+ "node_modules/delegate": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
+ "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
+ },
"node_modules/delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
@@ -28778,6 +28803,14 @@
"node": ">= 0.10"
}
},
+ "node_modules/good-listener": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
+ "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
+ "dependencies": {
+ "delegate": "^3.1.2"
+ }
+ },
"node_modules/google-protobuf": {
"version": "3.17.3",
"resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.17.3.tgz",
@@ -44904,6 +44937,20 @@
"react-dom": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
}
},
+ "node_modules/react-clipboard.js": {
+ "version": "2.0.16",
+ "resolved": "https://registry.npmjs.org/react-clipboard.js/-/react-clipboard.js-2.0.16.tgz",
+ "integrity": "sha512-COwmnbrRbl8y4f/SjtonnJTeBRD03YzsHBL5on8iL/uyjERsMkKC7djtfmns7iRAbzadn/84MdpaqaQ3ITP47g==",
+ "dependencies": {
+ "@types/clipboard": "^2.0.1",
+ "clipboard": "^2.0.0",
+ "prop-types": "^15.5.0"
+ },
+ "peerDependencies": {
+ "react": ">=15.5.0",
+ "react-dom": ">=15.0.0"
+ }
+ },
"node_modules/react-data-table-component": {
"version": "6.11.7",
"resolved": "https://registry.npmjs.org/react-data-table-component/-/react-data-table-component-6.11.7.tgz",
@@ -47656,6 +47703,11 @@
"seek-table": "bin/seek-bzip-table"
}
},
+ "node_modules/select": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
+ "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
+ },
"node_modules/select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -51465,6 +51517,11 @@
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
},
+ "node_modules/tiny-emitter": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+ "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
+ },
"node_modules/tiny-queue": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/tiny-queue/-/tiny-queue-0.2.1.tgz",
@@ -66972,6 +67029,14 @@
"classnames": "*"
}
},
+ "@types/clipboard": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/clipboard/-/clipboard-2.0.7.tgz",
+ "integrity": "sha512-VwVFUHlneOsWfv/GaaY7Kwk4XasDqkAlyFQtsHxnOw0yyBYWTrlEXtmb9RtC+VFBCdtuOeIXECmELNd5RrKp/g==",
+ "requires": {
+ "clipboard": "*"
+ }
+ },
"@types/common-tags": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@types/common-tags/-/common-tags-1.8.0.tgz",
@@ -72373,6 +72438,16 @@
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz",
"integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw=="
},
+ "clipboard": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.8.tgz",
+ "integrity": "sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==",
+ "requires": {
+ "good-listener": "^1.2.2",
+ "select": "^1.1.2",
+ "tiny-emitter": "^2.0.0"
+ }
+ },
"clipboardy": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz",
@@ -73977,6 +74052,11 @@
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
+ "delegate": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz",
+ "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw=="
+ },
"delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
@@ -81674,6 +81754,14 @@
"minimatch": "~3.0.2"
}
},
+ "good-listener": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz",
+ "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=",
+ "requires": {
+ "delegate": "^3.1.2"
+ }
+ },
"google-protobuf": {
"version": "3.17.3",
"resolved": "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.17.3.tgz",
@@ -94695,6 +94783,16 @@
"prop-types": "^15.7.2"
}
},
+ "react-clipboard.js": {
+ "version": "2.0.16",
+ "resolved": "https://registry.npmjs.org/react-clipboard.js/-/react-clipboard.js-2.0.16.tgz",
+ "integrity": "sha512-COwmnbrRbl8y4f/SjtonnJTeBRD03YzsHBL5on8iL/uyjERsMkKC7djtfmns7iRAbzadn/84MdpaqaQ3ITP47g==",
+ "requires": {
+ "@types/clipboard": "^2.0.1",
+ "clipboard": "^2.0.0",
+ "prop-types": "^15.5.0"
+ }
+ },
"react-data-table-component": {
"version": "6.11.7",
"resolved": "https://registry.npmjs.org/react-data-table-component/-/react-data-table-component-6.11.7.tgz",
@@ -96908,6 +97006,11 @@
"commander": "^2.8.1"
}
},
+ "select": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz",
+ "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0="
+ },
"select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
@@ -100004,6 +100107,11 @@
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q="
},
+ "tiny-emitter": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
+ "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
+ },
"tiny-queue": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/tiny-queue/-/tiny-queue-0.2.1.tgz",
diff --git a/package.json b/package.json
index 00d7cac9c..7bfab8799 100644
--- a/package.json
+++ b/package.json
@@ -70,6 +70,7 @@
"query-string": "^7.0.0",
"react": "^17.0.2",
"react-chartjs-2": "^2.11.2",
+ "react-clipboard.js": "^2.0.16",
"react-data-table-component": "^6.11.7",
"react-dom": "^17.0.2",
"react-dotdotdot": "^1.3.1",
diff --git a/src/components/atoms/Copy.module.css b/src/components/atoms/Copy.module.css
new file mode 100644
index 000000000..ebc157ee4
--- /dev/null
+++ b/src/components/atoms/Copy.module.css
@@ -0,0 +1,35 @@
+.button {
+ display: inline-block;
+ margin: 0;
+ border: 0;
+ box-shadow: none;
+ background: none;
+ padding: 0;
+ cursor: pointer;
+ position: relative;
+}
+
+.icon {
+ fill: var(--color-secondary);
+ transition: 0.15s ease-out;
+ width: 10px;
+ height: 10px;
+}
+
+.button:hover .icon {
+ fill: var(--font-color-text);
+}
+
+.copied .icon,
+.button.copied:hover .icon {
+ fill: var(--brand-alert-green);
+}
+
+.copied::after {
+ content: 'Copied!';
+ position: absolute;
+ top: -150%;
+ left: -100%;
+ font-size: var(--font-size-mini);
+ color: var(--brand-alert-green);
+}
diff --git a/src/components/atoms/Copy.tsx b/src/components/atoms/Copy.tsx
new file mode 100644
index 000000000..d0693963f
--- /dev/null
+++ b/src/components/atoms/Copy.tsx
@@ -0,0 +1,33 @@
+import React, { ReactElement, useEffect, useState } from 'react'
+import loadable from '@loadable/component'
+import styles from './Copy.module.css'
+import { ReactComponent as IconCopy } from '../../images/copy.svg'
+
+// lazy load when needed only, as library is a bit big
+const Clipboard = loadable(() => import('react-clipboard.js'))
+
+export default function Copy({ text }: { text: string }): ReactElement {
+ const [isCopied, setIsCopied] = useState(false)
+
+ // Clear copy success style after 5 sec.
+ useEffect(() => {
+ if (!isCopied) return
+
+ const timeout = setTimeout(() => {
+ setIsCopied(false)
+ }, 5000)
+
+ return () => clearTimeout(timeout)
+ }, [isCopied])
+
+ return (
+ setIsCopied(true)}
+ className={`${styles.button} ${isCopied ? styles.copied : ''}`}
+ >
+
+
+ )
+}
diff --git a/src/components/atoms/Publisher/ProfileDetails.module.css b/src/components/atoms/Publisher/ProfileDetails.module.css
deleted file mode 100644
index a0e85bea5..000000000
--- a/src/components/atoms/Publisher/ProfileDetails.module.css
+++ /dev/null
@@ -1,72 +0,0 @@
-.profile {
- background: var(--background-highlight);
- border-radius: var(--border-radius);
- padding: calc(var(--spacer) / 2);
- margin-bottom: calc(var(--spacer) / 4);
-}
-
-@media (min-width: 40rem) {
- .profile {
- margin: calc(var(--spacer) / 8);
- margin-bottom: calc(var(--spacer) / 4);
- }
-}
-
-.profile p {
- margin-bottom: calc(var(--spacer) / 4);
-}
-
-.profile code {
- padding: 0;
- color: var(--color-secondary);
- font-size: var(--font-size-mini);
- overflow-wrap: break-word;
- word-wrap: break-word;
- word-break: break-word;
-}
-
-.header {
- margin-bottom: calc(var(--spacer) / 4);
- text-align: center;
-}
-
-.header::after {
- content: '';
- display: block;
- margin: calc(var(--spacer) / 2) auto;
- width: 20%;
- height: 2px;
- background: var(--border-color);
-}
-
-.image {
- width: 48px;
- height: 48px;
- border-radius: 50%;
- overflow: hidden;
- display: inline-block;
- margin-bottom: calc(var(--spacer) / 4);
- border: 1px solid var(--border-color);
- box-shadow: 0 6px 17px 0 var(--box-shadow-color);
-}
-
-.title {
- font-size: var(--font-size-base);
- margin-bottom: 0;
-}
-
-.description {
- font-size: var(--font-size-small);
-}
-
-.profile p:last-child {
- margin-bottom: 0;
-}
-
-.meta {
- color: var(--color-secondary);
- font-size: var(--font-size-mini);
- text-align: right;
- margin-left: calc(var(--spacer) / 4);
- margin-right: calc(var(--spacer) / 4);
-}
diff --git a/src/components/atoms/Publisher/ProfileDetails.tsx b/src/components/atoms/Publisher/ProfileDetails.tsx
deleted file mode 100644
index 7f4be381b..000000000
--- a/src/components/atoms/Publisher/ProfileDetails.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import React, { ReactElement } from 'react'
-import styles from './ProfileDetails.module.css'
-import { Profile } from '../../../models/Profile'
-import ExplorerLink from '../ExplorerLink'
-import PublisherLinks from './PublisherLinks'
-
-export default function ProfileDetails({
- profile,
- networkId,
- account
-}: {
- profile: Profile
- networkId: number
- account: string
-}): ReactElement {
- return (
- <>
-
-
- {profile?.image && (
-
-
-
- )}
-
- {profile?.emoji} {profile?.name}
-
-
-
- {account}
-
-
-
- {profile?.description && (
-
{profile?.description}
- )}
-
-
-
- >
- )
-}
diff --git a/src/components/atoms/Publisher/index.module.css b/src/components/atoms/Publisher/index.module.css
index 71a0287b8..93592f599 100644
--- a/src/components/atoms/Publisher/index.module.css
+++ b/src/components/atoms/Publisher/index.module.css
@@ -8,40 +8,9 @@
}
}
-.links {
- display: inline;
-}
-
-.links a,
-.links span {
- margin-left: calc(var(--spacer) / 3);
- font-size: var(--font-size-mini);
-}
-
-.links a:first-child,
-.links span:first-child {
- margin-left: 0;
-}
-
-.links a:hover,
-.links a:focus {
- color: var(--brand-pink);
-}
-
.linksExternal {
width: 6px;
height: 6px;
display: inline-block;
fill: var(--color-secondary);
}
-
-.detailsTrigger {
- cursor: help;
-}
-
-.detailsTrigger svg {
- width: 10px;
- height: 10px;
- position: relative;
- bottom: -1px;
-}
diff --git a/src/components/atoms/Publisher/index.tsx b/src/components/atoms/Publisher/index.tsx
index 8fac6942c..38934bf90 100644
--- a/src/components/atoms/Publisher/index.tsx
+++ b/src/components/atoms/Publisher/index.tsx
@@ -1,15 +1,11 @@
import React, { ReactElement, useEffect, useState } from 'react'
import styles from './index.module.css'
import classNames from 'classnames/bind'
-import Tooltip from '../Tooltip'
import { Profile } from '../../../models/Profile'
import { Link } from 'gatsby'
import get3BoxProfile from '../../../utils/profile'
-import ExplorerLink from '../ExplorerLink'
import { accountTruncate } from '../../../utils/web3'
import axios from 'axios'
-import { ReactComponent as Info } from '../../../images/info.svg'
-import ProfileDetails from './ProfileDetails'
import Add from './Add'
import { useWeb3 } from '../../../providers/Web3'
@@ -62,35 +58,10 @@ export default function Publisher({
name
) : (
<>
-
+
{name}
-
- {' — '}
- {profile && (
-
- }
- >
-
- Profile
-
-
- )}
- {showAdd &&
}
-
- Explorer
-
-
+ {showAdd && }
>
)}
diff --git a/src/components/atoms/Tabs.module.css b/src/components/atoms/Tabs.module.css
index 3d76fc0d6..f138f9458 100644
--- a/src/components/atoms/Tabs.module.css
+++ b/src/components/atoms/Tabs.module.css
@@ -1,8 +1,7 @@
.tabList {
text-align: center;
border-bottom: 1px solid var(--border-color);
- padding-top: calc(var(--spacer) / 2);
- padding-bottom: calc(var(--spacer) / 2);
+ padding: calc(var(--spacer) / 2);
}
.tab {
@@ -36,5 +35,11 @@
}
.tabContent {
- padding: var(--spacer);
+ padding: calc(var(--spacer) / 2);
+}
+
+@media (min-width: 40rem) {
+ .tabContent {
+ padding: var(--spacer);
+ }
}
diff --git a/src/components/molecules/NumberUnit.module.css b/src/components/molecules/NumberUnit.module.css
new file mode 100644
index 000000000..13fb622f4
--- /dev/null
+++ b/src/components/molecules/NumberUnit.module.css
@@ -0,0 +1,48 @@
+.number,
+.number * {
+ font-weight: var(--font-weight-bold);
+ font-size: var(--font-size-h4);
+ color: var(--font-color-heading);
+}
+
+.number {
+ white-space: nowrap;
+ display: inline-flex;
+ align-items: center;
+ line-height: 1;
+}
+
+.number.small,
+.number.small * {
+ font-size: var(--font-size-h5);
+}
+
+.label {
+ display: block;
+}
+
+.number svg {
+ width: var(--font-size-large);
+ height: var(--font-size-large);
+ margin-right: calc(var(--spacer) / 4);
+ stroke: currentColor;
+}
+
+.unit {
+ font-size: var(--font-size-small);
+ color: var(--color-secondary);
+}
+
+.unit a {
+ color: var(--color-secondary);
+ display: block;
+ padding: 0.5rem 1rem;
+ border: 0.1rem solid transparent;
+ border-radius: 0.2rem;
+}
+
+.unit a:hover,
+.unit a:focus {
+ background: var(--brand-white);
+ border: 0.1rem solid var(--brand-pink);
+}
diff --git a/src/components/molecules/NumberUnit.tsx b/src/components/molecules/NumberUnit.tsx
new file mode 100644
index 000000000..72ffc7daa
--- /dev/null
+++ b/src/components/molecules/NumberUnit.tsx
@@ -0,0 +1,45 @@
+import React, { ReactElement } from 'react'
+import styles from './NumberUnit.module.css'
+
+interface NumberInnerProps {
+ label: string
+ value: number | string | Element | ReactElement
+ small?: boolean
+ icon?: Element | ReactElement
+}
+
+interface NumberUnitProps extends NumberInnerProps {
+ link?: string
+ linkTooltip?: string
+}
+
+const NumberInner = ({ small, label, value, icon }: NumberInnerProps) => (
+ <>
+
+ {icon && icon}
+ {value}
+
+ {label}
+ >
+)
+
+export default function NumberUnit({
+ link,
+ linkTooltip,
+ small,
+ label,
+ value,
+ icon
+}: NumberUnitProps): ReactElement {
+ return (
+
+ {link ? (
+
+
+
+ ) : (
+
+ )}
+
+ )
+}
diff --git a/src/components/organisms/AssetActions/Compute/index.tsx b/src/components/organisms/AssetActions/Compute/index.tsx
index 448e724ef..7984835d7 100644
--- a/src/components/organisms/AssetActions/Compute/index.tsx
+++ b/src/components/organisms/AssetActions/Compute/index.tsx
@@ -39,10 +39,10 @@ import { AssetSelectionAsset } from '../../../molecules/FormFields/AssetSelectio
import AlgorithmDatasetsListForCompute from '../../AssetContent/AlgorithmDatasetsListForCompute'
import { getPreviousOrders, getPrice } from '../../../../utils/subgraph'
import AssetActionHistoryTable from '../../AssetActionHistoryTable'
-import ComputeJobs from '../../../pages/Account/History/ComputeJobs'
+import ComputeJobs from '../../../pages/Profile/History/ComputeJobs'
const SuccessAction = () => (
-