diff --git a/common/utils/apiQueries.js b/common/utils/apiQueries.js index cee683b4a..2dfd6f463 100644 --- a/common/utils/apiQueries.js +++ b/common/utils/apiQueries.js @@ -857,6 +857,21 @@ export const ADMIN_WORK_DAYS_QUERY = gql` } `; +export const ADMIN_USERS_SINCE_DATE = gql` + query adminCompanies($id: Int!, $activityAfter: Date, $companyIds: [Int]) { + user(id: $id) { + adminedCompanies(companyIds: $companyIds) { + id + users(fromDate: $activityAfter) { + id + firstName + lastName + } + } + } + } +`; + export const GET_EMPLOYMENT_QUERY = gql` query getInvitation($token: String!) { employment(token: $token) { diff --git a/web/admin/modals/C1BExportModal.js b/web/admin/modals/C1BExportModal.js index 40ae6fe78..50f6bac51 100644 --- a/web/admin/modals/C1BExportModal.js +++ b/web/admin/modals/C1BExportModal.js @@ -22,6 +22,7 @@ import { TeamFilter } from "../components/TeamFilter"; import { EmployeeFilter } from "../components/EmployeeFilter"; import { CompanyFilter } from "../components/CompanyFilter"; import Modal, { modalStyles } from "../../common/Modal"; +import { syncUsers } from "./ExcelExportModal"; export default function C1BExportModal({ open, @@ -31,7 +32,8 @@ export default function C1BExportModal({ initialTeams = [], defaultMinDate = null, defaultMaxDate = null, - defaultCompany + defaultCompany, + getUsersSinceDate }) { const MAX_RANGE_DAYS = 60; const today = new Date(); @@ -50,6 +52,13 @@ export default function C1BExportModal({ const [teams, setTeams] = React.useState(initialTeams); const [employeeVersion, setEmployeeVersion] = React.useState(true); + React.useEffect(async () => { + if (minDate < defaultMinDate) { + const newUsers = await getUsersSinceDate(minDate); + syncUsers(setUsers, newUsers); + } + }, [minDate]); + const invalidDateRange = (minDate, maxDate) => maxDate && minDate && diff --git a/web/admin/modals/ExcelExportModal.js b/web/admin/modals/ExcelExportModal.js index 1ca028d1b..5f353a6ea 100644 --- a/web/admin/modals/ExcelExportModal.js +++ b/web/admin/modals/ExcelExportModal.js @@ -22,6 +22,15 @@ import Modal, { modalStyles } from "../../common/Modal"; import { TeamFilter } from "../components/TeamFilter"; import { EmployeeFilter } from "../components/EmployeeFilter"; +export const syncUsers = (setUsers, newUsers) => { + setUsers(currentUsers => [ + ...currentUsers, + ...newUsers.filter( + newUser => + !currentUsers.map(currentUser => currentUser.id).includes(newUser.id) + ) + ]); +}; export default function ExcelExportModal({ open, handleClose, @@ -30,7 +39,8 @@ export default function ExcelExportModal({ initialUsers, initialTeams, defaultMinDate = null, - defaultMaxDate = null + defaultMaxDate = null, + getUsersSinceDate }) { const api = useApi(); const alerts = useSnackbarAlerts(); @@ -45,6 +55,13 @@ export default function ExcelExportModal({ const [isEnabledDownload, setIsEnabledDownload] = React.useState(true); + React.useEffect(async () => { + if (minDate < defaultMinDate) { + const newUsers = await getUsersSinceDate(minDate); + syncUsers(setUsers, newUsers); + } + }, [minDate]); + React.useEffect(() => setIsEnabledDownload(true), [ minDate, maxDate, diff --git a/web/admin/panels/Activities.js b/web/admin/panels/Activities.js index bd7b62025..d0f8d8d9a 100644 --- a/web/admin/panels/Activities.js +++ b/web/admin/panels/Activities.js @@ -64,6 +64,7 @@ import { LogHolidayButton } from "../../common/LogHolidayButton"; import { LogHolidayForm } from "../../common/LogHolidayForm"; import { graphQLErrorMatchesCode } from "common/utils/errors"; import { usePageTitle } from "../../common/UsePageTitle"; +import { useGetUsersSinceDate } from "../../common/hooks/useGetUsersSinceDate"; const useStyles = makeStyles(theme => ({ filterGrid: { @@ -165,6 +166,7 @@ function ActivitiesPanel() { const api = useApi(); const history = useHistory(); const { trackEvent } = useMatomo(); + const { getUsersSinceDate } = useGetUsersSinceDate(); const [users, setUsers] = React.useState(adminStore.activitiesFilters.users); const [teams, setTeams] = React.useState(adminStore.activitiesFilters.teams); @@ -392,7 +394,8 @@ function ActivitiesPanel() { defaultMinDate: minDate ? new Date(minDate) : null, defaultMaxDate: maxDate ? new Date(maxDate) - : startOfDayAsDate(new Date()) + : startOfDayAsDate(new Date()), + getUsersSinceDate }); }} > @@ -413,7 +416,8 @@ function ActivitiesPanel() { defaultMinDate: minDate ? new Date(minDate) : null, defaultMaxDate: maxDate ? new Date(maxDate) - : startOfDayAsDate(new Date()) + : startOfDayAsDate(new Date()), + getUsersSinceDate }); }} > diff --git a/web/common/hooks/useGetUsersSinceDate.js b/web/common/hooks/useGetUsersSinceDate.js new file mode 100644 index 000000000..dc7addab6 --- /dev/null +++ b/web/common/hooks/useGetUsersSinceDate.js @@ -0,0 +1,36 @@ +import React from "react"; +import { ADMIN_USERS_SINCE_DATE } from "common/utils/apiQueries"; +import { useApi } from "common/utils/api"; +import { useAdminStore } from "../../admin/store/store"; +import { isoFormatLocalDate } from "common/utils/time"; +import { useSnackbarAlerts } from "../Snackbar"; +import { formatApiError } from "common/utils/errors"; + +export const useGetUsersSinceDate = () => { + const api = useApi(); + const alerts = useSnackbarAlerts(); + const adminStore = useAdminStore(); + const earliestDate = React.useRef(null); + const memo = React.useRef(null); + + const getUsersSinceDate = async fromDate => { + if (!earliestDate.current || fromDate < earliestDate.current) { + try { + const payload = await api.graphQlQuery(ADMIN_USERS_SINCE_DATE, { + id: adminStore.userId, + activityAfter: isoFormatLocalDate(fromDate), + companyIds: [adminStore.companyId] + }); + const users = payload?.data?.user?.adminedCompanies[0]?.users; + earliestDate.current = fromDate; + memo.current = users; + return users; + } catch (err) { + alerts.error(formatApiError(err), "get_users_since_date", 6000); + } + } + return memo.current; + }; + + return { getUsersSinceDate }; +};