Skip to content

Commit f0d9b18

Browse files
committed
Fixed issues with duplicate current user profile in state, added preferences card to profile page with switch to turn off birthday celebration, and removed deprecated docker compose version
1 parent 34d888d commit f0d9b18

File tree

8 files changed

+204
-58
lines changed

8 files changed

+204
-58
lines changed

docker-compose.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
version: '3'
21
services:
32
postgresql:
43
image: postgres:17.2

server/src/main/java/com/objectcomputing/checkins/services/memberprofile/MemberProfileController.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public HttpResponse<MemberProfileResponseDTO> getById(UUID id) {
5858
public List<MemberProfileResponseDTO> getSupervisorsForId(UUID id) {
5959
return memberProfileServices.getSupervisorsForId(id)
6060
.stream()
61-
.map(this::fromEntity)
61+
.map(MemberProfileController::fromEntity)
6262
.toList();
6363
}
6464

@@ -83,7 +83,7 @@ public List<MemberProfileResponseDTO> findByValue(@Nullable String firstName,
8383
@QueryValue(value = "terminated", defaultValue = "false") Boolean terminated) {
8484
return memberProfileServices.findByValues(firstName, lastName, title, pdlId, workEmail, supervisorId, terminated)
8585
.stream()
86-
.map(this::fromEntity)
86+
.map(MemberProfileController::fromEntity)
8787
.toList();
8888
}
8989

@@ -128,7 +128,7 @@ protected URI location(UUID id) {
128128
return URI.create("/member-profiles/" + id);
129129
}
130130

131-
private MemberProfileResponseDTO fromEntity(MemberProfile entity) {
131+
public static MemberProfileResponseDTO fromEntity(MemberProfile entity) {
132132
MemberProfileResponseDTO dto = new MemberProfileResponseDTO();
133133
dto.setId(entity.getId());
134134
dto.setFirstName(entity.getFirstName());

server/src/main/java/com/objectcomputing/checkins/services/memberprofile/currentuser/CurrentUserController.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.objectcomputing.checkins.services.memberprofile.currentuser;
22

33
import com.objectcomputing.checkins.services.memberprofile.MemberProfile;
4+
import com.objectcomputing.checkins.services.memberprofile.MemberProfileController;
45
import com.objectcomputing.checkins.services.memberprofile.MemberProfileServices;
56
import com.objectcomputing.checkins.services.memberprofile.MemberProfileUtils;
67
import com.objectcomputing.checkins.services.permissions.Permission;
@@ -86,7 +87,7 @@ private CurrentUserDTO fromEntity(MemberProfile entity, String imageUrl, List<Pe
8687
dto.setPermissions(permissions);
8788
dto.setRole(roles);
8889
dto.setImageUrl(imageUrl);
89-
dto.setMemberProfile(entity);
90+
dto.setMemberProfile(MemberProfileController.fromEntity(entity));
9091
return dto;
9192
}
9293
}

server/src/main/java/com/objectcomputing/checkins/services/memberprofile/currentuser/CurrentUserDTO.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.objectcomputing.checkins.services.memberprofile.currentuser;
22

33
import com.objectcomputing.checkins.services.memberprofile.MemberProfile;
4+
import com.objectcomputing.checkins.services.memberprofile.MemberProfileResponseDTO;
45
import com.objectcomputing.checkins.services.permissions.Permission;
56
import io.micronaut.core.annotation.Introspected;
67
import io.micronaut.core.annotation.Nullable;
@@ -45,6 +46,6 @@ public class CurrentUserDTO {
4546

4647
@NotNull
4748
@Schema(implementation = MemberProfile.class)
48-
private MemberProfile memberProfile;
49+
private MemberProfileResponseDTO memberProfile;
4950

5051
}

web-ui/src/context/actions.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export const UPDATE_TEAMS = '@@check-ins/update_teams';
2828
export const UPDATE_TERMINATED_MEMBERS =
2929
'@@check-ins/update_terminated_members';
3030
export const UPDATE_TOAST = '@@check-ins/update_toast';
31+
export const UPDATE_CURRENT_USER_PROFILE = '@@check-ins/update_current_user_profile';
3132
export const UPDATE_USER_BIO = '@@check-ins/update_bio';
3233
export const UPDATE_FEEEDBACK_SUGGESTIONS =
3334
'@@check-ins/update_feedback_suggestions';

web-ui/src/context/reducer.js

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {
2727
UPDATE_TEAMS,
2828
UPDATE_TEAM_MEMBERS,
2929
UPDATE_TOAST,
30-
UPDATE_USER_BIO,
30+
UPDATE_CURRENT_USER_PROFILE,
3131
UPDATE_PEOPLE_LOADING,
3232
UPDATE_TEAMS_LOADING,
3333
UPDATE_REVIEW_PERIOD,
@@ -59,13 +59,42 @@ export const initialState = {
5959
reviewPeriods: []
6060
};
6161

62+
// Converts member dates *in place*, I don't love this. I'll be back, convertMemberDates...don't get comfortable.
63+
const convertMemberDates = member => {
64+
member.birthDay = Array.isArray(member.birthDay)
65+
? new Date(member.birthDay.join('/'))
66+
: member && member.birthDay
67+
? member.birthDay
68+
: null;
69+
member.startDate = Array.isArray(member.startDate)
70+
? new Date(member.startDate.join('/'))
71+
: member && member.startDate
72+
? member.startDate
73+
: new Date();
74+
member.terminationDate = Array.isArray(member.terminationDate)
75+
? new Date(member.terminationDate.join('/'))
76+
: member && member.terminationDate
77+
? member.terminationDate
78+
: null;
79+
};
80+
6281
export const reducer = (state, action) => {
6382
switch (action.type) {
6483
case MY_PROFILE_UPDATE:
65-
state.userProfile = action.payload;
66-
break;
67-
case UPDATE_USER_BIO:
68-
state.userProfile.memberProfile.bioText = action.payload;
84+
convertMemberDates(action.payload.memberProfile);
85+
state.userProfile = { ...action.payload };
86+
break;
87+
case UPDATE_CURRENT_USER_PROFILE:
88+
convertMemberDates(action.payload);
89+
state.userProfile = { ...state.userProfile, memberProfile: { ...action.payload } };
90+
const profileId = action.payload.id;
91+
const memberProfiles = state.memberProfiles.reduce((acc, current) => {
92+
if(current.id !== profileId) {
93+
acc.push({...current});
94+
}
95+
return acc;
96+
}, [{ ...action.payload }])
97+
state.memberProfiles = memberProfiles;
6998
break;
7099
case ADD_CHECKIN:
71100
if (state?.checkins?.length > 0) {
@@ -144,43 +173,20 @@ export const reducer = (state, action) => {
144173
state.loading = { ...state.loading, memberProfiles: action.payload };
145174
break;
146175
case UPDATE_MEMBER_PROFILES:
147-
action.payload.forEach(member => {
148-
member.birthDay = Array.isArray(member.birthDay)
149-
? new Date(member.birthDay.join('/'))
150-
: member && member.birthDay
151-
? member.birthDay
152-
: null;
153-
member.startDate = Array.isArray(member.startDate)
154-
? new Date(member.startDate.join('/'))
155-
: member && member.startDate
156-
? member.startDate
157-
: new Date();
158-
member.terminationDate = Array.isArray(member.terminationDate)
159-
? new Date(member.terminationDate.join('/'))
160-
: member && member.terminationDate
161-
? member.terminationDate
162-
: null;
176+
action.payload.forEach(convertMemberDates);
177+
const currentProfileId = state?.userProfile?.memberProfile?.id;
178+
const currentProfile = action.payload.find((current) => {
179+
if(currentProfileId && current.id === currentProfileId) {
180+
return current;
181+
}
163182
});
183+
if(currentProfile) {
184+
state.userProfile.memberProfile = { ...currentProfile };
185+
}
164186
state.memberProfiles = action.payload;
165187
break;
166188
case UPDATE_TERMINATED_MEMBERS:
167-
action.payload.forEach(member => {
168-
member.birthDay = Array.isArray(member.birthDay)
169-
? new Date(member.birthDay.join('/'))
170-
: member && member.birthDay
171-
? member.birthDay
172-
: null;
173-
member.startDate = Array.isArray(member.startDate)
174-
? new Date(member.startDate.join('/'))
175-
: member && member.startDate
176-
? member.startDate
177-
: new Date();
178-
member.terminationDate = Array.isArray(member.terminationDate)
179-
? new Date(member.terminationDate.join('/'))
180-
: member && member.terminationDate
181-
? member.terminationDate
182-
: null;
183-
});
189+
action.payload.forEach(convertMemberDates);
184190
state.terminatedMembers = action.payload;
185191
break;
186192
case UPDATE_TEAM_MEMBERS:

web-ui/src/pages/ProfilePage.jsx

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ import { AppContext } from '../context/AppContext';
55
import {
66
selectCurrentUser,
77
selectMyGuilds,
8-
selectUserProfile,
98
selectMyTeams
109
} from '../context/selectors';
11-
import { UPDATE_GUILD, UPDATE_USER_BIO } from '../context/actions';
10+
import { UPDATE_GUILD, UPDATE_CURRENT_USER_PROFILE } from '../context/actions';
1211
import { addGuildMember, deleteGuildMember } from '../api/guild';
1312
import { updateMember } from '../api/member';
1413
import { getEmployeeHours } from '../api/hours';
@@ -18,10 +17,15 @@ import SkillSection from '../components/skills/SkillSection';
1817
import ProgressBar from '../components/contribution_hours/ProgressBar';
1918
import VolunteerTables from '../components/volunteer/VolunteerTables';
2019

21-
import { Info } from '@mui/icons-material';
20+
import { Info, ManageAccounts } from '@mui/icons-material';
2221
import { Card, CardContent, CardHeader, Chip, TextField, Avatar } from '@mui/material';
2322
import GroupIcon from '@mui/icons-material/Group';
2423
import Autocomplete from '@mui/material/Autocomplete';
24+
import FormLabel from '@mui/material/FormLabel';
25+
import FormControl from '@mui/material/FormControl';
26+
import FormGroup from '@mui/material/FormGroup';
27+
import FormControlLabel from '@mui/material/FormControlLabel';
28+
import Switch from '@mui/material/Switch';
2529

2630
import './ProfilePage.css';
2731

@@ -32,13 +36,12 @@ const storeMember = debounce(realStoreMember, 1500);
3236
const ProfilePage = () => {
3337
const { state, dispatch } = useContext(AppContext);
3438
const memberProfile = selectCurrentUser(state);
35-
const userProfile = selectUserProfile(state);
3639

3740
const { csrf, guilds } = state;
38-
const { id, bioText, pdlId } = memberProfile;
39-
const { firstName, lastName, name } = userProfile;
41+
const { id, bioText, pdlId, ignoreBirthday, firstName, lastName, name } = memberProfile;
4042

4143
const [bio, setBio] = useState();
44+
const [prefs, setPrefs] = useState({ignoreBirthday});
4245
const [myHours, setMyHours] = useState(null);
4346

4447
const myTeams = selectMyTeams(state);
@@ -62,24 +65,43 @@ const ProfilePage = () => {
6265
setBio(bioText);
6366
}
6467
updateBio();
65-
}, [bioText]);
68+
}, [setBio, bioText]);
6669

67-
const updateProfile = newBio => {
70+
useEffect(() => {
71+
async function updatePrefs() {
72+
setPrefs({...prefs, ignoreBirthday})
73+
}
74+
updatePrefs()
75+
}, [setPrefs, ignoreBirthday]);
76+
77+
const updateProfile = newProfile => {
6878
dispatch({
69-
type: UPDATE_USER_BIO,
70-
payload: newBio
79+
type: UPDATE_CURRENT_USER_PROFILE,
80+
payload: newProfile
7181
});
7282
};
7383

74-
const handleBioChange = e => {
84+
const handleIgnoreBirthdayChange = useCallback(async e => {
85+
if (!csrf) {
86+
return;
87+
}
88+
const { checked } = e.target;
89+
setPrefs({ ...prefs, ignoreBirthday: !checked });
90+
const newProfile = { ...memberProfile, ignoreBirthday: !checked };
91+
const { payload } = await realStoreMember(newProfile, csrf);
92+
updateProfile(payload.data);
93+
}, [csrf, prefs, setPrefs, memberProfile, realStoreMember, updateProfile]);
94+
95+
const handleBioChange = useCallback(async e => {
7596
if (!csrf) {
7697
return;
7798
}
7899
const { value } = e.target;
79100
setBio(value);
80-
storeMember({ ...memberProfile, bioText: value }, csrf);
81-
updateProfile(value);
82-
};
101+
const newProfile = { ...memberProfile, bioText: value };
102+
storeMember(newProfile, csrf);
103+
updateProfile(newProfile);
104+
}, [csrf, setBio, memberProfile, storeMember, updateProfile]);
83105

84106
const addOrDeleteGuildMember = useCallback(
85107
async newVal => {
@@ -146,6 +168,28 @@ const ProfilePage = () => {
146168
<div className="Profile">
147169
<Profile memberId={id} pdlId={pdlId} />
148170
<div className="profile-grid">
171+
<div className="profile-page-prefs">
172+
<Card>
173+
<CardHeader
174+
avatar={<Avatar sx={{ mr: 1 }}><ManageAccounts /></Avatar>}
175+
title="Preferences"
176+
titleTypographyProps={{ variant: 'h5', component: 'h2' }}
177+
/>
178+
<CardContent>
179+
<FormControl fullWidth component="fieldset" variant="standard">
180+
<FormLabel component="legend">Celebrations</FormLabel>
181+
<FormGroup>
182+
<FormControlLabel
183+
control={
184+
<Switch checked={!!!prefs.ignoreBirthday} onChange={handleIgnoreBirthdayChange} name="birthday" />
185+
}
186+
label="My Birthday"
187+
/>
188+
</FormGroup>
189+
</FormControl>
190+
</CardContent>
191+
</Card>
192+
</div>
149193
<div className="profile-page-bio">
150194
<Card>
151195
<CardHeader

0 commit comments

Comments
 (0)