diff --git a/front/package.json b/front/package.json index 88ac53033..e0dcee673 100644 --- a/front/package.json +++ b/front/package.json @@ -13,7 +13,7 @@ "@floating-ui/react": "^0.24.3", "@hello-pangea/dnd": "^16.2.0", "@hookform/resolvers": "^3.1.1", - "@tabler/icons-react": "^2.20.0", + "@tabler/icons-react": "^2.30.0", "@types/node": "^16.18.4", "@types/react": "^18.0.25", "@types/react-dom": "^18.0.9", diff --git a/front/src/generated/graphql.tsx b/front/src/generated/graphql.tsx index c433c6e55..f7c6095d0 100644 --- a/front/src/generated/graphql.tsx +++ b/front/src/generated/graphql.tsx @@ -1250,6 +1250,7 @@ export type Person = { linkedinUrl?: Maybe; phone?: Maybe; updatedAt: Scalars['DateTime']; + xUrl?: Maybe; }; export type PersonCreateInput = { @@ -1268,6 +1269,7 @@ export type PersonCreateInput = { linkedinUrl?: InputMaybe; phone?: InputMaybe; updatedAt?: InputMaybe; + xUrl?: InputMaybe; }; export type PersonCreateNestedManyWithoutCompanyInput = { @@ -1313,6 +1315,7 @@ export type PersonOrderByWithRelationInput = { linkedinUrl?: InputMaybe; phone?: InputMaybe; updatedAt?: InputMaybe; + xUrl?: InputMaybe; }; export type PersonRelationFilter = { @@ -1334,7 +1337,8 @@ export enum PersonScalarFieldEnum { LinkedinUrl = 'linkedinUrl', Phone = 'phone', UpdatedAt = 'updatedAt', - WorkspaceId = 'workspaceId' + WorkspaceId = 'workspaceId', + XUrl = 'xUrl' } export type PersonUpdateInput = { @@ -1353,6 +1357,7 @@ export type PersonUpdateInput = { linkedinUrl?: InputMaybe; phone?: InputMaybe; updatedAt?: InputMaybe; + xUrl?: InputMaybe; }; export type PersonUpdateManyWithoutCompanyNestedInput = { @@ -1397,6 +1402,7 @@ export type PersonWhereInput = { linkedinUrl?: InputMaybe; phone?: InputMaybe; updatedAt?: InputMaybe; + xUrl?: InputMaybe; }; export type PersonWhereUniqueInput = { @@ -2510,7 +2516,7 @@ export type GetPeopleQueryVariables = Exact<{ }>; -export type GetPeopleQuery = { __typename?: 'Query', people: Array<{ __typename?: 'Person', id: string, phone?: string | null, email?: string | null, city?: string | null, firstName?: string | null, lastName?: string | null, displayName: string, jobTitle?: string | null, linkedinUrl?: string | null, avatarUrl?: string | null, createdAt: string, _activityCount: number, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null }> }; +export type GetPeopleQuery = { __typename?: 'Query', people: Array<{ __typename?: 'Person', id: string, phone?: string | null, email?: string | null, city?: string | null, firstName?: string | null, lastName?: string | null, displayName: string, jobTitle?: string | null, linkedinUrl?: string | null, xUrl?: string | null, avatarUrl?: string | null, createdAt: string, _activityCount: number, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null }> }; export type GetPersonPhoneByIdQueryVariables = Exact<{ id: Scalars['String']; @@ -2566,7 +2572,7 @@ export type GetPersonQueryVariables = Exact<{ }>; -export type GetPersonQuery = { __typename?: 'Query', findUniquePerson: { __typename?: 'Person', id: string, firstName?: string | null, lastName?: string | null, displayName: string, email?: string | null, createdAt: string, city?: string | null, jobTitle?: string | null, linkedinUrl?: string | null, avatarUrl?: string | null, phone?: string | null, _activityCount: number, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null } }; +export type GetPersonQuery = { __typename?: 'Query', findUniquePerson: { __typename?: 'Person', id: string, firstName?: string | null, lastName?: string | null, displayName: string, email?: string | null, createdAt: string, city?: string | null, jobTitle?: string | null, linkedinUrl?: string | null, xUrl?: string | null, avatarUrl?: string | null, phone?: string | null, _activityCount: number, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null } }; export type UpdateOnePersonMutationVariables = Exact<{ where: PersonWhereUniqueInput; @@ -2574,14 +2580,14 @@ export type UpdateOnePersonMutationVariables = Exact<{ }>; -export type UpdateOnePersonMutation = { __typename?: 'Mutation', updateOnePerson?: { __typename?: 'Person', id: string, city?: string | null, email?: string | null, jobTitle?: string | null, linkedinUrl?: string | null, firstName?: string | null, lastName?: string | null, displayName: string, phone?: string | null, createdAt: string, company?: { __typename?: 'Company', domainName: string, name: string, id: string } | null } | null }; +export type UpdateOnePersonMutation = { __typename?: 'Mutation', updateOnePerson?: { __typename?: 'Person', id: string, city?: string | null, email?: string | null, jobTitle?: string | null, linkedinUrl?: string | null, xUrl?: string | null, firstName?: string | null, lastName?: string | null, displayName: string, phone?: string | null, createdAt: string, company?: { __typename?: 'Company', domainName: string, name: string, id: string } | null } | null }; export type InsertOnePersonMutationVariables = Exact<{ data: PersonCreateInput; }>; -export type InsertOnePersonMutation = { __typename?: 'Mutation', createOnePerson: { __typename?: 'Person', id: string, city?: string | null, email?: string | null, firstName?: string | null, lastName?: string | null, jobTitle?: string | null, linkedinUrl?: string | null, displayName: string, phone?: string | null, createdAt: string, company?: { __typename?: 'Company', domainName: string, name: string, id: string } | null } }; +export type InsertOnePersonMutation = { __typename?: 'Mutation', createOnePerson: { __typename?: 'Person', id: string, city?: string | null, email?: string | null, firstName?: string | null, lastName?: string | null, jobTitle?: string | null, linkedinUrl?: string | null, xUrl?: string | null, displayName: string, phone?: string | null, createdAt: string, company?: { __typename?: 'Company', domainName: string, name: string, id: string } | null } }; export type DeleteManyPersonMutationVariables = Exact<{ ids?: InputMaybe | Scalars['String']>; @@ -3942,6 +3948,7 @@ export const GetPeopleDocument = gql` displayName jobTitle linkedinUrl + xUrl avatarUrl createdAt _activityCount @@ -4254,6 +4261,7 @@ export const GetPersonDocument = gql` city jobTitle linkedinUrl + xUrl avatarUrl phone _activityCount @@ -4306,6 +4314,7 @@ export const UpdateOnePersonDocument = gql` email jobTitle linkedinUrl + xUrl firstName lastName displayName @@ -4356,6 +4365,7 @@ export const InsertOnePersonDocument = gql` lastName jobTitle linkedinUrl + xUrl displayName phone createdAt diff --git a/front/src/modules/people/constants/peopleViewFields.tsx b/front/src/modules/people/constants/peopleViewFields.tsx index d52a086f1..8fb872b82 100644 --- a/front/src/modules/people/constants/peopleViewFields.tsx +++ b/front/src/modules/people/constants/peopleViewFields.tsx @@ -10,6 +10,7 @@ import { } from '@/ui/editable-field/types/ViewField'; import { IconBrandLinkedin, + IconBrandX, IconBriefcase, IconBuildingSkyscraper, IconCalendarEvent, @@ -120,4 +121,16 @@ export const peopleViewFields: ViewFieldDefinition[] = [ placeHolder: 'LinkedIn', }, } satisfies ViewFieldDefinition, + { + id: 'x', + columnLabel: 'X', + columnIcon: , + columnSize: 150, + columnOrder: 9, + metadata: { + type: 'url', + fieldName: 'xUrl', + placeHolder: 'X', + }, + } satisfies ViewFieldDefinition, ]; diff --git a/front/src/modules/people/queries/select.ts b/front/src/modules/people/queries/select.ts index fab383872..3c532687a 100644 --- a/front/src/modules/people/queries/select.ts +++ b/front/src/modules/people/queries/select.ts @@ -30,6 +30,7 @@ export const GET_PEOPLE = gql` displayName jobTitle linkedinUrl + xUrl avatarUrl createdAt _activityCount diff --git a/front/src/modules/people/queries/show.ts b/front/src/modules/people/queries/show.ts index 33939bef8..8e28589ed 100644 --- a/front/src/modules/people/queries/show.ts +++ b/front/src/modules/people/queries/show.ts @@ -14,6 +14,7 @@ export const GET_PERSON = gql` city jobTitle linkedinUrl + xUrl avatarUrl phone _activityCount diff --git a/front/src/modules/people/queries/update.ts b/front/src/modules/people/queries/update.ts index 5c3c31780..91c544f90 100644 --- a/front/src/modules/people/queries/update.ts +++ b/front/src/modules/people/queries/update.ts @@ -16,6 +16,7 @@ export const UPDATE_ONE_PERSON = gql` email jobTitle linkedinUrl + xUrl firstName lastName displayName @@ -40,6 +41,7 @@ export const INSERT_ONE_PERSON = gql` lastName jobTitle linkedinUrl + xUrl displayName phone createdAt diff --git a/front/src/modules/ui/icon/index.ts b/front/src/modules/ui/icon/index.ts index 37cad4639..a8b930519 100644 --- a/front/src/modules/ui/icon/index.ts +++ b/front/src/modules/ui/icon/index.ts @@ -51,5 +51,6 @@ export { IconUserCircle } from '@tabler/icons-react'; export { IconCalendar } from '@tabler/icons-react'; export { IconPencil } from '@tabler/icons-react'; export { IconCircleDot } from '@tabler/icons-react'; +export { IconBrandX } from '@tabler/icons-react'; export { IconTag } from '@tabler/icons-react'; export { IconHelpCircle } from '@tabler/icons-react'; diff --git a/front/src/modules/ui/input/url/components/URLTextInputDisplay.tsx b/front/src/modules/ui/input/url/components/URLTextInputDisplay.tsx index a5b905065..dcdfae21e 100644 --- a/front/src/modules/ui/input/url/components/URLTextInputDisplay.tsx +++ b/front/src/modules/ui/input/url/components/URLTextInputDisplay.tsx @@ -2,6 +2,7 @@ import { MouseEvent } from 'react'; import styled from '@emotion/styled'; import { RoundedLink } from '@/ui/link/components/RoundedLink'; +import { LinkType, SocialLink } from '@/ui/link/components/SocialLink'; const StyledRawLink = styled(RoundedLink)` overflow: hidden; @@ -17,17 +18,40 @@ type OwnProps = { value: string; }; +const checkUrlType = (url: string) => { + if ( + /^(http|https):\/\/(?:www\.)?linkedin.com(\w+:{0,1}\w*@)?(\S+)(:([0-9])+)?(\/|\/([\w#!:.?+=&%@!\-/]))?$/.test( + url, + ) + ) { + return LinkType.LinkedIn; + } + if (url.match(/^((http|https):\/\/)?(?:www\.)?twitter\.com\/(\w+)?$/i)) { + return LinkType.Twitter; + } + + return LinkType.Url; +}; + export function InplaceInputURLDisplayMode({ value }: OwnProps) { function handleClick(event: MouseEvent) { event.stopPropagation(); } - const absoluteUrl = value ? value.startsWith('http') ? value : 'https://' + value : ''; + const type = checkUrlType(absoluteUrl); + + if (type === LinkType.LinkedIn || type === LinkType.Twitter) { + return ( + + {value} + + ); + } return ( {value} diff --git a/front/src/modules/ui/link/components/SocialLink.tsx b/front/src/modules/ui/link/components/SocialLink.tsx new file mode 100644 index 000000000..dd4acb392 --- /dev/null +++ b/front/src/modules/ui/link/components/SocialLink.tsx @@ -0,0 +1,50 @@ +import * as React from 'react'; +import styled from '@emotion/styled'; + +import { RoundedLink } from './RoundedLink'; + +export enum LinkType { + Url = 'url', + LinkedIn = 'linkedin', + Twitter = 'twitter', +} + +type OwnProps = { + href: string; + children?: React.ReactNode; + type?: LinkType; + onClick?: (event: React.MouseEvent) => void; +}; + +const StyledRawLink = styled(RoundedLink)` + overflow: hidden; + + a { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } +`; + +export function SocialLink({ children, href, onClick, type }: OwnProps) { + let displayValue = children; + + if (type === 'linkedin') { + const splitUrl = href.split('/'); + const splitName = splitUrl[4].split('-'); + displayValue = splitName[2] + ? `${splitName[0]}-${splitName[1]}` + : splitName[0]; + } + + if (type === 'twitter') { + const splitUrl = href.split('/'); + displayValue = `@${splitUrl[3]}`; + } + + return ( + + {displayValue} + + ); +} diff --git a/front/src/modules/ui/table/editable-cell/components/EditableCell.tsx b/front/src/modules/ui/table/editable-cell/components/EditableCell.tsx index 530177968..1f41b6bd6 100644 --- a/front/src/modules/ui/table/editable-cell/components/EditableCell.tsx +++ b/front/src/modules/ui/table/editable-cell/components/EditableCell.tsx @@ -1,6 +1,9 @@ -import { ReactElement } from 'react'; +import { ReactElement, useState } from 'react'; import styled from '@emotion/styled'; +import { IconPencil } from '@tabler/icons-react'; +import { motion } from 'framer-motion'; +import { IconButton } from '@/ui/button/components/IconButton'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { CellHotkeyScopeContext } from '../../states/CellHotkeyScopeContext'; @@ -12,6 +15,11 @@ import { EditableCellDisplayMode } from './EditableCellDisplayMode'; import { EditableCellEditMode } from './EditableCellEditMode'; import { EditableCellSoftFocusMode } from './EditableCellSoftFocusMode'; +const StyledEditButtonContainer = styled(motion.div)` + position: absolute; + right: 5px; +`; + export const CellBaseContainer = styled.div` align-items: center; box-sizing: border-box; @@ -48,7 +56,38 @@ export function EditableCell({ transparent = false, maxContentWidth, }: OwnProps) { - const { isCurrentCellInEditMode } = useCurrentCellEditMode(); + const { isCurrentCellInEditMode, setCurrentCellInEditMode } = + useCurrentCellEditMode(); + const [isHovered, setIsHovered] = useState(false); + + function isValidUrl(value: string) { + let testUrl = value; + if (testUrl && !testUrl.startsWith('http')) { + testUrl = 'http://' + testUrl; + } + try { + new URL(testUrl); + return true; + } catch (err) { + return false; + } + } + + const handleClick = () => { + setCurrentCellInEditMode(); + }; + + function handleContainerMouseEnter() { + setIsHovered(true); + } + + function handleContainerMouseLeave() { + setIsHovered(false); + } + + const value = nonEditModeContent.props.value; + const showEditButton = + !isCurrentCellInEditMode && isValidUrl(value) && isHovered; const hasSoftFocus = useIsSoftFocusOnCurrentCell(); @@ -56,7 +95,10 @@ export function EditableCell({ - + {isCurrentCellInEditMode ? ( ) : ( - - {nonEditModeContent} - + <> + {showEditButton && ( + + } + /> + + )} + + + {nonEditModeContent} + + )} diff --git a/front/src/testing/mock-data/people.ts b/front/src/testing/mock-data/people.ts index 3716757f8..95c4c9224 100644 --- a/front/src/testing/mock-data/people.ts +++ b/front/src/testing/mock-data/people.ts @@ -13,6 +13,7 @@ type MockedPerson = RequiredAndNotNull< | 'lastName' | 'displayName' | 'linkedinUrl' + | 'xUrl' | 'jobTitle' | 'email' | '__typename' @@ -35,6 +36,7 @@ export const mockedPeopleData: MockedPerson[] = [ displayName: 'Alexandre Prot', email: 'alexandre@qonto.com', linkedinUrl: 'https://www.linkedin.com/in/alexandreprot/', + xUrl: 'https://twitter.com/alexandreprot', avatarUrl: 'data:image/jpeg;base64,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', jobTitle: 'CEO', @@ -57,6 +59,7 @@ export const mockedPeopleData: MockedPerson[] = [ lastName: 'Doe', displayName: 'John Doe', linkedinUrl: 'https://www.linkedin.com/in/johndoe/', + xUrl: 'https://twitter.com/johndoe', avatarUrl: '', jobTitle: 'CTO', email: 'john@linkedin.com', @@ -79,6 +82,7 @@ export const mockedPeopleData: MockedPerson[] = [ lastName: 'Doe', displayName: 'Jane Doe', linkedinUrl: 'https://www.linkedin.com/in/janedoe/', + xUrl: 'https://twitter.com/janedoe', avatarUrl: '', jobTitle: 'Investor', email: 'jane@sequoiacap.com', @@ -102,6 +106,7 @@ export const mockedPeopleData: MockedPerson[] = [ displayName: 'Janice Dane', email: 'janice@facebook.com', linkedinUrl: 'https://www.linkedin.com/in/janicedane/', + xUrl: 'https://twitter.com/janicedane', avatarUrl: '', jobTitle: 'CEO', company: { diff --git a/front/yarn.lock b/front/yarn.lock index 7adcdb047..66111aee8 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -4716,18 +4716,18 @@ "@svgr/plugin-jsx" "8.0.1" "@svgr/plugin-svgo" "8.0.1" -"@tabler/icons-react@^2.20.0": - version "2.24.0" - resolved "https://registry.yarnpkg.com/@tabler/icons-react/-/icons-react-2.24.0.tgz#86b6c97fdabcfde38c40a9226c9ad95754ee99f0" - integrity sha512-0pNc+ffp4HZCsozv9aN/hSDiC/RTGozTmf0MCL4U9NIo8yMQh8q3zEfXRNr18IM2InyIBJL95/1J2kzgU2lYeA== +"@tabler/icons-react@^2.30.0": + version "2.30.0" + resolved "https://registry.yarnpkg.com/@tabler/icons-react/-/icons-react-2.30.0.tgz#e7ece4b83d6cd66b3a4ec043b89bf18e5341c03e" + integrity sha512-aYggXusHW133L4KujJkVf4GIIrjg7tIRHgNf/n37mnoHqMjwNP+PjmVdrBM1Z8Ywx9PKFRlrwM0eUMDcG+I4HA== dependencies: - "@tabler/icons" "2.24.0" + "@tabler/icons" "2.30.0" prop-types "^15.7.2" -"@tabler/icons@2.24.0": - version "2.24.0" - resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-2.24.0.tgz#d24f7076dab1ad6c6889258ddee3d25f29080539" - integrity sha512-Otv6zrVF3HU54G6FK7OPODcQmKR9KgM6Ppi+ib3gHHB1LZEs2HIdQJYTHP5dGE+yOQWtXS9ZnGmSZDkSFLbkkg== +"@tabler/icons@2.30.0": + version "2.30.0" + resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-2.30.0.tgz#4ea3c4da56fd5653bb9d0be0dc7feaa33602555c" + integrity sha512-tvtmkI4ALjKThVVORh++sB9JnkFY7eGInKxNy+Df7WVQiF7T85tlvGADzlgX4Ic+CK5MIUzZ0jhOlQ/RRlgXpg== "@testing-library/dom@^8.3.0", "@testing-library/dom@^8.5.0": version "8.20.1" diff --git a/server/src/database/migrations/20230803175814_add_twitter_url/migration.sql b/server/src/database/migrations/20230803175814_add_twitter_url/migration.sql new file mode 100644 index 000000000..a57411345 --- /dev/null +++ b/server/src/database/migrations/20230803175814_add_twitter_url/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "people" ADD COLUMN "twitterUrl" TEXT; diff --git a/server/src/database/migrations/20230808152343_rename_twitter_url_to_x_url/migration.sql b/server/src/database/migrations/20230808152343_rename_twitter_url_to_x_url/migration.sql new file mode 100644 index 000000000..4f3993584 --- /dev/null +++ b/server/src/database/migrations/20230808152343_rename_twitter_url_to_x_url/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "people" RENAME COLUMN "twitterUrl" TO "xUrl"; diff --git a/server/src/database/schema.prisma b/server/src/database/schema.prisma index d11279bb3..9e2328895 100644 --- a/server/src/database/schema.prisma +++ b/server/src/database/schema.prisma @@ -266,6 +266,9 @@ model Person { linkedinUrl String? /// @Validator.IsString() /// @Validator.IsOptional() + xUrl String? + /// @Validator.IsString() + /// @Validator.IsOptional() jobTitle String? /// @Validator.IsString() /// @Validator.IsOptional()