first go at randomly-generated ocean waves

This commit is contained in:
Matthias Kretschmann 2021-11-16 21:06:02 +00:00
parent 08c42e8fa6
commit d3810168aa
Signed by: m
GPG Key ID: 606EEEF3C479A91F
10 changed files with 1346 additions and 78 deletions

1236
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,7 @@
"axios": "^0.24.0",
"chart.js": "^2.9.4",
"classnames": "^2.3.1",
"d3": "^7.1.1",
"date-fns": "^2.25.0",
"decimal.js": "^10.3.1",
"dom-confetti": "^0.2.2",
@ -80,6 +81,7 @@
"@graphql-codegen/typescript-react-apollo": "^3.1.6",
"@svgr/webpack": "^5.5.0",
"@types/chart.js": "^2.9.32",
"@types/d3": "^7.1.0",
"@types/js-cookie": "^3.0.0",
"@types/loadable__component": "^5.13.1",
"@types/lodash.debounce": "^4.0.3",

View File

@ -1,3 +1,5 @@
import { renderStaticWaves } from './oceanWaves'
export interface NftOptions {
name: string
symbol: string
@ -24,9 +26,10 @@ function encodeSvg(svgString: string): string {
}
export function generateNftOptions(): NftOptions {
// TODO: generate new SVG image here
// @images/arrow.svg test
const image = `<svg><path d="M0 10.4304L16.3396 10.4304L8.88727 17.6833L10.2401 19L20 9.5L10.2401 0L8.88727 1.31491L16.3396 8.56959L0 8.56959V10.4304Z" /></svg>`
const image = renderStaticWaves()
// const image = new XMLSerializer().serializeToString(waves)
// const image = `<svg><path d="M0 10.4304L16.3396 10.4304L8.88727 17.6833L10.2401 19L20 9.5L10.2401 0L8.88727 1.31491L16.3396 8.56959L0 8.56959V10.4304Z" /></svg>`
const newNft: NftOptions = {
name: 'Ocean Asset v4 NFT',

50
src/@utils/oceanWaves.ts Normal file
View File

@ -0,0 +1,50 @@
import * as d3 from 'd3'
/*
* Ocean Protocol D3 waves
* https://oceanprotocol.com/art
* Based off of Bostock's Circle Wave
* https://bl.ocks.org/mbostock/2d466ec3417722e3568cd83fc35338e3
*/
export function renderStaticWaves(): string {
const svg = d3.create('svg')
const width = 1000
const height = 250
console.log(height)
const x = d3.scaleLinear().range([0, width])
const angles = d3.range(Math.random(), 4 * Math.PI, Math.PI / 20)
const path = svg
// .append('rect')
// .attr('fill', '#fff')
// .attr('width', '100%')
// .attr('height', '100%')
.append('g')
.attr('transform', `translate(${width / -4}, ${height / 2})`)
.attr('fill', 'none')
.attr('stroke-width', 2)
.selectAll('path')
.data(['#FF4092', '#E000CF', '#8B98A9', '#E2E2E2'])
.enter()
.append('path')
.attr('stroke', (d) => d)
.style('mix-blend-mode', 'darken')
.datum((d, i) => {
return d3
.line()
.curve(d3.curveBasisOpen)
.x((angles: any) => x(angles / 4))
.y((angles: any) => {
const t = d3.now() / 3000
return (
Math.cos(angles * 8 - (i * 2 * Math.PI) / 10 + t) *
Math.pow((2 + Math.cos(angles - t)) / 2, 4) *
15
)
})
})
path.attr('d', (d) => d(angles as any))
return `<svg>${svg.node().innerHTML}</svg>`
}

View File

@ -6,9 +6,31 @@ export interface FileMetadata {
contentLength: string
}
export async function getEncryptedFileUrls(
files: string[],
providerUrl: string,
did: string,
accountId: string
): Promise<string> {
try {
// https://github.com/oceanprotocol/provider/blob/v4main/API.md#encrypt-endpoint
const url = `${providerUrl}/api/v1/services/encrypt`
const response: AxiosResponse<{ encryptedDocument: string }> =
await axios.post(url, {
documentId: did,
signature: '', // TODO: add signature
publisherAddress: accountId,
document: files
})
return response?.data?.encryptedDocument
} catch (error) {
console.error('Error parsing json: ' + error.message)
}
}
export async function getFileInfo(
url: string | DID,
providerUri: string,
providerUrl: string,
cancelToken: CancelToken
): Promise<FileMetadata[]> {
let postBody
@ -22,7 +44,7 @@ export async function getFileInfo(
url
}
const response: AxiosResponse<FileMetadata[]> = await axios.post(
`${providerUri}/api/v1/services/fileinfo`,
`${providerUrl}/api/v1/services/fileinfo`,
postBody,
{
cancelToken

View File

@ -1,3 +0,0 @@
.advancedBtn {
margin-bottom: 2rem;
}

View File

@ -1,48 +0,0 @@
import React, { ReactElement, useState, FormEvent, ChangeEvent } from 'react'
import Input from '@shared/FormInput'
import Button from '@shared/atoms/Button'
import { Field } from 'formik'
import styles from './AdvancedSettings.module.css'
export default function AdvancedSettings(prop: {
content: FormStepContent
handleFieldChange: (
e: ChangeEvent<HTMLInputElement>,
field: FormFieldContent
) => void
}): ReactElement {
const [showAdvancedSettings, setShowAdvancedSettings] =
useState<boolean>(false)
function toggleAdvancedSettings(e: FormEvent<Element>) {
e.preventDefault()
setShowAdvancedSettings(!!showAdvancedSettings)
}
return (
<>
<Button
className={styles.advancedBtn}
style="text"
size="small"
onClick={toggleAdvancedSettings}
>
Advanced Settings
</Button>
{showAdvancedSettings &&
prop.content.fields.map(
(field: FormFieldContent) =>
field.advanced === true && (
<Field
key={field.name}
{...field}
options={field.options}
component={Input}
onChange={(e: ChangeEvent<HTMLInputElement>) =>
prop.handleFieldChange(e, field)
}
/>
)
)}
</>
)
}

View File

@ -18,4 +18,17 @@
height: 128px;
border-radius: var(--border-radius);
border: 1px solid var(--border-color);
position: relative;
}
.refresh {
position: absolute;
right: calc(var(--spacer) / 4);
bottom: calc(var(--spacer) / 4);
}
.refresh svg {
fill: var(--brand-pink);
width: var(--font-size-mini);
height: var(--font-size-mini);
}

View File

@ -1,7 +1,9 @@
import Button from '@shared/atoms/Button'
import { InputProps } from '@shared/FormInput'
import { generateNftOptions } from '@utils/nft'
import { useField } from 'formik'
import React, { ReactElement, useEffect } from 'react'
import Refresh from '@images/refresh.svg'
import styles from './index.module.css'
export default function Nft(props: InputProps): ReactElement {
@ -19,6 +21,19 @@ export default function Nft(props: InputProps): ReactElement {
<div className={styles.nft}>
<figure className={styles.image}>
<img src={field?.value?.image} width="128" height="128" />
<Button
style="text"
size="small"
className={styles.refresh}
title="Generate new image"
onClick={(e) => {
e.preventDefault()
const nftOptions = generateNftOptions()
helpers.setValue({ ...nftOptions })
}}
>
<Refresh />
</Button>
</figure>
<div className={styles.token}>

View File

@ -1,4 +1,4 @@
import axios, { AxiosResponse } from 'axios'
import { getEncryptedFileUrls } from '@utils/provider'
import { sha256 } from 'js-sha256'
import slugify from 'slugify'
import { FormPublishData } from './_types'
@ -10,28 +10,6 @@ export function getFieldContent(
return fields.filter((field: FormFieldContent) => field.name === fieldName)[0]
}
async function getEncryptedFileUrls(
files: string[],
providerUrl: string,
did: string,
accountId: string
): Promise<string> {
try {
// https://github.com/oceanprotocol/provider/blob/v4main/API.md#encrypt-endpoint
const url = `${providerUrl}/api/v1/services/encrypt`
const response: AxiosResponse<{ encryptedDocument: string }> =
await axios.post(url, {
documentId: did,
signature: '', // TODO: add signature
publisherAddress: accountId,
document: files
})
return response?.data?.encryptedDocument
} catch (error) {
console.error('Error parsing json: ' + error.message)
}
}
function getUrlFileExtension(fileUrl: string): string {
const splittedFileUrl = fileUrl.split('.')
return splittedFileUrl[splittedFileUrl.length - 1]