Merge branch 'master' into feature/accepting-code-from-external-contributors
1
.gitignore
vendored
@ -7,3 +7,4 @@ yarn-error.log
|
||||
.DS_Store
|
||||
.env
|
||||
.env.*
|
||||
data/squid-js.json
|
||||
|
3
.gitmodules
vendored
@ -2,3 +2,6 @@
|
||||
path = external/dev-ocean
|
||||
url = https://github.com/oceanprotocol/dev-ocean
|
||||
branch = master
|
||||
[submodule "external/squid-js"]
|
||||
path = external/squid-js
|
||||
url = https://github.com/oceanprotocol/squid-js.git
|
||||
|
52
README.md
@ -82,37 +82,37 @@ All Markdown files should use
|
||||
|
||||
1. The file must begin with a section called YAML frontmatter that looks like this:
|
||||
|
||||
```md
|
||||
---
|
||||
title: This is the Title in Title Case
|
||||
description: A short description of the page.
|
||||
---
|
||||
```md
|
||||
---
|
||||
title: This is the Title in Title Case
|
||||
description: A short description of the page.
|
||||
---
|
||||
|
||||
Markdown content begins here.
|
||||
```
|
||||
Markdown content begins here.
|
||||
```
|
||||
|
||||
For external documents in other repos, defining the `slug` and `section` is required:
|
||||
For external documents in other repos, defining the `slug` and `section` is required:
|
||||
|
||||
```md
|
||||
---
|
||||
title: This is the Title in Title Case
|
||||
description: A short description of the page.
|
||||
slug: /concepts/architecture/
|
||||
section: concepts
|
||||
---
|
||||
```md
|
||||
---
|
||||
title: This is the Title in Title Case
|
||||
description: A short description of the page.
|
||||
slug: /concepts/architecture/
|
||||
section: concepts
|
||||
---
|
||||
|
||||
Markdown content begins here.
|
||||
```
|
||||
Markdown content begins here.
|
||||
```
|
||||
|
||||
Note: The `description` value will be rendered on-page below the title, and it will also be used for description tags in the HTML head.
|
||||
Note: The `description` value will be rendered on-page below the title, and it will also be used for description tags in the HTML head.
|
||||
|
||||
2. Don't include the page title or description in the Markdown section. That is, don't begin the Markdown content with `# This is the Title in Title Case`. Just write as if that were already there.
|
||||
3. start your heading levels with `h2`, so `## My heading`
|
||||
4. Internal links to other docs pages should be:
|
||||
1. Don't include the page title or description in the Markdown section. That is, don't begin the Markdown content with `# This is the Title in Title Case`. Just write as if that were already there.
|
||||
2. start your heading levels with `h2`, so `## My heading`
|
||||
3. Internal links to other docs pages should be:
|
||||
- to a absolute URL without the host, that looks like `/concepts/terminology/` with slashes on the beginning and end, and with no `.md` or `.html` at the end (before the last slash).
|
||||
- when linking from external repos, to the _full absolute URL_, such as `https://docs.oceanprotocol.com/hello/you-are-awesome/`
|
||||
5. no TOC please, this will be generated automatically from all headings
|
||||
6. for images and media, you can keep them in the original repo. Images will be automatically grabbed by the docs site on querying. When doing that, docs site will generate all sorts of image sizes to handle proper responsive images, so no need to keep an eye on image dimensions or file sizes
|
||||
4. no TOC please, this will be generated automatically from all headings
|
||||
5. for images and media, you can keep them in the original repo. Images will be automatically grabbed by the docs site on querying. When doing that, docs site will generate all sorts of image sizes to handle proper responsive images, so no need to keep an eye on image dimensions or file sizes
|
||||
|
||||
**Have a look at [docs.oceanprotocol.com/test/](https://docs.oceanprotocol.com/test/) to see what content elements can be used in all Markdown files included in docs site.**
|
||||
|
||||
@ -207,9 +207,11 @@ For more information about stylistic issues, take a look at the section in the t
|
||||
|
||||
#### TypeDoc specs
|
||||
|
||||
Reference pages based on generated `json` file from TypeDoc.
|
||||
Reference pages based on generated `json` file from TypeDoc. TypeScript-based projects are included as git submodules under `./external`.
|
||||
|
||||
_Coming soon... see [#45](https://github.com/oceanprotocol/docs/issues/45)_
|
||||
On site build, TypeDoc will automatically generate the required `json` spec file into `./data/squid-js.json` and create pages from it. The data from these json files is then used by the TypeDoc template.
|
||||
|
||||
To update the specs to the most recent version, the `./external/squid-js` submodule needs to be manuall updated. That's it, on next site build a new spec will be used.
|
||||
|
||||
## Development
|
||||
|
||||
|
@ -35,6 +35,10 @@ module.exports = {
|
||||
{
|
||||
from: '/references/',
|
||||
to: '/references/introduction/'
|
||||
},
|
||||
{
|
||||
from: '/tutorials/wallets/',
|
||||
to: '/concepts/wallets/'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ description: Help with Ocean Protocol development and have Ocean Tokens rain on
|
||||
|
||||
Check out the:
|
||||
|
||||
- [Ocean Protocol Bounties on Gitcoin](https://gitcoin.co/profile/oceanprotocol)
|
||||
- [Ocean Protocol Bounties on Gitcoin](https://gitcoin.co/explorer?network=mainnet&idx_status=open&keywords=oceanprotocol&order_by=-web3_created&org=oceanprotocol)
|
||||
- [Ocean Protocol Bounties on bounties.network](https://explorer.bounties.network/explorer?bountyStage=active&search=ocean%20protocol)
|
||||
|
||||
<repo name="ocean-bounties"></repo>
|
||||
|
@ -7,7 +7,7 @@ Before reading this page, you should understand some [Ocean-specific terminology
|
||||
|
||||
## Aquarius
|
||||
|
||||
Marketplaces run Aquarius to store and manage metadata about the data assets available in their marketplace. It provides an HTTP API for interacting with an off-chain database ([OceanDB](/concepts/components/#oceandb-drivers)).
|
||||
Marketplaces run Aquarius to store and manage metadata about the [assets](/concepts/terminology/#asset-or-data-asset) available in their marketplace. It provides an HTTP API for interacting with an off-chain database ([OceanDB](/concepts/components/#oceandb-drivers)).
|
||||
|
||||
<repo name="aquarius"></repo>
|
||||
|
||||
@ -15,7 +15,7 @@ Marketplaces run Aquarius to store and manage metadata about the data assets ava
|
||||
|
||||
Publishers run Brizo to manage interactions with marketplaces and consumers.
|
||||
It interacts with the publisher's cloud and/or on-premise infrastructure.
|
||||
The most basic scenario for a publisher is to provide access to the assets the publisher owns or manages, but [Brizo can do much more](/concepts/architecture/#brizo).
|
||||
The most basic scenario for a publisher is to provide access to the [assets](/concepts/terminology/#asset-or-data-asset) the publisher owns or manages, but [Brizo can do much more](/concepts/architecture/#brizo).
|
||||
|
||||
<repo name="brizo"></repo>
|
||||
|
||||
@ -33,7 +33,7 @@ See also: [Run a Keeper](/setup/keeper/)
|
||||
|
||||
## Pleuston
|
||||
|
||||
An example marketplace front-end for consumers to explore, download, and publish data assets within the Ocean Protocol network. Implemented using [React](https://reactjs.org/) and [🦑 squid-js](https://github.com/oceanprotocol/squid-js).
|
||||
An example marketplace front-end for consumers to explore, download, and publish [assets](/concepts/terminology/#asset-or-data-asset) within the Ocean Protocol network. Implemented using [React](https://reactjs.org/) and [🦑 squid-js](https://github.com/oceanprotocol/squid-js).
|
||||
|
||||
<repo name="pleuston"></repo>
|
||||
|
||||
@ -49,7 +49,7 @@ Client libraries used by applications (such as Pleuston or Jupyter notebooks) to
|
||||
|
||||
## OceanDB Drivers
|
||||
|
||||
OceanDB is an off-chain database for storing metadata about data assets.
|
||||
OceanDB is an off-chain database for storing metadata about [assets](/concepts/terminology/#asset-or-data-asset).
|
||||
|
||||
<repo name="oceandb-mongodb-driver"></repo>
|
||||
<repo name="oceandb-bigchaindb-driver"></repo>
|
||||
@ -61,7 +61,7 @@ These drivers are extended from a high-level module implementing OceanDB functio
|
||||
|
||||
## Secret Store
|
||||
|
||||
A [Parity Secret Store](https://wiki.parity.io/Secret-Store): software for distributed key pair generation, distributed key storage, and threshold retrieval. It's used to store asset access-control keys.
|
||||
A [Parity Secret Store](https://wiki.parity.io/Secret-Store): software for distributed key pair generation, distributed key storage, and threshold retrieval. It's used to store [asset](/concepts/terminology/#asset-or-data-asset) access-control keys.
|
||||
|
||||
There are several clients for integrating the Parity Secret Store into Ocean:
|
||||
|
||||
|
@ -21,16 +21,12 @@ Society is becoming increasingly reliant on data, especially with the advent of
|
||||
|
||||
Ocean Protocol aims to unlock data, for more equitable outcomes for users of data, using a thoughtful application of both technology and governance.
|
||||
|
||||
For more details, see the blog post "[Mission & Values for Ocean Protocol](https://blog.oceanprotocol.com/mission-values-for-ocean-protocol-aba998e95b8)".
|
||||
|
||||
## Papers
|
||||
|
||||
There are more details on the
|
||||
[Ocean Protocol home page](https://oceanprotocol.com/#papers),
|
||||
and in the whitepapers:
|
||||
All papers can be retrieved from the [Papers section](https://oceanprotocol.com/protocol/#papers) on our home page:
|
||||
|
||||
- [Technical Whitepaper](https://oceanprotocol.com/tech-whitepaper.pdf) - This paper presents Ocean Protocol. Ocean is a decentralized protocol and network of artificial intelligence (AI) data/services. It incentivizes for a vast supply of relevant AI data/services.
|
||||
- [Business Whitepaper](https://oceanprotocol.com/business-whitepaper.pdf) - This document presents a summary of the business model and ecosystem of Ocean Protocol. In addition, it describes the logic behind the Ocean utility token and the economic incentives driving the Protocol. It is complementary to the technical whitepaper for Ocean Protocol.
|
||||
- [Marketplace Framework](https://oceanprotocol.com/marketplace-framework.pdf) - This document presents a summary of the core marketplace attributes and components required to facilitate the successful deployment of the decentralized data exchange protocol and network called Ocean Protocol.
|
||||
|
||||
## More Information
|
||||
|
||||
- [Mission & Values for Ocean Protocol](https://blog.oceanprotocol.com/mission-values-for-ocean-protocol-aba998e95b8)
|
||||
- **Technical Whitepaper** - This paper presents Ocean Protocol. Ocean is a decentralized protocol and network of artificial intelligence (AI) data/services. It incentivizes for a vast supply of relevant AI data/services.
|
||||
- **Business Strategy** - This document presents a summary of the business model and ecosystem of Ocean Protocol. It is complementary to the technical whitepaper for Ocean Protocol.
|
||||
- **Marketplace Framework** - This document presents a summary of the core marketplace attributes and components required to facilitate the successful deployment of the decentralized data exchange protocol and network called Ocean Protocol.
|
||||
|
@ -5,7 +5,7 @@ description: Terminology specific to Ocean Protocol.
|
||||
|
||||
## Asset or Data Asset
|
||||
|
||||
A data set or data service.
|
||||
Anything that can be registered with and made available via the Ocean Network. Examples include data sets, trained model parameters, pipelines, and data-cleaning services.
|
||||
|
||||
## Data Owner or Data Service Provider
|
||||
|
||||
@ -17,7 +17,7 @@ Note: Initially, most data owners or data service providers will also be the pub
|
||||
|
||||
A service which mediates access to assets on behalf of data owners or data service providers.
|
||||
|
||||
Note: Initially, most publishers will also be the owners of the data assets they publish.
|
||||
Note: Initially, most publishers will also be the owners of the assets they publish.
|
||||
|
||||
## Consumer
|
||||
|
||||
@ -33,11 +33,11 @@ A person or a software service that checks some steps in transactions. For examp
|
||||
|
||||
## Service Execution Agreement (SEA)
|
||||
|
||||
A contract-like agreement between a provider, a consumer, and a verifier, specifying what data assets are to be delivered (from provider to consumer), the conditions that must be met, and the rewards for fulfilling the conditions.
|
||||
A contract-like agreement between a provider, a consumer, and a verifier, specifying what assets are to be delivered (from provider to consumer), the conditions that must be met, and the rewards for fulfilling the conditions.
|
||||
|
||||
We published an [Ocean Protocol blog post that explains SEAs in more detail](https://blog.oceanprotocol.com/exploring-the-sea-service-execution-agreements-65f7523d85e2).
|
||||
|
||||
## More Terminology
|
||||
|
||||
- See [the page about Ocean's Software Components](/concepts/components/).
|
||||
- See [the page about wallets (and other Ethereum terminology)](/tutorials/wallets/).
|
||||
- See [the page about wallets (and other Ethereum terminology)](/concepts/wallets/).
|
||||
|
@ -19,6 +19,10 @@ The Nile Testnet is similar to the Kovan Testnet, except all the nodes are opera
|
||||
|
||||
Moreover, there is a [Secret Store](/concepts/components/#secret-store) operated by the Ocean Protocol Foundation which is connected to the Nile Testnet.
|
||||
|
||||
## Spree Testnet
|
||||
|
||||
When Ocean Protocol developers run [Barge](https://github.com/oceanprotocol/barge) with the `--local-spree-node` option, a "Spree Testnet" node is deployed on their local machine: a local "testnet" not connected to any public testnet. It's named after the main river flowing through Berlin, Germany, where many Ocean Protocol developers are located.
|
||||
|
||||
## Technical Details about the Public Testnets
|
||||
|
||||
- [Details about the Nile Testnet](https://github.com/oceanprotocol/dev-ocean/blob/master/doc/devops/secret-store-cluster.md) (which is called the "Parity Secret Store Cluster" on that page).
|
||||
|
@ -5,18 +5,29 @@ description: Tools and examples for developing with Ocean Protocol.
|
||||
|
||||
## Tools
|
||||
|
||||
Coming soon!
|
||||
### Plecos
|
||||
|
||||
Plecos is a Python tool to check metadata (a JSON file) to see if it conforms to the [OEP8 schema](https://github.com/oceanprotocol/OEPs/tree/master/8). Plecos wraps the [jsonschema](https://github.com/Julian/jsonschema) validator. Users can use Plecos to check their metadata before sending it to an Aquarius instance. Aquarius can also use it to check metadata. Plecos can be found in [the Plecos repository on GitHub](https://github.com/oceanprotocol/plecos) and as [a Python package in PyPI](https://pypi.org/project/plecos/).
|
||||
|
||||
<repo name="Plecos"></repo>
|
||||
|
||||
Plecos can be used in a microservice to facilitate data onboarding, as described in the [plecos_service repository](https://github.com/oceanprotocol/plecos_service).
|
||||
|
||||
## Examples
|
||||
|
||||
The [Tutorials](/tutorials/introduction/) include many examples.
|
||||
### squid-py Examples
|
||||
|
||||
Examples of using the [🦑 squid-py](https://github.com/oceanprotocol/squid-js) Python library can be found in the [squid_py/examples/ directory of the squid-py repository](https://github.com/oceanprotocol/squid-py/tree/develop/squid_py/examples). More examples are in the repositories:
|
||||
- [The squid-py tutorials in Jupyter notebooks](/tutorials/jupyter-notebooks/)
|
||||
- [The squid_py/examples/ directory of the squid-py repository](https://github.com/oceanprotocol/squid-py/tree/develop/squid_py/examples)
|
||||
- [The squid-py tests](https://github.com/oceanprotocol/squid-py/tree/develop/tests)
|
||||
|
||||
<repo name="mantaray"></repo>
|
||||
<repo name="tuna"></repo>
|
||||
### squid-js Examples
|
||||
|
||||
Examples of using the [🦑 squid-js](https://github.com/oceanprotocol/squid-js) JavaScript library can be found in the [src/examples/ directory of the squid-js repository](https://github.com/oceanprotocol/squid-js/tree/develop/src/examples). More examples are in the repositories:
|
||||
- [The React App Tutorial](/tutorials/react-setup/)
|
||||
- [The src/examples/ directory of the squid-js repository](https://github.com/oceanprotocol/squid-js/tree/develop/src/examples)
|
||||
- [The squid-js tests](https://github.com/oceanprotocol/squid-js/tree/develop/test)
|
||||
|
||||
<repo name="pleuston"></repo>
|
||||
<repo name="tuna"></repo>
|
||||
### squid-java Examples
|
||||
|
||||
- [The squid-java README.md file](https://github.com/oceanprotocol/squid-java/blob/develop/README.md)
|
||||
- [The squid-java tests](https://github.com/oceanprotocol/squid-java/tree/develop/src/test)
|
||||
|
69
content/concepts/wallets.md
Normal file
@ -0,0 +1,69 @@
|
||||
---
|
||||
title: Wallet Basics
|
||||
description: Ocean users need a wallet to manage their Ocean Tokens and Ether. This page explains the basics of wallets.
|
||||
---
|
||||
|
||||
## Introduction
|
||||
|
||||
If you want to use the Ocean Network, then you need Ocean Tokens ([ERC-20 tokens](https://en.wikipedia.org/wiki/ERC-20)) and Ether. To get and manage Ocean Tokens and Ether, you need a _cryptocurrency wallet_ or _crypto wallet_.
|
||||
|
||||
## What Crypto Wallets Can Be Used with Ocean?
|
||||
|
||||
The following combinations will almost certainly work:
|
||||
|
||||
Wallet User Interface Software | Access Wallet with | Wallet (Stores Private Keys)
|
||||
-------------------------------|------------------------------|-----------------------------
|
||||
[MetaMask][1] | [MetaMask][1] | [MetaMask][1]
|
||||
[MetaMask][1] | [MetaMask][1] | [TREZOR][2] hardware wallet
|
||||
[MyEtherWallet][4] | [MetaMask][1] | [MetaMask][1]
|
||||
[MyEtherWallet][4] | [MetaMask][1] | [TREZOR][2] hardware wallet
|
||||
[MyEtherWallet][4] | [TREZOR][2] hardware wallet | [TREZOR][2] hardware wallet
|
||||
[MyCrypto][5] | [MetaMask][1] | [MetaMask][1]
|
||||
[MyCrypto][5] | [MetaMask][1] | [TREZOR][2] hardware wallet
|
||||
[MyCrypto][5] | [TREZOR][2] hardware wallet | [TREZOR][2] hardware wallet
|
||||
|
||||
Note: Other combinations will _probably_ also work. For example, a [Ledger][3] hardware wallet can probably be used in place of a TREZOR hardware wallet.
|
||||
|
||||
See the [MetaMask setup tutorial](/tutorials/metamask-setup/).
|
||||
|
||||
Why only those combinations? You need a combination that can:
|
||||
|
||||
1. connect to both the Main Ethereum Network or the Main Ocean Network (or a custom network), and
|
||||
1. manage Ether and Ocean Tokens (or custom tokens).
|
||||
|
||||
## Terminology
|
||||
|
||||
When you set up a new (crypto) wallet, it might generate a **seed phrase** for you. Store that seed phrase somewhere secure and non-digital (e.g. on paper in a safe). It's extremely secret and sensitive. Anyone with your wallet's seed phrase could spend all the Ether and Ocean Tokens in all the accounts in your wallet.
|
||||
|
||||
Once your wallet is set up, it will have one or more **accounts**.
|
||||
|
||||
Each account has several **balances**, e.g. an Ether balance, an Ocean Token balance, and maybe other balances. All balances start at zero.
|
||||
|
||||
An account's Ether balance might be 7.1 ETH in the Ethereum mainnet, 2.39 ETH in the Kovan testnet, and 0.1 ETH in the Nile testnet. You can't move ETH from one network to another (unless there is a special exchange or bridge set up). The same is true of Ocean Token balances.
|
||||
|
||||
Each account has one **private key**, one **public key** and one **address**. The public key and address can be calculated from the private key. You must keep the private key secret because it's what's needed to spend/transfer Ether and Ocean Tokens. You can share the address with others. In fact, if you want someone to send some Ether or Ocean Tokens to an account, you give them the account's address.
|
||||
|
||||
Notes:
|
||||
|
||||
- The blockchain has a record of every spend/receive transaction ever and it's public, so anyone can determine all the balances of all the accounts.
|
||||
- Unlike traditional pocket wallets, crypto wallets don't actually store the tokens or Ether. They store private keys and maybe other things. (An account's public key and address can be calculated from its private key.)
|
||||
|
||||
## Types of Wallets
|
||||
|
||||
It's easy to get confused or overwhelmed by all the types of wallets and all the options for accessing them. However, there are really only a few questions you need to ask about a given wallet + software combination:
|
||||
|
||||
1. Where are my private keys stored? How secure is that?
|
||||
1. Can the combination connect to the networks I care about (such as the Main Ocean Network)?
|
||||
1. Can the combination be used to manage the cryptocurrencies I care about (such as Ocean Tokens)?
|
||||
|
||||
Hardware wallets store private keys inside a "secure enclave" (on a special device) so they can't be read out easily. All you can do is send a transaction to the hardware wallet to get the transaction signed by the private key. It then returns the signed transaction. The private key never leaves the hardware wallet.
|
||||
Other wallets store private keys on a hard drive, in memory, on a remote server, or on a piece of paper.
|
||||
Each option gives you a tradeoff between security and ease of use / convenience. It's easier to steal or delete a private key if it's stored on a computer, especially a computer that's connected to the internet.
|
||||
|
||||
We encourage you to search around and read about wallets to understand the options. This page isn't a deep dive; it's just a primer.
|
||||
|
||||
[1]: https://metamask.io/
|
||||
[2]: https://trezor.io/
|
||||
[3]: https://www.ledger.com/
|
||||
[4]: https://www.myetherwallet.com/
|
||||
[5]: https://www.mycrypto.com/
|
@ -12,11 +12,8 @@ The following components expose a consumable REST API which are documented on th
|
||||
|
||||
Those are sourced from their respective Swagger specs. On this site you can't execute the documented API calls yet. If you need this, you can run a component's local Swagger UI as outlined in the repository instructions on GitHub.
|
||||
|
||||
References of all the functions and methods used in our libraries are not yet integrated here. For now, have a look at the respective repos for more infos:
|
||||
References of all the functions and methods used in our libraries:
|
||||
|
||||
<repo name="squid-js"></repo>
|
||||
<repo name="squid-py"></repo>
|
||||
|
||||
ReadTheDocs hosts the [squid-py API Reference Docs](https://squid-py.readthedocs.io/en/latest/).
|
||||
|
||||
<repo name="squid-java"></repo>
|
||||
|
7
content/references/squid-java.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Squid-Java API Reference
|
||||
---
|
||||
|
||||
Coming soon. For now, please see the squid-java source code on GitHub.
|
||||
|
||||
<repo name="squid-java"></repo>
|
@ -1,6 +1,5 @@
|
||||
---
|
||||
title: API Reference
|
||||
description:
|
||||
title: Squid-py API Reference
|
||||
---
|
||||
|
||||
ReadTheDocs hosts the [squid-py API Reference Docs](https://squid-py.readthedocs.io/en/latest/).
|
||||
|
@ -5,22 +5,28 @@ description: Set up and run a data marketplace in the Ocean network.
|
||||
|
||||
## What Does it Mean to Set Up a Marketplace?
|
||||
|
||||
An Ocean marketplace app is one of the primary ways that end users use the Ocean network. For example, a data scientist could use a marketplace app to see what data sets and data services (data assets) a marketplace has available. They can use the marketplace app to buy access to assets. Publishers make those data assets available.
|
||||
An Ocean marketplace app is one of the primary ways that end users use the Ocean network. For example, a data scientist could use a marketplace app to see what [assets](/concepts/terminology/#asset-or-data-asset) a marketplace has available. They can use the marketplace app to buy access to assets. Publishers make those assets available.
|
||||
|
||||
**Note: In the early days of the Ocean network, there won't be many marketplaces or publishers, so marketplaces will often also act as publishers.**
|
||||
|
||||
If you want to set up and run a marketplace in the Ocean network, then at a technical level, you must:
|
||||
|
||||
1. Have [Data Assets](/concepts/terminology/#asset-or-data-asset) to offer in your marketplace.
|
||||
1. Get those data assets set up to work with Ocean Protocol.
|
||||
1. Have [assets](/concepts/terminology/#asset-or-data-asset) to offer in your marketplace.
|
||||
1. Get those assets set up to work with Ocean Protocol.
|
||||
1. Develop a marketplace application (app).
|
||||
1. Run your marketplace app in production.
|
||||
|
||||
## Prepare Data Assets
|
||||
## Prepare Assets
|
||||
|
||||
At the time of writing, the only kind of [data assets](/concepts/terminology/#asset-or-data-asset) supported by Ocean Protocol were datasets stored in Azure Storage. See [the tutorial about setting up Azure Storage to work with Ocean Protocol](/tutorials/azure-for-brizo/).
|
||||
At the time of writing, the following kinds of [assets](/concepts/terminology/#asset-or-data-asset) were supported:
|
||||
|
||||
Support for other kinds of data assets (e.g. storage in AWS, computing in Azure) is coming soon.
|
||||
- data sets stored in Azure Storage (i.e. with "core.windows.net" in their URL). See [the tutorial about setting up Azure Storage to work with Ocean Protocol](/tutorials/azure-for-brizo/).
|
||||
- data sets stored in Amazon S3 storage (i.e. with "s3://" in their URL). See [the tutorial about setting up Amazon S3 storage to work with Ocean Protocol](/tutorials/amazon-s3-for-brizo/).
|
||||
- data sets stored in on-premise storage. See [the tutorial about setting up on-premise storage to work with Ocean Protocol](/tutorials/on-premise-for-brizo/).
|
||||
|
||||
Note: You can use _all_ of the above. You aren't restricted to using only one storage provider.
|
||||
|
||||
Support for other kinds of assets (e.g. computing in Azure) is coming.
|
||||
|
||||
## Develop a Marketplace App
|
||||
|
||||
@ -45,7 +51,7 @@ There are many ways to create an Ocean marketplace app. For example, you could u
|
||||
|
||||
Note: There are examples of how to use squid-py in the [Tutorials](/tutorials/introduction/). squid-py is to Ocean like boto3 is to AWS.
|
||||
|
||||
Of course, you could always write your own Squid library in the language of your choice. A squid-java library is in development.
|
||||
Of course, you could always write your own Squid library in the language of your choice.
|
||||
|
||||
## Run Your Marketplace App in Production
|
||||
|
||||
|
@ -9,16 +9,13 @@ You can [try some free, online Jupyter notebooks](/tutorials/jupyter-notebooks/)
|
||||
|
||||
## Option 2
|
||||
|
||||
You can run and try every [Ocean software component](/concepts/components/) in your local machine, all at once, using Docker Compose.
|
||||
**WARNING: This option is more for developers who don't mind some things not working together as expected (if at all). Eventually there will be a default-working version, but that doesn't exist yet.**
|
||||
|
||||
First, you must [set up some storage on Azure](/tutorials/azure-for-brizo/). (Yes, we know that's not quick. Some day there will be a local storage option and then this really will be quick.)
|
||||
|
||||
Then:
|
||||
You can run and try every [Ocean software component](/concepts/components/) in your local machine, all at once, using Docker Compose. Ocean Protocol software developers do this often, to test their code against all the other Ocean components.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/oceanprotocol/barge.git
|
||||
cd barge/
|
||||
|
||||
./start_ocean.sh --latest
|
||||
```
|
||||
|
||||
|
12
content/tutorials/amazon-s3-for-brizo.md
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
title: Set Up Amazon S3 Storage
|
||||
description: Tutorial about how to set up Amazon S3 storage for use with Ocean Protocol.
|
||||
---
|
||||
|
||||
To enable Brizo to use files stored in Amazon S3 (i.e. files with an URL containing "s3://"), you must:
|
||||
|
||||
1. have an Amazon AWS user account (IAM account) with permission to read those files from S3, and
|
||||
1. set the AWS credentials on the machine where Brizo is running to those of the AWS user in question. Instructions are given below.
|
||||
1. Note that you don't have to set any Brizo-specific configuration settings, e.g. in the `[osmosis]` section of the Brizo config file or in some special Brizo environment variables.
|
||||
|
||||
Under the hood, Brizo uses [boto3](https://aws.amazon.com/sdk-for-python/) (the Python library for interacting with AWS) to interact with AWS and boto3 has a whole process for determining AWS credentials. The easiest way to set the AWS credentials on the machine where Brizo is running is to install the [AWS CLI](https://aws.amazon.com/cli/) and then use the `aws configure` command. For more details, see [the boto3 user guide about credentials](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/configuration.html).
|
@ -1,18 +1,17 @@
|
||||
---
|
||||
title: Get Ether and Ocean Tokens for Testnets
|
||||
description: A tutorial about how to get Ether and Ocean Tokens for testnets.
|
||||
title: Get Ether and Ocean Tokens
|
||||
description: A tutorial about how to get Ether and Ocean Tokens.
|
||||
---
|
||||
|
||||
If you want to interact with a testnet, then you'll eventually need Ether or Ocean Tokens _for that testnet_. (Every Ethereum-based network has its own Ether and its own Ocean Tokens, and you can't use those in other networks, or at least it wasn't possible when we wrote this.)
|
||||
If you want to interact with an Ethereum-based network that supports Ocean Protocol, then you'll eventually need Ether or Ocean Tokens _for that network_. (Every Ethereum-based network has its own Ether and its own Ocean Tokens, and you can't use those in other networks.)
|
||||
|
||||
At the time of writing, there were some public testnets you could use to test an Ocean Protocol application. For more information about those, see the page about [testnets](/concepts/testnets/). You could also run a local testnet (i.e. on your local machine).
|
||||
At the time of writing, there were some public testnets you could use to test an Ocean Protocol application. For more information about those, see the page about [testnets](/concepts/testnets/).
|
||||
|
||||
## Get a Compatible Wallet
|
||||
|
||||
You will need a [wallet that can hold Ether (for any Ethereum network) and Ocean Tokens (for any Ethereum network)](/tutorials/wallets/). For the purpose of this tutorial, you can use [MetaMask](https://metamask.io/).
|
||||
You will need a [wallet that can hold Ether (for any Ethereum network) and Ocean Tokens (for any Ethereum network)](/concepts/wallets/). For the purpose of this tutorial, you can use MetaMask. See [our tutorial about how to set up MetaMask](/tutorials/metamask-setup/).
|
||||
|
||||
- Follow the MetaMask instructions to install it on your machine.
|
||||
- In MetaMask, switch from the **Main Ethereum Network** to the **Kovan Test Network** or the test network you're using.
|
||||
In MetaMask, be sure to switch from the **Main Ethereum Network** to whatever network you're using.
|
||||
|
||||
## Get Ether
|
||||
|
||||
@ -32,9 +31,9 @@ At the time of writing, there was no easy way to get Ether for the Nile Testnet.
|
||||
|
||||
If you're running a local Ganache-based testnet, then it creates several accounts at network launch time, and gives each of them some Ether. The addresses and private keys of those accounts should be shared (to logs or the console) during the launch process. You can use those accounts and their Ether.
|
||||
|
||||
### Get Ether for a Local Parity-Ethereum-Based Testnet
|
||||
### Get Ether for a Local Spree Testnet
|
||||
|
||||
If you're running a local Parity-Ethereum-based testnet based on [barge](https://github.com/oceanprotocol/barge), then you can send some Ether to `<YOUR ADDRESS>` using the command:
|
||||
If you're running a local Spree testnet, then you can send some Ether to `<YOUR ADDRESS>` using the command:
|
||||
|
||||
```bash
|
||||
curl --data '{"jsonrpc":"2.0","method":"personal_sendTransaction","params":[{"from":"0x00Bd138aBD70e2F00903268F3Db08f2D25677C9e","to":"<YOUR ADDRESS>","value":"0x7FFFFFFFFFFFFFFFFFF"}, "node0"],"id":0}' -H "Content-Type: application/json" -X POST localhost:8545
|
||||
|
BIN
content/tutorials/images/metamask-chrome-extension.png
Normal file
After Width: | Height: | Size: 86 KiB |
BIN
content/tutorials/images/metamask-create-username-password.png
Normal file
After Width: | Height: | Size: 403 KiB |
BIN
content/tutorials/images/metamask-secret-passcode.png
Normal file
After Width: | Height: | Size: 414 KiB |
BIN
content/tutorials/images/metamask_T_C.png
Normal file
After Width: | Height: | Size: 467 KiB |
BIN
content/tutorials/images/metamask_view-account-empty.png
Normal file
After Width: | Height: | Size: 259 KiB |
BIN
content/tutorials/images/metamask_view-account-options.png
Normal file
After Width: | Height: | Size: 295 KiB |
BIN
content/tutorials/images/react-app-05.png
Normal file
After Width: | Height: | Size: 172 KiB |
BIN
content/tutorials/images/view-metamask-account.png
Normal file
After Width: | Height: | Size: 259 KiB |
@ -3,9 +3,4 @@ title: Overview of the Tutorials
|
||||
description: What you can expect to find in these Ocean Protocol tutorials.
|
||||
---
|
||||
|
||||
The idea of these tutorials is to show you how to use squid-js (JavaScript) and squid-py (Python) to:
|
||||
|
||||
- publish a data set
|
||||
- get and use a data set
|
||||
- publish a compute service
|
||||
- get and use a compute service
|
||||
The idea of these tutorials is to show you how to use squid-js (JavaScript), squid-py (Python) and squid-java to publish a data set, to get & use a data set, and to do other things.
|
||||
|
@ -16,4 +16,7 @@ It's quite easy to figure out, but if you get stuck, here are some initial steps
|
||||
- When asked to select a kernel, select Python 3.
|
||||
- To make stuff happen (e.g. to run code cells), use the menus at the top of the JupyterLab console, or at the top of your current Jupyter notebook.
|
||||
|
||||
For more info, see the blog post titled, "[Project Manta Ray — Data Science powered by Ocean Protocol](https://blog.oceanprotocol.com/project-manta-ray-data-science-powered-by-ocean-protocol-535c54089b0f)."
|
||||
For more info, see the blog posts:
|
||||
|
||||
- "[Project Manta Ray — Data Science powered by Ocean Protocol](https://blog.oceanprotocol.com/project-manta-ray-data-science-powered-by-ocean-protocol-535c54089b0f)"
|
||||
- "[The Data Science Workflow — Powered by Ocean Protocol](https://blog.oceanprotocol.com/dive-into-ocean-protocol-ai-ecosystem-60f64eddf74d)"
|
||||
|
36
content/tutorials/metamask-setup.md
Normal file
@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Set Up MetaMask
|
||||
description: Tutorial about how to set up MetaMask for Chrome.
|
||||
---
|
||||
|
||||
## What is MetaMask?
|
||||
|
||||
[MetaMask](https://metamask.io/) is a browser extension that can:
|
||||
|
||||
- be used as a [wallet](/concepts/wallets) for Ether and ERC-20 tokens (such as Ocean tokens),
|
||||
- connect to TREZOR and Ledger hardware wallets,
|
||||
- be used to send Ether and ERC-20 tokens (i.e. to create, sign, and send Ethereum transactions).
|
||||
|
||||
## How to Set Up MetaMask for Chrome
|
||||
|
||||
**Note: MetaMask can also be used with a TREZOR or Ledger hardware wallet but we don't cover that option below; see [the MetaMask documentation](https://metamask.zendesk.com/hc/en-us/articles/360020394612-How-to-connect-a-Trezor-or-Ledger-Hardware-Wallet).**
|
||||
|
||||
1. Go to the [Chrome Web Store for extensions](https://chrome.google.com/webstore/category/extensions) and search for MetaMask.
|
||||
|
||||

|
||||
|
||||
2. Install MetaMask. It will get added as a browser extension in the top right corner of your browser. Read through and accept the terms and conditions. Create a username and password in the next step.
|
||||
|
||||

|
||||
|
||||
3. MetaMask will generate a secret backup phrase for you. Write it down, store it in a safe place, and click next.
|
||||
|
||||

|
||||
|
||||
4. Confirm your secret backup phrase and finish your MetaMask wallet setup.
|
||||
|
||||

|
||||
|
||||
5. Voila! Your account is now created. You can now manage Ether and Ocean Tokens with your wallet. You can copy your account address to clipboard from the options. When you want someone to send Ether or Ocean Tokens to you, you will have to give them that address. It's not a secret.
|
||||
|
||||
You can also watch our [tutorial video snippets](https://www.youtube.com/playlist?list=PL_dn0wVs9kWolBCbtHaFxsi408cumOeth) if you want more help setting up MetaMask.
|
8
content/tutorials/on-premise-for-brizo.md
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
title: Set Up On-Premise Storage
|
||||
description: Tutorial about how to set up on-premise storage for use with Ocean Protocol.
|
||||
---
|
||||
|
||||
To enable Brizo to use files stored in on-premise storage (i.e. files with an URL not containing "core.windows.net" or "s3://"), there is _nothing to do, other than make sure Brizo can resolve the URLs_. In particular, you don't have to set any Brizo-specific configuration settings, e.g. in the `[osmosis]` section of the Brizo config file or in some special Brizo environment variables.
|
||||
|
||||
Local and private network URLs are fine so long as they can be resolved by Brizo. Potential examples include `http://localhost/helicopter_data.xls`, `http://192.168.12.34/almond_sales_2012.csv` and `http://10.12.34.56/duck_photos.zip`.
|
@ -2,3 +2,184 @@
|
||||
title: Get & Use a Data Set
|
||||
description: Tutorial to get and use a data set in a basic React app.
|
||||
---
|
||||
|
||||
## Requirements
|
||||
|
||||
This is a continuation of the [React App Setup](/tutorials/react-setup/) and [React Publish Data-set](/tutorials/react-publish-data-set/) tutorial, so make sure you have done all the steps described in there.
|
||||
|
||||
Open `src/App.js` in your marketplace app from previous tutorials.
|
||||
|
||||
## Retrieve Assets
|
||||
|
||||
In the previous tutorial we added asset publishing. We can now search for published assets for consumption. Just after the `submitAsset()` function we can add a new function that will handle search:
|
||||
|
||||
```js
|
||||
async retrieveAssets() {
|
||||
this.dbAssets = await this.ocean.searchAssetsByText("Office Humidity")
|
||||
console.log(this.dbAssets)
|
||||
}
|
||||
```
|
||||
|
||||
The last thing we need is a button to start our search inside the render function just after `<button onClick={() => this.submitAsset()}>Register asset</button>`:
|
||||
|
||||
```jsx
|
||||
<button onClick={() => this.retrieveAssets()}>Retrieve assets</button>
|
||||
```
|
||||
|
||||
## Consume Assets
|
||||
|
||||
The retrieved assets can now be consumed so in this tutorial we consume the first one. The following code goes after `async retrieveAssets()` function.
|
||||
|
||||
```js
|
||||
async consumeAsset() {
|
||||
// get all accounts
|
||||
const accounts = await this.ocean.getAccounts()
|
||||
// get first asset
|
||||
const consumeAsset = this.dbAssets[0]
|
||||
// get service we want to execute
|
||||
const service = consumeAsset.findServiceByType('Access')
|
||||
// sign service
|
||||
const serviceAgreementSignatureResult = await this.ocean.signServiceAgreement(
|
||||
consumeAsset.id,
|
||||
service.serviceDefinitionId,
|
||||
accounts[0])
|
||||
// run it
|
||||
await this.ocean.initializeServiceAgreement(
|
||||
consumeAsset.id,
|
||||
service.serviceDefinitionId,
|
||||
serviceAgreementSignatureResult.serviceAgreementId,
|
||||
serviceAgreementSignatureResult.serviceAgreementSignature,
|
||||
// callback to handle the files we get
|
||||
(files) => { console.log('Asset files', files) },
|
||||
accounts[0])
|
||||
}
|
||||
```
|
||||
|
||||
We still need button in render function just after `<button onClick={()=>this.retrieveAssets()}>Retrieve assets</button>` to start consumption:
|
||||
|
||||
```jsx
|
||||
<button onClick={() => this.consumeAsset()}>Consume asset</button>
|
||||
```
|
||||
|
||||
With all these buttons in place, you should see this:
|
||||
|
||||

|
||||
|
||||
## Final Result
|
||||
|
||||
That's it. If you have no errors in your `console.log` and can see your asset files listed, you have a working marketplace.
|
||||
|
||||
Here is the full source of `src/App.js` that you should have if you followed this tutorial:
|
||||
|
||||
```jsx
|
||||
import React, { Component } from 'react'
|
||||
import './App.css'
|
||||
import { Ocean } from '@oceanprotocol/squid'
|
||||
import * as Web3 from 'web3'
|
||||
|
||||
const web3 = new Web3(window.web3.currentProvider)
|
||||
window.ethereum.enable()
|
||||
|
||||
const asset = {
|
||||
base: {
|
||||
name: 'Office Humidity',
|
||||
description: 'Weather information of UK including temperature and humidity',
|
||||
dateCreated: '2012-02-01T10:55:11+00:00',
|
||||
author: 'Met Office',
|
||||
size: '3.1bg',
|
||||
license: 'Public Domain',
|
||||
copyrightHolder: 'Met Office',
|
||||
contentUrls: [
|
||||
'https://testocnfiles.blob.core.windows.net/testfiles/testzkp.zip'
|
||||
],
|
||||
contentType: 'text/csv',
|
||||
links: [
|
||||
{
|
||||
name: 'Dataset sample',
|
||||
type: 'sample',
|
||||
url:
|
||||
'http://data.ceda.ac.uk/badc/ukcp09/data/gridded-land-obs/gridded-land-obs-daily/'
|
||||
}
|
||||
],
|
||||
tags: 'weather, uk, 2011, temperature, humidity',
|
||||
price: 5,
|
||||
type: 'dataset'
|
||||
},
|
||||
curation: {
|
||||
rating: 0,
|
||||
numVotes: 0,
|
||||
schema: 'Binary Voting'
|
||||
},
|
||||
additionalInformation: {
|
||||
updateFrequency: 'yearly'
|
||||
}
|
||||
}
|
||||
|
||||
class App extends Component {
|
||||
async componentDidMount() {
|
||||
this.ocean = await new Ocean.getInstance({
|
||||
web3Provider: web3,
|
||||
nodeUri: 'http://localhost:8545',
|
||||
aquariusUri: 'http://localhost:5000',
|
||||
brizoUri: 'http://localhost:8030',
|
||||
parityUri: 'http://localhost:8545',
|
||||
secretStoreUri: 'http://localhost:12001',
|
||||
threshold: 0,
|
||||
password: 'node0',
|
||||
address: '0x00bd138abd70e2f00903268f3db08f2d25677c9e'
|
||||
})
|
||||
console.log('Finished loading contracts!')
|
||||
}
|
||||
|
||||
async submitAsset() {
|
||||
const accounts = await this.ocean.getAccounts()
|
||||
const ddo = await this.ocean.registerAsset(asset, accounts[0])
|
||||
alert('Asset successfully submited: ', JSON.stringify(ddo))
|
||||
}
|
||||
|
||||
async retrieveAssets() {
|
||||
this.dbAssets = await this.ocean.searchAssetsByText('Office Humidity')
|
||||
console.log(this.dbAssets)
|
||||
}
|
||||
|
||||
async consumeAsset() {
|
||||
// get all accounts
|
||||
const accounts = await this.ocean.getAccounts()
|
||||
// get first asset
|
||||
const consumeAsset = this.dbAssets[0]
|
||||
// get service we want to execute
|
||||
const service = consumeAsset.findServiceByType('Access')
|
||||
// sign service
|
||||
const serviceAgreementSignatureResult = await this.ocean.signServiceAgreement(
|
||||
consumeAsset.id,
|
||||
service.serviceDefinitionId,
|
||||
accounts[0]
|
||||
)
|
||||
// run it
|
||||
await this.ocean.initializeServiceAgreement(
|
||||
consumeAsset.id,
|
||||
service.serviceDefinitionId,
|
||||
serviceAgreementSignatureResult.serviceAgreementId,
|
||||
serviceAgreementSignatureResult.serviceAgreementSignature,
|
||||
// callback to handle the files we get
|
||||
files => {
|
||||
console.log('Asset files', files)
|
||||
},
|
||||
accounts[0]
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="App App-header">
|
||||
<h1>Marketplace app</h1>
|
||||
<button onClick={() => this.submitAsset()}>Register asset</button>
|
||||
<button onClick={() => this.retrieveAssets()}>Retrieve assets</button>
|
||||
<button onClick={() => this.consumeAsset()}>Consume asset</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default App
|
||||
```
|
||||
|
@ -5,13 +5,13 @@ description: Tutorial to add dataset publishing capabilities to a basic React ap
|
||||
|
||||
## Requirements
|
||||
|
||||
This is a continuation of the [React App Setup](/tutorials/react-setup) tutorial, so make sure you have done all the steps described in there.
|
||||
This is a continuation of the [React App Setup](/tutorials/react-setup/) tutorial, so make sure you have done all the steps described in there.
|
||||
|
||||
Open `src/App.js` in your marketplace app from the [React App Setup](/tutorials/react-setup) tutorial.
|
||||
Open `src/App.js` in your marketplace app from the [React App Setup](/tutorials/react-setup/) tutorial.
|
||||
|
||||
## Define Asset
|
||||
|
||||
First, let's add the asset that we want to publish.
|
||||
First, let's add the [asset](/concepts/terminology/#asset-or-data-asset) that we want to publish.
|
||||
|
||||
To do that, we need to add the following code after `window.ethereum.enable()` line, defining our asset based on the [OEP-08](https://github.com/oceanprotocol/OEPs/tree/master/8) metadata structure:
|
||||
|
||||
@ -130,8 +130,8 @@ class App extends Component {
|
||||
parityUri: 'http://localhost:8545',
|
||||
secretStoreUri: 'http://localhost:12001',
|
||||
threshold: 0,
|
||||
password: 'secret',
|
||||
address: '0x068ed00cf0441e4829d9784fcbe7b9e26d4bd8d0'
|
||||
password: 'node0',
|
||||
address: '0x00bd138abd70e2f00903268f3db08f2d25677c9e'
|
||||
})
|
||||
console.log('Finished loading contracts!')
|
||||
}
|
||||
|
@ -84,8 +84,8 @@ async componentDidMount() {
|
||||
parityUri: "http://localhost:8545",
|
||||
secretStoreUri: "http://localhost:12001",
|
||||
threshold: 0,
|
||||
password: "secret",
|
||||
address: "0x068ed00cf0441e4829d9784fcbe7b9e26d4bd8d0",
|
||||
password: "node0",
|
||||
address: "0x00bd138abd70e2f00903268f3db08f2d25677c9e",
|
||||
})
|
||||
console.log("Finished loading contracts!")
|
||||
}
|
||||
@ -118,8 +118,8 @@ class App extends Component {
|
||||
parityUri: 'http://localhost:8545',
|
||||
secretStoreUri: 'http://localhost:12001',
|
||||
threshold: 0,
|
||||
password: 'secret',
|
||||
address: '0x068ed00cf0441e4829d9784fcbe7b9e26d4bd8d0'
|
||||
password: 'node0',
|
||||
address: '0x00bd138abd70e2f00903268f3db08f2d25677c9e'
|
||||
})
|
||||
console.log('Finished loading contracts!')
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
---
|
||||
title: Wallets for Ocean Tokens
|
||||
description: If you want to use the Ocean Network, you need Ocean Tokens (typical ERC-20 tokens), and to get Ocean Tokens, you need to get a wallet that can hold Ocean Tokens.
|
||||
---
|
||||
|
||||
## Some Terminology
|
||||
|
||||
There's a lot of terminology around wallets, so we'll start by going over some of it.
|
||||
|
||||
A wallet might contain only one **account** (Ethereum account) or it might contain many accounts.
|
||||
|
||||
Each account has a **balance** (e.g. 1.832 Ocean Tokens), an **address** (e.g. 0xa0A9d7e78bF29351997cA5589A0Af689eEC99211), a **public key** and a **private key**.
|
||||
|
||||
An account is identified by its address, so if you want someone to send some Ocean Tokens to a specific account, you give them the account's address.
|
||||
|
||||
The private key is used to spend the Ocean Tokens in the account. You must keep it secret, because anyone with that private key can spend those tokens. If you lose the secret key, and nobody else has it, then _nobody_ can spend those tokens, so don't lose it!
|
||||
|
||||
> Note: The same account might have an Ocean Token balance, an [Ether](https://www.ethereum.org/ether) balance, and other balances.
|
||||
|
||||
## Wallet Options
|
||||
|
||||
Ocean Tokens are [ERC-20 tokens](https://en.wikipedia.org/wiki/ERC-20), so any wallet that supports arbitrary ERC-20 tokens should work to hold Ocean Tokens.
|
||||
|
||||
There are many kinds of wallets (e.g. paper wallets, hardware wallets, software wallets, custodial wallets), each with its own advantages and disadvantages. There is a tradeoff between security and convenience. We encourage you to search around and read about wallets to understand the options.
|
||||
|
||||
**We don't recommend or endorse any particular wallets at this time.** Some wallets which _might_ work with Ocean Tokens are:
|
||||
|
||||
- Gnosis Safe
|
||||
- MetaMask
|
||||
- Trust Wallet
|
||||
- Tokenary
|
@ -20,8 +20,18 @@
|
||||
- group: Libraries
|
||||
items:
|
||||
- name: squid-js
|
||||
links:
|
||||
- name: API reference
|
||||
url: /references/squid-js/
|
||||
- name: squid-py
|
||||
links:
|
||||
- name: API reference
|
||||
url: /references/squid-py/
|
||||
- name: squid-java
|
||||
links:
|
||||
- name: API reference
|
||||
url: /references/squid-java/
|
||||
- name: Plecos
|
||||
|
||||
- group: OceanDB
|
||||
items:
|
||||
|
@ -10,6 +10,8 @@
|
||||
link: /concepts/tools/
|
||||
- title: Testnets
|
||||
link: /concepts/testnets/
|
||||
- title: Wallet Basics
|
||||
link: /concepts/wallets/
|
||||
|
||||
- group: Architecture
|
||||
items:
|
||||
|
@ -3,16 +3,6 @@
|
||||
- title: API References
|
||||
link: /references/introduction/
|
||||
|
||||
# - group: squid-js
|
||||
# items:
|
||||
# - title: API Reference
|
||||
# link: /references/squid-js/
|
||||
|
||||
- group: squid-py
|
||||
items:
|
||||
- title: API Reference
|
||||
link: /references/squid-py/
|
||||
|
||||
- group: aquarius
|
||||
items:
|
||||
- title: API Reference
|
||||
@ -22,3 +12,18 @@
|
||||
items:
|
||||
- title: API Reference
|
||||
link: /references/brizo/
|
||||
|
||||
- group: squid-js
|
||||
items:
|
||||
- title: API Reference
|
||||
link: /references/squid-js/
|
||||
|
||||
- group: squid-py
|
||||
items:
|
||||
- title: API Reference
|
||||
link: /references/squid-py/
|
||||
|
||||
- group: squid-java
|
||||
items:
|
||||
- title: API Reference
|
||||
link: /references/squid-java/
|
||||
|
@ -2,12 +2,16 @@
|
||||
items:
|
||||
- title: Introduction
|
||||
link: /tutorials/introduction/
|
||||
- title: Wallets for Ocean Tokens
|
||||
link: /tutorials/wallets/
|
||||
- title: Get Ether and Ocean Tokens for Testnets
|
||||
- title: Set Up MetaMask
|
||||
link: /tutorials/metamask-setup/
|
||||
- title: Get Ether and Ocean Tokens
|
||||
link: /tutorials/get-ether-and-ocean-tokens/
|
||||
- title: Set Up Azure Storage
|
||||
link: /tutorials/azure-for-brizo/
|
||||
- title: Set Up Amazon S3 Storage
|
||||
link: /tutorials/amazon-s3-for-brizo/
|
||||
- title: Set Up On-Premise Storage
|
||||
link: /tutorials/on-premise-for-brizo/
|
||||
|
||||
- group: React App Tutorial (squid-js)
|
||||
items:
|
||||
|
2
external/dev-ocean
vendored
@ -1 +1 @@
|
||||
Subproject commit 79786228757f8e39092d9dd5adf387097f0b02f6
|
||||
Subproject commit f7f8e10a5babd85fca48d2df40f6165cfb68fdff
|
1
external/squid-js
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 89cd8fd744ad5c61273b5da595e33f3b80c29c4f
|
@ -153,7 +153,7 @@ exports.createPages = ({ graphql, actions }) => {
|
||||
// Create pages from swagger json files
|
||||
//
|
||||
const apiSwaggerTemplate = path.resolve(
|
||||
'./src/templates/ApiSwagger.jsx'
|
||||
'./src/templates/Swagger/index.jsx'
|
||||
)
|
||||
|
||||
const petStoreSlug = '/references/petstore/'
|
||||
@ -197,6 +197,58 @@ exports.createPages = ({ graphql, actions }) => {
|
||||
}
|
||||
})
|
||||
|
||||
//
|
||||
// Create pages from TypeDoc json files
|
||||
//
|
||||
const typeDocSpecs = ['./data/squid-js.json']
|
||||
const typedocTemplate = path.resolve(
|
||||
'./src/templates/Typedoc/index.jsx'
|
||||
)
|
||||
|
||||
typeDocSpecs.forEach(spec => {
|
||||
const typedoc = require(spec) // eslint-disable-line
|
||||
|
||||
const name = path
|
||||
.basename(spec)
|
||||
.split('.json')
|
||||
.join('')
|
||||
|
||||
const slug = `/references/${name}/`
|
||||
|
||||
createPage({
|
||||
path: slug,
|
||||
component: typedocTemplate,
|
||||
context: {
|
||||
slug,
|
||||
typedoc,
|
||||
// TODO: defining these classes for inclusion
|
||||
// needs to be handled somewhere else to keep
|
||||
// it generic for all TypeDoc specs
|
||||
classes: [
|
||||
'ocean/Ocean',
|
||||
'ocean/OceanAccounts',
|
||||
'ocean/OceanAssets',
|
||||
'ocean/OceanAgreements',
|
||||
'ocean/Account',
|
||||
'ocean/DID',
|
||||
'ocean/ServiceAgreements/ServiceAgreement',
|
||||
'ddo/DDO',
|
||||
'ddo/Service',
|
||||
'aquarius/AquariusProvider',
|
||||
'aquarius/Aquarius',
|
||||
'aquarius/query/SearchQuery',
|
||||
'brizo/BrizoProvider',
|
||||
'brizo/Brizo',
|
||||
'keeper/Keeper',
|
||||
'keeper/Web3Provider',
|
||||
'secretstore/SecretStoreProvider',
|
||||
'models/Config',
|
||||
'models/Balance'
|
||||
]
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
//
|
||||
// create redirects
|
||||
//
|
||||
|
80
package.json
@ -5,8 +5,8 @@
|
||||
"author": "Ocean Protocol <devops@oceanprotocol.com>",
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"build": "gatsby build",
|
||||
"start": "gatsby develop",
|
||||
"build": "npm run typedoc && gatsby build",
|
||||
"start": "npm run typedoc && gatsby develop",
|
||||
"ssr": "npm run build && serve -s public/",
|
||||
"format:js": "prettier --write '**/*.{js,jsx}'",
|
||||
"format:css": "prettier-stylelint --write --quiet 'src/**/*.{css,scss}'",
|
||||
@ -19,65 +19,71 @@
|
||||
"lint:yml": "prettier '**/*.{yml,yaml}' --list-different",
|
||||
"lint": "run-p --continue-on-error lint:js lint:css lint:md lint:yml",
|
||||
"test": "npm run lint",
|
||||
"deploy": "./scripts/deploy.sh"
|
||||
"deploy": "./scripts/deploy.sh",
|
||||
"typedoc": "node ./scripts/typedoc.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@oceanprotocol/art": "^2.1.0",
|
||||
"@oceanprotocol/art": "^2.2.0",
|
||||
"axios": "^0.18.0",
|
||||
"classnames": "^2.2.6",
|
||||
"gatsby": "^2.0.67",
|
||||
"gatsby-image": "^2.0.25",
|
||||
"gatsby-plugin-catch-links": "^2.0.9",
|
||||
"gatsby-plugin-google-analytics": "^2.0.8",
|
||||
"gatsby-plugin-manifest": "^2.0.12",
|
||||
"gatsby-plugin-offline": "^2.0.19",
|
||||
"gatsby-plugin-react-helmet": "^3.0.4",
|
||||
"gatsby-plugin-sass": "^2.0.7",
|
||||
"gatsby-plugin-sharp": "^2.0.15",
|
||||
"gatsby-plugin-sitemap": "^2.0.3",
|
||||
"gatsby": "^2.0.115",
|
||||
"gatsby-image": "^2.0.29",
|
||||
"gatsby-plugin-catch-links": "^2.0.10",
|
||||
"gatsby-plugin-google-analytics": "^2.0.13",
|
||||
"gatsby-plugin-manifest": "^2.0.17",
|
||||
"gatsby-plugin-offline": "^2.0.22",
|
||||
"gatsby-plugin-react-helmet": "^3.0.6",
|
||||
"gatsby-plugin-sass": "^2.0.10",
|
||||
"gatsby-plugin-sharp": "^2.0.20",
|
||||
"gatsby-plugin-sitemap": "^2.0.5",
|
||||
"gatsby-plugin-svgr": "^2.0.1",
|
||||
"gatsby-remark-autolink-headers": "^2.0.12",
|
||||
"gatsby-remark-autolink-headers": "^2.0.13",
|
||||
"gatsby-remark-component": "^1.1.3",
|
||||
"gatsby-remark-copy-linked-files": "^2.0.7",
|
||||
"gatsby-remark-embed-video": "^1.4.0",
|
||||
"gatsby-remark-github": "^1.0.1",
|
||||
"gatsby-remark-images": "^3.0.1",
|
||||
"gatsby-remark-prismjs": "^3.1.4",
|
||||
"gatsby-remark-responsive-iframe": "^2.0.7",
|
||||
"gatsby-remark-smartypants": "^2.0.7",
|
||||
"gatsby-source-filesystem": "^2.0.12",
|
||||
"gatsby-source-graphql": "^2.0.7",
|
||||
"gatsby-transformer-remark": "^2.1.15",
|
||||
"gatsby-remark-copy-linked-files": "^2.0.9",
|
||||
"gatsby-remark-embed-video": "^1.7.0",
|
||||
"gatsby-remark-github": "^2.0.0",
|
||||
"gatsby-remark-images": "^3.0.3",
|
||||
"gatsby-remark-prismjs": "^3.2.4",
|
||||
"gatsby-remark-responsive-iframe": "^2.0.9",
|
||||
"gatsby-remark-smartypants": "^2.0.8",
|
||||
"gatsby-source-filesystem": "^2.0.20",
|
||||
"gatsby-source-graphql": "^2.0.10",
|
||||
"gatsby-transformer-remark": "^2.2.4",
|
||||
"gatsby-transformer-sharp": "^2.1.9",
|
||||
"gatsby-transformer-yaml": "^2.1.6",
|
||||
"gatsby-transformer-yaml": "^2.1.8",
|
||||
"giphy-js-sdk-core": "^1.0.6",
|
||||
"intersection-observer": "^0.5.1",
|
||||
"node-sass": "^4.11.0",
|
||||
"prismjs": "^1.15.0",
|
||||
"react": "^16.6.3",
|
||||
"react-dom": "^16.6.3",
|
||||
"react": "^16.8.0",
|
||||
"react-dom": "^16.8.0",
|
||||
"react-helmet": "^5.2.0",
|
||||
"react-scrollspy": "^3.3.5",
|
||||
"rehype-react": "^3.1.0",
|
||||
"remark": "^10.0.1",
|
||||
"remark-react": "^5.0.0",
|
||||
"remark-github-plugin": "^1.3.1",
|
||||
"remark-react": "^5.0.1",
|
||||
"slugify": "^1.3.4",
|
||||
"swagger-client": "^3.8.22"
|
||||
"smoothscroll-polyfill": "^0.4.3",
|
||||
"swagger-client": "^3.8.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@svgr/webpack": "^4.1.0",
|
||||
"dotenv": "^6.2.0",
|
||||
"eslint": "^5.10.0",
|
||||
"eslint": "^5.13.0",
|
||||
"eslint-config-oceanprotocol": "^1.3.0",
|
||||
"eslint-config-prettier": "^3.3.0",
|
||||
"eslint-plugin-prettier": "^3.0.0",
|
||||
"markdownlint-cli": "^0.13.0",
|
||||
"eslint-config-prettier": "^4.0.0",
|
||||
"eslint-plugin-prettier": "^3.0.1",
|
||||
"markdownlint-cli": "^0.14.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^1.15.3",
|
||||
"ora": "^3.0.0",
|
||||
"prettier": "^1.16.4",
|
||||
"prettier-stylelint": "^0.4.2",
|
||||
"stylelint": "^9.9.0",
|
||||
"stylelint": "^9.10.1",
|
||||
"stylelint-config-bigchaindb": "^1.2.1",
|
||||
"stylelint-config-css-modules": "^1.3.0",
|
||||
"stylelint-config-standard": "^18.2.0"
|
||||
"stylelint-config-standard": "^18.2.0",
|
||||
"typedoc": "^0.14.2"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
66
scripts/typedoc.js
Normal file
@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/* eslint-disable no-console, security/detect-child-process, security/detect-non-literal-fs-filename */
|
||||
|
||||
const fs = require('fs')
|
||||
const typedoc = require('typedoc')
|
||||
const typescript = require('typescript')
|
||||
const ora = require('ora')
|
||||
const squidJsPackage = require('../external/squid-js/package.json')
|
||||
const { exec } = require('child_process')
|
||||
|
||||
const { description, version } = squidJsPackage
|
||||
|
||||
// Setup our paths, relative to project root
|
||||
const outPath = './data/squid-js.json'
|
||||
const files = ['./external/squid-js/src/squid.ts']
|
||||
|
||||
// specifically point to tsconfig, otherwise TypeDoc fails
|
||||
const config = typescript.findConfigFile(
|
||||
'./external/squid-js',
|
||||
typescript.sys.fileExists
|
||||
)
|
||||
|
||||
// npm install for squid-js
|
||||
const spinnerNpm = ora('Installing submodule dependencies...').start()
|
||||
const install = exec(
|
||||
'cd ./external/squid-js && npm i && git checkout package-lock.json'
|
||||
)
|
||||
|
||||
install.on('exit', () => {
|
||||
spinnerNpm.succeed('Installed submodule dependencies.')
|
||||
generateJson()
|
||||
})
|
||||
|
||||
const generateJson = () => {
|
||||
const spinnerTypedoc = ora('Generating TypeDoc json...').start()
|
||||
|
||||
// Setup our TypeDoc app
|
||||
const app = new typedoc.Application({
|
||||
tsconfig: config
|
||||
})
|
||||
|
||||
const src = app.expandInputFiles(files)
|
||||
const project = app.convert(src)
|
||||
|
||||
// Generate the JSON file
|
||||
app.generateJson(project, outPath)
|
||||
|
||||
// Parse and modify json output
|
||||
const jsonOrig = JSON.parse(fs.readFileSync(outPath, 'utf8'))
|
||||
|
||||
const jsonFinal = {
|
||||
info: {
|
||||
title: 'Squid-js',
|
||||
description,
|
||||
version,
|
||||
sourceUrl:
|
||||
'https://github.com/oceanprotocol/squid-js/tree/develop/src/'
|
||||
},
|
||||
...jsonOrig
|
||||
}
|
||||
|
||||
fs.writeFileSync(outPath, JSON.stringify(jsonFinal, null, 4))
|
||||
|
||||
spinnerTypedoc.succeed('Generated TypeDoc json.')
|
||||
}
|
@ -27,6 +27,39 @@
|
||||
word-wrap: normal;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
// stylelint-disable selector-no-qualifying-type
|
||||
:not(pre) > code,
|
||||
:not(pre) > code[class*='language-'] {
|
||||
background: darken($brand-white, 5%);
|
||||
color: $brand-grey-dark;
|
||||
display: inline-block;
|
||||
padding-left: .3rem;
|
||||
padding-right: .3rem;
|
||||
}
|
||||
// stylelint-enable selector-no-qualifying-type
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
margin-bottom: $spacer;
|
||||
padding: 0;
|
||||
background: $brand-black;
|
||||
|
||||
// make 'em scrollable
|
||||
overflow: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
|
||||
code {
|
||||
padding: $spacer;
|
||||
white-space: pre;
|
||||
display: block;
|
||||
color: $brand-grey-lighter;
|
||||
overflow-wrap: normal;
|
||||
word-wrap: normal;
|
||||
word-break: normal;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.empty {
|
||||
|
@ -2,7 +2,7 @@ import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { ReactComponent as Pencil } from '../images/pencil.svg'
|
||||
import styles from './DocFooter.module.scss'
|
||||
import { githubContentPath, githubDevOceanPath } from '../../config'
|
||||
import { social, githubContentPath, githubDevOceanPath } from '../../config'
|
||||
|
||||
const DocFooter = ({ post, url, externalName }) => {
|
||||
let path
|
||||
@ -24,6 +24,7 @@ const DocFooter = ({ post, url, externalName }) => {
|
||||
|
||||
return (
|
||||
<footer className={styles.footer}>
|
||||
<a href={social.gitter}>✋ Ask a question on Gitter</a>
|
||||
<a href={url} className={post && !post.html ? styles.active : null}>
|
||||
<Pencil /> Edit this page on GitHub
|
||||
{externalName && (
|
||||
|
@ -6,12 +6,22 @@
|
||||
font-size: $font-size-small;
|
||||
text-align: center;
|
||||
|
||||
@media (min-width: $break-point--small) {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
a {
|
||||
font-family: $font-family-button;
|
||||
font-weight: $font-weight-bold;
|
||||
text-transform: uppercase;
|
||||
color: $brand-grey-light;
|
||||
margin: 0 $spacer / 2;
|
||||
display: block;
|
||||
margin-bottom: $spacer / 2;
|
||||
|
||||
@media (min-width: $break-point--small) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
@ -24,6 +34,10 @@
|
||||
margin-bottom: -1px;
|
||||
fill: $brand-grey-light;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
85
src/components/Scroll.jsx
Normal file
@ -0,0 +1,85 @@
|
||||
import smoothscroll from 'smoothscroll-polyfill'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
export default class TocScroll extends React.Component {
|
||||
static propTypes = {
|
||||
type: PropTypes.string,
|
||||
element: PropTypes.string,
|
||||
offset: PropTypes.number,
|
||||
timeout: PropTypes.number,
|
||||
children: PropTypes.node.isRequired
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
smoothscroll.polyfill()
|
||||
}
|
||||
|
||||
handleClick = e => {
|
||||
e.preventDefault()
|
||||
|
||||
let elem = 0
|
||||
let scroll = true
|
||||
const { type, element, offset, timeout } = this.props
|
||||
|
||||
if (type && element) {
|
||||
switch (type) {
|
||||
case 'class':
|
||||
// eslint-disable-next-line prefer-destructuring
|
||||
elem = document.getElementsByClassName(element)[0]
|
||||
scroll = !!elem
|
||||
break
|
||||
case 'id':
|
||||
elem = document.getElementById(element)
|
||||
scroll = !!elem
|
||||
break
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
if (scroll) {
|
||||
this.scrollTo(elem, offset, timeout)
|
||||
|
||||
// update browser url
|
||||
if (typeof window !== 'undefined') {
|
||||
window.history.pushState({}, null, `#${element}`)
|
||||
}
|
||||
} else {
|
||||
console.log(`Element not found: ${element}`) // eslint-disable-line
|
||||
}
|
||||
}
|
||||
|
||||
scrollTo(element, offSet = 0, timeout = null) {
|
||||
const elemPos = element
|
||||
? element.getBoundingClientRect().top + window.pageYOffset
|
||||
: 0
|
||||
|
||||
if (timeout) {
|
||||
setTimeout(() => {
|
||||
window.scroll({
|
||||
top: elemPos + offSet,
|
||||
left: 0,
|
||||
behavior: 'smooth'
|
||||
})
|
||||
}, timeout)
|
||||
} else {
|
||||
window.scroll({
|
||||
top: elemPos + offSet,
|
||||
left: 0,
|
||||
behavior: 'smooth'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<a
|
||||
onClick={this.handleClick}
|
||||
href={`#${this.props.element}`}
|
||||
{...this.props}
|
||||
>
|
||||
{this.props.children}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
}
|
@ -34,13 +34,10 @@ SidebarLink.propTypes = {
|
||||
linkClasses: PropTypes.string
|
||||
}
|
||||
|
||||
const SidebarList = ({ items, location, toc, tableOfContents }) => (
|
||||
const SidebarList = ({ items, location, toc, tocComponent }) => (
|
||||
<div className={styles.list}>
|
||||
{toc ? (
|
||||
<div
|
||||
className={styles.toc}
|
||||
dangerouslySetInnerHTML={{ __html: tableOfContents }}
|
||||
/>
|
||||
<div className={styles.toc}>{tocComponent}</div>
|
||||
) : (
|
||||
<ul>
|
||||
{items.map((item, j) => (
|
||||
@ -65,7 +62,7 @@ SidebarList.propTypes = {
|
||||
items: PropTypes.array.isRequired,
|
||||
location: PropTypes.object.isRequired,
|
||||
toc: PropTypes.bool,
|
||||
tableOfContents: PropTypes.string
|
||||
tocComponent: PropTypes.object
|
||||
}
|
||||
|
||||
const SidebarGroupTitle = ({ group }) => (
|
||||
@ -98,25 +95,25 @@ const SidebarGroup = ({ i, group, location, ...props }) => (
|
||||
</>
|
||||
)
|
||||
|
||||
SidebarGroup.propTypes = {
|
||||
i: PropTypes.number,
|
||||
group: PropTypes.object,
|
||||
location: PropTypes.object
|
||||
}
|
||||
|
||||
export default class Sidebar extends Component {
|
||||
static propTypes = {
|
||||
sidebar: PropTypes.string,
|
||||
location: PropTypes.object.isRequired,
|
||||
collapsed: PropTypes.bool,
|
||||
toc: PropTypes.bool,
|
||||
tableOfContents: PropTypes.string
|
||||
tocComponent: PropTypes.element
|
||||
}
|
||||
|
||||
static defaultProps = { location: { pathname: '/' } }
|
||||
|
||||
render() {
|
||||
const {
|
||||
sidebar,
|
||||
location,
|
||||
collapsed,
|
||||
toc,
|
||||
tableOfContents
|
||||
} = this.props
|
||||
const { sidebar, location, collapsed, toc, tocComponent } = this.props
|
||||
|
||||
if (sidebar) {
|
||||
try {
|
||||
@ -143,7 +140,7 @@ export default class Sidebar extends Component {
|
||||
group={group}
|
||||
location={location}
|
||||
toc={toc}
|
||||
tableOfContents={tableOfContents}
|
||||
tocComponent={tocComponent}
|
||||
/>
|
||||
) : (
|
||||
<SidebarGroupTitle group={group} />
|
||||
|
@ -16,8 +16,8 @@
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
@ -79,22 +79,50 @@
|
||||
&:focus {
|
||||
transform: none;
|
||||
color: $brand-purple;
|
||||
|
||||
:global(.setup) & {
|
||||
color: $brand-blue;
|
||||
}
|
||||
|
||||
:global(.tutorials) & {
|
||||
color: $orange;
|
||||
}
|
||||
|
||||
:global(.references) & {
|
||||
color: $green;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.toc {
|
||||
ul {
|
||||
padding-left: 0;
|
||||
margin: 0;
|
||||
|
||||
ul {
|
||||
padding-left: $spacer / 2;
|
||||
margin: 0;
|
||||
border-left: 1px solid $brand-grey-lighter;
|
||||
margin-left: $spacer;
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
padding-top: $spacer / 12;
|
||||
padding-bottom: $spacer / 12;
|
||||
}
|
||||
|
||||
code {
|
||||
background: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
[data-deprecated='true'] code {
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
|
||||
.active {
|
||||
@ -111,4 +139,16 @@
|
||||
color: $orange;
|
||||
border-left-color: $orange;
|
||||
}
|
||||
|
||||
:global(.references) & {
|
||||
color: $green;
|
||||
border-left-color: $green;
|
||||
}
|
||||
}
|
||||
|
||||
.scrollspyActive {
|
||||
> a {
|
||||
color: $green;
|
||||
border-left-color: $green;
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,11 @@ const SectionBox = ({ to, children, ...props }) =>
|
||||
<div {...props}>{children}</div>
|
||||
)
|
||||
|
||||
SectionBox.propTypes = {
|
||||
to: PropTypes.string.isRequired,
|
||||
children: PropTypes.any.isRequired
|
||||
}
|
||||
|
||||
const SectionLink = ({ to, title, color, children }) => {
|
||||
// eslint-disable-next-line
|
||||
let classNames = classnames(styles.link, {
|
||||
|
@ -244,6 +244,7 @@ table {
|
||||
border-bottom: 1px solid $brand-grey-lighter;
|
||||
text-align: left;
|
||||
font-size: 90%;
|
||||
vertical-align: top;
|
||||
|
||||
&[align='center'] {
|
||||
text-align: center;
|
||||
@ -282,35 +283,35 @@ samp {
|
||||
}
|
||||
}
|
||||
|
||||
:not(pre) > code {
|
||||
background: darken($brand-white, 5%) !important;
|
||||
color: $brand-grey-dark !important;
|
||||
display: inline-block;
|
||||
padding-left: .3rem !important;
|
||||
padding-right: .3rem !important;
|
||||
}
|
||||
// :not(pre) > code {
|
||||
// background: darken($brand-white, 5%);
|
||||
// color: $brand-grey-dark;
|
||||
// display: inline-block;
|
||||
// padding-left: .3rem;
|
||||
// padding-right: .3rem;
|
||||
// }
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
margin-bottom: $spacer !important;
|
||||
padding: 0 !important;
|
||||
background: $brand-black !important;
|
||||
// pre {
|
||||
// display: block;
|
||||
// margin-bottom: $spacer;
|
||||
// padding: 0;
|
||||
// background: $brand-black;
|
||||
|
||||
// make 'em scrollable
|
||||
overflow: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
// // make 'em scrollable
|
||||
// overflow: auto;
|
||||
// -webkit-overflow-scrolling: touch;
|
||||
|
||||
code {
|
||||
padding: $spacer;
|
||||
white-space: pre;
|
||||
display: block;
|
||||
color: $brand-grey-lighter !important;
|
||||
overflow-wrap: normal;
|
||||
word-wrap: normal;
|
||||
word-break: normal;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
// code {
|
||||
// padding: $spacer;
|
||||
// white-space: pre;
|
||||
// display: block;
|
||||
// color: $brand-grey-lighter;
|
||||
// overflow-wrap: normal;
|
||||
// word-wrap: normal;
|
||||
// word-break: normal;
|
||||
// overflow: auto;
|
||||
// }
|
||||
// }
|
||||
|
||||
// Selection
|
||||
/////////////////////////////////////
|
||||
|
@ -1,321 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { graphql } from 'gatsby'
|
||||
import Helmet from 'react-helmet'
|
||||
import slugify from 'slugify'
|
||||
import Layout from '../components/Layout'
|
||||
import Content from '../components/Content'
|
||||
import HeaderSection from '../components/HeaderSection'
|
||||
import Sidebar from '../components/Sidebar'
|
||||
import DocHeader from '../components/DocHeader'
|
||||
import DocFooter from '../components/DocFooter'
|
||||
import SEO from '../components/Seo'
|
||||
import stylesDoc from './Doc.module.scss'
|
||||
import styles from './ApiSwagger.module.scss'
|
||||
|
||||
const cleanKey = key => {
|
||||
let keyCleaned = key
|
||||
|
||||
if (key.includes('aquarius')) {
|
||||
keyCleaned = key.replace(/\/api\/v1\/aquarius/gi, '')
|
||||
}
|
||||
|
||||
if (key.includes('brizo')) {
|
||||
keyCleaned = key.replace(/\/api\/v1\/brizo/gi, '')
|
||||
}
|
||||
|
||||
return keyCleaned
|
||||
}
|
||||
|
||||
const toc = api => {
|
||||
const items = Object.keys(api.paths).map(
|
||||
key => `<li key=${key}>
|
||||
<a href="#${slugify(cleanKey(key))}"><code>${cleanKey(
|
||||
key
|
||||
)}</code></a>
|
||||
</li>`
|
||||
)
|
||||
|
||||
return `<ul>${items}</ul>`
|
||||
}
|
||||
|
||||
const SwaggerMeta = ({ contact, license }) => (
|
||||
<ul className={styles.swaggerMeta}>
|
||||
{contact && (
|
||||
<li>
|
||||
<a href={`mailto:${contact.email}`}>{contact.email}</a>
|
||||
</li>
|
||||
)}
|
||||
{license && (
|
||||
<li>
|
||||
<a href={license.url}>{license.name}</a>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
)
|
||||
|
||||
SwaggerMeta.propTypes = {
|
||||
contact: PropTypes.object,
|
||||
license: PropTypes.object
|
||||
}
|
||||
|
||||
const ParameterExample = ({ properties }) => (
|
||||
//
|
||||
// HEADS UP!
|
||||
//
|
||||
// Constructing the example request body here based on the defined properties
|
||||
// where `key` is the name of the property, and `properties[key].example` is
|
||||
// the value for it.
|
||||
//
|
||||
// Making prism.js pick up on the strings only output didn't work out so well
|
||||
// so the spans and classes this plugin would add are added manually here. Since we
|
||||
// include the prism css file globally this is picked up by that.
|
||||
//
|
||||
// But this can only work if all keys and values are manually constructed here, which
|
||||
// is almost impossible to do for deep nested objects or arrays as example value. Running
|
||||
// that code through `JSON.stringify` won't syntax highlight that part of the code.
|
||||
//
|
||||
<pre className="language-json">
|
||||
<code className="language-json">
|
||||
{'{'}
|
||||
{properties &&
|
||||
Object.keys(properties).map(key => (
|
||||
<div key={key}>
|
||||
<span className="token property">{` "${key}"`}</span>
|
||||
<span className="token operator">{`: `}</span>
|
||||
{properties[key].type === 'string' && (
|
||||
<span className="token string">{`"${
|
||||
properties[key].example
|
||||
}"`}</span>
|
||||
)}
|
||||
{(properties[key].type === 'integer' ||
|
||||
properties[key].type === 'number') && (
|
||||
<span className="token number">
|
||||
{`${properties[key].example}`}
|
||||
</span>
|
||||
)}
|
||||
{(properties[key].type === 'array' ||
|
||||
properties[key].type === 'object') &&
|
||||
JSON.stringify(properties[key].example, null, 2)}
|
||||
,
|
||||
</div>
|
||||
))}
|
||||
{'}'}
|
||||
</code>
|
||||
</pre>
|
||||
)
|
||||
|
||||
ParameterExample.propTypes = {
|
||||
properties: PropTypes.object
|
||||
}
|
||||
|
||||
const Parameters = ({ parameters }) => (
|
||||
<>
|
||||
<h4 className={styles.subHeading}>Parameters</h4>
|
||||
|
||||
{parameters.map(parameter => {
|
||||
const { name, type, required, description, schema } = parameter
|
||||
|
||||
return (
|
||||
<div className={styles.parameters} key={parameter.name}>
|
||||
<h5>
|
||||
<code>{name}</code>
|
||||
{required && (
|
||||
<span
|
||||
className={styles.parameterRequired}
|
||||
title="required parameter"
|
||||
>
|
||||
*
|
||||
</span>
|
||||
)}
|
||||
<span className={styles.parameterType}>{type}</span>
|
||||
</h5>
|
||||
|
||||
<p>{description}</p>
|
||||
|
||||
{schema && (
|
||||
<ParameterExample properties={schema.properties} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)
|
||||
|
||||
const Responses = ({ responses }) => (
|
||||
<>
|
||||
<h4 className={styles.subHeading}>Responses</h4>
|
||||
{Object.keys(responses).map(key => (
|
||||
<div key={key} className={styles.response}>
|
||||
<code>{key}</code> {responses[key].description}
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
|
||||
const Method = ({ keyName, value }) => {
|
||||
const { summary, description, parameters, responses } = value
|
||||
|
||||
return (
|
||||
<div className={styles.method}>
|
||||
<h3 className={styles.pathMethod} data-type={keyName}>
|
||||
{keyName}
|
||||
</h3>
|
||||
|
||||
<p>{summary}</p>
|
||||
|
||||
{description && <p>{description}</p>}
|
||||
|
||||
{/*
|
||||
{consumes &&
|
||||
consumes.map((item, i) => (
|
||||
<div key={i}>
|
||||
<code>{item}</code>
|
||||
</div>
|
||||
))}
|
||||
*/}
|
||||
|
||||
{parameters && parameters.length && (
|
||||
<Parameters parameters={parameters} />
|
||||
)}
|
||||
{responses && Object.keys(responses).length !== 0 && (
|
||||
<Responses responses={responses} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Method.propTypes = {
|
||||
keyName: PropTypes.string,
|
||||
value: PropTypes.object
|
||||
}
|
||||
|
||||
const Paths = ({ paths }) =>
|
||||
Object.entries(paths).map(([key, value]) => (
|
||||
<div key={key}>
|
||||
<h2 id={slugify(cleanKey(key))} className={styles.pathName}>
|
||||
<code>{cleanKey(key)}</code>
|
||||
</h2>
|
||||
|
||||
{Object.entries(value).map(([key, value]) => (
|
||||
<Method key={key} keyName={key} value={value} />
|
||||
))}
|
||||
</div>
|
||||
))
|
||||
|
||||
const BasePath = ({ host, basePath }) => (
|
||||
<div className={styles.basePath}>
|
||||
<h2>Base Path</h2>
|
||||
<code>
|
||||
<span>{host}</span>
|
||||
{basePath}
|
||||
</code>
|
||||
</div>
|
||||
)
|
||||
|
||||
BasePath.propTypes = {
|
||||
host: PropTypes.string,
|
||||
basePath: PropTypes.string
|
||||
}
|
||||
|
||||
export default class ApiSwaggerTemplate extends Component {
|
||||
static propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
location: PropTypes.object.isRequired,
|
||||
pageContext: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
render() {
|
||||
const { location, data, pageContext } = this.props
|
||||
const sections = data.allSectionsYaml.edges
|
||||
const { api } = pageContext
|
||||
const { host, basePath, info, paths } = api
|
||||
const { title, description, version, license, contact } = info
|
||||
|
||||
// output section title as defined in sections.yml
|
||||
const sectionTitle = sections.map(({ node }) => {
|
||||
// compare section against section title from sections.yml
|
||||
if (node.title.toLowerCase().includes('references')) {
|
||||
return node.title
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<body className={'references'} />
|
||||
</Helmet>
|
||||
|
||||
<SEO
|
||||
title={title}
|
||||
description={description}
|
||||
slug={pageContext.slug}
|
||||
article
|
||||
/>
|
||||
|
||||
<Layout location={location}>
|
||||
<HeaderSection title={sectionTitle} />
|
||||
|
||||
<Content>
|
||||
<main className={stylesDoc.wrapper}>
|
||||
<aside className={stylesDoc.sidebar}>
|
||||
<Sidebar
|
||||
location={location}
|
||||
sidebar={'references'}
|
||||
collapsed
|
||||
toc
|
||||
tableOfContents={toc(api)
|
||||
.split(',')
|
||||
.join('')}
|
||||
/>
|
||||
</aside>
|
||||
<article className={stylesDoc.main}>
|
||||
<DocHeader
|
||||
title={title}
|
||||
description={description}
|
||||
prepend={
|
||||
<span className={styles.version}>
|
||||
{version}
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
|
||||
{(contact || license) && (
|
||||
<SwaggerMeta
|
||||
contact={contact}
|
||||
license={license}
|
||||
/>
|
||||
)}
|
||||
|
||||
{(host || basePath) && (
|
||||
<BasePath host={host} basePath={basePath} />
|
||||
)}
|
||||
|
||||
<Paths paths={paths} />
|
||||
|
||||
<DocFooter
|
||||
url={`https://github.com/oceanprotocol/${title.toLowerCase()}`}
|
||||
externalName={`${title} Swagger spec`}
|
||||
/>
|
||||
</article>
|
||||
</main>
|
||||
</Content>
|
||||
</Layout>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export const apiSwaggerQuery = graphql`
|
||||
query {
|
||||
allSectionsYaml {
|
||||
edges {
|
||||
node {
|
||||
title
|
||||
description
|
||||
link
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
@ -26,8 +26,8 @@ const DocMain = ({ title, description, tableOfContents, post, single }) => (
|
||||
|
||||
DocMain.propTypes = {
|
||||
title: PropTypes.string.isRequired,
|
||||
description: PropTypes.string.isRequired,
|
||||
tableOfContents: PropTypes.string,
|
||||
description: PropTypes.string,
|
||||
tableOfContents: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
|
||||
post: PropTypes.object.isRequired,
|
||||
single: PropTypes.bool
|
||||
}
|
||||
@ -38,22 +38,25 @@ export default class DocTemplate extends Component {
|
||||
location: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
// output section title as defined in sections.yml
|
||||
sectionTitle = this.props.data.allSectionsYaml.edges.map(({ node }) => {
|
||||
// compare section against section title from sections.yml
|
||||
if (
|
||||
node.title
|
||||
.toLowerCase()
|
||||
.includes(this.props.data.markdownRemark.fields.section)
|
||||
) {
|
||||
return node.title
|
||||
}
|
||||
})
|
||||
|
||||
render() {
|
||||
const { location } = this.props
|
||||
const post = this.props.data.markdownRemark
|
||||
const sections = this.props.data.allSectionsYaml.edges
|
||||
const { section, slug } = post.fields
|
||||
const { title, description } = post.frontmatter
|
||||
const { tableOfContents } = post
|
||||
|
||||
// output section title as defined in sections.yml
|
||||
const sectionTitle = sections.map(({ node }) => {
|
||||
// compare section against section title from sections.yml
|
||||
if (node.title.toLowerCase().includes(section)) {
|
||||
return node.title
|
||||
}
|
||||
})
|
||||
|
||||
const isApiSection = location.pathname.includes('/references/')
|
||||
|
||||
return (
|
||||
@ -70,7 +73,9 @@ export default class DocTemplate extends Component {
|
||||
/>
|
||||
|
||||
<Layout location={location}>
|
||||
<HeaderSection title={section ? sectionTitle : title} />
|
||||
<HeaderSection
|
||||
title={section ? this.sectionTitle : title}
|
||||
/>
|
||||
|
||||
<Content>
|
||||
{section ? (
|
||||
|
@ -14,6 +14,7 @@
|
||||
@media (min-width: $break-point--medium) {
|
||||
width: 27%;
|
||||
margin-bottom: 0;
|
||||
margin-top: 0;
|
||||
order: 1;
|
||||
|
||||
+ .main {
|
||||
@ -47,3 +48,9 @@
|
||||
max-width: 73%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.version {
|
||||
font-size: $font-size-base;
|
||||
font-family: $font-family-monospace;
|
||||
color: $brand-grey-light;
|
||||
}
|
||||
|
159
src/templates/Swagger/Paths.jsx
Normal file
@ -0,0 +1,159 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import slugify from 'slugify'
|
||||
import { cleanPathKey } from './utils'
|
||||
import styles from './Paths.module.scss'
|
||||
|
||||
const ParameterExample = ({ properties }) => (
|
||||
//
|
||||
// HEADS UP!
|
||||
//
|
||||
// Constructing the example request body here based on the defined properties
|
||||
// where `key` is the name of the property, and `properties[key].example` is
|
||||
// the value for it.
|
||||
//
|
||||
// Making prism.js pick up on the strings only output didn't work out so well
|
||||
// so the spans and classes this plugin would add are added manually here. Since we
|
||||
// include the prism css file globally this is picked up by that.
|
||||
//
|
||||
// But this can only work if all keys and values are manually constructed here, which
|
||||
// is almost impossible to do for deep nested objects or arrays as example value. Running
|
||||
// that code through `JSON.stringify` won't syntax highlight that part of the code.
|
||||
//
|
||||
<pre className="language-json">
|
||||
<code className="language-json">
|
||||
{'{'}
|
||||
{properties &&
|
||||
Object.keys(properties).map(key => (
|
||||
<div key={key}>
|
||||
<span className="token property">{` "${key}"`}</span>
|
||||
<span className="token operator">{`: `}</span>
|
||||
{properties[key].type === 'string' && (
|
||||
<span className="token string">{`"${
|
||||
properties[key].example
|
||||
}"`}</span>
|
||||
)}
|
||||
{(properties[key].type === 'integer' ||
|
||||
properties[key].type === 'number') && (
|
||||
<span className="token number">
|
||||
{`${properties[key].example}`}
|
||||
</span>
|
||||
)}
|
||||
{(properties[key].type === 'array' ||
|
||||
properties[key].type === 'object') &&
|
||||
JSON.stringify(properties[key].example, null, 2)}
|
||||
,
|
||||
</div>
|
||||
))}
|
||||
{'}'}
|
||||
</code>
|
||||
</pre>
|
||||
)
|
||||
|
||||
ParameterExample.propTypes = {
|
||||
properties: PropTypes.object
|
||||
}
|
||||
|
||||
const Parameters = ({ parameters }) => (
|
||||
<>
|
||||
<h4 className={styles.subHeading}>Parameters</h4>
|
||||
|
||||
{parameters.map(parameter => {
|
||||
const { name, type, required, description, schema } = parameter
|
||||
|
||||
return (
|
||||
<div className={styles.parameters} key={parameter.name}>
|
||||
<h5>
|
||||
<code>{name}</code>
|
||||
{required && (
|
||||
<span
|
||||
className={styles.parameterRequired}
|
||||
title="required parameter"
|
||||
>
|
||||
*
|
||||
</span>
|
||||
)}
|
||||
<span className={styles.parameterType}>{type}</span>
|
||||
</h5>
|
||||
|
||||
<p>{description}</p>
|
||||
|
||||
{schema && (
|
||||
<ParameterExample properties={schema.properties} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)
|
||||
|
||||
Parameters.propTypes = {
|
||||
parameters: PropTypes.array.isRequired
|
||||
}
|
||||
|
||||
const Responses = ({ responses }) => (
|
||||
<>
|
||||
<h4 className={styles.subHeading}>Responses</h4>
|
||||
{Object.keys(responses).map(key => (
|
||||
<div key={key} className={styles.response}>
|
||||
<code>{key}</code> {responses[key].description}
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
|
||||
Responses.propTypes = {
|
||||
responses: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
const Method = ({ keyName, value }) => {
|
||||
const { summary, description, parameters, responses } = value
|
||||
|
||||
return (
|
||||
<div className={styles.method}>
|
||||
<h3 className={styles.pathMethod} data-type={keyName}>
|
||||
{keyName}
|
||||
</h3>
|
||||
|
||||
<p>{summary}</p>
|
||||
|
||||
{description && <p>{description}</p>}
|
||||
|
||||
{/*
|
||||
{consumes &&
|
||||
consumes.map((item, i) => (
|
||||
<div key={i}>
|
||||
<code>{item}</code>
|
||||
</div>
|
||||
))}
|
||||
*/}
|
||||
|
||||
{parameters && parameters.length && (
|
||||
<Parameters parameters={parameters} />
|
||||
)}
|
||||
{responses && Object.keys(responses).length !== 0 && (
|
||||
<Responses responses={responses} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Method.propTypes = {
|
||||
keyName: PropTypes.string,
|
||||
value: PropTypes.object
|
||||
}
|
||||
|
||||
const Paths = ({ paths }) =>
|
||||
Object.entries(paths).map(([key, value]) => (
|
||||
<div key={key} id={slugify(cleanPathKey(key))}>
|
||||
<h2 className={styles.pathName}>
|
||||
<code>{cleanPathKey(key)}</code>
|
||||
</h2>
|
||||
|
||||
{Object.entries(value).map(([key, value]) => (
|
||||
<Method key={key} keyName={key} value={value} />
|
||||
))}
|
||||
</div>
|
||||
))
|
||||
|
||||
export default Paths
|
@ -1,52 +1,5 @@
|
||||
@import 'variables';
|
||||
|
||||
.version {
|
||||
font-size: $font-size-base;
|
||||
font-family: $font-family-monospace;
|
||||
color: $brand-grey-light;
|
||||
}
|
||||
|
||||
.swaggerMeta {
|
||||
margin-top: -($spacer);
|
||||
padding: 0;
|
||||
font-size: $font-size-small;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
margin-left: $spacer;
|
||||
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&:before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.basePath {
|
||||
margin-top: $spacer;
|
||||
|
||||
h2 {
|
||||
font-size: $font-size-h3;
|
||||
border-bottom: 1px solid $brand-grey-lighter;
|
||||
padding-bottom: $spacer / 2;
|
||||
margin-top: $spacer * 2;
|
||||
margin-bottom: $spacer;
|
||||
}
|
||||
|
||||
span {
|
||||
color: $brand-grey-light;
|
||||
}
|
||||
|
||||
code {
|
||||
// stylelint-disable-next-line
|
||||
font-size: $font-size-large !important;
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
}
|
||||
|
||||
.pathName {
|
||||
font-size: $font-size-h3;
|
||||
border-bottom: 1px solid $brand-grey-lighter;
|
43
src/templates/Swagger/Toc.jsx
Normal file
@ -0,0 +1,43 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import slugify from 'slugify'
|
||||
import Scrollspy from 'react-scrollspy'
|
||||
import Scroll from '../../components/Scroll'
|
||||
import { cleanPathKey } from './utils'
|
||||
import stylesSidebar from '../../components/Sidebar.module.scss'
|
||||
|
||||
const Toc = ({ data }) => {
|
||||
let Ids = []
|
||||
|
||||
const items = Object.keys(data.paths).map(key => {
|
||||
Ids.push(slugify(cleanPathKey(key)))
|
||||
|
||||
return (
|
||||
<li key={key}>
|
||||
<Scroll
|
||||
type="id"
|
||||
element={`${slugify(cleanPathKey(key))}`}
|
||||
offset={-20}
|
||||
>
|
||||
<code>{cleanPathKey(key)}</code>
|
||||
</Scroll>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
|
||||
return (
|
||||
<Scrollspy
|
||||
items={Ids}
|
||||
currentClassName={stylesSidebar.scrollspyActive}
|
||||
offset={-100}
|
||||
>
|
||||
{items}
|
||||
</Scrollspy>
|
||||
)
|
||||
}
|
||||
|
||||
Toc.propTypes = {
|
||||
data: PropTypes.oneOfType([PropTypes.array, PropTypes.object])
|
||||
}
|
||||
|
||||
export default Toc
|
152
src/templates/Swagger/index.jsx
Normal file
@ -0,0 +1,152 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { graphql } from 'gatsby'
|
||||
import Helmet from 'react-helmet'
|
||||
|
||||
import Layout from '../../components/Layout'
|
||||
import Content from '../../components/Content'
|
||||
import HeaderSection from '../../components/HeaderSection'
|
||||
import Sidebar from '../../components/Sidebar'
|
||||
import DocHeader from '../../components/DocHeader'
|
||||
import DocFooter from '../../components/DocFooter'
|
||||
import SEO from '../../components/Seo'
|
||||
|
||||
import Toc from './Toc'
|
||||
import Paths from './Paths'
|
||||
|
||||
import stylesDoc from '../Doc.module.scss'
|
||||
import styles from './index.module.scss'
|
||||
|
||||
const SwaggerMeta = ({ contact, license }) => (
|
||||
<ul className={styles.swaggerMeta}>
|
||||
{contact && (
|
||||
<li>
|
||||
<a href={`mailto:${contact.email}`}>{contact.email}</a>
|
||||
</li>
|
||||
)}
|
||||
{license && (
|
||||
<li>
|
||||
<a href={license.url}>{license.name}</a>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
)
|
||||
|
||||
SwaggerMeta.propTypes = {
|
||||
contact: PropTypes.object,
|
||||
license: PropTypes.object
|
||||
}
|
||||
|
||||
const BasePath = ({ host, basePath }) => (
|
||||
<div className={styles.basePath}>
|
||||
<h2>Base Path</h2>
|
||||
<code>
|
||||
<span>{host}</span>
|
||||
{basePath}
|
||||
</code>
|
||||
</div>
|
||||
)
|
||||
|
||||
BasePath.propTypes = {
|
||||
host: PropTypes.string,
|
||||
basePath: PropTypes.string
|
||||
}
|
||||
|
||||
export default class ApiSwaggerTemplate extends Component {
|
||||
static propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
location: PropTypes.object.isRequired,
|
||||
pageContext: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
// output section title as defined in sections.yml
|
||||
sectionTitle = this.props.data.allSectionsYaml.edges.map(({ node }) => {
|
||||
// compare section against section title from sections.yml
|
||||
if (node.title.toLowerCase().includes('references')) {
|
||||
return node.title
|
||||
}
|
||||
})
|
||||
|
||||
render() {
|
||||
const { location, pageContext } = this.props
|
||||
const { api } = pageContext
|
||||
const { host, basePath, info, paths } = api
|
||||
const { title, description, version, license, contact } = info
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<body className={'references'} />
|
||||
</Helmet>
|
||||
|
||||
<SEO
|
||||
title={title}
|
||||
description={description}
|
||||
slug={pageContext.slug}
|
||||
article
|
||||
/>
|
||||
|
||||
<Layout location={location}>
|
||||
<HeaderSection title={this.sectionTitle} />
|
||||
|
||||
<Content>
|
||||
<main className={stylesDoc.wrapper}>
|
||||
<aside className={stylesDoc.sidebar}>
|
||||
<Sidebar
|
||||
location={location}
|
||||
sidebar={'references'}
|
||||
collapsed
|
||||
toc
|
||||
tocComponent={<Toc data={api} />}
|
||||
/>
|
||||
</aside>
|
||||
<article className={stylesDoc.main}>
|
||||
<DocHeader
|
||||
title={title}
|
||||
description={description}
|
||||
prepend={
|
||||
<span className={stylesDoc.version}>
|
||||
{version}
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
|
||||
{(contact || license) && (
|
||||
<SwaggerMeta
|
||||
contact={contact}
|
||||
license={license}
|
||||
/>
|
||||
)}
|
||||
|
||||
{(host || basePath) && (
|
||||
<BasePath host={host} basePath={basePath} />
|
||||
)}
|
||||
|
||||
<Paths paths={paths} />
|
||||
|
||||
<DocFooter
|
||||
url={`https://github.com/oceanprotocol/${title.toLowerCase()}`}
|
||||
externalName={`${title} Swagger spec`}
|
||||
/>
|
||||
</article>
|
||||
</main>
|
||||
</Content>
|
||||
</Layout>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export const apiSwaggerQuery = graphql`
|
||||
query {
|
||||
allSectionsYaml {
|
||||
edges {
|
||||
node {
|
||||
title
|
||||
description
|
||||
link
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
42
src/templates/Swagger/index.module.scss
Normal file
@ -0,0 +1,42 @@
|
||||
@import 'variables';
|
||||
|
||||
.swaggerMeta {
|
||||
margin-top: -($spacer);
|
||||
padding: 0;
|
||||
font-size: $font-size-small;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
margin-left: $spacer;
|
||||
|
||||
&:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
&:before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.basePath {
|
||||
margin-top: $spacer;
|
||||
|
||||
h2 {
|
||||
font-size: $font-size-h3;
|
||||
border-bottom: 1px solid $brand-grey-lighter;
|
||||
padding-bottom: $spacer / 2;
|
||||
margin-top: $spacer * 2;
|
||||
margin-bottom: $spacer;
|
||||
}
|
||||
|
||||
span {
|
||||
color: $brand-grey-light;
|
||||
}
|
||||
|
||||
code {
|
||||
// stylelint-disable-next-line
|
||||
font-size: $font-size-large !important;
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
}
|
13
src/templates/Swagger/utils.js
Normal file
@ -0,0 +1,13 @@
|
||||
export const cleanPathKey = key => {
|
||||
let keyCleaned = key
|
||||
|
||||
if (key.includes('aquarius')) {
|
||||
keyCleaned = key.replace(/\/api\/v1\/aquarius/gi, '')
|
||||
}
|
||||
|
||||
if (key.includes('brizo')) {
|
||||
keyCleaned = key.replace(/\/api\/v1\/brizo/gi, '')
|
||||
}
|
||||
|
||||
return keyCleaned
|
||||
}
|
252
src/templates/Typedoc/Entities.jsx
Normal file
@ -0,0 +1,252 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import slugify from 'slugify'
|
||||
import Scroll from '../../components/Scroll'
|
||||
import styles from './Entities.module.scss'
|
||||
import { filterByKindOfProperty } from './utils'
|
||||
|
||||
const Type = ({ type }) => {
|
||||
let isArray = false
|
||||
if (type.type === 'array') {
|
||||
isArray = true
|
||||
type = type.elementType
|
||||
}
|
||||
const { name, type: typeOfType, typeArguments, id } = type
|
||||
const isInternal = typeOfType === 'reference' && id
|
||||
|
||||
return (
|
||||
<div className={styles.type}>
|
||||
<span>
|
||||
{isInternal && (
|
||||
<Scroll type="id" element={`${slugify(name)}`} offset={-20}>
|
||||
{type.name}
|
||||
</Scroll>
|
||||
)}
|
||||
{!isInternal && <span>{type.name}</span>}
|
||||
</span>
|
||||
|
||||
{typeArguments && (
|
||||
<span>
|
||||
<span className={styles.typeSymbol}><</span>
|
||||
<span>
|
||||
{typeArguments.map((typeArgument, i) => (
|
||||
<span key={i}>
|
||||
{i !== 0 && (
|
||||
<span className={styles.typeSymbol}>
|
||||
,{' '}
|
||||
</span>
|
||||
)}
|
||||
<Type type={typeArgument} key={i} />
|
||||
</span>
|
||||
))}
|
||||
</span>
|
||||
<span className={styles.typeSymbol}>></span>
|
||||
</span>
|
||||
)}
|
||||
|
||||
{isArray && <span className={styles.typeSymbol}>[]</span>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Type.propTypes = {
|
||||
type: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
const PropertyDetails = ({ property }) => {
|
||||
const { type } = property
|
||||
return (
|
||||
<div>
|
||||
<Type type={type} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
PropertyDetails.propTypes = {
|
||||
property: PropTypes.object
|
||||
}
|
||||
|
||||
const MethodDetails = ({ property }) => {
|
||||
const signature = property.signatures[0]
|
||||
const { parameters, type } = signature
|
||||
return (
|
||||
<>
|
||||
{parameters && parameters.length && (
|
||||
<div>
|
||||
<h4 className={styles.subHeading}>Parameters</h4>
|
||||
|
||||
{parameters.map(parameter => {
|
||||
const { name, type, flags, comment } = parameter
|
||||
const { isOptional } = flags
|
||||
const description =
|
||||
comment && (comment.text || comment.shortText)
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.parameters}
|
||||
key={parameter.name}
|
||||
>
|
||||
<h5>
|
||||
<code>{name}</code>
|
||||
{isOptional && (
|
||||
<span
|
||||
className={styles.parameterOptional}
|
||||
title="optional parameter"
|
||||
>
|
||||
?
|
||||
</span>
|
||||
)}
|
||||
</h5>
|
||||
<Type type={type} />
|
||||
|
||||
<p>{description}</p>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{type && (
|
||||
<div>
|
||||
<h4 className={styles.subHeading}>Returns</h4>
|
||||
|
||||
<Type type={type} />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
MethodDetails.propTypes = {
|
||||
property: PropTypes.object
|
||||
}
|
||||
|
||||
const PropertyWrapper = ({ property, sourceUrl, parentAnchor }) => {
|
||||
const {
|
||||
name,
|
||||
kindString,
|
||||
flags,
|
||||
signatures,
|
||||
sources,
|
||||
decorators
|
||||
} = property
|
||||
const { isPublic, isStatic } = flags
|
||||
const signature = signatures && signatures[0]
|
||||
const comment = (signature && signature.comment) || property.comment
|
||||
const { fileName, line } = sources[0]
|
||||
const deprecation = (decorators || []).filter(
|
||||
({ name }) => name === 'deprecated'
|
||||
)[0] // Assuming deprecated annotation
|
||||
let deprecatedUse, deprecatedSlug
|
||||
if (deprecation) {
|
||||
deprecatedUse = deprecation.arguments.alternative.replace(/('|")/g, '')
|
||||
deprecatedSlug = slugify(deprecatedUse.replace('.', '-'))
|
||||
}
|
||||
|
||||
const sourceLink = `${sourceUrl}${fileName}#L${line}`
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.property}
|
||||
data-private={!isPublic}
|
||||
data-deprecated={!!deprecation}
|
||||
id={`${parentAnchor}-${slugify(name)}`}
|
||||
>
|
||||
<h3 className={styles.propertyName}>{name}</h3>
|
||||
|
||||
<div
|
||||
className={styles.propertyType}
|
||||
data-type={kindString.toLowerCase()}
|
||||
>
|
||||
{kindString}
|
||||
</div>
|
||||
|
||||
{isStatic && <div className={styles.propertyModifier}>static</div>}
|
||||
{!isPublic && (
|
||||
<div className={styles.propertyModifier} data-secondary>
|
||||
private
|
||||
</div>
|
||||
)}
|
||||
|
||||
{comment && !deprecation && (
|
||||
<div className={styles.propertyDescription}>
|
||||
{comment.text || comment.shortText}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{deprecation && (
|
||||
<div className={styles.deprecation}>
|
||||
<strong>Deprecated</strong>: use{' '}
|
||||
<code>
|
||||
<Scroll
|
||||
type="id"
|
||||
element={`${deprecatedSlug}`}
|
||||
offset={-20}
|
||||
>
|
||||
{deprecatedUse}
|
||||
</Scroll>
|
||||
</code>{' '}
|
||||
instead
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!deprecation &&
|
||||
(() => {
|
||||
switch (kindString) {
|
||||
case 'Method':
|
||||
return <MethodDetails property={property} />
|
||||
case 'Property':
|
||||
return <PropertyDetails property={property} />
|
||||
}
|
||||
})()}
|
||||
|
||||
{fileName && (
|
||||
<a
|
||||
className={styles.sourceLink}
|
||||
href={sourceLink}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{`${fileName}#L${line}`}
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
PropertyWrapper.propTypes = {
|
||||
property: PropTypes.object,
|
||||
sourceUrl: PropTypes.string,
|
||||
parentAnchor: PropTypes.string
|
||||
}
|
||||
|
||||
const Entities = ({ entities, sourceUrl }) =>
|
||||
entities.map(({ name, comment, children }) => (
|
||||
<div key={name} id={slugify(name)}>
|
||||
<h2 className={styles.entityName}>
|
||||
<code>{name}</code>
|
||||
</h2>
|
||||
|
||||
{comment && (
|
||||
<div className={styles.entityDescription}>
|
||||
{comment.text || comment.shortText}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{children.filter(filterByKindOfProperty).map(property => (
|
||||
<PropertyWrapper
|
||||
key={`${name}/${property.id}`}
|
||||
property={property}
|
||||
sourceUrl={sourceUrl}
|
||||
parentAnchor={slugify(name)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
))
|
||||
|
||||
Entities.propTypes = {
|
||||
entities: PropTypes.array.isRequired,
|
||||
sourceUrl: PropTypes.string
|
||||
}
|
||||
|
||||
export default Entities
|
173
src/templates/Typedoc/Entities.module.scss
Normal file
@ -0,0 +1,173 @@
|
||||
@import 'variables';
|
||||
|
||||
.entityName {
|
||||
font-size: $font-size-h2;
|
||||
border-bottom: 1px solid $brand-grey-lighter;
|
||||
padding-bottom: $spacer / 2;
|
||||
margin-top: $spacer * 2;
|
||||
margin-bottom: $spacer;
|
||||
|
||||
code {
|
||||
// stylelint-disable declaration-no-important
|
||||
background: none !important;
|
||||
padding: 0 !important;
|
||||
// stylelint-enable declaration-no-important
|
||||
}
|
||||
}
|
||||
|
||||
.entityDescription {
|
||||
padding-bottom: $spacer;
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
.property {
|
||||
padding: $spacer / 2;
|
||||
border: 1px solid $brand-grey-lighter;
|
||||
margin-bottom: $spacer;
|
||||
border-radius: $border-radius;
|
||||
position: relative;
|
||||
|
||||
&[data-deprecated='true'] {
|
||||
> *:not(.deprecation) {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
code {
|
||||
opacity: 1;
|
||||
background: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.sourceLink {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.propertyName,
|
||||
.propertyType,
|
||||
.propertyModifier {
|
||||
font-size: $font-size-base;
|
||||
font-family: $font-family-monospace;
|
||||
margin-bottom: $spacer / 4;
|
||||
margin-top: 0;
|
||||
display: inline-block;
|
||||
padding: 0 $spacer / 4;
|
||||
border-radius: $border-radius;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.propertyName {
|
||||
font-size: $font-size-large;
|
||||
padding: 0;
|
||||
margin-right: $spacer / 3;
|
||||
}
|
||||
|
||||
.propertyType,
|
||||
.propertyModifier {
|
||||
font-size: $font-size-small;
|
||||
color: $brand-grey;
|
||||
margin-right: $spacer / 4;
|
||||
}
|
||||
|
||||
.propertyType {
|
||||
&[data-type='method'] {
|
||||
background: rgba($green, .3);
|
||||
}
|
||||
|
||||
&[data-type='property'] {
|
||||
background: rgba($yellow, .3);
|
||||
}
|
||||
}
|
||||
|
||||
.propertyModifier {
|
||||
background: rgba($red, .2);
|
||||
|
||||
&[data-secondary] {
|
||||
background: rgba($brand-blue, .2);
|
||||
}
|
||||
}
|
||||
|
||||
.propertyDescription {
|
||||
margin-bottom: $spacer;
|
||||
}
|
||||
|
||||
.sourceLink {
|
||||
display: block;
|
||||
font-size: $font-size-mini;
|
||||
color: $brand-grey-light;
|
||||
margin-top: $spacer / 2;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
@media (min-width: $break-point--large) {
|
||||
margin-top: 0;
|
||||
position: absolute;
|
||||
bottom: $spacer / 2;
|
||||
right: $spacer / 2;
|
||||
}
|
||||
}
|
||||
|
||||
.deprecation {
|
||||
font-size: $font-size-small;
|
||||
margin-top: $spacer / 4;
|
||||
|
||||
strong {
|
||||
color: $brand-grey-light;
|
||||
}
|
||||
}
|
||||
|
||||
.type {
|
||||
display: inline-block;
|
||||
color: $brand-grey;
|
||||
font-family: $font-family-monospace;
|
||||
font-size: $font-size-small;
|
||||
|
||||
a {
|
||||
&:hover {
|
||||
opacity: .6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.typeSymbol {
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
.subHeading {
|
||||
font-size: $font-size-base;
|
||||
border-bottom: 1px solid $brand-grey-lighter;
|
||||
padding-bottom: $spacer / 4;
|
||||
margin-bottom: $spacer / 4;
|
||||
color: $brand-grey;
|
||||
}
|
||||
|
||||
.parameters {
|
||||
margin-top: $spacer / 1.5;
|
||||
|
||||
h5,
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: $font-size-small;
|
||||
margin-bottom: $spacer / 4;
|
||||
margin-right: $spacer / 4;
|
||||
margin-left: -(.2rem);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
code {
|
||||
padding: .2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.parameterOptional {
|
||||
font-size: $font-size-small;
|
||||
vertical-align: top;
|
||||
color: $brand-purple;
|
||||
}
|
63
src/templates/Typedoc/Toc.jsx
Normal file
@ -0,0 +1,63 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import slugify from 'slugify'
|
||||
import Scrollspy from 'react-scrollspy'
|
||||
import Scroll from '../../components/Scroll'
|
||||
import { filterByKindOfProperty } from './utils'
|
||||
import stylesSidebar from '../../components/Sidebar.module.scss'
|
||||
|
||||
export default class Toc extends PureComponent {
|
||||
static propTypes = {
|
||||
data: PropTypes.array
|
||||
}
|
||||
|
||||
subItems = (children, parentName) =>
|
||||
children.filter(filterByKindOfProperty).map(({ name, decorators }) => {
|
||||
const deprecation = (decorators || []).filter(
|
||||
({ name }) => name === 'deprecated'
|
||||
)[0] // Assuming deprecated annotation
|
||||
|
||||
return (
|
||||
<li key={name}>
|
||||
<Scroll
|
||||
type="id"
|
||||
element={`${parentName}-${slugify(name)}`}
|
||||
data-deprecated={!!deprecation}
|
||||
offset={-20}
|
||||
>
|
||||
<code>{name}</code>
|
||||
</Scroll>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
|
||||
items = this.props.data.map(({ name, children }) => {
|
||||
let subIds = []
|
||||
const parentName = name
|
||||
|
||||
subIds.push(
|
||||
children.filter(filterByKindOfProperty).map(({ name }) => {
|
||||
return `${parentName}-${slugify(name)}`
|
||||
})
|
||||
)
|
||||
|
||||
return (
|
||||
<li key={name}>
|
||||
<Scroll type="id" element={`${slugify(name)}`} offset={-20}>
|
||||
<code>{name}</code>
|
||||
</Scroll>
|
||||
<Scrollspy
|
||||
items={subIds[0]}
|
||||
currentClassName={stylesSidebar.scrollspyActive}
|
||||
offset={-30}
|
||||
>
|
||||
{this.subItems(children, name)}
|
||||
</Scrollspy>
|
||||
</li>
|
||||
)
|
||||
})
|
||||
|
||||
render() {
|
||||
return <ul>{this.items}</ul>
|
||||
}
|
||||
}
|
109
src/templates/Typedoc/index.jsx
Normal file
@ -0,0 +1,109 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { graphql } from 'gatsby'
|
||||
import Helmet from 'react-helmet'
|
||||
import Layout from '../../components/Layout'
|
||||
import Content from '../../components/Content'
|
||||
import HeaderSection from '../../components/HeaderSection'
|
||||
import Sidebar from '../../components/Sidebar'
|
||||
import DocHeader from '../../components/DocHeader'
|
||||
import SEO from '../../components/Seo'
|
||||
import { cleanTypedocData } from './utils'
|
||||
|
||||
import Entities from './Entities'
|
||||
import Toc from './Toc'
|
||||
|
||||
import stylesDoc from '../Doc.module.scss'
|
||||
|
||||
export default class TypedocTemplate extends Component {
|
||||
static propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
location: PropTypes.object.isRequired,
|
||||
pageContext: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
typedocCleaned = cleanTypedocData(
|
||||
this.props.pageContext.typedoc,
|
||||
this.props.pageContext.classes
|
||||
)
|
||||
|
||||
// output section title as defined in sections.yml
|
||||
sectionTitle = this.props.data.allSectionsYaml.edges.map(({ node }) => {
|
||||
// compare section against section title from sections.yml
|
||||
if (node.title.toLowerCase().includes('references')) {
|
||||
return node.title
|
||||
}
|
||||
})
|
||||
|
||||
render() {
|
||||
const { location, pageContext } = this.props
|
||||
const { typedoc } = pageContext
|
||||
const { info } = typedoc
|
||||
const { title, description, version, sourceUrl } = info
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<body className={'references'} />
|
||||
</Helmet>
|
||||
|
||||
<SEO
|
||||
title={title}
|
||||
description={description}
|
||||
slug={pageContext.slug}
|
||||
article
|
||||
/>
|
||||
|
||||
<Layout location={location}>
|
||||
<HeaderSection title={this.sectionTitle} />
|
||||
|
||||
<Content>
|
||||
<main className={stylesDoc.wrapper}>
|
||||
<aside className={stylesDoc.sidebar}>
|
||||
<Sidebar
|
||||
location={location}
|
||||
sidebar={'references'}
|
||||
collapsed
|
||||
toc
|
||||
tocComponent={
|
||||
<Toc data={this.typedocCleaned} />
|
||||
}
|
||||
/>
|
||||
</aside>
|
||||
<article className={stylesDoc.main}>
|
||||
<DocHeader
|
||||
title={title}
|
||||
description={description}
|
||||
prepend={
|
||||
<span className={stylesDoc.version}>
|
||||
{version}
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
|
||||
<Entities
|
||||
entities={this.typedocCleaned}
|
||||
sourceUrl={sourceUrl}
|
||||
/>
|
||||
</article>
|
||||
</main>
|
||||
</Content>
|
||||
</Layout>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export const TypedocQuery = graphql`
|
||||
query {
|
||||
allSectionsYaml {
|
||||
edges {
|
||||
node {
|
||||
title
|
||||
description
|
||||
link
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
34
src/templates/Typedoc/utils.js
Normal file
@ -0,0 +1,34 @@
|
||||
export const cleanTypedocData = (data, useClasses) => {
|
||||
const nodes = data.children
|
||||
|
||||
const cleanData = nodes
|
||||
.map(node => ({
|
||||
...node,
|
||||
name: node.name.replace(/"/g, ''),
|
||||
child: node.children && node.children[0]
|
||||
}))
|
||||
.filter(({ name }) => (useClasses || []).includes(name))
|
||||
.sort((a, b) => useClasses.indexOf(a.name) - useClasses.indexOf(b.name))
|
||||
.map(({ child }) => child)
|
||||
.map(node => ({
|
||||
...node,
|
||||
children: node.children.sort((a, b) => a.id - b.id)
|
||||
}))
|
||||
|
||||
return cleanData
|
||||
}
|
||||
|
||||
// more kinds: 'Property', 'Class'
|
||||
const showKindOfProperty = {
|
||||
Method: { onlyPublic: true },
|
||||
Property: { onlyPublic: true }
|
||||
}
|
||||
|
||||
export const filterByKindOfProperty = ({ kindString, flags }) => {
|
||||
const config = showKindOfProperty[kindString]
|
||||
if (!config) return
|
||||
|
||||
if (config.onlyPublic && !flags.isPublic) return
|
||||
|
||||
return true
|
||||
}
|