Skip to content

Commit ad546f1

Browse files
authored
Merge branch 'develop' into feature-2805/convert-skills-data-structure
2 parents 873f997 + 1a72af3 commit ad546f1

File tree

18 files changed

+1324
-57
lines changed

18 files changed

+1324
-57
lines changed

server/src/main/java/com/objectcomputing/checkins/services/permissions/Permission.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public enum Permission {
1717
CAN_ADMINISTER_FEEDBACK_ANSWER("Administer feedback answers", "Feedback"),
1818
CAN_ADMINISTER_FEEDBACK_TEMPLATES("Administer feedback templates", "Feedback"),
1919
CAN_SEND_EMAIL("Send email", "Feedback"),
20+
CAN_VIEW_TERMINATED_MEMBERS("Can view the profiles of terminated members", "User Management"),
2021
CAN_EDIT_ALL_ORGANIZATION_MEMBERS("Edit all member profiles", "User Management"),
2122
CAN_DELETE_ORGANIZATION_MEMBERS("Delete organization members", "User Management"),
2223
CAN_CREATE_ORGANIZATION_MEMBERS("Create organization members", "User Management"),

web-ui/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"canvas-confetti": "^1.6.0",
2525
"date-fns": "^2.24.0",
2626
"dayjs": "^1.11.11",
27-
"dompurify": "^3.1.0",
27+
"dompurify": "^3.2.4",
2828
"fuse.js": "^6.4.6",
2929
"html-react-parser": "^5.1.12",
3030
"isomorphic-fetch": "^3.0.0",

web-ui/src/components/kudos/PublicKudosCard.jsx

Lines changed: 100 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@ import {
1717
DialogContentText,
1818
DialogActions,
1919
TextField,
20+
Link,
2021
} from "@mui/material";
21-
import { selectCsrfToken, selectProfile } from "../../context/selectors";
22+
import {
23+
selectCsrfToken,
24+
selectActiveOrInactiveProfile,
25+
} from "../../context/selectors";
2226
import { AppContext } from "../../context/AppContext";
2327
import { getAvatarURL } from "../../api/api";
2428
import DateFnsUtils from "@date-io/date-fns";
@@ -49,7 +53,92 @@ const KudosCard = ({ kudos }) => {
4953
const { state, dispatch } = useContext(AppContext);
5054
const csrf = selectCsrfToken(state);
5155

52-
const sender = selectProfile(state, kudos.senderId);
56+
const sender = selectActiveOrInactiveProfile(state, kudos.senderId);
57+
58+
const regexIndexOf = (text, regex, start) => {
59+
const indexInSuffix = text.slice(start).search(regex);
60+
return indexInSuffix < 0 ? indexInSuffix : indexInSuffix + start;
61+
};
62+
63+
const linkMember = (member, name, message) => {
64+
const components = [];
65+
let index = 0;
66+
do {
67+
index = regexIndexOf(message,
68+
new RegExp('\\b' + name + '\\b', 'i'), index);
69+
if (index != -1) {
70+
const link = <Link key={`${member.id}-${index}`}
71+
href={`/profile/${member.id}`}>
72+
{name}
73+
</Link>;
74+
if (index > 0) {
75+
components.push(message.slice(0, index));
76+
}
77+
components.push(link);
78+
message = message.slice(index + name.length);
79+
}
80+
} while(index != -1);
81+
components.push(message);
82+
return components;
83+
};
84+
85+
const searchNames = (member, members) => {
86+
const names = [];
87+
if (member.middleName) {
88+
names.push(`${member.firstName} ${member.middleName} ${member.lastName}`);
89+
}
90+
const firstAndLast = `${member.firstName} ${member.lastName}`;
91+
if (!members.some((k) => k.id != member.id &&
92+
firstAndLast != `${k.firstName} ${k.lastName}`)) {
93+
names.push(firstAndLast);
94+
}
95+
if (!members.some((k) => k.id != member.id &&
96+
(member.lastName == k.lastName ||
97+
member.lastName == k.firstName))) {
98+
// If there are no other recipients with a name that contains this
99+
// member's last name, we can replace based on that.
100+
names.push(member.lastName);
101+
}
102+
if (!members.some((k) => k.id != member.id &&
103+
(member.firstName == k.lastName ||
104+
member.firstName == k.firstName))) {
105+
// If there are no other recipients with a name that contains this
106+
// member's first name, we can replace based on that.
107+
names.push(member.firstName);
108+
}
109+
return names;
110+
};
111+
112+
const linkNames = (kudos) => {
113+
const components = [ kudos.message ];
114+
for (let member of kudos.recipientMembers) {
115+
const names = searchNames(member, kudos.recipientMembers);
116+
for (let name of names) {
117+
for (let i = 0; i < components.length; i++) {
118+
const component = components[i];
119+
if (typeof(component) === "string") {
120+
const built = linkMember(member, name, component);
121+
if (built.length > 1) {
122+
components.splice(i, 1, ...built);
123+
}
124+
}
125+
}
126+
}
127+
}
128+
return components;
129+
};
130+
131+
const multiTooltip = (num, list) => {
132+
let tooltip = "";
133+
let prefix = "";
134+
for (let member of list.slice(-num)) {
135+
tooltip += prefix + `${member.firstName} ${member.lastName}`;
136+
prefix = ", ";
137+
}
138+
return <Tooltip arrow title={tooltip}>
139+
<Typography>{`+${num}`}</Typography>
140+
</Tooltip>;
141+
};
53142

54143
const getRecipientComponent = useCallback(() => {
55144
if (kudos.recipientTeam) {
@@ -67,7 +156,9 @@ const KudosCard = ({ kudos }) => {
67156
}
68157

69158
return (
70-
<AvatarGroup max={4}>
159+
<AvatarGroup max={4}
160+
renderSurplus={(extra) => multiTooltip(
161+
extra, kudos.recipientMembers)}>
71162
{kudos.recipientMembers.map((member) => (
72163
<Tooltip
73164
arrow
@@ -98,9 +189,13 @@ const KudosCard = ({ kudos }) => {
98189
subheaderTypographyProps={{variant:"subtitle1"}}
99190
/>
100191
<CardContent>
101-
<Typography variant="body1"><em>{kudos.message}</em></Typography>
192+
<Typography variant="body1">
193+
{linkNames(kudos)}
194+
</Typography>
102195
{kudos.recipientTeam && (
103-
<AvatarGroup max={12}>
196+
<AvatarGroup max={12}
197+
renderSurplus={(extra) => multiTooltip(
198+
extra, kudos.recipientMembers)}>
104199
{kudos.recipientMembers.map((member) => (
105200
<Tooltip
106201
arrow
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import React from 'react';
2+
import PublicKudosCard from './PublicKudosCard';
3+
import { AppContextProvider } from '../../context/AppContext';
4+
5+
const initialState = {
6+
state: {
7+
csrf: 'O_3eLX2-e05qpS_yOeg1ZVAs9nDhspEi',
8+
teams: [],
9+
userProfile: {
10+
id: "1",
11+
firstName: 'Jimmy',
12+
lastName: 'Johnson',
13+
role: ['MEMBER'],
14+
},
15+
memberProfiles: [
16+
{
17+
id: "1",
18+
firstName: 'Jimmy',
19+
lastName: 'Johnson',
20+
role: ['MEMBER'],
21+
},
22+
{
23+
id: "2",
24+
firstName: 'Jimmy',
25+
lastName: 'Olsen',
26+
role: ['MEMBER'],
27+
},
28+
{
29+
id: "3",
30+
firstName: 'Clark',
31+
lastName: 'Kent',
32+
role: ['MEMBER'],
33+
},
34+
{
35+
id: "4",
36+
firstName: 'Kent',
37+
lastName: 'Brockman',
38+
role: ['MEMBER'],
39+
},
40+
{
41+
id: "5",
42+
firstName: 'Jerry',
43+
lastName: 'Garcia',
44+
role: ['MEMBER'],
45+
},
46+
{
47+
id: "6",
48+
firstName: 'Brock',
49+
lastName: 'Smith',
50+
role: ['MEMBER'],
51+
},
52+
{
53+
id: "7",
54+
firstName: 'Jimmy',
55+
middleName: 'T.',
56+
lastName: 'Olsen',
57+
role: ['MEMBER'],
58+
},
59+
],
60+
}
61+
};
62+
63+
const kudos = {
64+
id: 'test-kudos',
65+
message: "Brock and Brockman did a great job helping Clark, Jimmy Olsen, Jimmy T. Olsen, and Johnson",
66+
senderId: "5",
67+
dateCreated: [ 2025, 2, 14 ],
68+
recipientMembers: [
69+
{
70+
id: "1",
71+
firstName: 'Jimmy',
72+
lastName: 'Johnson',
73+
role: ['MEMBER'],
74+
},
75+
{
76+
id: "2",
77+
firstName: 'Jimmy',
78+
lastName: 'Olsen',
79+
role: ['MEMBER'],
80+
},
81+
{
82+
id: "3",
83+
firstName: 'Clark',
84+
lastName: 'Kent',
85+
role: ['MEMBER'],
86+
},
87+
{
88+
id: "6",
89+
firstName: 'Brock',
90+
lastName: 'Smith',
91+
role: ['MEMBER'],
92+
},
93+
{
94+
id: "4",
95+
firstName: 'Kent',
96+
lastName: 'Brockman',
97+
role: ['MEMBER'],
98+
},
99+
{
100+
id: "7",
101+
firstName: 'Jimmy',
102+
middleName: 'T.',
103+
lastName: 'Olsen',
104+
role: ['MEMBER'],
105+
},
106+
],
107+
};
108+
109+
it('renders correctly', () => {
110+
snapshot(
111+
<AppContextProvider value={initialState}>
112+
<PublicKudosCard
113+
kudos={kudos}
114+
/>
115+
</AppContextProvider>
116+
);
117+
});

0 commit comments

Comments
 (0)