diff --git a/api/resolvers/item.js b/api/resolvers/item.js
index e3271cbe..36404912 100644
--- a/api/resolvers/item.js
+++ b/api/resolvers/item.js
@@ -219,8 +219,23 @@ export default {
throw new UserInputError('sats must be positive', { argumentName: 'sats' })
}
+ // if we are tipping disallow self tips
+ if (act === 'TIP') {
+ const [item] = await models.$queryRaw(`
+ ${SELECT}
+ FROM "Item"
+ WHERE id = $1 AND "userId" = $2`, Number(id), me.id)
+ if (item) {
+ throw new UserInputError('cannot tip your self')
+ }
+ }
+
await serialize(models, models.$queryRaw`SELECT item_act(${Number(id)}, ${me.id}, ${act}, ${Number(sats)})`)
- return sats
+
+ return {
+ sats,
+ act
+ }
}
},
@@ -260,7 +275,20 @@ export default {
return sats || 0
},
- meSats: async (item, args, { me, models }) => {
+ tips: async (item, args, { models }) => {
+ const { sum: { sats } } = await models.itemAct.aggregate({
+ sum: {
+ sats: true
+ },
+ where: {
+ itemId: item.id,
+ act: 'TIP'
+ }
+ })
+
+ return sats || 0
+ },
+ meVote: async (item, args, { me, models }) => {
if (!me) return 0
const { sum: { sats } } = await models.itemAct.aggregate({
@@ -276,6 +304,38 @@ export default {
return sats || 0
},
+ meBoost: async (item, args, { me, models }) => {
+ if (!me) return 0
+
+ const { sum: { sats } } = await models.itemAct.aggregate({
+ sum: {
+ sats: true
+ },
+ where: {
+ itemId: item.id,
+ userId: me.id,
+ act: 'BOOST'
+ }
+ })
+
+ return sats || 0
+ },
+ meTip: async (item, args, { me, models }) => {
+ if (!me) return 0
+
+ const { sum: { sats } } = await models.itemAct.aggregate({
+ sum: {
+ sats: true
+ },
+ where: {
+ itemId: item.id,
+ userId: me.id,
+ act: 'TIP'
+ }
+ })
+
+ return sats || 0
+ },
root: async (item, args, { models }) => {
if (!item.parentId) {
return null
diff --git a/api/typeDefs/item.js b/api/typeDefs/item.js
index 9aa36d4a..36c2c177 100644
--- a/api/typeDefs/item.js
+++ b/api/typeDefs/item.js
@@ -15,6 +15,11 @@ export default gql`
TIP
}
+ type ItemActResult {
+ sats: Int!
+ act: ItemAct!
+ }
+
extend type Mutation {
createLink(title: String!, url: String): Item!
updateLink(id: ID!, title: String!, url: String): Item!
@@ -22,7 +27,7 @@ export default gql`
updateDiscussion(id: ID!, title: String!, text: String): Item!
createComment(text: String!, parentId: ID!): Item!
updateComment(id: ID!, text: String!): Item!
- act(id: ID!, act: ItemAct!, sats: Int): Int!
+ act(id: ID!, act: ItemAct!, sats: Int): ItemActResult!
}
type Items {
@@ -48,7 +53,10 @@ export default gql`
depth: Int!
sats: Int!
boost: Int!
- meSats: Int!
+ tips: Int!
+ meVote: Int!
+ meBoost: Int!
+ meTip: Int!
ncomments: Int!
comments: [Item!]!
path: String
diff --git a/components/action-tooltip.js b/components/action-tooltip.js
index 9421ee8e..07d862aa 100644
--- a/components/action-tooltip.js
+++ b/components/action-tooltip.js
@@ -1,7 +1,7 @@
import { useFormikContext } from 'formik'
import { OverlayTrigger, Tooltip } from 'react-bootstrap'
-export default function ActionTooltip ({ children, notForm }) {
+export default function ActionTooltip ({ children, notForm, overlayText }) {
// if we're in a form, we want to hide tooltip on submit
let formik
if (!notForm) {
@@ -12,7 +12,7 @@ export default function ActionTooltip ({ children, notForm }) {
placement='bottom'
overlay={
- 1 sat
+ {overlayText || '1 sat'}
}
trigger={['hover', 'focus']}
diff --git a/components/comment.js b/components/comment.js
index 20023d4e..ddcba996 100644
--- a/components/comment.js
+++ b/components/comment.js
@@ -63,14 +63,22 @@ export default function Comment ({ item, children, replyOpen, includeParent, roo
ref={ref} className={includeParent ? '' : `${styles.comment} ${collapse ? styles.collapsed : ''}`}
>
-
+
{item.sats} sats
\
-
{item.boost} boost
-
\
+ {item.boost > 0 &&
+ <>
+
{item.boost} boost
+
\
+ >}
+ {item.tips > 0 &&
+ <>
+
{item.tips} tipped
+
\
+ >}
e.stopPropagation()} className='text-reset'>{item.ncomments} replies
diff --git a/components/item.js b/components/item.js
index 033f128a..36e90519 100644
--- a/components/item.js
+++ b/components/item.js
@@ -22,7 +22,7 @@ export default function Item ({ item, rank, children }) {
)
:
}
-
+
@@ -44,6 +44,11 @@ export default function Item ({ item, rank, children }) {
{item.boost} boost
\
>}
+ {item.tips > 0 &&
+ <>
+
{item.tips} tipped
+
\
+ >}
{item.ncomments} comments
diff --git a/components/seo.js b/components/seo.js
index 19d4bd9c..606eb5d5 100644
--- a/components/seo.js
+++ b/components/seo.js
@@ -20,9 +20,17 @@ export default function Seo ({ item, user }) {
desc = desc.replace(/\s+/g, ' ')
}
} else {
- desc = `@${item.user.name} stacked ${item.sats} sats ${item.url ? `posting ${item.url}` : ''}`
+ desc = `@${item.user.name} stacked ${(item.sats > 0 ? item.sats - 1 : 0) + item.tips} sats ${item.url ? `posting ${item.url}` : 'with this discussion'}`
+ }
+ if (item.ncomments) {
+ desc += ` [${item.ncomments} comments`
+ if (item.boost) {
+ desc += `, ${item.boost} boost`
+ }
+ desc += ']'
+ } else if (item.boost) {
+ desc += ` [${item.boost} boost]`
}
- desc += ` [${item.ncomments} comments, ${item.boost} boost]`
}
if (user) {
desc = `@${user.name} has [${user.stacked} stacked, ${user.sats} sats, ${user.nitems} posts, ${user.ncomments} comments]`
diff --git a/components/upvote.js b/components/upvote.js
index 8684b8d0..ce0d5ffc 100644
--- a/components/upvote.js
+++ b/components/upvote.js
@@ -6,38 +6,61 @@ import { signIn, useSession } from 'next-auth/client'
import { useFundError } from './fund-error'
import ActionTooltip from './action-tooltip'
import { useItemAct } from './item-act'
+import Window from '../svgs/window-2-fill.svg'
-export default function UpVote ({ itemId, meSats, className }) {
+export default function UpVote ({ item, className }) {
const [session] = useSession()
const { setError } = useFundError()
const { setItem } = useItemAct()
const [act] = useMutation(
gql`
mutation act($id: ID!, $act: ItemAct! $sats: Int!) {
- act(id: $id, act: $act, sats: $sats)
+ act(id: $id, act: $act, sats: $sats) {
+ act,
+ sats
+ }
}`, {
- update (cache, { data: { act } }) {
+ update (cache, { data: { act: { act, sats } } }) {
// read in the cached object so we don't use meSats prop
// which can be stale
- const item = cache.readFragment({
- id: `Item:${itemId}`,
- fragment: gql`
- fragment actedItem on Item {
- meSats
- }
- `
- })
cache.modify({
- id: `Item:${itemId}`,
+ id: `Item:${item.id}`,
fields: {
- meSats (existingMeSats = 0) {
- return existingMeSats + act
+ meVote (existingMeVote = 0) {
+ if (act === 'VOTE') {
+ return existingMeVote + sats
+ }
+ return existingMeVote
+ },
+ meBoost (existingMeBoost = 0) {
+ if (act === 'BOOST') {
+ return existingMeBoost + sats
+ }
+ return existingMeBoost
+ },
+ meTip (existingMeTip = 0) {
+ if (act === 'TIP') {
+ return existingMeTip + sats
+ }
+ return existingMeTip
},
sats (existingSats = 0) {
- return item.meSats === 0 ? existingSats + act : existingSats
+ if (act === 'VOTE') {
+ return existingSats + sats
+ }
+ return existingSats
},
boost (existingBoost = 0) {
- return item.meSats >= 1 ? existingBoost + act : existingBoost
+ if (act === 'BOOST') {
+ return existingBoost + sats
+ }
+ return existingBoost
+ },
+ tips (existingTips = 0) {
+ if (act === 'TIP') {
+ return existingTips + sats
+ }
+ return existingTips
}
}
})
@@ -48,29 +71,29 @@ export default function UpVote ({ itemId, meSats, className }) {
return (
{({ strike }) =>
-
+ : '1 sat'}>
1 ? styles.stimi : styles.voted) : ''}`
+ ${item?.meVote ? styles.voted : ''}`
}
onClick={
session
? async (e) => {
e.stopPropagation()
- if (meSats >= 1) {
- setItem({ itemId, act, strike })
+ if (item?.meVote) {
+ setItem({ itemId: item.id, act, strike })
return
}
strike()
- if (!itemId) return
+ if (!item) return
try {
- await act({ variables: { id: itemId, act: 'VOTE', sats: 1 } })
+ await act({ variables: { id: item.id, act: 'VOTE', sats: 1 } })
} catch (error) {
if (error.toString().includes('insufficient funds')) {
setError(true)
diff --git a/fragments/comments.js b/fragments/comments.js
index 9bdbbd55..2235c586 100644
--- a/fragments/comments.js
+++ b/fragments/comments.js
@@ -12,7 +12,10 @@ export const COMMENT_FIELDS = gql`
}
sats
boost
- meSats
+ tips
+ meVote
+ meBoost
+ meTip
ncomments
root {
id
diff --git a/fragments/items.js b/fragments/items.js
index c7828e55..592a375d 100644
--- a/fragments/items.js
+++ b/fragments/items.js
@@ -13,7 +13,10 @@ export const ITEM_FIELDS = gql`
}
sats
boost
- meSats
+ tips
+ meVote
+ meBoost
+ meTip
ncomments
root {
id
diff --git a/svgs/window-2-fill.svg b/svgs/window-2-fill.svg
new file mode 100644
index 00000000..737b0d53
--- /dev/null
+++ b/svgs/window-2-fill.svg
@@ -0,0 +1 @@
+
\ No newline at end of file