diff --git a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableURLCell.tsx b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableURLCell.tsx
index aadf2f4cfd..7a080f7811 100644
--- a/front/src/modules/ui/table/editable-cell/type/components/GenericEditableURLCell.tsx
+++ b/front/src/modules/ui/table/editable-cell/type/components/GenericEditableURLCell.tsx
@@ -8,6 +8,7 @@ import {
ViewFieldDefinition,
ViewFieldURLMetadata,
} from '@/ui/table/types/ViewField';
+import { sanitizeURL } from '~/utils';
import { GenericEditableURLCellEditMode } from './GenericEditableURLCellEditMode';
@@ -33,7 +34,9 @@ export function GenericEditableURLCell({
}
- nonEditModeContent={}
+ nonEditModeContent={
+
+ }
>
);
}
diff --git a/front/src/modules/users/components/Avatar.tsx b/front/src/modules/users/components/Avatar.tsx
index cf7b9ab473..25718306c2 100644
--- a/front/src/modules/users/components/Avatar.tsx
+++ b/front/src/modules/users/components/Avatar.tsx
@@ -1,3 +1,4 @@
+import { useEffect, useState } from 'react';
import styled from '@emotion/styled';
import { isNonEmptyString } from '~/utils/isNonEmptyString';
@@ -86,6 +87,20 @@ export function Avatar({
type = 'squared',
}: OwnProps) {
const noAvatarUrl = !isNonEmptyString(avatarUrl);
+ const [isInvalidAvatarUrl, setIsInvalidAvatarUrl] = useState(false);
+
+ useEffect(() => {
+ if (avatarUrl) {
+ new Promise((resolve) => {
+ const img = new Image();
+ img.onload = () => resolve(false);
+ img.onerror = () => resolve(true);
+ img.src = getImageAbsoluteURIOrBase64(avatarUrl) as string;
+ }).then((res) => {
+ setIsInvalidAvatarUrl(res as boolean);
+ });
+ }
+ }, [avatarUrl]);
return (
- {noAvatarUrl && placeholder[0]?.toLocaleUpperCase()}
+ {(noAvatarUrl || isInvalidAvatarUrl) &&
+ placeholder[0]?.toLocaleUpperCase()}
);
}
diff --git a/front/src/utils/__tests__/utils.test.ts b/front/src/utils/__tests__/utils.test.ts
index 8ac6b54752..9fa996f498 100644
--- a/front/src/utils/__tests__/utils.test.ts
+++ b/front/src/utils/__tests__/utils.test.ts
@@ -1,21 +1,49 @@
-import { getLogoUrlFromDomainName } from '..';
+import { getLogoUrlFromDomainName, sanitizeURL } from '..';
+
+describe('sanitizeURL', () => {
+ test('should sanitize the URL correctly', () => {
+ expect(sanitizeURL('http://example.com/')).toBe('example.com');
+ expect(sanitizeURL('https://www.example.com/')).toBe('example.com');
+ expect(sanitizeURL('www.example.com')).toBe('example.com');
+ expect(sanitizeURL('example.com')).toBe('example.com');
+ expect(sanitizeURL('example.com/')).toBe('example.com');
+ });
+
+ test('should handle undefined input', () => {
+ expect(sanitizeURL(undefined)).toBe('');
+ });
+});
describe('getLogoUrlFromDomainName', () => {
- it(`should generate logo url if undefined `, () => {
+ test('should return the correct logo URL for a given domain', () => {
+ expect(getLogoUrlFromDomainName('example.com')).toBe(
+ 'https://favicon.twenty.com/example.com',
+ );
+
+ expect(getLogoUrlFromDomainName('http://example.com/')).toBe(
+ 'https://favicon.twenty.com/example.com',
+ );
+
+ expect(getLogoUrlFromDomainName('https://www.example.com/')).toBe(
+ 'https://favicon.twenty.com/example.com',
+ );
+
+ expect(getLogoUrlFromDomainName('www.example.com')).toBe(
+ 'https://favicon.twenty.com/example.com',
+ );
+
+ expect(getLogoUrlFromDomainName('example.com/')).toBe(
+ 'https://favicon.twenty.com/example.com',
+ );
+
+ expect(getLogoUrlFromDomainName('apple.com')).toBe(
+ 'https://favicon.twenty.com/apple.com',
+ );
+ });
+
+ test('should handle undefined input', () => {
expect(getLogoUrlFromDomainName(undefined)).toBe(
- 'https://api.faviconkit.com/undefined/144',
- );
- });
-
- it(`should generate logo url if defined `, () => {
- expect(getLogoUrlFromDomainName('test.com')).toBe(
- 'https://api.faviconkit.com/test.com/144',
- );
- });
-
- it(`should generate logo url if empty `, () => {
- expect(getLogoUrlFromDomainName('')).toBe(
- 'https://api.faviconkit.com//144',
+ 'https://favicon.twenty.com/',
);
});
});
diff --git a/front/src/utils/index.ts b/front/src/utils/index.ts
index fcab4d1e0b..ed5a6745c7 100644
--- a/front/src/utils/index.ts
+++ b/front/src/utils/index.ts
@@ -10,6 +10,15 @@ export function formatToHumanReadableDate(date: Date | string) {
}).format(parsedJSDate);
}
-export const getLogoUrlFromDomainName = (domainName?: string): string => {
- return `https://api.faviconkit.com/${domainName}/144`;
-};
+export function sanitizeURL(link: string | null | undefined) {
+ return link
+ ? link.replace(/(https?:\/\/)|(www\.)/g, '').replace(/\/$/, '')
+ : '';
+}
+
+export function getLogoUrlFromDomainName(
+ domainName?: string,
+): string | undefined {
+ const sanitizedDomain = sanitizeURL(domainName);
+ return `https://favicon.twenty.com/${sanitizedDomain}`;
+}