- Replace avatar image from API with gradient avatar from twake-mui (#457)
- Display 2-letter initials (e.g., "JD" for "John Doe") instead of single letter - Add getInitials helper function in avatarUtils for reusability - Update Avatar in PeopleSearch, CalendarSearch, and Menubar components - Remove avatarUrl prop usage across all Avatar components
This commit is contained in:
@@ -100,7 +100,7 @@ describe("Calendar App Component Display Tests", () => {
|
||||
/>,
|
||||
preloadedState
|
||||
);
|
||||
expect(screen.getByText("t")).toBeInTheDocument();
|
||||
expect(screen.getByText("T")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// Edge cases for avatar display logic
|
||||
@@ -131,7 +131,7 @@ describe("Calendar App Component Display Tests", () => {
|
||||
/>,
|
||||
preloadedState
|
||||
);
|
||||
expect(screen.getByText("t")).toBeInTheDocument();
|
||||
expect(screen.getByText("T")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("handles user with only name", () => {
|
||||
@@ -161,7 +161,7 @@ describe("Calendar App Component Display Tests", () => {
|
||||
/>,
|
||||
preloadedState
|
||||
);
|
||||
expect(screen.getByText("t")).toBeInTheDocument();
|
||||
expect(screen.getByText("T")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("handles user with both name and family_name", () => {
|
||||
@@ -221,7 +221,7 @@ describe("Calendar App Component Display Tests", () => {
|
||||
/>,
|
||||
preloadedState
|
||||
);
|
||||
expect(screen.getByText("t")).toBeInTheDocument();
|
||||
expect(screen.getByText("T")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("handles user with empty email", () => {
|
||||
|
||||
@@ -2032,6 +2032,25 @@ describe("Helper functions", () => {
|
||||
expect(typeof result.color).toBe("string");
|
||||
});
|
||||
|
||||
it("stringAvatar returns 2-letter initials for full name", () => {
|
||||
const result = stringAvatar("John Doe");
|
||||
expect(result.children).toBe("JD");
|
||||
expect(result.color).toBeDefined();
|
||||
expect(typeof result.color).toBe("string");
|
||||
});
|
||||
|
||||
it("stringAvatar handles single word names", () => {
|
||||
const result = stringAvatar("Alice");
|
||||
expect(result.children).toBe("A");
|
||||
expect(result.color).toBeDefined();
|
||||
});
|
||||
|
||||
it("stringAvatar handles email addresses", () => {
|
||||
const result = stringAvatar("test@example.com");
|
||||
expect(result.children).toBe("T");
|
||||
expect(result.color).toBeDefined();
|
||||
});
|
||||
|
||||
it("InfoRow renders text and link if url is valid", () => {
|
||||
renderWithProviders(
|
||||
<InfoRow
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
import { getInitials, stringToGradient } from "../../src/utils/avatarUtils";
|
||||
|
||||
jest.mock("@linagora/twake-mui", () => ({
|
||||
nameToColor: jest.fn((name: string) => {
|
||||
if (!name) return undefined;
|
||||
const colors = [
|
||||
"sunrise",
|
||||
"downy",
|
||||
"sugarCoral",
|
||||
"pinkBonnet",
|
||||
"blueMana",
|
||||
"nightBlue",
|
||||
"snowPea",
|
||||
"pluviophile",
|
||||
"cornflower",
|
||||
"paleGreen",
|
||||
"moonBlue",
|
||||
];
|
||||
const hash = Array.from(name.toUpperCase())
|
||||
.map((letter) => letter.charCodeAt(0))
|
||||
.reduce((sum, number) => sum + number, 0);
|
||||
return colors[hash % colors.length];
|
||||
}),
|
||||
}));
|
||||
|
||||
describe("avatarUtils", () => {
|
||||
describe("getInitials", () => {
|
||||
it("returns 2-letter initials for full name", () => {
|
||||
expect(getInitials("John Doe")).toBe("JD");
|
||||
expect(getInitials("Alice Smith")).toBe("AS");
|
||||
expect(getInitials("Nguyễn Văn")).toBe("NV");
|
||||
});
|
||||
|
||||
it("returns single letter for single word", () => {
|
||||
expect(getInitials("Alice")).toBe("A");
|
||||
expect(getInitials("John")).toBe("J");
|
||||
});
|
||||
|
||||
it("returns uppercase initials", () => {
|
||||
expect(getInitials("john doe")).toBe("JD");
|
||||
expect(getInitials("ALICE SMITH")).toBe("AS");
|
||||
expect(getInitials("a")).toBe("A");
|
||||
});
|
||||
|
||||
it("handles multiple spaces between words", () => {
|
||||
expect(getInitials("John Doe")).toBe("JD");
|
||||
expect(getInitials("Alice Smith Brown")).toBe("AS");
|
||||
});
|
||||
|
||||
it("handles email addresses", () => {
|
||||
expect(getInitials("john.doe@email.com")).toBe("J");
|
||||
expect(getInitials("test@example.com")).toBe("T");
|
||||
});
|
||||
|
||||
it("handles empty string", () => {
|
||||
expect(getInitials("")).toBe("");
|
||||
});
|
||||
|
||||
it("handles whitespace-only string", () => {
|
||||
expect(getInitials(" ")).toBe("");
|
||||
});
|
||||
|
||||
it("handles single character", () => {
|
||||
expect(getInitials("A")).toBe("A");
|
||||
expect(getInitials("a")).toBe("A");
|
||||
});
|
||||
|
||||
it("handles names with special characters", () => {
|
||||
expect(getInitials("Jean-Pierre")).toBe("J");
|
||||
expect(getInitials("Mary Jane Watson")).toBe("MJ");
|
||||
});
|
||||
|
||||
it("handles unicode characters", () => {
|
||||
expect(getInitials("Nguyễn Văn")).toBe("NV");
|
||||
expect(getInitials("José María")).toBe("JM");
|
||||
});
|
||||
|
||||
it("takes first two words for names with more than two words", () => {
|
||||
expect(getInitials("John Michael Smith")).toBe("JM");
|
||||
expect(getInitials("Alice Bob Charlie")).toBe("AB");
|
||||
});
|
||||
});
|
||||
|
||||
describe("stringToGradient", () => {
|
||||
it("returns color for valid string", () => {
|
||||
const result = stringToGradient("John Doe");
|
||||
expect(result).toBeDefined();
|
||||
expect(typeof result).toBe("string");
|
||||
});
|
||||
|
||||
it("returns same color for same input", () => {
|
||||
const result1 = stringToGradient("John Doe");
|
||||
const result2 = stringToGradient("John Doe");
|
||||
expect(result1).toBe(result2);
|
||||
});
|
||||
|
||||
it("returns undefined for empty string", () => {
|
||||
expect(stringToGradient("")).toBeUndefined();
|
||||
});
|
||||
|
||||
it("returns color for single character", () => {
|
||||
const result = stringToGradient("A");
|
||||
expect(result).toBeDefined();
|
||||
expect(typeof result).toBe("string");
|
||||
});
|
||||
|
||||
it("returns color for email address", () => {
|
||||
const result = stringToGradient("test@example.com");
|
||||
expect(result).toBeDefined();
|
||||
expect(typeof result).toBe("string");
|
||||
});
|
||||
});
|
||||
});
|
||||
Generated
+41
-3
@@ -138,6 +138,7 @@
|
||||
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
"@babel/generator": "^7.28.5",
|
||||
@@ -2070,6 +2071,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
@@ -2093,6 +2095,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
@@ -2195,6 +2198,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
|
||||
"integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.18.3",
|
||||
"@emotion/babel-plugin": "^11.13.5",
|
||||
@@ -2238,6 +2242,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz",
|
||||
"integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.18.3",
|
||||
"@emotion/babel-plugin": "^11.13.5",
|
||||
@@ -2510,6 +2515,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@fullcalendar/core/-/core-6.1.20.tgz",
|
||||
"integrity": "sha512-1cukXLlePFiJ8YKXn/4tMKsy0etxYLCkXk8nUCFi11nRONF2Ba2CD5b21/ovtOO2tL6afTJfwmc1ed3HG7eB1g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"preact": "~10.12.1"
|
||||
}
|
||||
@@ -3136,6 +3142,7 @@
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://npm.pkg.github.com/download/@linagora/twake-mui/1.1.3/c8ed9f2e04beaf55c1cfd1e014d2f43081c975ae",
|
||||
"integrity": "sha512-lLylOmnMOpXRlkFCsKq2Jaf1bfaobQsHz1fvxRIR0MIs8EAy2gyKc/5D22Q/Mqo3aN2zEum9qrd1D030lm8NJg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
@@ -3251,6 +3258,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.6.tgz",
|
||||
"integrity": "sha512-R4DaYF3dgCQCUAkr4wW1w26GHXcf5rCmBRHVBuuvJvaGLmZdD8EjatP80Nz5JCw0KxORAzwftnHzXVnjR8HnFw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.28.4",
|
||||
"@mui/core-downloads-tracker": "^7.3.6",
|
||||
@@ -3361,6 +3369,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@mui/system/-/system-7.3.6.tgz",
|
||||
"integrity": "sha512-8fehAazkHNP1imMrdD2m2hbA9sl7Ur6jfuNweh5o4l9YPty4iaZzRXqYvBCWQNwFaSHmMEj2KPbyXGp7Bt73Rg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.28.4",
|
||||
"@mui/private-theming": "^7.3.6",
|
||||
@@ -3719,6 +3728,7 @@
|
||||
"integrity": "sha512-LvoOF53PL6zXgdzEhgnnP51S4FseDFH1bHrobK4EK6zZX/tN8qgf5tdlmN7h4OkMv/Qs1oUfvj0QcLWSstnnvA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@rspack/core": "1.6.8",
|
||||
"@rspack/lite-tapable": "~1.1.0",
|
||||
@@ -3946,6 +3956,7 @@
|
||||
"integrity": "sha512-FolcIAH5FW4J2FET+qwjd1kNeFbCkd0VLuIHO0thyolEjaPSxw5qxG67DA7BZGm6PVcoiSgPLks1DL6eZ8c+fA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@module-federation/runtime-tools": "0.21.6",
|
||||
"@rspack/binding": "1.6.8",
|
||||
@@ -4205,6 +4216,7 @@
|
||||
"integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.21.3",
|
||||
"@svgr/babel-preset": "8.1.0",
|
||||
@@ -4289,6 +4301,7 @@
|
||||
"integrity": "sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.8.0"
|
||||
}
|
||||
@@ -4299,6 +4312,7 @@
|
||||
"integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.10.4",
|
||||
"@babel/runtime": "^7.12.5",
|
||||
@@ -4594,6 +4608,7 @@
|
||||
"integrity": "sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
@@ -4615,6 +4630,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz",
|
||||
"integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"csstype": "^3.2.2"
|
||||
@@ -4626,6 +4642,7 @@
|
||||
"integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"@types/react": "^18.0.0"
|
||||
}
|
||||
@@ -4682,6 +4699,7 @@
|
||||
"integrity": "sha512-XtssGWJvypyM2ytBnSnKtHYOGT+4ZwTnBVl36TA4nRO2f4PRNGz5/1OszHzcZCvcBMh+qb7I06uoCmLTRdR9og==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.10.0",
|
||||
"@typescript-eslint/scope-manager": "8.51.0",
|
||||
@@ -4711,6 +4729,7 @@
|
||||
"integrity": "sha512-3xP4XzzDNQOIqBMWogftkwxhg5oMKApqY0BAflmLZiFYHqyhSOxv/cd/zPQLTcCXr4AkaKb25joocY0BD1WC6A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.51.0",
|
||||
"@typescript-eslint/types": "8.51.0",
|
||||
@@ -5217,6 +5236,7 @@
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -5976,6 +5996,7 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"baseline-browser-mapping": "^2.9.0",
|
||||
"caniuse-lite": "^1.0.30001759",
|
||||
@@ -6687,6 +6708,7 @@
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
|
||||
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.21.0"
|
||||
},
|
||||
@@ -6702,7 +6724,8 @@
|
||||
"version": "1.11.19",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz",
|
||||
"integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.3",
|
||||
@@ -7301,6 +7324,7 @@
|
||||
"integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
@@ -8655,6 +8679,7 @@
|
||||
"resolved": "https://registry.npmjs.org/history/-/history-5.3.0.tgz",
|
||||
"integrity": "sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.7.6"
|
||||
}
|
||||
@@ -9629,6 +9654,7 @@
|
||||
"integrity": "sha512-F26gjC0yWN8uAA5m5Ss8ZQf5nDHWGlN/xWZIh8S5SRbsEKBovwZhxGd6LJlbZYxBgCYOtreSUyb8hpXyGC5O4A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jest/core": "30.2.0",
|
||||
"@jest/types": "30.2.0",
|
||||
@@ -10392,6 +10418,7 @@
|
||||
"integrity": "sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.19.6",
|
||||
"@svgr/babel-preset": "^6.5.1",
|
||||
@@ -10850,6 +10877,7 @@
|
||||
"integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"cssstyle": "^4.2.1",
|
||||
"data-urls": "^5.0.0",
|
||||
@@ -11286,6 +11314,7 @@
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
@@ -11295,6 +11324,7 @@
|
||||
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz",
|
||||
"integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"moment": "^2.29.4"
|
||||
},
|
||||
@@ -11330,7 +11360,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"nanoid": "bin/nanoid.cjs"
|
||||
},
|
||||
@@ -12279,6 +12308,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
},
|
||||
@@ -12301,6 +12331,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"scheduler": "^0.23.2"
|
||||
@@ -12320,6 +12351,7 @@
|
||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
|
||||
"integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/use-sync-external-store": "^0.0.6",
|
||||
"use-sync-external-store": "^1.4.0"
|
||||
@@ -12344,6 +12376,7 @@
|
||||
"integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -12444,7 +12477,8 @@
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
|
||||
"integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==",
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/redux-first-history": {
|
||||
"version": "5.2.0",
|
||||
@@ -13671,6 +13705,7 @@
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -13851,6 +13886,7 @@
|
||||
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
|
||||
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@cspotcode/source-map-support": "^0.8.0",
|
||||
"@tsconfig/node10": "^1.0.7",
|
||||
@@ -14067,6 +14103,7 @@
|
||||
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -14875,6 +14912,7 @@
|
||||
"integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
ListItemText,
|
||||
TextField,
|
||||
} from "@linagora/twake-mui";
|
||||
import { stringAvatar } from "../Event/utils/eventUtils";
|
||||
import {
|
||||
type ReactNode,
|
||||
useCallback,
|
||||
@@ -287,7 +288,7 @@ export function PeopleSearch({
|
||||
return (
|
||||
<ListItem key={key + option?.email} {...otherProps} disableGutters>
|
||||
<ListItemAvatar>
|
||||
<Avatar src={option.avatarUrl} alt={option.displayName} />
|
||||
<Avatar {...stringAvatar(option.displayName || option.email)} />
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={option.displayName}
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
useTheme,
|
||||
} from "@linagora/twake-mui";
|
||||
import { useI18n } from "twake-i18n";
|
||||
import { stringAvatar } from "../Event/utils/eventUtils";
|
||||
import { useState } from "react";
|
||||
import { useAppDispatch, useAppSelector } from "../../app/hooks";
|
||||
import { getCalendars } from "../../features/Calendars/CalendarApi";
|
||||
@@ -50,8 +51,7 @@ function CalendarItem({
|
||||
>
|
||||
<Box display="flex" alignItems="center" gap={2}>
|
||||
<Avatar
|
||||
src={cal.owner.avatarUrl}
|
||||
alt={cal.owner.email}
|
||||
{...stringAvatar(cal.owner.displayName || cal.owner.email)}
|
||||
style={{
|
||||
border: `2px solid ${cal.cal["apple:color"] || defaultColors[0].light}`,
|
||||
boxShadow: cal.cal["apple:color"]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import CancelIcon from "@mui/icons-material/Cancel";
|
||||
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
|
||||
import { Avatar, Badge, Box, Typography } from "@linagora/twake-mui";
|
||||
import { stringToGradient } from "../../../utils/avatarUtils";
|
||||
import { stringToGradient, getInitials } from "../../../utils/avatarUtils";
|
||||
import { ThunkDispatch } from "@reduxjs/toolkit";
|
||||
import { emptyEventsCal } from "../../../features/Calendars/CalendarSlice";
|
||||
import { getCalendarsListAsync } from "../../../features/Calendars/services/getCalendarsListAsync";
|
||||
@@ -103,7 +103,7 @@ export function stringToColor(string: string) {
|
||||
export function stringAvatar(name: string) {
|
||||
return {
|
||||
color: stringToGradient(name),
|
||||
children: name[0],
|
||||
children: getInitials(name),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import SettingsIcon from "@mui/icons-material/Settings";
|
||||
import LogoutIcon from "@mui/icons-material/Logout";
|
||||
import "./Menubar.styl";
|
||||
import { useAppDispatch, useAppSelector } from "../../app/hooks";
|
||||
import { stringToGradient } from "../../utils/avatarUtils";
|
||||
import { stringToGradient, getInitials } from "../../utils/avatarUtils";
|
||||
import {
|
||||
Avatar,
|
||||
IconButton,
|
||||
@@ -262,19 +262,11 @@ export function Menubar({
|
||||
<div className="menu-items">
|
||||
<IconButton onClick={handleUserMenuClick}>
|
||||
<Avatar
|
||||
color={stringToGradient(
|
||||
user && user.family_name
|
||||
? user.family_name
|
||||
: user && user.email
|
||||
? user.email
|
||||
: ""
|
||||
)}
|
||||
color={stringToGradient(getUserDisplayName(user))}
|
||||
size="m"
|
||||
aria-label={t("menubar.userProfile")}
|
||||
>
|
||||
{user?.name && user?.family_name
|
||||
? `${user.name[0]}${user.family_name[0]}`
|
||||
: (user?.email?.[0] ?? "")}
|
||||
{getInitials(getUserDisplayName(user))}
|
||||
</Avatar>
|
||||
</IconButton>
|
||||
</div>
|
||||
@@ -338,19 +330,11 @@ export function Menubar({
|
||||
}}
|
||||
>
|
||||
<Avatar
|
||||
color={stringToGradient(
|
||||
user && user.family_name
|
||||
? user.family_name
|
||||
: user && user.email
|
||||
? user.email
|
||||
: ""
|
||||
)}
|
||||
color={stringToGradient(getUserDisplayName(user))}
|
||||
size="m"
|
||||
sx={{ marginBottom: "8px" }}
|
||||
>
|
||||
{user?.name && user?.family_name
|
||||
? `${user.name[0]}${user.family_name[0]}`
|
||||
: (user?.email?.[0] ?? "")}
|
||||
{getInitials(getUserDisplayName(user))}
|
||||
</Avatar>
|
||||
<Typography variant="body1" sx={{ fontWeight: 500 }}>
|
||||
{getUserDisplayName(user)}
|
||||
|
||||
@@ -9,3 +9,21 @@ export function stringToGradient(str: string): string | undefined {
|
||||
if (!str) return undefined;
|
||||
return nameToColor(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get initials from a name string (max 2 characters)
|
||||
* @param name - Name string like "John Doe", "Alice", or "john.doe@email.com"
|
||||
* @returns Initials like "JD", "A", or "J"
|
||||
*/
|
||||
export function getInitials(name: string): string {
|
||||
if (!name) return "";
|
||||
|
||||
const trimmed = name.trim();
|
||||
const words = trimmed.split(/\s+/).filter(Boolean);
|
||||
|
||||
if (words.length >= 2) {
|
||||
return `${words[0][0]}${words[1][0]}`.toUpperCase();
|
||||
}
|
||||
|
||||
return trimmed[0]?.toUpperCase() ?? "";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user