From 650ad03de5094cbd4499f98de60b652717f06fb7 Mon Sep 17 00:00:00 2001 From: keyan Date: Sat, 11 Sep 2021 16:52:19 -0500 Subject: [PATCH] move boost to post creation --- api/resolvers/item.js | 25 +++++++++++++++++-------- api/typeDefs/item.js | 4 ++-- components/accordian-item.js | 31 +++++++++++++++++++++++++++++++ components/adv-post-form.js | 29 +++++++++++++++++++++++++++++ components/discussion-form.js | 24 +++++++++++++++--------- components/item-act.js | 30 +++--------------------------- components/item.module.css | 2 +- components/link-form.js | 25 ++++++++++++++++--------- 8 files changed, 114 insertions(+), 56 deletions(-) create mode 100644 components/accordian-item.js create mode 100644 components/adv-post-form.js diff --git a/api/resolvers/item.js b/api/resolvers/item.js index 36404912..c777760e 100644 --- a/api/resolvers/item.js +++ b/api/resolvers/item.js @@ -113,7 +113,7 @@ export default { }, Mutation: { - createLink: async (parent, { title, url }, { me, models }) => { + createLink: async (parent, { title, url, boost }, { me, models }) => { if (!title) { throw new UserInputError('link must have title', { argumentName: 'title' }) } @@ -122,7 +122,7 @@ export default { throw new UserInputError('link must have url', { argumentName: 'url' }) } - return await createItem(parent, { title, url: ensureProtocol(url) }, { me, models }) + return await createItem(parent, { title, url: ensureProtocol(url), boost }, { me, models }) }, updateLink: async (parent, { id, title, url }, { me, models }) => { if (!id) { @@ -149,12 +149,12 @@ export default { return await updateItem(parent, { id, data: { title, url: ensureProtocol(url) } }, { me, models }) }, - createDiscussion: async (parent, { title, text }, { me, models }) => { + createDiscussion: async (parent, { title, text, boost }, { me, models }) => { if (!title) { throw new UserInputError('discussion must have title', { argumentName: 'title' }) } - return await createItem(parent, { title, text }, { me, models }) + return await createItem(parent, { title, text, boost }, { me, models }) }, updateDiscussion: async (parent, { id, title, text }, { me, models }) => { if (!id) { @@ -407,14 +407,23 @@ const updateItem = async (parent, { id, data }, { me, models }) => { return item } -const createItem = async (parent, { title, url, text, parentId }, { me, models }) => { +const createItem = async (parent, { title, url, text, boost, parentId }, { me, models }) => { if (!me) { throw new AuthenticationError('you must be logged in') } - const [item] = await serialize(models, models.$queryRaw( - `${SELECT} FROM create_item($1, $2, $3, $4, $5) AS "Item"`, - title, url, text, Number(parentId), Number(me.id))) + if (boost && boost < 0) { + throw new UserInputError('boost must be positive', { argumentName: 'boost' }) + } + + const [item] = await serialize(models, + models.$queryRaw(`${SELECT} FROM create_item($1, $2, $3, $4, $5) AS "Item"`, + title, url, text, Number(parentId), Number(me.id))) + + if (boost) { + await serialize(models, + models.$queryRaw`SELECT item_act(${item.id}, ${me.id}, 'BOOST', ${Number(boost)})`) + } await createMentions(item, models) diff --git a/api/typeDefs/item.js b/api/typeDefs/item.js index 36c2c177..8ce34d39 100644 --- a/api/typeDefs/item.js +++ b/api/typeDefs/item.js @@ -21,9 +21,9 @@ export default gql` } extend type Mutation { - createLink(title: String!, url: String): Item! + createLink(title: String!, url: String, boost: Int): Item! updateLink(id: ID!, title: String!, url: String): Item! - createDiscussion(title: String!, text: String): Item! + createDiscussion(title: String!, text: String, boost: Int): Item! updateDiscussion(id: ID!, title: String!, text: String): Item! createComment(text: String!, parentId: ID!): Item! updateComment(id: ID!, text: String!): Item! diff --git a/components/accordian-item.js b/components/accordian-item.js new file mode 100644 index 00000000..65561dc9 --- /dev/null +++ b/components/accordian-item.js @@ -0,0 +1,31 @@ +import { Accordion } from 'react-bootstrap' +import ArrowRight from '../svgs/arrow-right-s-fill.svg' +import ArrowDown from '../svgs/arrow-down-s-fill.svg' +import { useEffect, useState } from 'react' + +export default function AccordianItem ({ header, body, headerColor = 'grey' }) { + const [open, setOpen] = useState(false) + + useEffect(() => { + setOpen(false) + }, []) + + return ( + +
} + eventKey='0' + style={{ cursor: 'pointer', display: 'flex', alignItems: 'center' }} + onClick={() => setOpen(!open)} + > + {open + ? + : } +
{header}
+ + +
{body}
+
+ + ) +} diff --git a/components/adv-post-form.js b/components/adv-post-form.js new file mode 100644 index 00000000..282a3ad7 --- /dev/null +++ b/components/adv-post-form.js @@ -0,0 +1,29 @@ +import AccordianItem from './accordian-item' +import * as Yup from 'yup' +import { Input } from './form' +import { InputGroup } from 'react-bootstrap' + +export const AdvPostSchema = { + boost: Yup.number().typeError('must be a number') + .min(0, 'must be positive').integer('must be whole') +} + +export const AdvPostInitial = { + boost: 0 +} + +export default function AdvPostForm () { + return ( + advanced
} + body={ + boost ranks posts higher temporarily depending on the amount} + append={sats} + /> + } + /> + ) +} diff --git a/components/discussion-form.js b/components/discussion-form.js index 612a8eef..1ca397f5 100644 --- a/components/discussion-form.js +++ b/components/discussion-form.js @@ -5,17 +5,19 @@ import { gql, useMutation } from '@apollo/client' import ActionTooltip from '../components/action-tooltip' import TextareaAutosize from 'react-textarea-autosize' import Countdown from './countdown' +import AdvPostForm, { AdvPostInitial, AdvPostSchema } from './adv-post-form' export const DiscussionSchema = Yup.object({ - title: Yup.string().required('required').trim() + title: Yup.string().required('required').trim(), + ...AdvPostSchema }) export function DiscussionForm ({ item, editThreshold }) { const router = useRouter() const [createDiscussion] = useMutation( gql` - mutation createDiscussion($title: String!, $text: String) { - createDiscussion(title: $title, text: $text) { + mutation createDiscussion($title: String!, $text: String, $boost: Int) { + createDiscussion(title: $title, text: $text, boost: $boost) { id } }` @@ -47,15 +49,16 @@ export function DiscussionForm ({ item, editThreshold }) {
{ + onSubmit={async ({ boost, ...values }) => { let id, error if (item) { ({ data: { updateDiscussion: { id } }, error } = await updateDiscussion({ variables: { ...values, id: item.id } })) } else { - ({ data: { createDiscussion: { id } }, error } = await createDiscussion({ variables: values })) + ({ data: { createDiscussion: { id } }, error } = await createDiscussion({ variables: { boost: Number(boost), ...values } })) } if (error) { throw new Error({ message: error.toString() }) @@ -78,9 +81,12 @@ export function DiscussionForm ({ item, editThreshold }) { ? : null} /> - - {item ? 'save' : 'post'} - + {!item && } +
+ + {item ? 'save' : 'post'} + +
) } diff --git a/components/item-act.js b/components/item-act.js index e493868b..7cbe5dbe 100644 --- a/components/item-act.js +++ b/components/item-act.js @@ -1,9 +1,7 @@ -import { Accordion, InputGroup, Modal } from 'react-bootstrap' +import { InputGroup, Modal } from 'react-bootstrap' import React, { useState, useCallback, useContext, useRef, useEffect } from 'react' import * as Yup from 'yup' import { Form, Input, SubmitButton } from './form' -import ArrowRight from '../svgs/arrow-right-s-fill.svg' -import ArrowDown from '../svgs/arrow-down-s-fill.svg' export const ItemActContext = React.createContext({ item: null, @@ -37,7 +35,6 @@ export const ActSchema = Yup.object({ export function ItemActModal () { const { item, setItem } = useItemAct() - const [open, setOpen] = useState(false) const inputRef = useRef(null) useEffect(() => { @@ -49,7 +46,6 @@ export function ItemActModal () { show={!!item} onHide={() => { setItem(null) - setOpen(false) }} > @@ -61,7 +57,6 @@ export function ItemActModal () { onSubmit={async ({ amount, submit }) => { await item.act({ variables: { id: item.itemId, act: submit, sats: Number(amount) } }) await item.strike() - setOpen(false) setItem(null) }} > @@ -73,28 +68,9 @@ export function ItemActModal () { autoFocus append={sats} /> -
- boost - tip +
+ tip
- -
} - eventKey='0' - style={{ cursor: 'pointer', display: 'flex', justifyContent: 'center', alignItems: 'center' }} - onClick={() => setOpen(!open)} - > - {open - ? - : } - I'm confused - - - Tips go directly to the poster or commenter. Boosts boost the rank - of the post or comment for a limited time, and the sats go to the site. - - - diff --git a/components/item.module.css b/components/item.module.css index a5fcfe6e..f35a702d 100644 --- a/components/item.module.css +++ b/components/item.module.css @@ -17,7 +17,7 @@ } a.link:visited { - color: grey; + color: #7acaf5; } .other { diff --git a/components/link-form.js b/components/link-form.js index c1ae6024..7c236806 100644 --- a/components/link-form.js +++ b/components/link-form.js @@ -5,6 +5,7 @@ import { gql, useLazyQuery, useMutation } from '@apollo/client' import { ensureProtocol } from '../lib/url' import ActionTooltip from '../components/action-tooltip' import Countdown from './countdown' +import AdvPostForm, { AdvPostInitial, AdvPostSchema } from './adv-post-form' export const LinkSchema = Yup.object({ title: Yup.string().required('required').trim(), @@ -20,7 +21,8 @@ export const LinkSchema = Yup.object({ } }, message: 'invalid url' - }).required('required') + }).required('required'), + ...AdvPostSchema }) export function LinkForm ({ item, editThreshold }) { @@ -31,8 +33,8 @@ export function LinkForm ({ item, editThreshold }) { const router = useRouter() const [createLink] = useMutation( gql` - mutation createLink($title: String!, $url: String!) { - createLink(title: $title, url: $url) { + mutation createLink($title: String!, $url: String!, $boost: Int) { + createLink(title: $title, url: $url, boost: $boost) { id } }` @@ -66,15 +68,16 @@ export function LinkForm ({ item, editThreshold }) {
{ + onSubmit={async ({ boost, ...values }) => { let id, error if (item) { ({ data: { updateLink: { id } }, error } = await updateLink({ variables: { ...values, id: item.id } })) } else { - ({ data: { createLink: { id } }, error } = await createLink({ variables: values })) + ({ data: { createLink: { id } }, error } = await createLink({ variables: { boost: Number(boost), ...values } })) } if (error) { throw new Error({ message: error.toString() }) @@ -104,9 +107,13 @@ export function LinkForm ({ item, editThreshold }) { } }} /> - - {item ? 'save' : 'post'} - + {!item && } + +
+ + {item ? 'save' : 'post'} + +
) }