Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { isNonEmptyString } from '@sniptt/guards';
import { LinkType, RoundedLink, SocialLink } from 'twenty-ui/navigation';
import { checkUrlType } from '~/utils/checkUrlType';

type LinkDisplayProps = {
value: { url: string; label?: string | null };
Expand All @@ -22,13 +23,13 @@ export const LinkDisplay = ({ value }: LinkDisplayProps) => {
? value.label
: url?.replace(/^http[s]?:\/\/(?:[w]+\.)?/gm, '').replace(/^[w]+\./gm, '');

const type = displayedValue.startsWith('linkedin.')
? LinkType.LinkedIn
: displayedValue.startsWith('twitter.')
? LinkType.Twitter
: LinkType.Url;
const type = checkUrlType(absoluteUrl);

if (type === LinkType.LinkedIn || type === LinkType.Twitter) {
if (
type === LinkType.LinkedIn ||
type === LinkType.Twitter ||
type === LinkType.Facebook
) {
return <SocialLink href={absoluteUrl} type={type} label={displayedValue} />;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ export const LinksDisplay = ({ value, onLinkClick }: LinksDisplayProps) => {
return (
<ExpandableList>
{links.map(({ url, label, type }, index) =>
type === LinkType.LinkedIn || type === LinkType.Twitter ? (
type === LinkType.LinkedIn ||
type === LinkType.Twitter ||
type === LinkType.Facebook ? (
<SocialLink
key={index}
href={url}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ export const URLDisplay = ({ value }: URLDisplayProps) => {

const type = checkUrlType(absoluteUrl);

if (type === LinkType.LinkedIn || type === LinkType.Twitter) {
if (
type === LinkType.LinkedIn ||
type === LinkType.Twitter ||
type === LinkType.Facebook
) {
return (
<EllipsisDisplay>
<SocialLink
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ describe('checkUrlType', () => {
it('should return "url", if neither linkedin nor twitter url', () => {
expect(checkUrlType('https://www.example.com')).toBe('url');
});

it('should return "facebook", if facebook url', () => {
expect(checkUrlType('https://www.facebook.com/john-doe')).toBe('facebook');
});
});

This file was deleted.

3 changes: 3 additions & 0 deletions packages/twenty-front/src/utils/checkUrlType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ export const checkUrlType = (url: string) => {
if (/^(https?:\/\/)?(www\.)?x\.com\/.+$/.test(url)) {
return LinkType.Twitter;
}
if (/^(https?:\/\/)?(www\.)?facebook\.com\/.+$/.test(url)) {
return LinkType.Facebook;
}

return LinkType.Url;
};
34 changes: 0 additions & 34 deletions packages/twenty-front/src/utils/getDisplayValueByUrlType.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export enum LinkType {
Url = 'url',
LinkedIn = 'linkedin',
Twitter = 'twitter',
Facebook = 'facebook',
}

type SocialLinkProps = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { LinkType } from '@ui/navigation/link/components/SocialLink';

import { getDisplayValueByUrlType } from '../getDisplayValueByUrlType';

describe('getDisplayValueByUrlType', () => {
describe('linkedin', () => {
it('should extract username from LinkedIn profile URL', () => {
const result = getDisplayValueByUrlType({
type: LinkType.LinkedIn,
href: 'https://www.linkedin.com/in/johndoe',
});
expect(result).toBe('johndoe');
});

it('should extract company name from LinkedIn company URL', () => {
const result = getDisplayValueByUrlType({
type: LinkType.LinkedIn,
href: 'https://www.linkedin.com/company/acme-corp',
});
expect(result).toBe('acme-corp');
});

it('should extract school name from LinkedIn school URL', () => {
const result = getDisplayValueByUrlType({
type: LinkType.LinkedIn,
href: 'https://www.linkedin.com/school/mit',
});
expect(result).toBe('mit');
});

it('should handle LinkedIn URL without protocol', () => {
const result = getDisplayValueByUrlType({
type: LinkType.LinkedIn,
href: 'linkedin.com/in/johndoe',
});
expect(result).toBe('johndoe');
});

it('should handle LinkedIn URL without www', () => {
const result = getDisplayValueByUrlType({
type: LinkType.LinkedIn,
href: 'https://linkedin.com/in/johndoe',
});
expect(result).toBe('johndoe');
});

it('should decode URL-encoded characters in LinkedIn username', () => {
const result = getDisplayValueByUrlType({
type: LinkType.LinkedIn,
href: 'https://www.linkedin.com/in/john%20doe',
});
expect(result).toBe('john doe');
});

it('should return "LinkedIn" for invalid LinkedIn URLs', () => {
const result = getDisplayValueByUrlType({
type: LinkType.LinkedIn,
href: 'https://www.linkedin.com/feed',
});
expect(result).toBe('LinkedIn');
});
});

describe('twitter', () => {
it('should extract username from Twitter URL with @ prefix', () => {
const result = getDisplayValueByUrlType({
type: LinkType.Twitter,
href: 'https://www.twitter.com/johndoe',
});
expect(result).toBe('@johndoe');
});

it('should handle Twitter URL without protocol', () => {
const result = getDisplayValueByUrlType({
type: LinkType.Twitter,
href: 'twitter.com/johndoe',
});
expect(result).toBe('@johndoe');
});

it('should handle Twitter URL without www', () => {
const result = getDisplayValueByUrlType({
type: LinkType.Twitter,
href: 'https://twitter.com/johndoe',
});
expect(result).toBe('@johndoe');
});

it('should return "@twitter" when no username can be extracted', () => {
const result = getDisplayValueByUrlType({
type: LinkType.Twitter,
href: 'https://www.twitter.com',
});
expect(result).toBe('@twitter');
});
});

describe('facebook', () => {
it('should extract username from Facebook profile URL', () => {
const result = getDisplayValueByUrlType({
type: LinkType.Facebook,
href: 'https://www.facebook.com/johndoe',
});
expect(result).toBe('johndoe');
});

it('should handle Facebook URL without protocol', () => {
const result = getDisplayValueByUrlType({
type: LinkType.Facebook,
href: 'facebook.com/johndoe',
});
expect(result).toBe('johndoe');
});

it('should handle Facebook URL without www', () => {
const result = getDisplayValueByUrlType({
type: LinkType.Facebook,
href: 'https://facebook.com/johndoe',
});
expect(result).toBe('johndoe');
});

it('should decode URL-encoded characters in Facebook username', () => {
const result = getDisplayValueByUrlType({
type: LinkType.Facebook,
href: 'https://www.facebook.com/john%20doe',
});
expect(result).toBe('john doe');
});

it('should return "Facebook" for invalid Facebook URLs', () => {
const result = getDisplayValueByUrlType({
type: LinkType.Facebook,
href: 'https://www.facebook.com/',
});
expect(result).toBe('Facebook');
});
});

describe('url type', () => {
it('should return undefined for generic url type', () => {
const result = getDisplayValueByUrlType({
type: LinkType.Url,
href: 'https://example.com',
});
expect(result).toBeUndefined();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,13 @@ export const getDisplayValueByUrlType = ({
return '@twitter';
}
}

if (type === 'facebook') {
const matches = href.match(/(?:https?:\/\/)?(?:www.)?facebook.com\/(.+)/);
if (isDefined(matches?.[1])) {
return decodeURIComponent(matches?.[1]);
} else {
return 'Facebook';
}
}
};