1
0
mirror of https://github.com/oceanprotocol/commons.git synced 2023-03-15 18:03:00 +01:00

Merge pull request #12 from oceanprotocol/feature/layout

Base Layout
This commit is contained in:
Jernej Pregelj 2019-02-11 10:47:55 +01:00 committed by GitHub
commit dd177475bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 714 additions and 254 deletions

View File

@ -14,6 +14,8 @@
- [Code Style](#code-style)
- [License](#license)
<img alt="screen shot 2019-02-08 at 16 53 57" src="https://user-images.githubusercontent.com/90316/52489283-27080e80-2bc2-11e9-8ec0-508c21eb86f7.png">
## Development
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).

139
package-lock.json generated
View File

@ -1016,6 +1016,11 @@
"integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
"dev": true
},
"@oceanprotocol/art": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@oceanprotocol/art/-/art-2.2.0.tgz",
"integrity": "sha512-p2n505t2K0zD1ZvGPhI6EsSviEVLCB7BYowhf/ONmVaWED138PaG4Z9nY6YuHU383uOoIWT+Lq3dLkFzDzstXw=="
},
"@oceanprotocol/keeper-contracts": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@oceanprotocol/keeper-contracts/-/keeper-contracts-0.5.3.tgz",
@ -1181,8 +1186,7 @@
"@types/prop-types": {
"version": "15.5.8",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.5.8.tgz",
"integrity": "sha512-3AQoUxQcQtLHsK25wtTWIoIpgYjH3vSDroZOUr7PpCHw/jLY1RB9z9E8dBT/OSmwStVgkRNvdh+ZHNiomRieaw==",
"dev": true
"integrity": "sha512-3AQoUxQcQtLHsK25wtTWIoIpgYjH3vSDroZOUr7PpCHw/jLY1RB9z9E8dBT/OSmwStVgkRNvdh+ZHNiomRieaw=="
},
"@types/q": {
"version": "1.5.1",
@ -1200,7 +1204,6 @@
"version": "16.8.2",
"resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.2.tgz",
"integrity": "sha512-6mcKsqlqkN9xADrwiUz2gm9Wg4iGnlVGciwBRYFQSMWG6MQjhOZ/AVnxn+6v8nslFgfYTV8fNdE6XwKu6va5PA==",
"dev": true,
"requires": {
"@types/prop-types": "*",
"csstype": "^2.2.0"
@ -1215,6 +1218,14 @@
"@types/react": "*"
}
},
"@types/react-helmet": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-5.0.8.tgz",
"integrity": "sha512-ZTr12eDAYI0yUiMx1K82EHqRYa8J1BOOLus+0gL+AkksUiIPwLE0wLiXa9FNqD8r9GXAi+yRPZImkRh1JNlTkQ==",
"requires": {
"@types/react": "*"
}
},
"@types/react-router": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-4.4.3.tgz",
@ -3568,7 +3579,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@ -3589,12 +3601,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -3609,17 +3623,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
@ -3736,7 +3753,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"ini": {
"version": "1.3.5",
@ -3748,6 +3766,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -3762,6 +3781,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -3769,12 +3789,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@ -3793,6 +3815,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -3873,7 +3896,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
@ -3885,6 +3909,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -3970,7 +3995,8 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@ -4006,6 +4032,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -4025,6 +4052,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -4068,12 +4096,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
}
}
},
@ -5123,8 +5153,7 @@
"csstype": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.2.tgz",
"integrity": "sha512-Rl7PvTae0pflc1YtxtKbiSqq20Ts6vpIYOD5WBafl4y123DyHUeLrRdQP66sQW8/6gmX8jrYJLXwNeMqYVJcow==",
"dev": true
"integrity": "sha512-Rl7PvTae0pflc1YtxtKbiSqq20Ts6vpIYOD5WBafl4y123DyHUeLrRdQP66sQW8/6gmX8jrYJLXwNeMqYVJcow=="
},
"currently-unhandled": {
"version": "0.4.1",
@ -5293,8 +5322,7 @@
"deep-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
"dev": true
"integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
},
"deep-extend": {
"version": "0.6.0",
@ -6432,6 +6460,11 @@
"clone-regexp": "^1.0.0"
}
},
"exenv": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
"integrity": "sha1-KueOhdmJQVhnCwPUe+wfA72Ru50="
},
"exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
@ -7576,7 +7609,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
@ -7597,12 +7631,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -7617,17 +7653,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
@ -7744,7 +7783,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"ini": {
"version": "1.3.5",
@ -7756,6 +7796,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@ -7770,6 +7811,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -7777,12 +7819,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"minipass": {
"version": "2.2.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.1",
"yallist": "^3.0.0"
@ -7801,6 +7845,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
@ -7881,7 +7926,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
@ -7893,6 +7939,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
@ -7978,7 +8025,8 @@
"safe-buffer": {
"version": "5.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
@ -8014,6 +8062,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@ -8033,6 +8082,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@ -8076,12 +8126,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"yallist": {
"version": "3.0.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
}
}
},
@ -16508,6 +16560,17 @@
"integrity": "sha512-7kEBKwU9R8fKnZJBRa5RSIfay4KJwnYvKB6gODGicUmDSAhQJ7Tdnll5S0RLtYrzRfMVXlqYw61rzrSpP4ThLQ==",
"dev": true
},
"react-helmet": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-5.2.0.tgz",
"integrity": "sha1-qBgR3yExOm1VxfBYxK66XW89l6c=",
"requires": {
"deep-equal": "^1.0.1",
"object-assign": "^4.1.1",
"prop-types": "^15.5.4",
"react-side-effect": "^1.1.0"
}
},
"react-router": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz",
@ -16866,6 +16929,15 @@
}
}
},
"react-side-effect": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-1.1.5.tgz",
"integrity": "sha512-Z2ZJE4p/jIfvUpiUMRydEVpQRf2f8GMHczT6qLcARmX7QRb28JDBTpnM2g/i5y/p7ZDEXYGHWg0RbhikE+hJRw==",
"requires": {
"exenv": "^1.2.1",
"shallowequal": "^1.0.1"
}
},
"read-pkg": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
@ -18617,6 +18689,11 @@
}
}
},
"shallowequal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
"integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
},
"shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
@ -22198,7 +22275,7 @@
"lodash": "^4.17.11",
"oboe": "2.1.4",
"url-parse": "1.4.4",
"websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2",
"websocket": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible",
"xhr2-cookies": "1.1.0"
},
"dependencies": {
@ -22243,7 +22320,7 @@
"requires": {
"underscore": "1.8.3",
"web3-core-helpers": "1.0.0-beta.37",
"websocket": "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2"
"websocket": "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible"
}
},
"web3-shh": {

View File

@ -15,12 +15,15 @@
"lint": "npm run lint:js && npm run lint:css"
},
"dependencies": {
"@oceanprotocol/art": "^2.2.0",
"@oceanprotocol/squid": "^0.2.8",
"@types/react-helmet": "^5.0.8",
"classnames": "^2.2.6",
"eslint": "^5.6.0",
"query-string": "^6.2.0",
"react": "^16.8.1",
"react-dom": "^16.8.1",
"react-helmet": "^5.2.0",
"react-router-dom": "^4.3.1",
"slugify": "^1.3.4",
"web3": "^1.0.0-beta.43"

View File

@ -102,14 +102,5 @@
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"><span class="loader"></span></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
--></body>
</body>
</html>

View File

@ -1,3 +1,14 @@
@import './styles/variables';
.app {
height: 100%;
// for sticky footer
display: flex;
min-height: calc(100vh - #{$page-frame * 2});
flex-direction: column;
}
.main {
flex: 1;
}

View File

@ -1,10 +1,13 @@
import React, { Component } from 'react'
import Web3 from 'web3'
import styles from './App.module.scss'
import { BrowserRouter as Router } from 'react-router-dom'
import Header from './components/Header'
import Footer from './components/Footer'
import { User } from './context/User'
import { provideOcean } from './ocean'
import Routes from './Routes'
import './styles/global.scss'
import styles from './App.module.scss'
import { nodeHost, nodePort, nodeScheme } from './config'
@ -47,16 +50,6 @@ class App extends Component<{}, AppState> {
this.bootstrap()
}
public render() {
return (
<div className={styles.app}>
<User.Provider value={this.state}>
<Routes />
</User.Provider>
</div>
)
}
private startLoginProcess = async () => {
this.setState({ isLoading: true })
if (window.web3) {
@ -107,6 +100,26 @@ class App extends Component<{}, AppState> {
ocean
})
}
public render() {
return (
<div className={styles.app}>
<User.Provider value={this.state}>
<Router>
<>
<Header />
<main className={styles.main}>
<Routes />
</main>
<Footer />
</>
</Router>
</User.Provider>
</div>
)
}
}
export default App

View File

@ -1,26 +1,24 @@
import React from 'react'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import { Route, Switch } from 'react-router-dom'
import About from './pages/About'
import Details from './pages/Details'
import Home from './pages/Home'
import NotFound from './pages/NotFound'
import Publish from './pages/Publish'
import Search from './pages/Search'
import Styleguide from './pages/Styleguide'
import About from './routes/About'
import Details from './routes/Details'
import Home from './routes/Home'
import NotFound from './routes/NotFound'
import Publish from './routes/Publish'
import Search from './routes/Search'
import Styleguide from './routes/Styleguide'
const Routes = () => (
<Router>
<Switch>
<Route exact component={Home} path="/" />
<Route component={Styleguide} path="/styleguide" />
<Route component={About} path="/about" />
<Route component={Publish} path="/publish" />
<Route component={Search} path="/search" />
<Route component={Details} path="/asset/:did" />
<Route component={NotFound} />
</Switch>
</Router>
<Switch>
<Route exact component={Home} path="/" />
<Route component={Styleguide} path="/styleguide" />
<Route component={About} path="/about" />
<Route component={Publish} path="/publish" />
<Route component={Search} path="/search" />
<Route component={Details} path="/asset/:did" />
<Route component={NotFound} />
</Switch>
)
export default Routes

View File

@ -0,0 +1,59 @@
@import '../styles/variables';
.footer {
color: $brand-grey-light;
width: 100%;
text-align: center;
margin-top: $spacer;
padding-top: $spacer;
padding-bottom: $spacer;
align-self: flex-end;
> div {
align-self: flex-end;
@media screen and (min-width: $break-point--small) {
text-align: left;
display: flex;
justify-content: space-between;
}
}
&,
small {
font-size: $font-size-mini;
}
a {
color: inherit;
&:hover,
&:focus {
color: $brand-grey;
}
}
svg {
display: inline-block;
width: $font-size-large;
height: $font-size-large;
}
}
.links {
margin-top: $spacer / 2;
@media screen and (min-width: $break-point--small) {
text-align: right;
margin-top: 0;
}
a {
margin: 0 $spacer / 2;
display: inline-block;
&:last-child {
margin-right: 0;
}
}
}

27
src/components/Footer.tsx Normal file
View File

@ -0,0 +1,27 @@
import React from 'react'
import Content from '../components/atoms/Content'
import styles from './Footer.module.scss'
import meta from '../data/meta.json'
const Footer = () => (
<footer className={styles.footer}>
<Content wide>
<small>
&copy; {new Date().getFullYear()}{' '}
<a href={meta.social[0].url}>{meta.company}</a> &mdash; All
Rights Reserved
</small>
<nav className={styles.links}>
{meta.social.map(site => (
<a key={site.title} href={site.url}>
{site.title}
</a>
))}
</nav>
</Content>
</footer>
)
export default Footer

View File

@ -0,0 +1,96 @@
@import '../styles/variables';
.header {
// background: $brand-black
// url('@oceanprotocol/art/mantaray/mantaray-back.svg') no-repeat center -6rem;
// background-size: cover;
width: 100%;
padding: $spacer / 2 0;
}
.headerContent {
composes: wide from './atoms/Content.module.scss';
display: flex;
align-items: center;
}
.headerLogo {
display: flex;
align-items: center;
cursor: pointer;
&:hover,
&:focus,
&:active {
transform: none;
}
}
.headerLogoImage {
width: 4rem;
height: 4rem;
fill: #fff;
margin: 0;
}
.headerTitle {
font-size: $font-size-h3;
color: $brand-grey-light;
margin-left: $spacer / 2;
display: none;
@media (min-width: $break-point--medium) {
display: inline-block;
}
}
.headerMenu {
flex: 1;
justify-self: flex-end;
text-align: right;
white-space: nowrap;
overflow-y: hidden;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
margin-right: -($spacer / 2);
padding-right: $spacer;
@media (min-width: $break-point--medium) {
padding-right: 0;
margin-right: 0;
}
&::-webkit-scrollbar,
&::-moz-scrollbar {
display: none;
}
&::-webkit-scrollbar {
width: 3px;
height: 3px;
transition: opacity .2s ease-out;
}
}
.link {
display: inline-block;
margin: 0 $spacer / 2;
font-family: $font-family-button;
color: $brand-grey;
&:last-child {
margin-right: 0;
}
&:hover,
&:focus,
&:active {
color: $brand-pink;
}
}
.linkActive {
composes: link;
color: $brand-pink;
pointer-events: none;
}

34
src/components/Header.tsx Normal file
View File

@ -0,0 +1,34 @@
import React from 'react'
import { NavLink } from 'react-router-dom'
import { ReactComponent as Logo } from '@oceanprotocol/art/logo/logo.svg'
import styles from './Header.module.scss'
import menu from '../data/menu.json'
import meta from '../data/meta.json'
const Header = () => (
<header className={styles.header}>
<div className={styles.headerContent}>
<NavLink to={'/'} className={styles.headerLogo}>
<Logo className={styles.headerLogoImage} />
<h1 className={styles.headerTitle}>{meta.title}</h1>
</NavLink>
<nav className={styles.headerMenu}>
{menu.map(item => (
<NavLink
key={item.title}
to={item.link}
className={styles.link}
activeClassName={styles.linkActive}
exact
>
{item.title}
</NavLink>
))}
</nav>
</div>
</header>
)
export default Header

View File

@ -66,6 +66,7 @@
padding: 0;
color: $brand-pink;
font-size: $font-size-base;
font-family: inherit;
box-shadow: none;
cursor: pointer;
}

View File

@ -0,0 +1,16 @@
@import '../../styles/variables';
.content {
padding: 0 $spacer / 1.5;
max-width: $break-point--small;
margin: 0 auto;
@media (min-width: $break-point--small) {
padding: 0 $spacer;
}
}
.wide {
composes: content;
max-width: $break-point--large;
}

View File

@ -0,0 +1,8 @@
import React from 'react'
import styles from './Content.module.scss'
const Content = ({ wide, children }: { wide?: boolean; children: any }) => (
<div className={wide ? styles.wide : styles.content}>{children}</div>
)
export default Content

View File

@ -2,9 +2,6 @@
.form {
width: 100%;
margin: 0 auto;
margin-top: 4rem;
max-width: 40rem;
fieldset {
border: 0;

View File

@ -14,10 +14,14 @@ const Form = ({
onSubmit?: any
}) => (
<form className={styles.form} onSubmit={onSubmit} {...props}>
<header className={styles.formHeader}>
<h1 className={styles.formTitle}>{title}</h1>
<p className={styles.formDescription}>{description}</p>
</header>
{title && (
<header className={styles.formHeader}>
<h1 className={styles.formTitle}>{title}</h1>
{description && (
<p className={styles.formDescription}>{description}</p>
)}
</header>
)}
{children}
</form>

View File

@ -3,7 +3,6 @@
.inputWrap {
background: $brand-gradient;
border-radius: $border-radius;
width: 100%;
padding: 2px;
display: flex;
position: relative;
@ -17,16 +16,16 @@
composes: inputWrap;
.input {
padding-left: $spacer / 1.25;
padding-left: $spacer * 1.5;
}
svg {
position: absolute;
left: $spacer / 3;
left: $spacer / 2;
width: 1.25rem;
height: 1.25rem;
top: 50%;
margin-top: -.75rem;
margin-top: -.6rem;
fill: rgba($brand-grey-light, .7);
}
}

View File

@ -6,6 +6,7 @@ import Help from './Help'
import styles from './Input.module.scss'
import Label from './Label'
import Row from './Row'
import InputGroup from './InputGroup'
interface InputProps {
name: string
@ -16,10 +17,11 @@ interface InputProps {
tag?: string
type?: string
options?: string[]
additionalComponent?: void
additionalComponent?: any
value?: string
onChange?: any
rows?: number
group?: any
}
interface InputState {
@ -50,6 +52,7 @@ export default class Input extends PureComponent<InputProps, InputState> {
return (
<div className={this.inputWrapClasses()}>
<select className={styles.select} {...props}>
<option value="none">---</option>
{props.options &&
props.options.map(
(option: string, index: number) => (
@ -105,7 +108,16 @@ export default class Input extends PureComponent<InputProps, InputState> {
return (
<div className={this.inputWrapClasses()}>
<input className={styles.input} {...props} />
{props.group ? (
<InputGroup>
<input className={styles.input} {...props} />
{props.group}
</InputGroup>
) : (
<input className={styles.input} {...props} />
)}
{props.type === 'search' && <SearchIcon />}
</div>
)
}
@ -139,7 +151,6 @@ export default class Input extends PureComponent<InputProps, InputState> {
onFocus={this.toggleFocus}
onBlur={this.toggleFocus}
/>
{type === 'search' && <SearchIcon />}
{help && <Help>{help}</Help>}

View File

@ -0,0 +1,39 @@
@import '../../../styles/variables';
.inputGroup {
width: 100%;
@media screen and (min-width: $break-point--small) {
display: flex;
}
> input {
@media screen and (min-width: $break-point--small) {
width: 75%;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
}
> button {
width: 100%;
position: absolute;
left: 0;
bottom: -120%;
@media screen and (min-width: $break-point--small) {
position: relative;
bottom: auto;
width: 25%;
height: 100%;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
box-shadow: none;
}
&:hover,
&:focus {
transform: none;
}
}
}

View File

@ -0,0 +1,8 @@
import React from 'react'
import styles from './InputGroup.module.scss'
const InputGroup = ({ children }: { children: any }) => (
<div className={styles.inputGroup}>{children}</div>
)
export default InputGroup

View File

@ -0,0 +1,15 @@
@import '../../styles/variables';
.header {
margin-top: $spacer;
margin-bottom: $spacer * 2;
h1 {
margin: 0;
}
p {
margin-top: $spacer / 2;
font-size: $font-size-large;
}
}

View File

@ -0,0 +1,37 @@
import React from 'react'
import Helmet from 'react-helmet'
import Content from '../atoms/Content'
import styles from './Route.module.scss'
import meta from '../../data/meta.json'
const Route = ({
title,
description,
wide,
children,
className
}: {
title: string
description?: string
children: any
wide?: boolean
className?: string
}) => (
<div className={className}>
<Helmet defaultTitle={meta.title} titleTemplate={`%s - ${meta.title}`}>
<title>{title}</title>
{description && <meta name="description" content={description} />}
</Helmet>
<Content wide={wide}>
<header className={styles.header}>
<h1>{title}</h1>
{description && <p>{description}</p>}
</header>
{children}
</Content>
</div>
)
export default Route

View File

@ -38,14 +38,13 @@
"label": "Type",
"type": "select",
"required": true,
"options": ["", "Data set", "Algorithm", "Container", "Workflow", "Other"]
"options": ["Data set", "Algorithm", "Container", "Workflow", "Other"]
},
"license": {
"label": "License",
"type": "select",
"required": true,
"options": [
"No License Specified",
"Public Domain",
"CC BY: Attribution",
"CC BY-SA: Attribution ShareAlike",
@ -66,7 +65,6 @@
"type": "select",
"required": true,
"options": [
"",
"Image Recognition",
"Dataset Of Datasets",
"Language",

14
src/data/menu.json Normal file
View File

@ -0,0 +1,14 @@
[
{
"title": "Publish",
"link": "/publish"
},
{
"title": "About",
"link": "/about"
},
{
"title": "Styleguide",
"link": "/styleguide"
}
]

31
src/data/meta.json Normal file
View File

@ -0,0 +1,31 @@
{
"title": "Commons",
"description": "A marketplace to find and publish open data sets in the Ocean Network.",
"company": "Ocean Protocol Foundation Ltd.",
"social": [
{
"title": "Site",
"url": "https://oceanprotocol.com"
},
{
"title": "Blog",
"url": "https://blog.oceanprotocol.com"
},
{
"title": "Twitter",
"url": "https://twitter.com/oceanprotocol"
},
{
"title": "GitHub",
"url": "https://github.com/oceanprotocol"
},
{
"title": "Gitter",
"url": "https://gitter.im/oceanprotocol/Lobby"
},
{
"title": "Telegram",
"url": "https://t.me/joinchat/GUyxrE0Hi154D0NrlOqLFg"
}
]
}

View File

@ -1,16 +0,0 @@
@import '../styles/variables';
.about {
background: $brand-black;
color: $brand-white;
min-height: calc(100vh - #{$page-frame} * 2);
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
> div {
text-align: center;
width: 100%;
}
}

View File

@ -1,19 +0,0 @@
import React, { Component } from 'react'
import Button from '../components/atoms/Button'
import styles from './About.module.scss'
class About extends Component {
public render() {
return (
<div className={styles.about}>
<Button>I am a button</Button>
<Button primary>I am a primary button</Button>
<Button href="https://hello.com">
I am a link disguised as a button
</Button>
</div>
)
}
}
export default About

View File

@ -1,32 +0,0 @@
@import '../styles/variables';
.home {
background: $brand-black;
color: $brand-white;
min-height: calc(100vh - #{$page-frame} * 2);
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
padding-top: 4rem;
padding-bottom: 4rem;
> div {
text-align: center;
width: 100%;
}
}
.form {
width: 100%;
background: $brand-grey-lighter;
margin: 0 auto;
max-width: 40rem;
padding: $spacer;
margin-top: 4rem;
fieldset {
border: 0;
padding: 0;
}
}

View File

@ -1,54 +0,0 @@
import React, { ChangeEvent, Component, FormEvent } from 'react'
import { Link } from 'react-router-dom'
import Button from '../components/atoms/Button'
import Form from '../components/atoms/Form/Form'
import Input from '../components/atoms/Form/Input'
import styles from './Home.module.scss'
interface HomeState {
search?: string
}
interface HomeProps {
history: any
}
class Home extends Component<HomeProps, HomeState> {
public state = { search: '' }
public render() {
return (
<div className={styles.home}>
<div>Home</div>
<Link to={'/styleguide'}>Styleguide</Link>
<div>
<Form onSubmit={this.searchAssets}>
<Input
type="search"
name="search"
label="Search"
value={this.state.search}
onChange={this.inputChange}
/>
<Button>Search</Button>
</Form>
</div>
</div>
)
}
private inputChange = (event: ChangeEvent<HTMLInputElement>) => {
this.setState({
[event.target.name]: event.target.value
})
}
private searchAssets = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault()
this.props.history.push(`/search?q=${this.state.search}`)
}
}
export default Home

View File

@ -1,7 +0,0 @@
@import '../styles/variables';
.page {
margin: 0 auto;
max-width: 40rem;
padding: $spacer;
}

10
src/routes/About.tsx Normal file
View File

@ -0,0 +1,10 @@
import React, { Component } from 'react'
import Route from '../components/templates/Route'
class About extends Component {
public render() {
return <Route title="About">Hello About</Route>
}
}
export default About

View File

@ -1,5 +1,6 @@
import { Logger } from '@oceanprotocol/squid'
import React, { Component } from 'react'
import Route from '../components/templates/Route'
import Button from '../components/atoms/Button'
import { User } from '../context/User'
@ -64,13 +65,13 @@ export default class Details extends Component<DetailsProps, DetailsState> {
public render() {
return (
<>
<Route title={'Details'}>
{this.state.metadata ? (
this.showDetails(this.state.ddo)
) : (
<div>Loading</div>
)}
</>
</Route>
)
}
}

View File

@ -0,0 +1,23 @@
@import '../styles/variables';
.home {
display: block;
}
.published {
margin-top: $spacer * 3;
margin-bottom: $spacer;
> div {
text-align: center;
margin-top: $spacer;
margin-bottom: $spacer;
}
}
.subTitle {
font-size: $font-size-h4;
color: $brand-grey-light;
border-bottom: 1px solid $brand-grey-lighter;
padding-bottom: $spacer / 2;
}

65
src/routes/Home.tsx Normal file
View File

@ -0,0 +1,65 @@
import React, { ChangeEvent, Component, FormEvent } from 'react'
import { Link } from 'react-router-dom'
import Button from '../components/atoms/Button'
import Form from '../components/atoms/Form/Form'
import Input from '../components/atoms/Form/Input'
import Route from '../components/templates/Route'
import styles from './Home.module.scss'
import meta from '../data/meta.json'
interface HomeState {
search?: string
}
interface HomeProps {
history: any
}
class Home extends Component<HomeProps, HomeState> {
public state = { search: '' }
public render() {
return (
<Route
title={meta.title}
description={meta.description}
className={styles.home}
>
<Form onSubmit={this.searchAssets}>
<Input
type="search"
name="search"
label="Search"
placeholder="i.e. almond sales data"
value={this.state.search}
onChange={this.inputChange}
group={<Button>Search</Button>}
/>
</Form>
<div className={styles.published}>
<h2 className={styles.subTitle}>Your Data Sets</h2>
<div>
<p>None yet.</p>
<Link to="/publish">+ Publish A Data Set</Link>
</div>
</div>
</Route>
)
}
private inputChange = (event: ChangeEvent<HTMLInputElement>) => {
this.setState({
[event.target.name]: event.target.value
})
}
private searchAssets = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault()
this.props.history.push(`/search?q=${this.state.search}`)
}
}
export default Home

View File

@ -1,8 +1,9 @@
import React, { Component } from 'react'
import Route from '../components/templates/Route'
class NotFound extends Component {
public render() {
return <div>Not found</div>
return <Route title="404 - Not Found">Not Found</Route>
}
}

View File

@ -1,4 +1,5 @@
import React, { ChangeEvent, Component, FormEvent } from 'react'
import Route from '../components/templates/Route'
import Button from '../components/atoms/Button'
import Form from '../components/atoms/Form/Form'
import Input from '../components/atoms/Form/Input'
@ -115,8 +116,7 @@ class Publish extends Component<{}, PublishState> {
const entries = Object.entries(form.fields)
return (
<div>
<h1>Publish</h1>
<Route title="Publish">
<Form
title={form.title}
description={form.description}
@ -138,7 +138,7 @@ class Publish extends Component<{}, PublishState> {
}
</User.Consumer>
</Form>
</div>
</Route>
)
}
}

View File

@ -1,6 +1,7 @@
import queryString from 'query-string'
import React, { Component } from 'react'
import { Link } from 'react-router-dom'
import Route from '../components/templates/Route'
import { provideOcean } from '../ocean'
interface SearchState {
@ -12,7 +13,7 @@ interface SearchProps {
history: any
}
class Search extends Component<SearchProps, SearchState> {
export default class Search extends Component<SearchProps, SearchState> {
public state = { results: [] }
public async componentDidMount() {
@ -32,18 +33,6 @@ class Search extends Component<SearchProps, SearchState> {
this.setState({ results: assets })
}
public render() {
return (
<>
{this.state.results.length ? (
this.state.results.map(asset => this.renderAssetBox(asset))
) : (
<div>No data sets yet</div>
)}
</>
)
}
private renderAssetBox = (asset: any) => {
const { metadata } = asset.findServiceByType('Metadata')
return (
@ -54,6 +43,16 @@ class Search extends Component<SearchProps, SearchState> {
</Link>
)
}
}
export default Search
public render() {
return (
<Route title="Search Results" wide>
{this.state.results.length ? (
this.state.results.map(asset => this.renderAssetBox(asset))
) : (
<div>No data sets yet</div>
)}
</Route>
)
}
}

View File

@ -0,0 +1,6 @@
.buttons {
> * {
display: block;
margin-bottom: 2rem;
}
}

View File

@ -2,8 +2,8 @@ import React, { Component } from 'react'
import Button from '../components/atoms/Button'
import Form from '../components/atoms/Form/Form'
import Input from '../components/atoms/Form/Input'
import Route from '../components/templates/Route'
import styles from './Styleguide.module.scss'
import form from '../data/form-styleguide.json'
class Styleguide extends Component {
@ -24,19 +24,20 @@ class Styleguide extends Component {
public render() {
const entries = Object.entries(form.fields)
return (
<div className={styles.page}>
<h1>Styleguide</h1>
<Button>I am a button</Button>
<Button primary>I am a primary button</Button>
<Button href="https://hello.com">
I am a link disguised as a button
</Button>
<Route title="Styleguide" className={styles.styleguide}>
<div className={styles.buttons}>
<Button>I am a button</Button>
<Button primary>I am a primary button</Button>
<Button href="https://hello.com">
I am a link disguised as a button
</Button>
<Button link>I am a button disguised as a text link</Button>
</div>
<Form title={form.title} description={form.description}>
{this.formFields(entries)}
</Form>
</div>
</Route>
)
}
}

View File

@ -332,10 +332,3 @@ pre {
background: $brand-grey-light;
color: #fff;
}
// Gatsby specific
/////////////////////////////////////
.anchor {
margin-top: .6rem;
}