tables
This commit is contained in:
parent
9acde2df1c
commit
bc5d4d4808
|
@ -1,43 +1,71 @@
|
|||
import { UserInputError, AuthenticationError } from 'apollo-server-micro'
|
||||
|
||||
const createItem = async (parent, { title, text, url, parentId }, { me, models }) => {
|
||||
if (!me) {
|
||||
throw new AuthenticationError('You must be logged in')
|
||||
}
|
||||
|
||||
const data = {
|
||||
title,
|
||||
url,
|
||||
text,
|
||||
user: {
|
||||
connect: {
|
||||
name: me.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (parentId) {
|
||||
data.parent = {
|
||||
connect: {
|
||||
id: parseInt(parentId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await models.item.create({ data })
|
||||
}
|
||||
|
||||
export default {
|
||||
Query: {
|
||||
items: async (parent, args, { models }) => {
|
||||
return await models.$queryRaw(`
|
||||
SELECT id, text, "userId", ltree2text("path") AS "path"
|
||||
SELECT id, "created_at" as "createdAt", title, url, text, "userId", ltree2text("path") AS "path"
|
||||
FROM "Item"
|
||||
ORDER BY "path"`)
|
||||
}
|
||||
},
|
||||
|
||||
Mutation: {
|
||||
createItem: async (parent, { text, parentId }, { me, models }) => {
|
||||
if (!me) {
|
||||
throw new AuthenticationError('You must be logged in')
|
||||
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('Item must have text', { argumentName: 'text' })
|
||||
throw new UserInputError('Comment must have text', { argumentName: 'text' })
|
||||
}
|
||||
|
||||
const data = {
|
||||
text,
|
||||
user: {
|
||||
connect: {
|
||||
name: me.name
|
||||
}
|
||||
}
|
||||
if (!parentId) {
|
||||
throw new UserInputError('Comment must have text', { argumentName: 'text' })
|
||||
}
|
||||
|
||||
if (parentId) {
|
||||
data.parent = {
|
||||
connect: {
|
||||
id: parseInt(parentId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await models.item.create({ data })
|
||||
return await createItem(parent, { text, parentId }, { me, models })
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -56,6 +84,8 @@ export default {
|
|||
WHERE id = ${item.id}`
|
||||
|
||||
return path.split('.').length - 1
|
||||
}
|
||||
},
|
||||
comments: () => 0,
|
||||
sats: () => 0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,13 +6,20 @@ export default gql`
|
|||
}
|
||||
|
||||
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 {
|
||||
id: ID!
|
||||
text: String!
|
||||
createdAt: String!
|
||||
title: String
|
||||
url: String
|
||||
text: String
|
||||
user: User!
|
||||
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 styles from './header.module.css'
|
||||
import { useRouter } from 'next/router'
|
||||
import { Container } from 'react-bootstrap'
|
||||
|
||||
export default function Header () {
|
||||
const [session, loading] = useSession()
|
||||
|
@ -30,25 +31,27 @@ export default function Header () {
|
|||
|
||||
return (
|
||||
<>
|
||||
<Navbar bg='brand' className={styles.navbar}>
|
||||
<Link href='/' passHref>
|
||||
<Navbar.Brand className={styles.brand}>STACKER NEWS</Navbar.Brand>
|
||||
</Link>
|
||||
<Nav className='mr-auto align-items-center' activeKey={router.pathname}>
|
||||
<Nav.Item>
|
||||
<Link href='/recent' passHref>
|
||||
<Nav.Link>recent</Nav.Link>
|
||||
</Link>
|
||||
</Nav.Item>
|
||||
<Nav.Item>
|
||||
<Link href='/post' passHref>
|
||||
<Nav.Link>post</Nav.Link>
|
||||
</Link>
|
||||
</Nav.Item>
|
||||
</Nav>
|
||||
<Nav className='ml-auto align-items-center'>
|
||||
<Corner />
|
||||
</Nav>
|
||||
<Navbar bg='primary' className={styles.navbar}>
|
||||
<Container>
|
||||
<Link href='/' passHref>
|
||||
<Navbar.Brand className={styles.brand}>STACKER NEWS</Navbar.Brand>
|
||||
</Link>
|
||||
<Nav className='mr-auto align-items-center' activeKey={router.pathname}>
|
||||
<Nav.Item>
|
||||
<Link href='/recent' passHref>
|
||||
<Nav.Link>recent</Nav.Link>
|
||||
</Link>
|
||||
</Nav.Item>
|
||||
<Nav.Item>
|
||||
<Link href='/post' passHref>
|
||||
<Nav.Link>post</Nav.Link>
|
||||
</Link>
|
||||
</Nav.Item>
|
||||
</Nav>
|
||||
<Nav className='ml-auto align-items-center'>
|
||||
<Corner />
|
||||
</Nav>
|
||||
</Container>
|
||||
</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",
|
||||
"apollo-server-micro": "^2.21.2",
|
||||
"bootstrap": "^4.6.0",
|
||||
"formik": "^2.2.6",
|
||||
"graphql": "^15.5.0",
|
||||
"next": "10.0.9",
|
||||
"next-auth": "^3.13.3",
|
||||
"react": "17.0.1",
|
||||
"react-bootstrap": "^1.5.2",
|
||||
"react-dom": "17.0.1",
|
||||
"swr": "^0.5.4"
|
||||
"sass": "^1.32.8",
|
||||
"swr": "^0.5.4",
|
||||
"yup": "^0.32.9"
|
||||
},
|
||||
"standard": {
|
||||
"parser": "babel-eslint",
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import 'bootstrap/dist/css/bootstrap.min.css'
|
||||
import '../styles/globals.css'
|
||||
import '../styles/globals.scss'
|
||||
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client'
|
||||
import { Provider } from 'next-auth/client'
|
||||
|
||||
|
|
196
pages/index.js
196
pages/index.js
|
@ -1,103 +1,106 @@
|
|||
import { useQuery, gql, useMutation } from '@apollo/client'
|
||||
import { useState } from 'react'
|
||||
import { useSession } from 'next-auth/client'
|
||||
import styles from '../styles/index.module.css'
|
||||
import { useQuery, gql } from '@apollo/client'
|
||||
// import styles from '../styles/index.module.css'
|
||||
import Layout from '../components/layout'
|
||||
import Item from '../components/item'
|
||||
import Container from 'react-bootstrap/Container'
|
||||
|
||||
function Users () {
|
||||
const { loading, error, data } = useQuery(gql`{ users { id, name } }`)
|
||||
if (error) return <div>Failed to load</div>
|
||||
if (loading) return <div>Loading...</div>
|
||||
const { users } = data
|
||||
return (
|
||||
<div>
|
||||
{users.map(user => (
|
||||
<div key={user.id}>{user.name}</div>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
// function Users () {
|
||||
// const { loading, error, data } = useQuery(gql`{ users { id, name } }`)
|
||||
// if (error) return <div>Failed to load</div>
|
||||
// if (loading) return <div>Loading...</div>
|
||||
// const { users } = data
|
||||
// return (
|
||||
// <div>
|
||||
// {users.map(user => (
|
||||
// <div key={user.id}>{user.name}</div>
|
||||
// ))}
|
||||
// </div>
|
||||
// )
|
||||
// }
|
||||
|
||||
function NewItem ({ parentId }) {
|
||||
const [session] = useSession()
|
||||
const [createItem] = useMutation(
|
||||
gql`
|
||||
mutation CreateItem($text: String!, $parentId: ID) {
|
||||
createItem(text: $text, parentId: $parentId) {
|
||||
id
|
||||
}
|
||||
}`, {
|
||||
update (cache, { data: { createItem } }) {
|
||||
cache.modify({
|
||||
fields: {
|
||||
items (existingItems = [], { readField }) {
|
||||
const newItemRef = cache.writeFragment({
|
||||
data: createItem,
|
||||
fragment: gql`
|
||||
fragment NewItem on Item {
|
||||
id
|
||||
user {
|
||||
name
|
||||
}
|
||||
text
|
||||
depth
|
||||
}
|
||||
`
|
||||
})
|
||||
for (let i = 0; i < existingItems.length; i++) {
|
||||
if (readField('id', existingItems[i]) === parentId) {
|
||||
return [...existingItems.slice(0, i), newItemRef, ...existingItems.slice(i)]
|
||||
}
|
||||
}
|
||||
return [newItemRef, ...existingItems]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
const [open, setOpen] = useState(false)
|
||||
// function NewItem ({ parentId }) {
|
||||
// const [session] = useSession()
|
||||
// const [createItem] = useMutation(
|
||||
// gql`
|
||||
// mutation CreateItem($text: String!, $parentId: ID) {
|
||||
// createItem(text: $text, parentId: $parentId) {
|
||||
// id
|
||||
// }
|
||||
// }`, {
|
||||
// update (cache, { data: { createItem } }) {
|
||||
// cache.modify({
|
||||
// fields: {
|
||||
// items (existingItems = [], { readField }) {
|
||||
// const newItemRef = cache.writeFragment({
|
||||
// data: createItem,
|
||||
// fragment: gql`
|
||||
// fragment NewItem on Item {
|
||||
// id
|
||||
// user {
|
||||
// name
|
||||
// }
|
||||
// text
|
||||
// depth
|
||||
// }
|
||||
// `
|
||||
// })
|
||||
// for (let i = 0; i < existingItems.length; i++) {
|
||||
// if (readField('id', existingItems[i]) === parentId) {
|
||||
// return [...existingItems.slice(0, i), newItemRef, ...existingItems.slice(i)]
|
||||
// }
|
||||
// }
|
||||
// return [newItemRef, ...existingItems]
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
// const [open, setOpen] = useState(false)
|
||||
|
||||
if (!session) return null
|
||||
// if (!session) return null
|
||||
|
||||
if (!open) {
|
||||
return (
|
||||
<div onClick={() => setOpen(true)}>
|
||||
{parentId ? 'reply' : 'submit'}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
// if (!open) {
|
||||
// return (
|
||||
// <div onClick={() => setOpen(true)}>
|
||||
// {parentId ? 'reply' : 'submit'}
|
||||
// </div>
|
||||
// )
|
||||
// }
|
||||
|
||||
let text
|
||||
return (
|
||||
<form
|
||||
style={{ marginLeft: '5px' }}
|
||||
onSubmit={e => {
|
||||
e.preventDefault()
|
||||
createItem({ variables: { text: text.value, parentId } })
|
||||
setOpen(false)
|
||||
text.value = ''
|
||||
}}
|
||||
>
|
||||
<textarea
|
||||
ref={node => {
|
||||
text = node
|
||||
}}
|
||||
/>
|
||||
<button type='submit'>Submit</button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
// let text
|
||||
// return (
|
||||
// <form
|
||||
// style={{ marginLeft: '5px' }}
|
||||
// onSubmit={e => {
|
||||
// e.preventDefault()
|
||||
// createItem({ variables: { text: text.value, parentId } })
|
||||
// setOpen(false)
|
||||
// text.value = ''
|
||||
// }}
|
||||
// >
|
||||
// <textarea
|
||||
// ref={node => {
|
||||
// text = node
|
||||
// }}
|
||||
// />
|
||||
// <button type='submit'>Submit</button>
|
||||
// </form>
|
||||
// )
|
||||
// }
|
||||
|
||||
function Items () {
|
||||
const { loading, error, data } = useQuery(
|
||||
gql`
|
||||
{ items {
|
||||
id
|
||||
createdAt
|
||||
title
|
||||
url
|
||||
user {
|
||||
name
|
||||
}
|
||||
text
|
||||
depth
|
||||
sats
|
||||
comments
|
||||
} }`
|
||||
)
|
||||
if (error) return <div>Failed to load</div>
|
||||
|
@ -105,15 +108,18 @@ function Items () {
|
|||
const { items } = data
|
||||
return (
|
||||
<>
|
||||
<NewItem />
|
||||
<div>
|
||||
{items.map(item => (
|
||||
<div key={item.id} style={{ marginLeft: `${5 * item.depth}px` }}>
|
||||
<div>{item.user.name} : {item.text}</div>
|
||||
<NewItem parentId={item.id} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<Container className='my-1 py-2 px-sm-0'>
|
||||
<table>
|
||||
<tbody>
|
||||
{items.map((item, i) => (
|
||||
<tr className='align-items-center' key={item.id}>
|
||||
<td align='right' className='font-weight-bold text-muted mr-1'>{i + 1}</td>
|
||||
<td><Item item={item} /></td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</Container>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
@ -121,8 +127,6 @@ function Items () {
|
|||
export default function Index () {
|
||||
return (
|
||||
<Layout>
|
||||
<div className={`${styles.box} flashit`} />
|
||||
<Users />
|
||||
<Items />
|
||||
</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 Button from 'react-bootstrap/Button'
|
||||
import { Form, Input, SubmitButton } from '../components/form'
|
||||
import { useRouter } from 'next/router'
|
||||
import Link from 'next/link'
|
||||
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 () {
|
||||
const router = useRouter()
|
||||
const [createDiscussion] = useMutation(
|
||||
gql`
|
||||
mutation createDiscussion($title: String!, $text: String) {
|
||||
createDiscussion(title: $title, text: $text) {
|
||||
id
|
||||
}
|
||||
}`
|
||||
)
|
||||
|
||||
return (
|
||||
<Form>
|
||||
<Form.Group>
|
||||
<Form.Label>title</Form.Label>
|
||||
<Form.Control type='text' />
|
||||
</Form.Group>
|
||||
<Form.Group>
|
||||
<Form.Label>text <small className='text-muted ml-2'>optional</small></Form.Label>
|
||||
<Form.Control as='textarea' rows={4} />
|
||||
</Form.Group>
|
||||
<Button className='mt-2' variant='main' size='lg' type='submit'>post</Button>
|
||||
<Form
|
||||
initial={{
|
||||
title: '',
|
||||
text: ''
|
||||
}}
|
||||
schema={DiscussionSchema}
|
||||
onSubmit={async (values) => {
|
||||
const { data: { createDiscussion: { id } }, error } = await createDiscussion({ variables: values })
|
||||
if (error) {
|
||||
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>
|
||||
)
|
||||
}
|
||||
|
||||
export const LinkSchema = Yup.object({
|
||||
title: Yup.string().required('required').trim(),
|
||||
url: Yup.string().url('invalid url')
|
||||
})
|
||||
|
||||
export function LinkForm () {
|
||||
const router = useRouter()
|
||||
const [createLink] = useMutation(
|
||||
gql`
|
||||
mutation createLink($title: String!, $url: String!) {
|
||||
createLink(title: $title, url: $url) {
|
||||
id
|
||||
}
|
||||
}`
|
||||
)
|
||||
|
||||
return (
|
||||
<Form>
|
||||
<Form.Group>
|
||||
<Form.Label>title</Form.Label>
|
||||
<Form.Control type='text' />
|
||||
</Form.Group>
|
||||
<Form.Group>
|
||||
<Form.Label>url</Form.Label>
|
||||
<Form.Control type='url' />
|
||||
</Form.Group>
|
||||
<Button className='mt-2' variant='main' size='lg' type='submit'>post</Button>
|
||||
<Form
|
||||
initial={{
|
||||
title: '',
|
||||
url: ''
|
||||
}}
|
||||
schema={LinkSchema}
|
||||
onSubmit={async (values) => {
|
||||
const { data: { createLink: { id } }, error } = await createLink({ variables: values })
|
||||
if (error) {
|
||||
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>
|
||||
)
|
||||
}
|
||||
|
@ -44,11 +108,11 @@ export function PostForm () {
|
|||
return (
|
||||
<div className='align-items-center'>
|
||||
<Link href='/post?type=link'>
|
||||
<Button variant='main' size='lg'>link</Button>
|
||||
<Button variant='secondary'>link</Button>
|
||||
</Link>
|
||||
<span className='mx-3 font-weight-bold text-muted'>or</span>
|
||||
<Link href='/post?type=discussion'>
|
||||
<Button variant='main' size='lg'> discussion</Button>
|
||||
<Button variant='secondary'> discussion</Button>
|
||||
</Link>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -28,6 +28,7 @@ CREATE TABLE "Item" (
|
|||
"id" SERIAL NOT NULL,
|
||||
"created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updated_at" TIMESTAMP(3) NOT NULL,
|
||||
"title" TEXT,
|
||||
"text" TEXT,
|
||||
"url" TEXT,
|
||||
"userId" INTEGER NOT NULL,
|
||||
|
|
|
@ -35,7 +35,7 @@ model Item {
|
|||
id Int @id @default(autoincrement())
|
||||
createdAt DateTime @default(now()) @map(name: "created_at")
|
||||
updatedAt DateTime @updatedAt @map(name: "updated_at")
|
||||
title String
|
||||
title String?
|
||||
text String?
|
||||
url String?
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
|
|
|
@ -5,29 +5,14 @@ async function main () {
|
|||
where: { name: 'k00b' },
|
||||
update: {},
|
||||
create: {
|
||||
name: 'k00b',
|
||||
messages: {
|
||||
create: {
|
||||
text: 'Hello world'
|
||||
}
|
||||
}
|
||||
name: 'k00b'
|
||||
}
|
||||
})
|
||||
const satoshi = await prisma.user.upsert({
|
||||
where: { name: 'satoshi' },
|
||||
update: {},
|
||||
create: {
|
||||
name: 'satoshi',
|
||||
messages: {
|
||||
create: [
|
||||
{
|
||||
text: 'Peer to peer digital cash'
|
||||
},
|
||||
{
|
||||
text: 'Reengineer the world'
|
||||
}
|
||||
]
|
||||
}
|
||||
name: 'satoshi'
|
||||
}
|
||||
})
|
||||
const greg = await prisma.user.upsert({
|
||||
|
@ -49,52 +34,39 @@ async function main () {
|
|||
where: { id: 0 },
|
||||
update: {},
|
||||
create: {
|
||||
text: 'A',
|
||||
userId: satoshi.id,
|
||||
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
|
||||
},
|
||||
{
|
||||
text: 'E',
|
||||
userId: greg.id
|
||||
},
|
||||
{
|
||||
text: 'F',
|
||||
userId: stan.id
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
title: 'System76 Developing “Cosmic” Desktop Environment',
|
||||
url: 'https://blog.system76.com/post/648371526931038208/cosmic-to-arrive-in-june-release-of-popos-2104',
|
||||
userId: satoshi.id
|
||||
}
|
||||
})
|
||||
|
||||
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
|
||||
}
|
||||
})
|
||||
|
||||
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
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
}
|
|
@ -2,4 +2,10 @@
|
|||
width: 100px;
|
||||
height: 100px;
|
||||
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:
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d"
|
||||
integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==
|
||||
|
@ -522,6 +522,11 @@
|
|||
"@types/koa-compose" "*"
|
||||
"@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":
|
||||
version "4.0.1"
|
||||
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"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
chokidar@3.5.1:
|
||||
chokidar@3.5.1, "chokidar@>=2.0.0 <4.0.0":
|
||||
version "3.5.1"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a"
|
||||
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"
|
||||
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:
|
||||
version "1.1.3"
|
||||
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"
|
||||
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:
|
||||
version "2.0.4"
|
||||
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"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
||||
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
||||
|
@ -2835,7 +2858,7 @@ locate-path@^5.0.0:
|
|||
dependencies:
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
|
||||
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
|
||||
|
@ -3028,6 +3051,11 @@ mz@^2.4.0:
|
|||
object-assign "^4.0.1"
|
||||
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:
|
||||
version "3.1.22"
|
||||
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"
|
||||
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:
|
||||
version "4.0.3"
|
||||
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"
|
||||
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:
|
||||
version "16.13.1"
|
||||
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"
|
||||
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:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
|
@ -4360,6 +4405,11 @@ timers-browserify@^2.0.4:
|
|||
dependencies:
|
||||
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:
|
||||
version "1.0.1"
|
||||
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"
|
||||
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:
|
||||
version "1.0.1"
|
||||
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"
|
||||
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:
|
||||
version "0.8.21"
|
||||
resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz#85d0031fbbde1eba3cd07d3ba90da241215f421d"
|
||||
|
|
Loading…
Reference in New Issue