tables
This commit is contained in:
parent
9acde2df1c
commit
bc5d4d4808
|
@ -1,26 +1,13 @@
|
||||||
import { UserInputError, AuthenticationError } from 'apollo-server-micro'
|
import { UserInputError, AuthenticationError } from 'apollo-server-micro'
|
||||||
|
|
||||||
export default {
|
const createItem = async (parent, { title, text, url, parentId }, { me, models }) => {
|
||||||
Query: {
|
|
||||||
items: async (parent, args, { models }) => {
|
|
||||||
return await models.$queryRaw(`
|
|
||||||
SELECT id, text, "userId", ltree2text("path") AS "path"
|
|
||||||
FROM "Item"
|
|
||||||
ORDER BY "path"`)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
Mutation: {
|
|
||||||
createItem: async (parent, { text, parentId }, { me, models }) => {
|
|
||||||
if (!me) {
|
if (!me) {
|
||||||
throw new AuthenticationError('You must be logged in')
|
throw new AuthenticationError('You must be logged in')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!text) {
|
|
||||||
throw new UserInputError('Item must have text', { argumentName: 'text' })
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
|
title,
|
||||||
|
url,
|
||||||
text,
|
text,
|
||||||
user: {
|
user: {
|
||||||
connect: {
|
connect: {
|
||||||
|
@ -39,6 +26,47 @@ export default {
|
||||||
|
|
||||||
return await models.item.create({ data })
|
return await models.item.create({ data })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
Query: {
|
||||||
|
items: async (parent, args, { models }) => {
|
||||||
|
return await models.$queryRaw(`
|
||||||
|
SELECT id, "created_at" as "createdAt", title, url, text, "userId", ltree2text("path") AS "path"
|
||||||
|
FROM "Item"
|
||||||
|
ORDER BY "path"`)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Mutation: {
|
||||||
|
createLink: async (parent, { title, url }, { me, models }) => {
|
||||||
|
if (!title) {
|
||||||
|
throw new UserInputError('Link must have title', { argumentName: 'title' })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!url) {
|
||||||
|
throw new UserInputError('Link must have url', { argumentName: 'url' })
|
||||||
|
}
|
||||||
|
|
||||||
|
return await createItem(parent, { title, url }, { me, models })
|
||||||
|
},
|
||||||
|
createDiscussion: async (parent, { title, text }, { me, models }) => {
|
||||||
|
if (!title) {
|
||||||
|
throw new UserInputError('Link must have title', { argumentName: 'title' })
|
||||||
|
}
|
||||||
|
|
||||||
|
return await createItem(parent, { title, text }, { me, models })
|
||||||
|
},
|
||||||
|
createComment: async (parent, { text, parentId }, { me, models }) => {
|
||||||
|
if (!text) {
|
||||||
|
throw new UserInputError('Comment must have text', { argumentName: 'text' })
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parentId) {
|
||||||
|
throw new UserInputError('Comment must have text', { argumentName: 'text' })
|
||||||
|
}
|
||||||
|
|
||||||
|
return await createItem(parent, { text, parentId }, { me, models })
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
Item: {
|
Item: {
|
||||||
|
@ -56,6 +84,8 @@ export default {
|
||||||
WHERE id = ${item.id}`
|
WHERE id = ${item.id}`
|
||||||
|
|
||||||
return path.split('.').length - 1
|
return path.split('.').length - 1
|
||||||
}
|
},
|
||||||
|
comments: () => 0,
|
||||||
|
sats: () => 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,20 @@ export default gql`
|
||||||
}
|
}
|
||||||
|
|
||||||
extend type Mutation {
|
extend type Mutation {
|
||||||
createItem(text: String!, parentId: ID): Item!
|
createLink(title: String!, url: String): Item!
|
||||||
|
createDiscussion(title: String!, text: String): Item!
|
||||||
|
createComment(text: String!, parentId: ID!): Item!
|
||||||
}
|
}
|
||||||
|
|
||||||
type Item {
|
type Item {
|
||||||
id: ID!
|
id: ID!
|
||||||
text: String!
|
createdAt: String!
|
||||||
|
title: String
|
||||||
|
url: String
|
||||||
|
text: String
|
||||||
user: User!
|
user: User!
|
||||||
depth: Int!
|
depth: Int!
|
||||||
|
sats: Int!
|
||||||
|
comments: Int!
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
import Button from 'react-bootstrap/Button'
|
||||||
|
import InputGroup from 'react-bootstrap/InputGroup'
|
||||||
|
import BootstrapForm from 'react-bootstrap/Form'
|
||||||
|
import Alert from 'react-bootstrap/Alert'
|
||||||
|
import { Formik, Form as FormikForm, useFormikContext, useField } from 'formik'
|
||||||
|
import { useState } from 'react'
|
||||||
|
|
||||||
|
export function SubmitButton ({ children, variant, ...props }) {
|
||||||
|
const { isSubmitting } = useFormikContext()
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant={variant || 'main'}
|
||||||
|
type='submit'
|
||||||
|
disabled={isSubmitting}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Input ({ label, prepend, append, hint, ...props }) {
|
||||||
|
const [field, meta] = useField(props)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BootstrapForm.Group>
|
||||||
|
{label && <BootstrapForm.Label>{label}</BootstrapForm.Label>}
|
||||||
|
<InputGroup hasValidation>
|
||||||
|
{prepend && (
|
||||||
|
<InputGroup.Prepend>
|
||||||
|
{prepend}
|
||||||
|
</InputGroup.Prepend>
|
||||||
|
)}
|
||||||
|
<BootstrapForm.Control
|
||||||
|
{...field} {...props}
|
||||||
|
isInvalid={meta.touched && meta.error}
|
||||||
|
/>
|
||||||
|
{append && (
|
||||||
|
<InputGroup.Append>
|
||||||
|
{append}
|
||||||
|
</InputGroup.Append>
|
||||||
|
)}
|
||||||
|
<BootstrapForm.Control.Feedback type='invalid'>
|
||||||
|
{meta.touched && meta.error}
|
||||||
|
</BootstrapForm.Control.Feedback>
|
||||||
|
{hint && (
|
||||||
|
<BootstrapForm.Text>
|
||||||
|
{hint}
|
||||||
|
</BootstrapForm.Text>
|
||||||
|
)}
|
||||||
|
</InputGroup>
|
||||||
|
</BootstrapForm.Group>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Form ({
|
||||||
|
initial, schema, onSubmit, children, ...props
|
||||||
|
}) {
|
||||||
|
const [error, setError] = useState()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Formik
|
||||||
|
initialValues={initial}
|
||||||
|
validationSchema={schema}
|
||||||
|
onSubmit={(...args) =>
|
||||||
|
onSubmit(...args).catch(e => setError(e.message))}
|
||||||
|
>
|
||||||
|
<FormikForm {...props} noValidate>
|
||||||
|
{error && <Alert variant='danger' onClose={() => setError(undefined)} dismissible>{error}</Alert>}
|
||||||
|
{children}
|
||||||
|
</FormikForm>
|
||||||
|
</Formik>
|
||||||
|
)
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import Nav from 'react-bootstrap/Nav'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import styles from './header.module.css'
|
import styles from './header.module.css'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
import { Container } from 'react-bootstrap'
|
||||||
|
|
||||||
export default function Header () {
|
export default function Header () {
|
||||||
const [session, loading] = useSession()
|
const [session, loading] = useSession()
|
||||||
|
@ -30,7 +31,8 @@ export default function Header () {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Navbar bg='brand' className={styles.navbar}>
|
<Navbar bg='primary' className={styles.navbar}>
|
||||||
|
<Container>
|
||||||
<Link href='/' passHref>
|
<Link href='/' passHref>
|
||||||
<Navbar.Brand className={styles.brand}>STACKER NEWS</Navbar.Brand>
|
<Navbar.Brand className={styles.brand}>STACKER NEWS</Navbar.Brand>
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -49,6 +51,7 @@ export default function Header () {
|
||||||
<Nav className='ml-auto align-items-center'>
|
<Nav className='ml-auto align-items-center'>
|
||||||
<Corner />
|
<Corner />
|
||||||
</Nav>
|
</Nav>
|
||||||
|
</Container>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
import UpVote from '../svgs/lightning-arrow.svg'
|
||||||
|
import styles from './item.module.css'
|
||||||
|
|
||||||
|
function timeSince (timeStamp) {
|
||||||
|
const now = new Date()
|
||||||
|
const secondsPast = (now.getTime() - timeStamp) / 1000
|
||||||
|
if (secondsPast < 60) {
|
||||||
|
return parseInt(secondsPast) + 's'
|
||||||
|
}
|
||||||
|
if (secondsPast < 3600) {
|
||||||
|
return parseInt(secondsPast / 60) + 'm'
|
||||||
|
}
|
||||||
|
if (secondsPast <= 86400) {
|
||||||
|
return parseInt(secondsPast / 3600) + 'h'
|
||||||
|
}
|
||||||
|
if (secondsPast > 86400) {
|
||||||
|
const day = timeStamp.getDate()
|
||||||
|
const month = timeStamp.toDateString().match(/ [a-zA-Z]*/)[0].replace(' ', '')
|
||||||
|
const year = timeStamp.getFullYear() === now.getFullYear() ? '' : ' ' + timeStamp.getFullYear()
|
||||||
|
return day + ' ' + month + year
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Item ({ item }) {
|
||||||
|
return (
|
||||||
|
<div className='d-flex justify-content-start align-items-center'>
|
||||||
|
<UpVote width={32} height={32} className={styles.upvote} />
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
<span className={styles.title}>{item.title}</span>
|
||||||
|
<a className={styles.link} href={item.url}>{item.url.replace(/(^\w+:|^)\/\//, '')}</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className={styles.other}>
|
||||||
|
<span>{item.sats} sats</span>
|
||||||
|
<span> \ </span>
|
||||||
|
<span>{item.comments} comments</span>
|
||||||
|
<span> </span>
|
||||||
|
<a href='/satoshi'>@{item.user.name}</a>
|
||||||
|
<span> </span>
|
||||||
|
<span>{timeSince(new Date(item.createdAt))}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
.upvote {
|
||||||
|
fill: grey;
|
||||||
|
margin-right: .25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upvote:hover {
|
||||||
|
fill: darkgray;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
font-size: 80%;
|
||||||
|
margin-left: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.other {
|
||||||
|
font-size: 70%;
|
||||||
|
color: grey;
|
||||||
|
}
|
|
@ -12,13 +12,16 @@
|
||||||
"@prisma/client": "^2.19.0",
|
"@prisma/client": "^2.19.0",
|
||||||
"apollo-server-micro": "^2.21.2",
|
"apollo-server-micro": "^2.21.2",
|
||||||
"bootstrap": "^4.6.0",
|
"bootstrap": "^4.6.0",
|
||||||
|
"formik": "^2.2.6",
|
||||||
"graphql": "^15.5.0",
|
"graphql": "^15.5.0",
|
||||||
"next": "10.0.9",
|
"next": "10.0.9",
|
||||||
"next-auth": "^3.13.3",
|
"next-auth": "^3.13.3",
|
||||||
"react": "17.0.1",
|
"react": "17.0.1",
|
||||||
"react-bootstrap": "^1.5.2",
|
"react-bootstrap": "^1.5.2",
|
||||||
"react-dom": "17.0.1",
|
"react-dom": "17.0.1",
|
||||||
"swr": "^0.5.4"
|
"sass": "^1.32.8",
|
||||||
|
"swr": "^0.5.4",
|
||||||
|
"yup": "^0.32.9"
|
||||||
},
|
},
|
||||||
"standard": {
|
"standard": {
|
||||||
"parser": "babel-eslint",
|
"parser": "babel-eslint",
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import 'bootstrap/dist/css/bootstrap.min.css'
|
import '../styles/globals.scss'
|
||||||
import '../styles/globals.css'
|
|
||||||
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client'
|
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client'
|
||||||
import { Provider } from 'next-auth/client'
|
import { Provider } from 'next-auth/client'
|
||||||
|
|
||||||
|
|
194
pages/index.js
194
pages/index.js
|
@ -1,103 +1,106 @@
|
||||||
import { useQuery, gql, useMutation } from '@apollo/client'
|
import { useQuery, gql } from '@apollo/client'
|
||||||
import { useState } from 'react'
|
// import styles from '../styles/index.module.css'
|
||||||
import { useSession } from 'next-auth/client'
|
|
||||||
import styles from '../styles/index.module.css'
|
|
||||||
import Layout from '../components/layout'
|
import Layout from '../components/layout'
|
||||||
|
import Item from '../components/item'
|
||||||
|
import Container from 'react-bootstrap/Container'
|
||||||
|
|
||||||
function Users () {
|
// function Users () {
|
||||||
const { loading, error, data } = useQuery(gql`{ users { id, name } }`)
|
// const { loading, error, data } = useQuery(gql`{ users { id, name } }`)
|
||||||
if (error) return <div>Failed to load</div>
|
// if (error) return <div>Failed to load</div>
|
||||||
if (loading) return <div>Loading...</div>
|
// if (loading) return <div>Loading...</div>
|
||||||
const { users } = data
|
// const { users } = data
|
||||||
return (
|
// return (
|
||||||
<div>
|
// <div>
|
||||||
{users.map(user => (
|
// {users.map(user => (
|
||||||
<div key={user.id}>{user.name}</div>
|
// <div key={user.id}>{user.name}</div>
|
||||||
))}
|
// ))}
|
||||||
</div>
|
// </div>
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
|
|
||||||
function NewItem ({ parentId }) {
|
// function NewItem ({ parentId }) {
|
||||||
const [session] = useSession()
|
// const [session] = useSession()
|
||||||
const [createItem] = useMutation(
|
// const [createItem] = useMutation(
|
||||||
gql`
|
// gql`
|
||||||
mutation CreateItem($text: String!, $parentId: ID) {
|
// mutation CreateItem($text: String!, $parentId: ID) {
|
||||||
createItem(text: $text, parentId: $parentId) {
|
// createItem(text: $text, parentId: $parentId) {
|
||||||
id
|
// id
|
||||||
}
|
// }
|
||||||
}`, {
|
// }`, {
|
||||||
update (cache, { data: { createItem } }) {
|
// update (cache, { data: { createItem } }) {
|
||||||
cache.modify({
|
// cache.modify({
|
||||||
fields: {
|
// fields: {
|
||||||
items (existingItems = [], { readField }) {
|
// items (existingItems = [], { readField }) {
|
||||||
const newItemRef = cache.writeFragment({
|
// const newItemRef = cache.writeFragment({
|
||||||
data: createItem,
|
// data: createItem,
|
||||||
fragment: gql`
|
// fragment: gql`
|
||||||
fragment NewItem on Item {
|
// fragment NewItem on Item {
|
||||||
id
|
// id
|
||||||
user {
|
// user {
|
||||||
name
|
// name
|
||||||
}
|
// }
|
||||||
text
|
// text
|
||||||
depth
|
// depth
|
||||||
}
|
// }
|
||||||
`
|
// `
|
||||||
})
|
// })
|
||||||
for (let i = 0; i < existingItems.length; i++) {
|
// for (let i = 0; i < existingItems.length; i++) {
|
||||||
if (readField('id', existingItems[i]) === parentId) {
|
// if (readField('id', existingItems[i]) === parentId) {
|
||||||
return [...existingItems.slice(0, i), newItemRef, ...existingItems.slice(i)]
|
// return [...existingItems.slice(0, i), newItemRef, ...existingItems.slice(i)]
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return [newItemRef, ...existingItems]
|
// return [newItemRef, ...existingItems]
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
const [open, setOpen] = useState(false)
|
// const [open, setOpen] = useState(false)
|
||||||
|
|
||||||
if (!session) return null
|
// if (!session) return null
|
||||||
|
|
||||||
if (!open) {
|
// if (!open) {
|
||||||
return (
|
// return (
|
||||||
<div onClick={() => setOpen(true)}>
|
// <div onClick={() => setOpen(true)}>
|
||||||
{parentId ? 'reply' : 'submit'}
|
// {parentId ? 'reply' : 'submit'}
|
||||||
</div>
|
// </div>
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
|
|
||||||
let text
|
// let text
|
||||||
return (
|
// return (
|
||||||
<form
|
// <form
|
||||||
style={{ marginLeft: '5px' }}
|
// style={{ marginLeft: '5px' }}
|
||||||
onSubmit={e => {
|
// onSubmit={e => {
|
||||||
e.preventDefault()
|
// e.preventDefault()
|
||||||
createItem({ variables: { text: text.value, parentId } })
|
// createItem({ variables: { text: text.value, parentId } })
|
||||||
setOpen(false)
|
// setOpen(false)
|
||||||
text.value = ''
|
// text.value = ''
|
||||||
}}
|
// }}
|
||||||
>
|
// >
|
||||||
<textarea
|
// <textarea
|
||||||
ref={node => {
|
// ref={node => {
|
||||||
text = node
|
// text = node
|
||||||
}}
|
// }}
|
||||||
/>
|
// />
|
||||||
<button type='submit'>Submit</button>
|
// <button type='submit'>Submit</button>
|
||||||
</form>
|
// </form>
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
|
|
||||||
function Items () {
|
function Items () {
|
||||||
const { loading, error, data } = useQuery(
|
const { loading, error, data } = useQuery(
|
||||||
gql`
|
gql`
|
||||||
{ items {
|
{ items {
|
||||||
id
|
id
|
||||||
|
createdAt
|
||||||
|
title
|
||||||
|
url
|
||||||
user {
|
user {
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
text
|
sats
|
||||||
depth
|
comments
|
||||||
} }`
|
} }`
|
||||||
)
|
)
|
||||||
if (error) return <div>Failed to load</div>
|
if (error) return <div>Failed to load</div>
|
||||||
|
@ -105,15 +108,18 @@ function Items () {
|
||||||
const { items } = data
|
const { items } = data
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<NewItem />
|
<Container className='my-1 py-2 px-sm-0'>
|
||||||
<div>
|
<table>
|
||||||
{items.map(item => (
|
<tbody>
|
||||||
<div key={item.id} style={{ marginLeft: `${5 * item.depth}px` }}>
|
{items.map((item, i) => (
|
||||||
<div>{item.user.name} : {item.text}</div>
|
<tr className='align-items-center' key={item.id}>
|
||||||
<NewItem parentId={item.id} />
|
<td align='right' className='font-weight-bold text-muted mr-1'>{i + 1}</td>
|
||||||
</div>
|
<td><Item item={item} /></td>
|
||||||
|
</tr>
|
||||||
))}
|
))}
|
||||||
</div>
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</Container>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -121,8 +127,6 @@ function Items () {
|
||||||
export default function Index () {
|
export default function Index () {
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout>
|
||||||
<div className={`${styles.box} flashit`} />
|
|
||||||
<Users />
|
|
||||||
<Items />
|
<Items />
|
||||||
</Layout>
|
</Layout>
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import Container from "react-bootstrap/Container";
|
||||||
|
import Item from "../../../components/item";
|
||||||
|
import Layout from "../../../components/layout";
|
||||||
|
|
||||||
|
export default function AnItem () {
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<Container className='my-4'>
|
||||||
|
<Item />
|
||||||
|
</Container>
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
|
}
|
112
pages/post.js
112
pages/post.js
|
@ -1,38 +1,102 @@
|
||||||
import Button from 'react-bootstrap/Button'
|
|
||||||
import Form from 'react-bootstrap/Form'
|
|
||||||
import Layout from '../components/layout'
|
import Layout from '../components/layout'
|
||||||
|
import Button from 'react-bootstrap/Button'
|
||||||
|
import { Form, Input, SubmitButton } from '../components/form'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import styles from '../styles/post.module.css'
|
import styles from '../styles/post.module.css'
|
||||||
|
import * as Yup from 'yup'
|
||||||
|
import { gql, useMutation } from '@apollo/client'
|
||||||
|
|
||||||
|
export const DiscussionSchema = Yup.object({
|
||||||
|
title: Yup.string().required('required').trim()
|
||||||
|
})
|
||||||
|
|
||||||
export function DiscussionForm () {
|
export function DiscussionForm () {
|
||||||
|
const router = useRouter()
|
||||||
|
const [createDiscussion] = useMutation(
|
||||||
|
gql`
|
||||||
|
mutation createDiscussion($title: String!, $text: String) {
|
||||||
|
createDiscussion(title: $title, text: $text) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form>
|
<Form
|
||||||
<Form.Group>
|
initial={{
|
||||||
<Form.Label>title</Form.Label>
|
title: '',
|
||||||
<Form.Control type='text' />
|
text: ''
|
||||||
</Form.Group>
|
}}
|
||||||
<Form.Group>
|
schema={DiscussionSchema}
|
||||||
<Form.Label>text <small className='text-muted ml-2'>optional</small></Form.Label>
|
onSubmit={async (values) => {
|
||||||
<Form.Control as='textarea' rows={4} />
|
const { data: { createDiscussion: { id } }, error } = await createDiscussion({ variables: values })
|
||||||
</Form.Group>
|
if (error) {
|
||||||
<Button className='mt-2' variant='main' size='lg' type='submit'>post</Button>
|
throw new Error({ message: error.toString() })
|
||||||
|
}
|
||||||
|
router.push(`items/${id}`)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
label='title'
|
||||||
|
name='title'
|
||||||
|
required
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
label={<>text <small className='text-muted ml-2'>optional</small></>}
|
||||||
|
name='text'
|
||||||
|
as='textarea'
|
||||||
|
rows={4}
|
||||||
|
/>
|
||||||
|
<SubmitButton variant='secondary' className='mt-2'>post</SubmitButton>
|
||||||
</Form>
|
</Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const LinkSchema = Yup.object({
|
||||||
|
title: Yup.string().required('required').trim(),
|
||||||
|
url: Yup.string().url('invalid url')
|
||||||
|
})
|
||||||
|
|
||||||
export function LinkForm () {
|
export function LinkForm () {
|
||||||
|
const router = useRouter()
|
||||||
|
const [createLink] = useMutation(
|
||||||
|
gql`
|
||||||
|
mutation createLink($title: String!, $url: String!) {
|
||||||
|
createLink(title: $title, url: $url) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form>
|
<Form
|
||||||
<Form.Group>
|
initial={{
|
||||||
<Form.Label>title</Form.Label>
|
title: '',
|
||||||
<Form.Control type='text' />
|
url: ''
|
||||||
</Form.Group>
|
}}
|
||||||
<Form.Group>
|
schema={LinkSchema}
|
||||||
<Form.Label>url</Form.Label>
|
onSubmit={async (values) => {
|
||||||
<Form.Control type='url' />
|
const { data: { createLink: { id } }, error } = await createLink({ variables: values })
|
||||||
</Form.Group>
|
if (error) {
|
||||||
<Button className='mt-2' variant='main' size='lg' type='submit'>post</Button>
|
throw new Error({ message: error.toString() })
|
||||||
|
}
|
||||||
|
router.push(`items/${id}`)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
label='title'
|
||||||
|
name='title'
|
||||||
|
required
|
||||||
|
autoFocus
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
label='url'
|
||||||
|
name='url'
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<SubmitButton variant='secondary' className='mt-2'>post</SubmitButton>
|
||||||
</Form>
|
</Form>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -44,11 +108,11 @@ export function PostForm () {
|
||||||
return (
|
return (
|
||||||
<div className='align-items-center'>
|
<div className='align-items-center'>
|
||||||
<Link href='/post?type=link'>
|
<Link href='/post?type=link'>
|
||||||
<Button variant='main' size='lg'>link</Button>
|
<Button variant='secondary'>link</Button>
|
||||||
</Link>
|
</Link>
|
||||||
<span className='mx-3 font-weight-bold text-muted'>or</span>
|
<span className='mx-3 font-weight-bold text-muted'>or</span>
|
||||||
<Link href='/post?type=discussion'>
|
<Link href='/post?type=discussion'>
|
||||||
<Button variant='main' size='lg'> discussion</Button>
|
<Button variant='secondary'> discussion</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -28,6 +28,7 @@ CREATE TABLE "Item" (
|
||||||
"id" SERIAL NOT NULL,
|
"id" SERIAL NOT NULL,
|
||||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
"updated_at" TIMESTAMP(3) NOT NULL,
|
"updated_at" TIMESTAMP(3) NOT NULL,
|
||||||
|
"title" TEXT,
|
||||||
"text" TEXT,
|
"text" TEXT,
|
||||||
"url" TEXT,
|
"url" TEXT,
|
||||||
"userId" INTEGER NOT NULL,
|
"userId" INTEGER NOT NULL,
|
||||||
|
|
|
@ -35,7 +35,7 @@ model Item {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
createdAt DateTime @default(now()) @map(name: "created_at")
|
createdAt DateTime @default(now()) @map(name: "created_at")
|
||||||
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
||||||
title String
|
title String?
|
||||||
text String?
|
text String?
|
||||||
url String?
|
url String?
|
||||||
user User @relation(fields: [userId], references: [id])
|
user User @relation(fields: [userId], references: [id])
|
||||||
|
|
|
@ -5,29 +5,14 @@ async function main () {
|
||||||
where: { name: 'k00b' },
|
where: { name: 'k00b' },
|
||||||
update: {},
|
update: {},
|
||||||
create: {
|
create: {
|
||||||
name: 'k00b',
|
name: 'k00b'
|
||||||
messages: {
|
|
||||||
create: {
|
|
||||||
text: 'Hello world'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const satoshi = await prisma.user.upsert({
|
const satoshi = await prisma.user.upsert({
|
||||||
where: { name: 'satoshi' },
|
where: { name: 'satoshi' },
|
||||||
update: {},
|
update: {},
|
||||||
create: {
|
create: {
|
||||||
name: 'satoshi',
|
name: 'satoshi'
|
||||||
messages: {
|
|
||||||
create: [
|
|
||||||
{
|
|
||||||
text: 'Peer to peer digital cash'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'Reengineer the world'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const greg = await prisma.user.upsert({
|
const greg = await prisma.user.upsert({
|
||||||
|
@ -49,53 +34,40 @@ async function main () {
|
||||||
where: { id: 0 },
|
where: { id: 0 },
|
||||||
update: {},
|
update: {},
|
||||||
create: {
|
create: {
|
||||||
text: 'A',
|
title: 'System76 Developing “Cosmic” Desktop Environment',
|
||||||
userId: satoshi.id,
|
url: 'https://blog.system76.com/post/648371526931038208/cosmic-to-arrive-in-june-release-of-popos-2104',
|
||||||
children: {
|
|
||||||
create: [
|
|
||||||
{
|
|
||||||
text: 'B',
|
|
||||||
userId: k00b.id,
|
|
||||||
children: {
|
|
||||||
create: [
|
|
||||||
{
|
|
||||||
text: 'G',
|
|
||||||
userId: satoshi.id,
|
|
||||||
children: {
|
|
||||||
create: [
|
|
||||||
{
|
|
||||||
text: 'H',
|
|
||||||
userId: greg.id
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: 'C',
|
|
||||||
userId: k00b.id,
|
|
||||||
children: {
|
|
||||||
create: [
|
|
||||||
{
|
|
||||||
text: 'D',
|
|
||||||
userId: satoshi.id
|
userId: satoshi.id
|
||||||
},
|
}
|
||||||
{
|
})
|
||||||
text: 'E',
|
|
||||||
|
await prisma.item.upsert({
|
||||||
|
where: { id: 1 },
|
||||||
|
update: {},
|
||||||
|
create: {
|
||||||
|
title: 'Deno 1.9',
|
||||||
|
url: 'https://deno.com/blog/v1.9',
|
||||||
|
userId: k00b.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
await prisma.item.upsert({
|
||||||
|
where: { id: 2 },
|
||||||
|
update: {},
|
||||||
|
create: {
|
||||||
|
title: '1Password Secrets Automation',
|
||||||
|
url: 'https://blog.1password.com/introducing-secrets-automation/',
|
||||||
userId: greg.id
|
userId: greg.id
|
||||||
},
|
}
|
||||||
{
|
})
|
||||||
text: 'F',
|
|
||||||
|
await prisma.item.upsert({
|
||||||
|
where: { id: 3 },
|
||||||
|
update: {},
|
||||||
|
create: {
|
||||||
|
title: '‘Counter Strike’ Bug Allows Hackers to Take over a PC with a Steam Invite',
|
||||||
|
url: 'https://www.vice.com/en/article/dyvgej/counter-strike-bug-allows-hackers-to-take-over-a-pc-with-a-steam-invite',
|
||||||
userId: stan.id
|
userId: stan.id
|
||||||
}
|
}
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
@font-face {
|
|
||||||
font-family: lightning;
|
|
||||||
src: url(/Lightningvolt-xoqm.ttf);
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
|
||||||
background-color: #fafafa !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
background-color: #fafafa !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-label {
|
|
||||||
font-size: 0.938rem;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-control {
|
|
||||||
border-radius: .36rem;
|
|
||||||
height: calc(1.5em + 1rem + 2px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
transition: none;
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 16px;
|
|
||||||
border-radius: .4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn:focus {
|
|
||||||
box-shadow: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:focus {
|
|
||||||
outline: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-main {
|
|
||||||
background-color: #F6911D;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-main:hover {
|
|
||||||
background-color: #F6911D;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-lg {
|
|
||||||
padding: 0.5rem 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-brand {
|
|
||||||
background: #FADA5E;
|
|
||||||
}
|
|
||||||
|
|
||||||
.flashit{
|
|
||||||
animation: flash ease-out 7s infinite;
|
|
||||||
animation-delay: -3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes flash {
|
|
||||||
from { opacity: 0; }
|
|
||||||
42% { opacity: 0; }
|
|
||||||
43% { opacity: 0.6; }
|
|
||||||
44% { opacity: 0.2; }
|
|
||||||
46% { opacity: 1; }
|
|
||||||
50% { opacity: 0; }
|
|
||||||
92% { opacity: 0; }
|
|
||||||
93% { opacity: 0.6; }
|
|
||||||
94% { opacity: 0.2; }
|
|
||||||
96% { opacity: 1; }
|
|
||||||
to { opacity: 0; }
|
|
||||||
}
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
$theme-colors: (
|
||||||
|
"primary" : #FADA5E,
|
||||||
|
"secondary" : #F6911D,
|
||||||
|
"danger" : #c03221,
|
||||||
|
"info" : #007cbe,
|
||||||
|
"success" : #5c8001
|
||||||
|
);
|
||||||
|
|
||||||
|
$body-bg: #fafafa;
|
||||||
|
$border-radius: .4rem;
|
||||||
|
$enable-transitions: false;
|
||||||
|
$enable-gradients: false;
|
||||||
|
$enable-shadows: false;
|
||||||
|
$btn-transition: none;
|
||||||
|
$form-feedback-icon-invalid: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='12' height='12'%3E%3Cpath fill='none' d='M0 0h24v24H0z'/%3E%3Cpath d='M22 15h-3V3h3a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1zm-5.293 1.293l-6.4 6.4a.5.5 0 0 1-.654.047L8.8 22.1a1.5 1.5 0 0 1-.553-1.57L9.4 16H3a2 2 0 0 1-2-2v-2.104a2 2 0 0 1 .15-.762L4.246 3.62A1 1 0 0 1 5.17 3H16a1 1 0 0 1 1 1v11.586a1 1 0 0 1-.293.707z' fill='rgba(192,50,33,1)'/%3E%3C/svg%3E");
|
||||||
|
$line-height-base: 1.75;
|
||||||
|
$input-btn-padding-y: .42rem;
|
||||||
|
$input-btn-padding-x: .84rem;
|
||||||
|
$btn-padding-y: .5rem;
|
||||||
|
$btn-padding-x: 1.1rem;
|
||||||
|
$btn-font-weight: bold;
|
||||||
|
$btn-focus-width: 0;
|
||||||
|
$btn-border-width: 0;
|
||||||
|
$btn-focus-box-shadow: none;
|
||||||
|
$alert-border-width: 0;
|
||||||
|
$close-text-shadow: none;
|
||||||
|
$close-color: inherit;
|
||||||
|
$alert-border-radius: #{33% 2%} / #{11% 74%};
|
||||||
|
$link-color: #007cbe;
|
||||||
|
$font-size-base: .9rem;
|
||||||
|
$enable-responsive-font-sizes: true;
|
||||||
|
$link-hover-decoration: none;
|
||||||
|
$container-max-widths: (
|
||||||
|
sm: 540px,
|
||||||
|
md: 720px,
|
||||||
|
lg: 900px,
|
||||||
|
xl: 900px
|
||||||
|
) !default;
|
||||||
|
|
||||||
|
|
||||||
|
@import "~bootstrap/scss/bootstrap";
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: lightning;
|
||||||
|
src: url(/Lightningvolt-xoqm.ttf);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-label {
|
||||||
|
font-size: 92%;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control:focus {
|
||||||
|
border-color: #fada5e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary,
|
||||||
|
.btn-secondary:hover,
|
||||||
|
.btn-secondary:disabled {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flashit{
|
||||||
|
animation: flash ease-out 7s infinite;
|
||||||
|
animation-delay: -3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes flash {
|
||||||
|
from { opacity: 0; }
|
||||||
|
42% { opacity: 0; }
|
||||||
|
43% { opacity: 0.6; }
|
||||||
|
44% { opacity: 0.2; }
|
||||||
|
46% { opacity: 1; }
|
||||||
|
50% { opacity: 0; }
|
||||||
|
92% { opacity: 0; }
|
||||||
|
93% { opacity: 0.6; }
|
||||||
|
94% { opacity: 0.2; }
|
||||||
|
96% { opacity: 1; }
|
||||||
|
to { opacity: 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.morphit{
|
||||||
|
animation: flash ease-out 7s infinite;
|
||||||
|
animation-delay: -3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes flash {
|
||||||
|
from { opacity: 0; }
|
||||||
|
42% { opacity: 0; }
|
||||||
|
43% { opacity: 0.6; }
|
||||||
|
44% { opacity: 0.2; }
|
||||||
|
46% { opacity: 1; }
|
||||||
|
50% { opacity: 0; }
|
||||||
|
92% { opacity: 0; }
|
||||||
|
93% { opacity: 0.6; }
|
||||||
|
94% { opacity: 0.2; }
|
||||||
|
96% { opacity: 1; }
|
||||||
|
to { opacity: 0; }
|
||||||
|
}
|
|
@ -3,3 +3,9 @@
|
||||||
height: 100px;
|
height: 100px;
|
||||||
background-color: grey;
|
background-color: grey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto auto auto;
|
||||||
|
width: 100%;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="32" height="32"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 8l6 6H6z"/></svg>
|
After Width: | Height: | Size: 150 B |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 114 287"><path d="M113.62 193.44h-49.1l17.93 93.28H18.9L.5 164.46h64.02L48.76 62.02h-26.3L61.74.5l39.46 61.52H77.95z"/></svg>
|
After Width: | Height: | Size: 178 B |
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 18.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 286.221 286.221" style="enable-background:new 0 0 286.221 286.221;" xml:space="preserve">
|
||||||
|
<g>
|
||||||
|
<polygon points="199.667,93.283 150.567,93.283 168.5,0 104.95,0 86.554,122.26 150.567,122.26 134.813,224.703 108.506,224.703
|
||||||
|
147.795,286.221 187.247,224.703 164,224.703 "/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 837 B |
|
@ -0,0 +1,5 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" >
|
||||||
|
<path d="M256,0.289L0,379.471l256,132.24l256-132.24L256,0.289z M240.992,470.175L54.582,373.882l186.411-96.294V470.175z
|
||||||
|
M240.992,243.805L67.197,333.582L240.992,76.16V243.805z M271.008,76.16l173.795,257.423l-173.795-89.778V76.16z
|
||||||
|
M271.008,277.588l186.411,96.294l-186.411,96.293V277.588z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 372 B |
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 72.72 72.719"><path d="M72.72,65.686H0L36.36,7.034L72.72,65.686z M5.388,62.686h61.943L36.36,12.727L5.388,62.686z"/></svg>
|
After Width: | Height: | Size: 176 B |
76
yarn.lock
76
yarn.lock
|
@ -149,7 +149,7 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.4"
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
"@babel/runtime@^7.12.1", "@babel/runtime@^7.13.8", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.7":
|
"@babel/runtime@^7.10.5", "@babel/runtime@^7.12.1", "@babel/runtime@^7.13.8", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.7":
|
||||||
version "7.13.10"
|
version "7.13.10"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d"
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d"
|
||||||
integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==
|
integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==
|
||||||
|
@ -522,6 +522,11 @@
|
||||||
"@types/koa-compose" "*"
|
"@types/koa-compose" "*"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/lodash@^4.14.165":
|
||||||
|
version "4.14.168"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.168.tgz#fe24632e79b7ade3f132891afff86caa5e5ce008"
|
||||||
|
integrity sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==
|
||||||
|
|
||||||
"@types/long@^4.0.0":
|
"@types/long@^4.0.0":
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
|
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.1.tgz#459c65fa1867dafe6a8f322c4c51695663cc55e9"
|
||||||
|
@ -1277,7 +1282,7 @@ chalk@^4.0.0, chalk@^4.1.0:
|
||||||
ansi-styles "^4.1.0"
|
ansi-styles "^4.1.0"
|
||||||
supports-color "^7.1.0"
|
supports-color "^7.1.0"
|
||||||
|
|
||||||
chokidar@3.5.1:
|
chokidar@3.5.1, "chokidar@>=2.0.0 <4.0.0":
|
||||||
version "3.5.1"
|
version "3.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a"
|
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a"
|
||||||
integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==
|
integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==
|
||||||
|
@ -1572,6 +1577,11 @@ deep-is@^0.1.3:
|
||||||
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
|
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
|
||||||
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
|
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
|
||||||
|
|
||||||
|
deepmerge@^2.1.1:
|
||||||
|
version "2.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
|
||||||
|
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
|
||||||
|
|
||||||
define-properties@^1.1.3:
|
define-properties@^1.1.3:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
|
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
|
||||||
|
@ -2196,6 +2206,19 @@ form-data@^3.0.0:
|
||||||
combined-stream "^1.0.8"
|
combined-stream "^1.0.8"
|
||||||
mime-types "^2.1.12"
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
|
formik@^2.2.6:
|
||||||
|
version "2.2.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/formik/-/formik-2.2.6.tgz#378a4bafe4b95caf6acf6db01f81f3fe5147559d"
|
||||||
|
integrity sha512-Kxk2zQRafy56zhLmrzcbryUpMBvT0tal5IvcifK5+4YNGelKsnrODFJ0sZQRMQboblWNym4lAW3bt+tf2vApSA==
|
||||||
|
dependencies:
|
||||||
|
deepmerge "^2.1.1"
|
||||||
|
hoist-non-react-statics "^3.3.0"
|
||||||
|
lodash "^4.17.14"
|
||||||
|
lodash-es "^4.17.14"
|
||||||
|
react-fast-compare "^2.0.1"
|
||||||
|
tiny-warning "^1.0.2"
|
||||||
|
tslib "^1.10.0"
|
||||||
|
|
||||||
fs-capacitor@^2.0.4:
|
fs-capacitor@^2.0.4:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/fs-capacitor/-/fs-capacitor-2.0.4.tgz#5a22e72d40ae5078b4fe64fe4d08c0d3fc88ad3c"
|
resolved "https://registry.yarnpkg.com/fs-capacitor/-/fs-capacitor-2.0.4.tgz#5a22e72d40ae5078b4fe64fe4d08c0d3fc88ad3c"
|
||||||
|
@ -2412,7 +2435,7 @@ hoek@6.x.x:
|
||||||
resolved "https://registry.yarnpkg.com/hoek/-/hoek-6.1.3.tgz#73b7d33952e01fe27a38b0457294b79dd8da242c"
|
resolved "https://registry.yarnpkg.com/hoek/-/hoek-6.1.3.tgz#73b7d33952e01fe27a38b0457294b79dd8da242c"
|
||||||
integrity sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==
|
integrity sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==
|
||||||
|
|
||||||
hoist-non-react-statics@^3.3.2:
|
hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2:
|
||||||
version "3.3.2"
|
version "3.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
||||||
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
||||||
|
@ -2835,7 +2858,7 @@ locate-path@^5.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
p-locate "^4.1.0"
|
p-locate "^4.1.0"
|
||||||
|
|
||||||
lodash-es@^4.17.20:
|
lodash-es@^4.17.14, lodash-es@^4.17.15, lodash-es@^4.17.20:
|
||||||
version "4.17.21"
|
version "4.17.21"
|
||||||
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
|
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
|
||||||
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
|
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
|
||||||
|
@ -3028,6 +3051,11 @@ mz@^2.4.0:
|
||||||
object-assign "^4.0.1"
|
object-assign "^4.0.1"
|
||||||
thenify-all "^1.0.0"
|
thenify-all "^1.0.0"
|
||||||
|
|
||||||
|
nanoclone@^0.2.1:
|
||||||
|
version "0.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4"
|
||||||
|
integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==
|
||||||
|
|
||||||
nanoid@^3.1.16:
|
nanoid@^3.1.16:
|
||||||
version "3.1.22"
|
version "3.1.22"
|
||||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.22.tgz#b35f8fb7d151990a8aebd5aa5015c03cf726f844"
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.22.tgz#b35f8fb7d151990a8aebd5aa5015c03cf726f844"
|
||||||
|
@ -3584,6 +3612,11 @@ prop-types@15.7.2, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
react-is "^16.8.1"
|
react-is "^16.8.1"
|
||||||
|
|
||||||
|
property-expr@^2.0.4:
|
||||||
|
version "2.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.4.tgz#37b925478e58965031bb612ec5b3260f8241e910"
|
||||||
|
integrity sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg==
|
||||||
|
|
||||||
public-encrypt@^4.0.0:
|
public-encrypt@^4.0.0:
|
||||||
version "4.0.3"
|
version "4.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0"
|
resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0"
|
||||||
|
@ -3694,6 +3727,11 @@ react-dom@17.0.1:
|
||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
scheduler "^0.20.1"
|
scheduler "^0.20.1"
|
||||||
|
|
||||||
|
react-fast-compare@^2.0.1:
|
||||||
|
version "2.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
|
||||||
|
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
|
||||||
|
|
||||||
react-is@16.13.1, react-is@^16.3.2, react-is@^16.7.0, react-is@^16.8.1:
|
react-is@16.13.1, react-is@^16.3.2, react-is@^16.7.0, react-is@^16.8.1:
|
||||||
version "16.13.1"
|
version "16.13.1"
|
||||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||||
|
@ -3888,6 +3926,13 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
|
||||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||||
|
|
||||||
|
sass@^1.32.8:
|
||||||
|
version "1.32.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/sass/-/sass-1.32.8.tgz#f16a9abd8dc530add8834e506878a2808c037bdc"
|
||||||
|
integrity sha512-Sl6mIeGpzjIUZqvKnKETfMf0iDAswD9TNlv13A7aAF3XZlRPMq4VvJWBC2N2DXbp94MQVdNSFG6LfF/iOXrPHQ==
|
||||||
|
dependencies:
|
||||||
|
chokidar ">=2.0.0 <4.0.0"
|
||||||
|
|
||||||
sax@>=0.6.0:
|
sax@>=0.6.0:
|
||||||
version "1.2.4"
|
version "1.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||||
|
@ -4360,6 +4405,11 @@ timers-browserify@^2.0.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
setimmediate "^1.0.4"
|
setimmediate "^1.0.4"
|
||||||
|
|
||||||
|
tiny-warning@^1.0.2:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
|
||||||
|
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
|
||||||
|
|
||||||
to-arraybuffer@^1.0.0:
|
to-arraybuffer@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
|
resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
|
||||||
|
@ -4382,6 +4432,11 @@ toidentifier@1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
||||||
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
|
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
|
||||||
|
|
||||||
|
toposort@^2.0.2:
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
|
||||||
|
integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=
|
||||||
|
|
||||||
tr46@^1.0.1:
|
tr46@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
|
resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
|
||||||
|
@ -4747,6 +4802,19 @@ yocto-queue@^0.1.0:
|
||||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||||
|
|
||||||
|
yup@^0.32.9:
|
||||||
|
version "0.32.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.9.tgz#9367bec6b1b0e39211ecbca598702e106019d872"
|
||||||
|
integrity sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.10.5"
|
||||||
|
"@types/lodash" "^4.14.165"
|
||||||
|
lodash "^4.17.20"
|
||||||
|
lodash-es "^4.17.15"
|
||||||
|
nanoclone "^0.2.1"
|
||||||
|
property-expr "^2.0.4"
|
||||||
|
toposort "^2.0.2"
|
||||||
|
|
||||||
zen-observable-ts@^0.8.21:
|
zen-observable-ts@^0.8.21:
|
||||||
version "0.8.21"
|
version "0.8.21"
|
||||||
resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz#85d0031fbbde1eba3cd07d3ba90da241215f421d"
|
resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz#85d0031fbbde1eba3cd07d3ba90da241215f421d"
|
||||||
|
|
Loading…
Reference in New Issue