From fdfb6f10e25552fd55f89a4857020659e4b9f438 Mon Sep 17 00:00:00 2001 From: Lucas Bordeau Date: Wed, 14 Jun 2023 18:48:26 +0200 Subject: [PATCH] Implemented comment thread target picker with new dropdown components (#295) * First draft of new relation picker and usage in comments --------- Co-authored-by: Charles Bochet --- front/package.json | 1 + front/src/generated/graphql.tsx | 12 +- .../components/comments/CommentHeader.tsx | 2 +- .../components/comments/CommentThread.tsx | 2 + .../comments/CommentThreadRelationPicker.tsx | 206 ++++++++++++++++++ .../CommentThreadRelationPicker.stories.tsx | 31 +++ front/src/modules/comments/services/select.ts | 8 + .../companies/components/CompanyChip.tsx | 14 +- .../modules/ui/components/form/Checkbox.tsx | 4 +- .../ui/components/menu/DropdownMenu.tsx | 2 + .../menu/DropdownMenuCheckableItem.tsx | 2 +- .../menu/stories/DropdownMenu.stories.tsx | 10 +- .../select-entity/SelectSingleEntity.tsx | 3 + front/src/modules/ui/icons/index.ts | 1 + front/src/modules/ui/layout/styles/themes.ts | 2 +- front/src/modules/users/components/Avatar.tsx | 16 +- .../components/__stories__/Avatar.stories.tsx | 18 +- .../src/testing/mock-data/comment-threads.ts | 76 +++++++ front/src/testing/mock-data/index.ts | 5 + front/yarn.lock | 25 ++- .../api/resolvers/comment-thread.resolver.ts | 10 +- .../comment-thread-relations.resolver.ts | 18 ++ 22 files changed, 421 insertions(+), 47 deletions(-) create mode 100644 front/src/modules/comments/components/comments/CommentThreadRelationPicker.tsx create mode 100644 front/src/modules/comments/components/comments/__stories__/CommentThreadRelationPicker.stories.tsx create mode 100644 front/src/modules/ui/components/select-entity/SelectSingleEntity.tsx create mode 100644 front/src/testing/mock-data/comment-threads.ts diff --git a/front/package.json b/front/package.json index 47e9e0346..20cede359 100644 --- a/front/package.json +++ b/front/package.json @@ -7,6 +7,7 @@ "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "@emotion/react": "^11.10.6", "@emotion/styled": "^11.10.5", + "@floating-ui/react": "^0.24.3", "@hello-pangea/dnd": "^16.2.0", "@tabler/icons-react": "^2.20.0", "@tanstack/react-table": "^8.8.5", diff --git a/front/src/generated/graphql.tsx b/front/src/generated/graphql.tsx index 506cd8dcf..3b694e9ce 100644 --- a/front/src/generated/graphql.tsx +++ b/front/src/generated/graphql.tsx @@ -1151,14 +1151,14 @@ export type GetCommentThreadsByTargetsQueryVariables = Exact<{ }>; -export type GetCommentThreadsByTargetsQuery = { __typename?: 'Query', findManyCommentThreads: Array<{ __typename?: 'CommentThread', id: string, comments?: Array<{ __typename?: 'Comment', id: string, body: string, createdAt: string, updatedAt: string, author: { __typename?: 'User', id: string, displayName: string, avatarUrl?: string | null } }> | null }> }; +export type GetCommentThreadsByTargetsQuery = { __typename?: 'Query', findManyCommentThreads: Array<{ __typename?: 'CommentThread', id: string, comments?: Array<{ __typename?: 'Comment', id: string, body: string, createdAt: string, updatedAt: string, author: { __typename?: 'User', id: string, displayName: string, avatarUrl?: string | null } }> | null, commentThreadTargets?: Array<{ __typename?: 'CommentThreadTarget', commentableId: string, commentableType: CommentableType }> | null }> }; export type GetCommentThreadQueryVariables = Exact<{ commentThreadId: Scalars['String']; }>; -export type GetCommentThreadQuery = { __typename?: 'Query', findManyCommentThreads: Array<{ __typename?: 'CommentThread', id: string, comments?: Array<{ __typename?: 'Comment', id: string, body: string, createdAt: string, updatedAt: string, author: { __typename?: 'User', id: string, displayName: string, avatarUrl?: string | null } }> | null }> }; +export type GetCommentThreadQuery = { __typename?: 'Query', findManyCommentThreads: Array<{ __typename?: 'CommentThread', id: string, comments?: Array<{ __typename?: 'Comment', id: string, body: string, createdAt: string, updatedAt: string, author: { __typename?: 'User', id: string, displayName: string, avatarUrl?: string | null } }> | null, commentThreadTargets?: Array<{ __typename?: 'CommentThreadTarget', commentableId: string, commentableType: CommentableType }> | null }> }; export type GetCompaniesQueryVariables = Exact<{ orderBy?: InputMaybe | CompanyOrderByWithRelationInput>; @@ -1414,6 +1414,10 @@ export const GetCommentThreadsByTargetsDocument = gql` avatarUrl } } + commentThreadTargets { + commentableId + commentableType + } } } `; @@ -1461,6 +1465,10 @@ export const GetCommentThreadDocument = gql` avatarUrl } } + commentThreadTargets { + commentableId + commentableType + } } } `; diff --git a/front/src/modules/comments/components/comments/CommentHeader.tsx b/front/src/modules/comments/components/comments/CommentHeader.tsx index 22e3da33e..a05228fe4 100644 --- a/front/src/modules/comments/components/comments/CommentHeader.tsx +++ b/front/src/modules/comments/components/comments/CommentHeader.tsx @@ -80,7 +80,7 @@ export function CommentHeader({ comment }: OwnProps) { {authorName} {showDate && ( diff --git a/front/src/modules/comments/components/comments/CommentThread.tsx b/front/src/modules/comments/components/comments/CommentThread.tsx index 0043241ba..47b5476af 100644 --- a/front/src/modules/comments/components/comments/CommentThread.tsx +++ b/front/src/modules/comments/components/comments/CommentThread.tsx @@ -11,6 +11,7 @@ import { isNonEmptyString } from '@/utils/type-guards/isNonEmptyString'; import { useCreateCommentMutation } from '~/generated/graphql'; import { CommentThreadItem } from './CommentThreadItem'; +import { CommentThreadRelationPicker } from './CommentThreadRelationPicker'; type OwnProps = { commentThread: CommentThreadForDrawer; @@ -88,6 +89,7 @@ export function CommentThread({ commentThread }: OwnProps) { ))} + ); diff --git a/front/src/modules/comments/components/comments/CommentThreadRelationPicker.tsx b/front/src/modules/comments/components/comments/CommentThreadRelationPicker.tsx new file mode 100644 index 000000000..5de2a9893 --- /dev/null +++ b/front/src/modules/comments/components/comments/CommentThreadRelationPicker.tsx @@ -0,0 +1,206 @@ +import { useState } from 'react'; +import { useTheme } from '@emotion/react'; +import styled from '@emotion/styled'; +import { + autoUpdate, + flip, + offset, + shift, + size, + useFloating, +} from '@floating-ui/react'; +import { debounce } from 'lodash'; + +import { CommentThreadForDrawer } from '@/comments/types/CommentThreadForDrawer'; +import CompanyChip from '@/companies/components/CompanyChip'; +import { DropdownMenu } from '@/ui/components/menu/DropdownMenu'; +import { DropdownMenuCheckableItem } from '@/ui/components/menu/DropdownMenuCheckableItem'; +import { DropdownMenuItem } from '@/ui/components/menu/DropdownMenuItem'; +import { DropdownMenuItemContainer } from '@/ui/components/menu/DropdownMenuItemContainer'; +import { DropdownMenuSearch } from '@/ui/components/menu/DropdownMenuSearch'; +import { DropdownMenuSeparator } from '@/ui/components/menu/DropdownMenuSeparator'; +import { IconArrowUpRight } from '@/ui/icons'; +import { Avatar } from '@/users/components/Avatar'; +import { getLogoUrlFromDomainName } from '@/utils/utils'; +import { QueryMode, useSearchCompanyQueryQuery } from '~/generated/graphql'; + +type OwnProps = { + commentThread: CommentThreadForDrawer; +}; + +const StyledContainer = styled.div` + align-items: center; + display: flex; + flex-direction: row; + gap: ${(props) => props.theme.spacing(2)}; + justify-content: flex-start; + + width: 100%; +`; + +const StyledRelationLabel = styled.div` + color: ${(props) => props.theme.text60}; + display: flex; + flex-direction: row; +`; + +const StyledRelationContainer = styled.div` + --horizontal-padding: ${(props) => props.theme.spacing(1)}; + --vertical-padding: ${(props) => props.theme.spacing(1.5)}; + + border: 1px solid transparent; + + cursor: pointer; + + display: flex; + gap: ${(props) => props.theme.spacing(2)}; + + height: calc(32px - 2 * var(--vertical-padding)); + + &:hover { + background-color: ${(props) => props.theme.secondaryBackground}; + border: 1px solid ${(props) => props.theme.lightBorder}; + } + + overflow: hidden; + + padding: var(--vertical-padding) var(--horizontal-padding); + + width: calc(100% - 2 * var(--horizontal-padding)); +`; + +// TODO: refactor icon button with new figma and merge +// const StyledAddButton = styled.div` +// align-items: center; +// background: ${(props) => props.theme.primaryBackgroundTransparent}; +// border-radius: ${(props) => props.theme.borderRadius}; +// box-shadow: ${(props) => props.theme.modalBoxShadow}; + +// cursor: pointer; +// display: flex; +// flex-direction: row; + +// &:hover { +// background-color: ${(props) => props.theme.tertiaryBackground}; +// } + +// height: 20px; +// justify-content: center; + +// width: 20px; +// `; + +export function CommentThreadRelationPicker({ commentThread }: OwnProps) { + const [isMenuOpen, setIsMenuOpen] = useState(false); + const [searchFilter, setSearchFilter] = useState(''); + + const debouncedSetSearchFilter = debounce(setSearchFilter, 100, { + leading: true, + }); + + const { refs, floatingStyles } = useFloating({ + strategy: 'fixed', + middleware: [offset(), flip(), shift(), size()], + whileElementsMounted: autoUpdate, + open: isMenuOpen, + }); + + const theme = useTheme(); + + const companyIds = commentThread.commentThreadTargets + ?.filter((relation) => relation.commentableType === 'Company') + .map((relation) => relation.commentableId); + + // const personIds = commentThread.commentThreadTargets + // ?.filter((relation) => relation.commentableType === 'Person') + // .map((relation) => relation.commentableId); + + const { data: dataForChips } = useSearchCompanyQueryQuery({ + variables: { + where: { + id: { + in: companyIds, + }, + }, + }, + }); + + const { data: dataForSelect } = useSearchCompanyQueryQuery({ + variables: { + where: { + name: { + contains: `%${searchFilter}%`, + mode: QueryMode.Insensitive, + }, + }, + limit: 5, + }, + }); + + function handleFilterChange(event: React.ChangeEvent) { + debouncedSetSearchFilter(event.currentTarget.value); + } + + function handleChangeRelationsClick() { + setIsMenuOpen((isOpen) => !isOpen); + } + + const companiesForChips = dataForChips?.searchResults ?? []; + const companiesForSelect = dataForSelect?.searchResults ?? []; + + return ( + + + Relations + + {companiesForChips?.map((company) => ( + + ))} + + {/* + + */} + {isMenuOpen && ( + + + + + {companiesForSelect?.slice(0, 5)?.map((company) => ( + companyForChip.id) + ?.includes(company.id) ?? false + } + onChange={(newCheckedValue) => { + if (newCheckedValue) { + } + }} + > + + {company.name} + + ))} + {companiesForSelect?.length === 0 && ( + No result + )} + + + )} + + ); +} diff --git a/front/src/modules/comments/components/comments/__stories__/CommentThreadRelationPicker.stories.tsx b/front/src/modules/comments/components/comments/__stories__/CommentThreadRelationPicker.stories.tsx new file mode 100644 index 000000000..61f778657 --- /dev/null +++ b/front/src/modules/comments/components/comments/__stories__/CommentThreadRelationPicker.stories.tsx @@ -0,0 +1,31 @@ +import styled from '@emotion/styled'; +import type { Meta, StoryObj } from '@storybook/react'; + +import { graphqlMocks } from '~/testing/graphqlMocks'; +import { mockedCommentThreads } from '~/testing/mock-data/comment-threads'; +import { getRenderWrapperForComponent } from '~/testing/renderWrappers'; + +import { CommentThreadRelationPicker } from '../CommentThreadRelationPicker'; + +const meta: Meta = { + title: 'Comments/CommentThreadRelationPicker', + component: CommentThreadRelationPicker, + parameters: { + msw: graphqlMocks, + }, +}; + +const StyledContainer = styled.div` + width: 400px; +`; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + render: getRenderWrapperForComponent( + + + , + ), +}; diff --git a/front/src/modules/comments/services/select.ts b/front/src/modules/comments/services/select.ts index edad8ca75..d914fd0ed 100644 --- a/front/src/modules/comments/services/select.ts +++ b/front/src/modules/comments/services/select.ts @@ -25,6 +25,10 @@ export const GET_COMMENT_THREADS_BY_TARGETS = gql` avatarUrl } } + commentThreadTargets { + commentableId + commentableType + } } } `; @@ -44,6 +48,10 @@ export const GET_COMMENT_THREAD = gql` avatarUrl } } + commentThreadTargets { + commentableId + commentableType + } } } `; diff --git a/front/src/modules/companies/components/CompanyChip.tsx b/front/src/modules/companies/components/CompanyChip.tsx index 3d1dd7984..d4618e881 100644 --- a/front/src/modules/companies/components/CompanyChip.tsx +++ b/front/src/modules/companies/components/CompanyChip.tsx @@ -1,6 +1,7 @@ -import * as React from 'react'; import styled from '@emotion/styled'; +import { Avatar } from '@/users/components/Avatar'; + export type CompanyChipPropsType = { name: string; picture?: string; @@ -15,6 +16,8 @@ const StyledContainer = styled.span` gap: ${(props) => props.theme.spacing(1)}; padding: ${(props) => props.theme.spacing(1)}; + user-select: none; + :hover { filter: brightness(95%); } @@ -30,10 +33,11 @@ function CompanyChip({ name, picture }: CompanyChipPropsType) { return ( {picture && ( - {`${name}-company-logo`} )} {name} diff --git a/front/src/modules/ui/components/form/Checkbox.tsx b/front/src/modules/ui/components/form/Checkbox.tsx index 146260db1..955792755 100644 --- a/front/src/modules/ui/components/form/Checkbox.tsx +++ b/front/src/modules/ui/components/form/Checkbox.tsx @@ -2,8 +2,8 @@ import * as React from 'react'; import styled from '@emotion/styled'; type OwnProps = { - name: string; - id: string; + name?: string; + id?: string; checked?: boolean; indeterminate?: boolean; onChange?: (newCheckedValue: boolean) => void; diff --git a/front/src/modules/ui/components/menu/DropdownMenu.tsx b/front/src/modules/ui/components/menu/DropdownMenu.tsx index 1b83a562e..8e2bb7103 100644 --- a/front/src/modules/ui/components/menu/DropdownMenu.tsx +++ b/front/src/modules/ui/components/menu/DropdownMenu.tsx @@ -17,4 +17,6 @@ export const DropdownMenu = styled.div` height: fit-content; width: 200px; + + z-index: ${(props) => props.theme.lastLayerZIndex}; `; diff --git a/front/src/modules/ui/components/menu/DropdownMenuCheckableItem.tsx b/front/src/modules/ui/components/menu/DropdownMenuCheckableItem.tsx index e1968d2d8..1202c40cc 100644 --- a/front/src/modules/ui/components/menu/DropdownMenuCheckableItem.tsx +++ b/front/src/modules/ui/components/menu/DropdownMenuCheckableItem.tsx @@ -8,7 +8,7 @@ import { DropdownMenuButton } from './DropdownMenuButton'; type Props = { checked: boolean; onChange?: (newCheckedValue: boolean) => void; - id: string; + id?: string; }; const DropdownMenuCheckableItemContainer = styled(DropdownMenuButton)` diff --git a/front/src/modules/ui/components/menu/stories/DropdownMenu.stories.tsx b/front/src/modules/ui/components/menu/stories/DropdownMenu.stories.tsx index ac47d2da5..cc9c40325 100644 --- a/front/src/modules/ui/components/menu/stories/DropdownMenu.stories.tsx +++ b/front/src/modules/ui/components/menu/stories/DropdownMenu.stories.tsx @@ -25,8 +25,10 @@ type Story = StoryObj; const FakeContentBelow = () => (
- askjdlaksjdlaksjdlakjsdlkj lkajsldkjalskd jalksdj alksjd alskjd alksjd - alksjd laksjd askjdlaksjdlaksjdlakjsdlkj lkajsldkjalskd jalksdj alksjd + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, + quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat.
); @@ -217,7 +219,7 @@ const FakeSelectableMenuItemWithAvatarList = () => { onClick={() => setSelectedItem(item.id)} > { }} > ; +} diff --git a/front/src/modules/ui/icons/index.ts b/front/src/modules/ui/icons/index.ts index 4afa2a893..016e11f81 100644 --- a/front/src/modules/ui/icons/index.ts +++ b/front/src/modules/ui/icons/index.ts @@ -26,3 +26,4 @@ export { IconChevronDown } from '@tabler/icons-react'; export { IconArrowNarrowDown } from '@tabler/icons-react'; export { IconArrowNarrowUp } from '@tabler/icons-react'; export { IconArrowRight } from '@tabler/icons-react'; +export { IconArrowUpRight } from '@tabler/icons-react'; diff --git a/front/src/modules/ui/layout/styles/themes.ts b/front/src/modules/ui/layout/styles/themes.ts index e47e580ee..9f1c3ae00 100644 --- a/front/src/modules/ui/layout/styles/themes.ts +++ b/front/src/modules/ui/layout/styles/themes.ts @@ -54,7 +54,7 @@ const lightThemeSpecific = { lighterBackgroundTransparent: 'rgba(0, 0, 0, 0.02)', primaryBorder: 'rgba(0, 0, 0, 0.08)', - lightBorder: '#f5f5f5', + lightBorder: 'rgba(245, 245, 245, 1)', mediumBorder: '#ebebeb', clickableElementBackgroundTransition: 'background 0.1s ease', diff --git a/front/src/modules/users/components/Avatar.tsx b/front/src/modules/users/components/Avatar.tsx index fee7729d5..77a0fab30 100644 --- a/front/src/modules/users/components/Avatar.tsx +++ b/front/src/modules/users/components/Avatar.tsx @@ -5,26 +5,30 @@ import { isNonEmptyString } from '@/utils/type-guards/isNonEmptyString'; type OwnProps = { avatarUrl: string | null | undefined; size: number; - placeholderLetter: string; + placeholder: string; type?: 'squared' | 'rounded'; }; -export const StyledAvatar = styled.div>` - align-items: center; +export const StyledAvatar = styled.div>` background-color: ${(props) => !isNonEmptyString(props.avatarUrl) ? props.theme.tertiaryBackground : 'none'}; background-image: url(${(props) => isNonEmptyString(props.avatarUrl) ? props.avatarUrl : 'none'}); + background-image: url(${(props) => + isNonEmptyString(props.avatarUrl) ? props.avatarUrl : 'none'}); background-position: center center; background-repeat: no-repeat; background-size: cover; border-radius: ${(props) => (props.type === 'rounded' ? '50%' : '2px')}; + border-radius: ${(props) => (props.type === 'rounded' ? '50%' : '2px')}; display: flex; - height: ${(props) => props.size}px; + height: ${(props) => props.size}px; + justify-content: center; + width: ${(props) => props.size}px; width: ${(props) => props.size}px; `; @@ -50,7 +54,7 @@ export const StyledPlaceholderLetter = styled.div` export function Avatar({ avatarUrl, size, - placeholderLetter, + placeholder, type = 'squared', }: OwnProps) { const noAvatarUrl = !isNonEmptyString(avatarUrl); @@ -59,7 +63,7 @@ export function Avatar({ {noAvatarUrl && ( - {placeholderLetter} + {placeholder[0]?.toLocaleUpperCase()} )} diff --git a/front/src/modules/users/components/__stories__/Avatar.stories.tsx b/front/src/modules/users/components/__stories__/Avatar.stories.tsx index c933efd58..6f610ec4b 100644 --- a/front/src/modules/users/components/__stories__/Avatar.stories.tsx +++ b/front/src/modules/users/components/__stories__/Avatar.stories.tsx @@ -17,34 +17,24 @@ const avatarUrl = export const Rounded: Story = { render: getRenderWrapperForComponent( - , + , ), }; export const Squared: Story = { render: getRenderWrapperForComponent( - , + , ), }; export const NoAvatarPictureRounded: Story = { render: getRenderWrapperForComponent( - , + , ), }; export const NoAvatarPictureSquared: Story = { render: getRenderWrapperForComponent( - , + , ), }; diff --git a/front/src/testing/mock-data/comment-threads.ts b/front/src/testing/mock-data/comment-threads.ts new file mode 100644 index 000000000..a8e7e1039 --- /dev/null +++ b/front/src/testing/mock-data/comment-threads.ts @@ -0,0 +1,76 @@ +import { CommentableType, CommentThread } from '~/generated/graphql'; + +export const mockedCommentThreads: Array = [ + { + id: '89bb825c-171e-4bcc-9cf7-43448d6fb230', + createdAt: '2023-04-26T10:12:42.33625+00:00', + updatedAt: '2023-04-26T10:23:42.33625+00:00', + commentThreadTargets: [ + { + id: '89bb825c-171e-4bcc-9cf7-43448d6fb300', + createdAt: '2023-04-26T10:12:42.33625+00:00', + updatedAt: '2023-04-26T10:23:42.33625+00:00', + commentableType: CommentableType.Company, + commentableId: '89bb825c-171e-4bcc-9cf7-43448d6fb278', // airbnb + commentThreadId: '89bb825c-171e-4bcc-9cf7-43448d6fb230', + commentThread: { + id: '89bb825c-171e-4bcc-9cf7-43448d6fb230', + createdAt: '2023-04-26T10:12:42.33625+00:00', + updatedAt: '2023-04-26T10:23:42.33625+00:00', + }, + __typename: 'CommentThreadTarget', + }, + { + id: '89bb825c-171e-4bcc-9cf7-43448d6fb301', + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + commentableType: CommentableType.Company, + commentableId: 'b396e6b9-dc5c-4643-bcff-61b6cf7523ae', // aircall + commentThreadId: '89bb825c-171e-4bcc-9cf7-43448d6fb231', + commentThread: { + id: '89bb825c-171e-4bcc-9cf7-43448d6fb231', + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }, + __typename: 'CommentThreadTarget', + }, + ], + __typename: 'CommentThread', + }, + { + id: '89bb825c-171e-4bcc-9cf7-43448d6fb278', + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + commentThreadTargets: [ + { + id: '89bb825c-171e-4bcc-9cf7-43448d6fb278', + createdAt: '2023-04-26T10:12:42.33625+00:00', + updatedAt: '2023-04-26T10:23:42.33625+00:00', + commentableType: CommentableType.Person, + commentableId: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b', // Alexandre + commentThreadId: '89bb825c-171e-4bcc-9cf7-43448d6fb278', + commentThread: { + id: '89bb825c-171e-4bcc-9cf7-43448d6fb278', + createdAt: '2023-04-26T10:12:42.33625+00:00', + updatedAt: '2023-04-26T10:23:42.33625+00:00', + }, + __typename: 'CommentThreadTarget', + }, + { + id: '89bb825c-171e-4bcc-9cf7-43448d6fb278', + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + commentableType: CommentableType.Person, + commentableId: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6d', // Jean d'Eau + commentThreadId: '89bb825c-171e-4bcc-9cf7-43448d6fb278', + commentThread: { + id: '89bb825c-171e-4bcc-9cf7-43448d6fb278', + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }, + __typename: 'CommentThreadTarget', + }, + ], + __typename: 'CommentThread', + }, +]; diff --git a/front/src/testing/mock-data/index.ts b/front/src/testing/mock-data/index.ts index 76b8cdf6a..97b71bb16 100644 --- a/front/src/testing/mock-data/index.ts +++ b/front/src/testing/mock-data/index.ts @@ -52,6 +52,11 @@ function filterData( filterElement.contains.replaceAll('%', '').toLocaleLowerCase(), ); } + if (filterElement.in) { + const itemValue = item[key as keyof typeof item] as string; + + return filterElement.in.includes(itemValue); + } } return false; }); diff --git a/front/yarn.lock b/front/yarn.lock index 86107293f..392a8dc88 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -1881,13 +1881,29 @@ resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.3.0.tgz#113bc85fa102cf890ae801668f43ee265c547a09" integrity sha512-vX1WVAdPjZg9DkDkC+zEx/tKtnST6/qcNpwcjeBgco3XRNHz5PUA+ivi/yr6G3o0kMR60uKBJcfOdfzOFI7PMQ== -"@floating-ui/dom@^1.0.0": +"@floating-ui/dom@^1.0.0", "@floating-ui/dom@^1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.3.0.tgz#69456f2164fc3d33eb40837686eaf71537235ac9" integrity sha512-qIAwejE3r6NeA107u4ELDKkH8+VtgRKdXqtSPaKflL2S2V+doyN+Wt9s5oHKXPDo4E8TaVXaHT3+6BbagH31xw== dependencies: "@floating-ui/core" "^1.3.0" +"@floating-ui/react-dom@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.0.1.tgz#7972a4fc488a8c746cded3cfe603b6057c308a91" + integrity sha512-rZtAmSht4Lry6gdhAJDrCp/6rKN7++JnL1/Anbr/DdeyYXQPxvg/ivrbYvJulbRf4vL8b212suwMM2lxbv+RQA== + dependencies: + "@floating-ui/dom" "^1.3.0" + +"@floating-ui/react@^0.24.3": + version "0.24.3" + resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.24.3.tgz#4f11f09c7245555724f5167dd6925133457db89c" + integrity sha512-wWC9duiog4HmbgKSKObDRuXqMjZR/6m75MIG+slm5CVWbridAjK9STcnCsGYmdpK78H/GmzYj4ADVP8paZVLYQ== + dependencies: + "@floating-ui/react-dom" "^2.0.1" + aria-hidden "^1.1.3" + tabbable "^6.0.1" + "@graphql-codegen/cli@^3.3.1": version "3.3.1" resolved "https://registry.yarnpkg.com/@graphql-codegen/cli/-/cli-3.3.1.tgz#103e7a2263126fdde168a1ce623fc2bdc05352f0" @@ -5437,7 +5453,7 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -aria-hidden@^1.1.1: +aria-hidden@^1.1.1, aria-hidden@^1.1.3: version "1.2.3" resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.3.tgz#14aeb7fb692bbb72d69bebfa47279c1fd725e954" integrity sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ== @@ -15557,6 +15573,11 @@ synchronous-promise@^2.0.15: resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.17.tgz#38901319632f946c982152586f2caf8ddc25c032" integrity sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g== +tabbable@^6.0.1: + version "6.1.2" + resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-6.1.2.tgz#b0d3ca81d582d48a80f71b267d1434b1469a3703" + integrity sha512-qCN98uP7i9z0fIS4amQ5zbGBOq+OSigYeGvPy7NDk8Y9yncqDZ9pRPgfsc2PJIVM9RrJj7GIfuRgmjoUU9zTHQ== + tailwindcss@^3.0.2: version "3.3.2" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.3.2.tgz#2f9e35d715fdf0bbf674d90147a0684d7054a2d3" diff --git a/server/src/api/resolvers/comment-thread.resolver.ts b/server/src/api/resolvers/comment-thread.resolver.ts index c76785465..aa3ee2dd3 100644 --- a/server/src/api/resolvers/comment-thread.resolver.ts +++ b/server/src/api/resolvers/comment-thread.resolver.ts @@ -65,15 +65,6 @@ export class CommentThreadResolver { } return createdCommentThread; - - // return this.prismaService.commentThread.create({ - // data: { - // ...args.data, - // ...{ commentThreadTargets: undefined }, - // ...{ comments: { createMany: { data: newCommentData } } }, - // ...{ workspace: { connect: { id: workspace.id } } }, - // }, - // }); } @Query(() => [CommentThread]) @@ -86,6 +77,7 @@ export class CommentThreadResolver { args, workspace, ); + const result = await this.prismaService.commentThread.findMany( preparedArgs, ); diff --git a/server/src/api/resolvers/relations/comment-thread-relations.resolver.ts b/server/src/api/resolvers/relations/comment-thread-relations.resolver.ts index 08001717d..4077d4783 100644 --- a/server/src/api/resolvers/relations/comment-thread-relations.resolver.ts +++ b/server/src/api/resolvers/relations/comment-thread-relations.resolver.ts @@ -1,4 +1,5 @@ import * as TypeGraphQL from '@nestjs/graphql'; +import { CommentThreadTarget } from 'src/api/@generated/comment-thread-target/comment-thread-target.model'; import { CommentThread } from 'src/api/@generated/comment-thread/comment-thread.model'; import { Comment } from 'src/api/@generated/comment/comment.model'; import { PrismaService } from 'src/database/prisma.service'; @@ -23,4 +24,21 @@ export class CommentThreadRelationsResolver { }, }); } + + @TypeGraphQL.ResolveField(() => [CommentThreadTarget], { + nullable: true, + }) + async commentThreadTargets( + @TypeGraphQL.Root() commentThread: CommentThread, + ): Promise { + return this.prismaService.commentThreadTarget.findMany({ + where: { + commentThreadId: commentThread.id, + }, + orderBy: { + // TODO: find a way to pass it in the query + createdAt: 'desc', + }, + }); + } }