diff --git a/api/src/graphql/partReactions.sdl.js b/api/src/graphql/partReactions.sdl.js
index 4eaaa26..b27334e 100644
--- a/api/src/graphql/partReactions.sdl.js
+++ b/api/src/graphql/partReactions.sdl.js
@@ -13,6 +13,7 @@ export const schema = gql`
type Query {
partReactions: [PartReaction!]!
partReaction(id: String!): PartReaction
+ partReactionsByPartId(partId: String!): [PartReaction!]!
}
input TogglePartReactionInput {
diff --git a/api/src/services/partReactions/partReactions.js b/api/src/services/partReactions/partReactions.js
index 9116014..6adac0f 100644
--- a/api/src/services/partReactions/partReactions.js
+++ b/api/src/services/partReactions/partReactions.js
@@ -15,6 +15,12 @@ export const partReaction = ({ id }) => {
})
}
+export const partReactionsByPartId = ({ partId }) => {
+ return db.partReaction.findMany({
+ where: { partId: partId },
+ })
+}
+
export const togglePartReaction = async ({ input }) => {
// if write fails emote_userId_partId @@unique constraint, then delete it instead
requireAuth()
diff --git a/web/src/components/EmojiReaction/EmojiReaction.js b/web/src/components/EmojiReaction/EmojiReaction.js
index ce254b9..dbc931a 100644
--- a/web/src/components/EmojiReaction/EmojiReaction.js
+++ b/web/src/components/EmojiReaction/EmojiReaction.js
@@ -20,6 +20,7 @@ const EmojiReaction = ({
emotes,
userEmotes,
onEmote = () => {},
+ onShowPartReactions,
className,
}) => {
const { currentUser } = useAuth()
@@ -107,17 +108,20 @@ const EmojiReaction = ({
horizontal: 'left',
}}
>
-
- {emojiMenu.map((emoji, i) => (
-
- ))}
+
+
+ {emojiMenu.map((emoji, i) => (
+
+ ))}
+
+
>
diff --git a/web/src/components/PartProfile/PartProfile.js b/web/src/components/PartProfile/PartProfile.js
index 7ff2d8e..222a47b 100644
--- a/web/src/components/PartProfile/PartProfile.js
+++ b/web/src/components/PartProfile/PartProfile.js
@@ -2,12 +2,14 @@ import { useState, useEffect, useRef } from 'react'
import { useAuth } from '@redwoodjs/auth'
import { Link, navigate, routes } from '@redwoodjs/router'
import Editor from 'rich-markdown-editor'
+import Dialog from '@material-ui/core/Dialog'
import ImageUploader from 'src/components/ImageUploader'
import ConfirmDialog from 'src/components/ConfirmDialog'
import Breadcrumb from 'src/components/Breadcrumb'
import EmojiReaction from 'src/components/EmojiReaction'
import Button from 'src/components/Button'
+import PartReactionsCell from '../PartReactionsCell'
import { countEmotes } from 'src/helpers/emote'
import { getActiveClasses } from 'get-active-classes'
@@ -21,6 +23,7 @@ const PartProfile = ({
}) => {
const [comment, setComment] = useState('')
const [isConfirmDialogOpen, setIsConfirmDialogOpen] = useState(false)
+ const [isReactionsModalOpen, setIsReactionsModalOpen] = useState(false)
const [isInvalid, setIsInvalid] = useState(false)
const { currentUser } = useAuth()
const editorRef = useRef(null)
@@ -94,6 +97,7 @@ const PartProfile = ({
emotes={emotes}
userEmotes={userEmotes}
onEmote={onReaction}
+ onShowPartReactions={() => setIsReactionsModalOpen(true)}
/>
+
>
)
}
diff --git a/web/src/components/PartReactions/PartReactions.js b/web/src/components/PartReactions/PartReactions.js
new file mode 100644
index 0000000..37e343a
--- /dev/null
+++ b/web/src/components/PartReactions/PartReactions.js
@@ -0,0 +1,75 @@
+import { useState } from 'react'
+import Tab from '@material-ui/core/Tab'
+import Tabs from '@material-ui/core/Tabs'
+import { Link, routes } from '@redwoodjs/router'
+import { countEmotes } from 'src/helpers/emote'
+import ImageUploader from 'src/components/ImageUploader'
+
+const PartReactions = ({ reactions }) => {
+ const emotes = countEmotes(reactions)
+ const [tab, setTab] = useState(0)
+ const onTabChange = (_, newValue) => {
+ setTab(newValue)
+ }
+
+ return (
+
+
+
+ {emotes.map((emote, i) => (
+
+ ))}
+
+
+ {reactions
+ .filter((reaction) =>
+ tab === 0 ? true : reaction.emote === emotes[tab - 1].emoji
+ )
+ .map((reactionPart, i) => (
+ -
+
+
+
+
+
+
+
+ {reactionPart.user?.userName}
+
+
+
+
+
+ {reactionPart.emote}
+
+
+ ))}
+
+
+ )
+}
+
+export default PartReactions
diff --git a/web/src/components/PartReactions/PartReactions.test.js b/web/src/components/PartReactions/PartReactions.test.js
new file mode 100644
index 0000000..e69de29
diff --git a/web/src/components/PartReactionsCell/PartReactionsCell.js b/web/src/components/PartReactionsCell/PartReactionsCell.js
new file mode 100644
index 0000000..2cf4c0c
--- /dev/null
+++ b/web/src/components/PartReactionsCell/PartReactionsCell.js
@@ -0,0 +1,26 @@
+import PartReactions from 'src/components/PartReactions'
+
+export const QUERY = gql`
+ query PartReactionsQuery($partId: String!) {
+ partReactionsByPartId(partId: $partId) {
+ id
+ emote
+ user {
+ id
+ userName
+ image
+ }
+ updatedAt
+ }
+ }
+`
+
+export const Loading = () =>
Loading...
+
+export const Empty = () =>
Empty
+
+export const Failure = ({ error }) =>
Error: {error.message}
+
+export const Success = ({ partReactionsByPartId }) => {
+ return
+}
diff --git a/web/src/components/PartReactionsCell/PartReactionsCell.mock.js b/web/src/components/PartReactionsCell/PartReactionsCell.mock.js
new file mode 100644
index 0000000..d96dad4
--- /dev/null
+++ b/web/src/components/PartReactionsCell/PartReactionsCell.mock.js
@@ -0,0 +1,6 @@
+// Define your own mock data here:
+export const standard = (/* vars, { ctx, req } */) => ({
+ partReactions: {
+ id: 42,
+ },
+})
diff --git a/web/src/components/PartReactionsCell/PartReactionsCell.stories.js b/web/src/components/PartReactionsCell/PartReactionsCell.stories.js
new file mode 100644
index 0000000..dfd7507
--- /dev/null
+++ b/web/src/components/PartReactionsCell/PartReactionsCell.stories.js
@@ -0,0 +1,20 @@
+import { Loading, Empty, Failure, Success } from './PartReactionsCell'
+import { standard } from './PartReactionsCell.mock'
+
+export const loading = () => {
+ return Loading ?
: null
+}
+
+export const empty = () => {
+ return Empty ?
: null
+}
+
+export const failure = () => {
+ return Failure ?
: null
+}
+
+export const success = () => {
+ return Success ?
: null
+}
+
+export default { title: 'Cells/PartReactionsCell' }
diff --git a/web/src/components/PartReactionsCell/PartReactionsCell.test.js b/web/src/components/PartReactionsCell/PartReactionsCell.test.js
new file mode 100644
index 0000000..0b9b0d1
--- /dev/null
+++ b/web/src/components/PartReactionsCell/PartReactionsCell.test.js
@@ -0,0 +1,26 @@
+import { render, screen } from '@redwoodjs/testing'
+import { Loading, Empty, Failure, Success } from './PartReactionsCell'
+import { standard } from './PartReactionsCell.mock'
+
+describe('PartReactionsCell', () => {
+ test('Loading renders successfully', () => {
+ render(
)
+ // Use screen.debug() to see output
+ expect(screen.getByText('Loading...')).toBeInTheDocument()
+ })
+
+ test('Empty renders successfully', async () => {
+ render(
)
+ expect(screen.getByText('Empty')).toBeInTheDocument()
+ })
+
+ test('Failure renders successfully', async () => {
+ render(
)
+ expect(screen.getByText(/Oh no/i)).toBeInTheDocument()
+ })
+
+ test('Success renders successfully', async () => {
+ render(
)
+ expect(screen.getByText(/42/i)).toBeInTheDocument()
+ })
+})