From a225086bdb9f16f04a4479427538190a298d205e Mon Sep 17 00:00:00 2001 From: Chad Elliott Date: Thu, 7 Nov 2024 12:11:45 -0600 Subject: [PATCH 1/9] Show only active teams and guilds when creating the member selector dialog or kudos dialog. --- web-ui/src/components/kudos_dialog/KudosDialog.jsx | 4 ++-- .../MemberSelectorDialog.jsx | 8 ++++---- web-ui/src/context/selectors.js | 14 ++++++++++++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/web-ui/src/components/kudos_dialog/KudosDialog.jsx b/web-ui/src/components/kudos_dialog/KudosDialog.jsx index 79b6aa584..92cc98a41 100644 --- a/web-ui/src/components/kudos_dialog/KudosDialog.jsx +++ b/web-ui/src/components/kudos_dialog/KudosDialog.jsx @@ -29,7 +29,7 @@ import { AppContext } from '../../context/AppContext'; import { selectCsrfToken, selectCurrentUser, - selectNormalizedTeams, + selectActiveTeams, selectOrderedCurrentMemberProfiles, selectProfile } from '../../context/selectors'; @@ -65,7 +65,7 @@ const KudosDialog = ({ open, recipient, teamId, onClose }) => { ); const currentUser = selectCurrentUser(state); - const teams = selectNormalizedTeams(state, ''); + const teams = selectActiveTeams(state); const memberProfiles = selectOrderedCurrentMemberProfiles(state); const handleSubmit = useCallback(() => { diff --git a/web-ui/src/components/member_selector/member_selector_dialog/MemberSelectorDialog.jsx b/web-ui/src/components/member_selector/member_selector_dialog/MemberSelectorDialog.jsx index 79cd42f71..a24fc8510 100644 --- a/web-ui/src/components/member_selector/member_selector_dialog/MemberSelectorDialog.jsx +++ b/web-ui/src/components/member_selector/member_selector_dialog/MemberSelectorDialog.jsx @@ -37,14 +37,14 @@ import { AppContext } from '../../../context/AppContext'; import { selectCsrfToken, selectCurrentMembers, - selectGuilds, + selectActiveGuilds, selectMappedUserRoles, selectRoles, selectSkills, selectSubordinates, selectSupervisors, selectTeamMembersBySupervisorId, - selectTeams + selectActiveTeams, } from '../../../context/selectors'; import { UPDATE_TOAST } from '../../../context/actions'; import { getMembersByTeam } from '../../../api/team'; @@ -172,14 +172,14 @@ const MemberSelectorDialog = ({ const getFilterOptions = () => { switch (filterType) { case FilterType.TEAM: - const teams = selectTeams(state); + const teams = selectActiveTeams(state); return { options: teams, label: team => team.name, equals: (team1, team2) => team1.id === team2.id }; case FilterType.GUILD: - const guilds = selectGuilds(state); + const guilds = selectActiveGuilds(state); return { options: guilds, label: guild => guild.name, diff --git a/web-ui/src/context/selectors.js b/web-ui/src/context/selectors.js index 725aa4a77..9ecfb34ed 100644 --- a/web-ui/src/context/selectors.js +++ b/web-ui/src/context/selectors.js @@ -686,11 +686,21 @@ export const selectNormalizedTeams = createSelector( }) ); +export const selectActiveTeams = createSelector( + selectTeams, + (teams, searchText) => teams?.filter(team => team.active) +); + +export const selectActiveGuilds = createSelector( + selectGuilds, + (guilds, searchText) => guilds?.filter(guild => guild.active) +); + export const selectMyGuilds = createSelector( selectCurrentUserId, selectGuilds, (id, guilds) => - guilds?.filter(guild => + guilds?.filter(guild => guild.active && guild.guildMembers?.some(member => member.memberId === id) ) ); @@ -699,7 +709,7 @@ export const selectMyTeams = createSelector( selectCurrentUserId, selectTeams, (id, teams) => - teams?.filter(team => + teams?.filter(team => team.active && team.teamMembers?.some(member => member.memberId === id) ) ); From c9e9f15700fedef41294ab0ae4870a8be4bac43b Mon Sep 17 00:00:00 2001 From: Chad Elliott Date: Thu, 7 Nov 2024 12:12:29 -0600 Subject: [PATCH 2/9] Modified the active/inactive indicator on the Team Summary Card to be like the Guild Summary Card. --- .../team-results/TeamSummaryCard.jsx | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/web-ui/src/components/team-results/TeamSummaryCard.jsx b/web-ui/src/components/team-results/TeamSummaryCard.jsx index c60abe631..450390b4b 100644 --- a/web-ui/src/components/team-results/TeamSummaryCard.jsx +++ b/web-ui/src/components/team-results/TeamSummaryCard.jsx @@ -16,7 +16,8 @@ import { DialogContent, DialogContentText, DialogTitle, - Tooltip + Tooltip, + Typography, } from '@mui/material'; import PropTypes from 'prop-types'; import { updateTeam } from '../../api/team.js'; @@ -34,7 +35,8 @@ const StyledCard = styled(Card)({ width: '340px', display: 'flex', flexDirection: 'column', - justifyContent: 'space-between' + justifyContent: 'space-between', + position: 'relative', }, [`& .${classes.header}`]: { width: '100%' @@ -46,6 +48,11 @@ const StyledCard = styled(Card)({ } }); +const inactiveStyle = { + 'color': 'var(--action-disabled)', + 'font-size': '0.75em', +}; + const propTypes = { team: PropTypes.shape({ id: PropTypes.string, @@ -101,7 +108,7 @@ const TeamSummaryCard = ({ team, index, onTeamSelect, selectedTeamId }) => { title: classes.title, subheader: classes.title }} - title={team.name + (team.active ? ' (Active)' : ' (Inactive)')} + title={team.name} subheader={ { } /> + {!team.active && ( + + Inactive + + )} {team.teamMembers == null ? ( Team Leads: None Assigned From 0789090019c23ee18ccbaeba4168779fd9a64097 Mon Sep 17 00:00:00 2001 From: Chad Elliott Date: Thu, 7 Nov 2024 12:25:08 -0600 Subject: [PATCH 3/9] Updated snapshots. --- .../guild-results/EditGuildModal.spec.jsx | 6 +++-- .../MemberSelectorDialog.spec.jsx | 3 ++- .../TeamSummaryCard.test.jsx.snap | 27 ++++++++++++++----- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/web-ui/src/components/guild-results/EditGuildModal.spec.jsx b/web-ui/src/components/guild-results/EditGuildModal.spec.jsx index 0473bb1e0..dced872d3 100644 --- a/web-ui/src/components/guild-results/EditGuildModal.spec.jsx +++ b/web-ui/src/components/guild-results/EditGuildModal.spec.jsx @@ -34,12 +34,14 @@ const testGuild = { guildMembers: [ { id: 125, name: 'Guild Member' }, { id: 126, name: 'Other Member' } - ] + ], + active: true, }; const emptyGuild = { name: 'Test Guild', - description: 'A guild used for testing.' + description: 'A guild used for testing.', + active: true, }; const currentUserProfile = { diff --git a/web-ui/src/components/member_selector/member_selector_dialog/MemberSelectorDialog.spec.jsx b/web-ui/src/components/member_selector/member_selector_dialog/MemberSelectorDialog.spec.jsx index 5e5f8cc15..9d3623795 100644 --- a/web-ui/src/components/member_selector/member_selector_dialog/MemberSelectorDialog.spec.jsx +++ b/web-ui/src/components/member_selector/member_selector_dialog/MemberSelectorDialog.spec.jsx @@ -39,7 +39,8 @@ const testGuild = { name: 'Test Guild', description: 'A guild used for testing.', guildLeads: [{ id: 124, name: managerProfile.name }], - guildMembers: [] + guildMembers: [], + active: true, }; const initialState = { diff --git a/web-ui/src/components/team-results/__snapshots__/TeamSummaryCard.test.jsx.snap b/web-ui/src/components/team-results/__snapshots__/TeamSummaryCard.test.jsx.snap index be253e7eb..6b55c5706 100644 --- a/web-ui/src/components/team-results/__snapshots__/TeamSummaryCard.test.jsx.snap +++ b/web-ui/src/components/team-results/__snapshots__/TeamSummaryCard.test.jsx.snap @@ -3,7 +3,7 @@ exports[`renders correctly 1`] = `
- string (Inactive) + string +

+ Inactive +

Team Leads: @@ -52,7 +57,7 @@ exports[`renders correctly 1`] = ` exports[`renders correctly for ADMIN 1`] = `
- string (Inactive) + string +

+ Inactive +

Team Leads: @@ -142,7 +152,7 @@ exports[`renders correctly for ADMIN 1`] = ` exports[`renders correctly for team lead 1`] = `
- stuff (Inactive) + stuff +

+ Inactive +

Team Leads: From be9c1403b9c34e5f122b7f2a14785b79c6ad5f87 Mon Sep 17 00:00:00 2001 From: Chad Elliott Date: Fri, 8 Nov 2024 07:13:07 -0600 Subject: [PATCH 4/9] Allow a user to see which members do not have a registered birthday. --- .../birthday/BirthDayServicesImpl.java | 11 +++++++++- web-ui/src/api/birthdayanniversary.js | 22 ++++++++++++++++--- .../pages/BirthdayAnniversaryReportPage.css | 1 - web-ui/src/pages/BirthdayReportPage.jsx | 21 +++++++++++++++--- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/server/src/main/java/com/objectcomputing/checkins/services/memberprofile/birthday/BirthDayServicesImpl.java b/server/src/main/java/com/objectcomputing/checkins/services/memberprofile/birthday/BirthDayServicesImpl.java index bea821aa5..d241cd378 100644 --- a/server/src/main/java/com/objectcomputing/checkins/services/memberprofile/birthday/BirthDayServicesImpl.java +++ b/server/src/main/java/com/objectcomputing/checkins/services/memberprofile/birthday/BirthDayServicesImpl.java @@ -23,6 +23,13 @@ public BirthDayServicesImpl(MemberProfileServices memberProfileServices) { public List findByValue(String[] months, Integer[] daysOfMonth) { Set memberProfiles = memberProfileServices.findByValues(null, null, null, null, null, null, false); List memberProfileAll = new ArrayList<>(memberProfiles); + if (months == null && daysOfMonth == null) { + // If nothing was passed in, get all members without birthdays. + memberProfileAll = memberProfileAll + .stream() + .filter(member -> member.getBirthDate() == null) + .toList(); + } if (months != null) { for (String month : months) { if (month != null) { @@ -66,7 +73,9 @@ private List profileToBirthDateResponseDto(List { export const getBirthdays = async (months, cookie) => { const results = []; - for (let month of months) { + if (months) { + for (let month of months) { + const res = await resolve({ + url: `${birthdayReportUrl}?month=${month}`, + headers: { 'X-CSRF-Header': cookie, Accept: 'application/json' } + }); + if (res.error) { + console.error(res.error); + } else { + results.push(...res.payload.data); + } + } + } else { const res = await resolve({ - url: `${birthdayReportUrl}?month=${month}`, + url: birthdayReportUrl, headers: { 'X-CSRF-Header': cookie, Accept: 'application/json' } }); - results.push(...res.payload.data); + if (res.error) { + console.error(res.error); + } else { + results.push(...res.payload.data); + } } return results; }; diff --git a/web-ui/src/pages/BirthdayAnniversaryReportPage.css b/web-ui/src/pages/BirthdayAnniversaryReportPage.css index 5e40155dc..b706346b3 100644 --- a/web-ui/src/pages/BirthdayAnniversaryReportPage.css +++ b/web-ui/src/pages/BirthdayAnniversaryReportPage.css @@ -20,7 +20,6 @@ .select-month { display: flex; - justify-content: space-between; align-items: center; margin-left: 15px; margin-right: 10px; diff --git a/web-ui/src/pages/BirthdayReportPage.jsx b/web-ui/src/pages/BirthdayReportPage.jsx index c9aa348b9..af1652015 100644 --- a/web-ui/src/pages/BirthdayReportPage.jsx +++ b/web-ui/src/pages/BirthdayReportPage.jsx @@ -2,7 +2,7 @@ import React, { useContext, useState } from 'react'; import { AppContext } from '../context/AppContext'; -import { Button, TextField } from '@mui/material'; +import { FormControlLabel, Switch, Button, TextField } from '@mui/material'; import Autocomplete from '@mui/material/Autocomplete'; import './BirthdayAnniversaryReportPage.css'; @@ -45,6 +45,7 @@ const BirthdayReportPage = () => { const [selectedMonths, setSelectedMonths] = useState(defaultMonths); const [hasSearched, setHasSearched] = useState(false); const [loading, setLoading] = useState(false); + const [noBirthday, setNoBirthday] = useState(false); useQueryParameters([ { @@ -61,7 +62,8 @@ const BirthdayReportPage = () => { const handleSearch = async monthsToSearch => { setLoading(true); try { - const birthdayResults = await getBirthdays(monthsToSearch, csrf); + const birthdayResults = await getBirthdays(noBirthday ? null : + monthsToSearch, csrf); setSearchBirthdayResults(sortBirthdays(birthdayResults)); setHasSearched(true); } catch(e) { @@ -101,12 +103,25 @@ const BirthdayReportPage = () => { placeholder="Choose a month" /> )} + disabled={noBirthday} + /> + { + const { checked } = event.target; + setNoBirthday(checked); + }} + /> + } + label="No Birthday Registered" />
+