diff --git a/src/client/pages/CourseSummary/SummaryV2/MyOrganisations.js b/src/client/pages/CourseSummary/SummaryV2/MyOrganisations.js
index 285d09764..4d5d4fa3d 100644
--- a/src/client/pages/CourseSummary/SummaryV2/MyOrganisations.js
+++ b/src/client/pages/CourseSummary/SummaryV2/MyOrganisations.js
@@ -1,38 +1,41 @@
import React from 'react'
-import { Box } from '@mui/material'
+import { Box, LinearProgress } from '@mui/material'
import { OrganisationSummaryRow, SorterRow } from './SummaryRow'
-import useAuthorizedUser from '../../../hooks/useAuthorizedUser'
import { useSummaryContext } from './context'
-
-const useRootOrganisations = organisations => {
- const rootOrganisations = React.useMemo(() => organisations.map(o => o.organisation), [organisations])
-
- return rootOrganisations
-}
+import { useOrganisationSummaries } from './api'
+import { useOrderedAndFilteredOrganisations } from './utils'
/**
*
*/
const MyOrganisations = () => {
- const { authorizedUser: user } = useAuthorizedUser()
- const rootOrganisations = useRootOrganisations(user.organisations)
const { dateRange } = useSummaryContext()
+ const { organisations, isLoading } = useOrganisationSummaries({
+ startDate: dateRange.start,
+ endDate: dateRange.end,
+ enabled: true,
+ })
+
+ const orderedAndFilteredOrganisations = useOrderedAndFilteredOrganisations(organisations)
return (
- {rootOrganisations.map((organisation, i) => (
-
- ))}
+ {isLoading ? (
+
+ ) : (
+ orderedAndFilteredOrganisations.map(organisation => (
+
+ ))
+ )}
)
}
diff --git a/src/client/pages/CourseSummary/SummaryV2/SummaryRow.js b/src/client/pages/CourseSummary/SummaryV2/SummaryRow.js
index 641304dab..c9cd15e29 100644
--- a/src/client/pages/CourseSummary/SummaryV2/SummaryRow.js
+++ b/src/client/pages/CourseSummary/SummaryV2/SummaryRow.js
@@ -11,7 +11,7 @@ import SummaryResultItem from '../../../components/SummaryResultItem/SummaryResu
import { CourseUnitLabel, OrganisationLabel } from '../Labels'
import PercentageCell from '../PercentageCell'
import useRandomColor from '../../../hooks/useRandomColor'
-import { useSummaryQuestions } from './utils'
+import { useOrderedAndFilteredOrganisations, useSummaryQuestions } from './utils'
import { useSummaryContext } from './context'
import Sort from './Sort'
@@ -257,7 +257,6 @@ const CourseUnitSummaryRow = ({ courseUnit, questions }) => {
}
const ChildOrganisationsList = ({ organisationId, startDate, endDate, questions }) => {
- const { showSummariesWithNoFeedback, sortBy, sortFunction } = useSummaryContext()
const { organisation, isLoading } = useSummaries({
entityId: organisationId,
startDate,
@@ -265,23 +264,13 @@ const ChildOrganisationsList = ({ organisationId, startDate, endDate, questions
include: 'childOrganisations',
})
- const filteredAndOrderedOrganisations = React.useMemo(
- () =>
- _.orderBy(
- showSummariesWithNoFeedback
- ? organisation?.childOrganisations
- : organisation?.childOrganisations?.filter(org => !!org.summary),
- org => sortFunction(org.summary),
- sortBy[1]
- ),
- [showSummariesWithNoFeedback, organisation, sortBy[0], sortBy[1]]
- )
+ const orderedAndFilteredOrganisations = useOrderedAndFilteredOrganisations(organisation?.childOrganisations)
if (isLoading) {
return
}
- return filteredAndOrderedOrganisations?.map(org => (
+ return orderedAndFilteredOrganisations?.map(org => (
{
alwaysOpen
startDate={dateRange.start}
endDate={dateRange.end}
- hasSorter
/>
>
)
diff --git a/src/client/pages/CourseSummary/SummaryV2/api.js b/src/client/pages/CourseSummary/SummaryV2/api.js
index 62a5b72ee..b807a85a1 100644
--- a/src/client/pages/CourseSummary/SummaryV2/api.js
+++ b/src/client/pages/CourseSummary/SummaryV2/api.js
@@ -3,6 +3,11 @@ import apiClient from '../../../util/apiClient'
const TWELVE_HOURS = 1000 * 60 * 60 * 12
+/**
+ * Fetches a summary row for an organisation.
+ * include can be 'childOrganisations' or 'courseUnits', in which case the organisation's
+ * corresponding children are included in the response, allowing the row to be expanded.
+ */
export const useSummaries = ({ startDate, endDate, entityId, enabled, include }) => {
const queryKey = ['summaries-v2', entityId, startDate, endDate, include]
@@ -32,11 +37,45 @@ export const useSummaries = ({ startDate, endDate, entityId, enabled, include })
return { organisation, ...rest }
}
+/**
+ * Fetches all summaries for a teacher based on their courses.
+ * Returns a list of organisations with course units as children.
+ */
export const useTeacherSummaries = ({ startDate, endDate, enabled }) => {
const queryKey = ['summaries-v2-teacher', startDate, endDate]
const queryFn = async () => {
- const { data } = await apiClient.get(`course-summaries/courses-v2`, {
+ const { data } = await apiClient.get(`course-summaries/user-courses-v2`, {
+ params: {
+ startDate,
+ endDate,
+ },
+ })
+
+ return data
+ }
+
+ const { data, ...rest } = useQuery(queryKey, queryFn, {
+ enabled,
+ retry: false,
+ refetchOnWindowFocus: false,
+ keepPreviousData: true,
+ staleTime: TWELVE_HOURS,
+ })
+
+ const organisations = data || []
+
+ return { organisations, ...rest }
+}
+
+/**
+ * Fetches all organisation rows for user based on their org access
+ */
+export const useOrganisationSummaries = ({ startDate, endDate, enabled }) => {
+ const queryKey = ['summaries-v2-organisations', startDate, endDate]
+
+ const queryFn = async () => {
+ const { data } = await apiClient.get(`course-summaries/user-organisations-v2`, {
params: {
startDate,
endDate,
diff --git a/src/client/pages/CourseSummary/SummaryV2/context.js b/src/client/pages/CourseSummary/SummaryV2/context.js
index fe1432d0a..d2e97a08f 100644
--- a/src/client/pages/CourseSummary/SummaryV2/context.js
+++ b/src/client/pages/CourseSummary/SummaryV2/context.js
@@ -92,10 +92,12 @@ export const SummaryContextProvider = ({ children }) => {
})
const updateSortByQS = React.useCallback(sortBy => {
- setSortBy(sortBy)
- params.set('sortBy', sortBy[0])
- params.set('order', sortBy[1])
- setParams(params)
+ React.startTransition(() => {
+ setSortBy(sortBy)
+ params.set('sortBy', sortBy[0])
+ params.set('order', sortBy[1])
+ setParams(params)
+ })
})
const sortFunction = React.useMemo(() => getSummarySortFunction(sortBy[0]), [sortBy[0]])
diff --git a/src/client/pages/CourseSummary/SummaryV2/utils.js b/src/client/pages/CourseSummary/SummaryV2/utils.js
index cb3695c66..963a291a0 100644
--- a/src/client/pages/CourseSummary/SummaryV2/utils.js
+++ b/src/client/pages/CourseSummary/SummaryV2/utils.js
@@ -1,4 +1,7 @@
+import React from 'react'
+import _ from 'lodash'
import useUniversitySurvey from '../../../hooks/useUniversitySurvey'
+import { useSummaryContext } from './context'
export const useSummaryQuestions = () => {
const { survey: universitySurvey, isLoading: isUniversitySurveyLoading } = useUniversitySurvey()
@@ -12,3 +15,18 @@ export const useSummaryQuestions = () => {
isLoading: isUniversitySurveyLoading,
}
}
+
+export const useOrderedAndFilteredOrganisations = organisations => {
+ const { showSummariesWithNoFeedback, sortBy, sortFunction } = useSummaryContext()
+ const filteredAndOrderedOrganisations = React.useMemo(
+ () =>
+ _.orderBy(
+ showSummariesWithNoFeedback ? organisations : organisations.filter(org => !!org.summary),
+ org => sortFunction(org.summary),
+ sortBy[1]
+ ),
+ [showSummariesWithNoFeedback, organisations, sortBy[0], sortBy[1]]
+ )
+
+ return filteredAndOrderedOrganisations
+}
diff --git a/src/server/routes/courseSummary/courseSummaryController.js b/src/server/routes/courseSummary/courseSummaryController.js
index d9c77e5c4..bc2a23276 100644
--- a/src/server/routes/courseSummary/courseSummaryController.js
+++ b/src/server/routes/courseSummary/courseSummaryController.js
@@ -1,6 +1,5 @@
const { Router } = require('express')
const { addYears, format } = require('date-fns')
-const { Op } = require('sequelize')
const { CourseUnit, Organisation } = require('../../models')
@@ -17,6 +16,7 @@ const {
getOrganisationSummaryWithCourseUnits,
getOrganisationSummary,
getTeacherSummary,
+ getUserOrganisationSummaries,
} = require('../../services/summary/summaryV2')
const { startOfStudyYear, endOfStudyYear } = require('../../util/common')
const { inProduction } = require('../../util/config')
@@ -250,11 +250,27 @@ const getCoursesV2 = async (req, res) => {
return res.send(organisations)
}
+const getUserOrganisationsV2 = async (req, res) => {
+ const { startDate: startDateString, endDate: endDateString } = req.query
+ const { user } = req
+
+ const { startDate, endDate } = parseDates(startDateString, endDateString)
+
+ const organisations = await getUserOrganisationSummaries({
+ user,
+ startDate,
+ endDate,
+ })
+
+ res.send(organisations)
+}
+
const router = Router()
router.get('/organisations', getOrganisations)
router.get('/organisations-v2', getOrganisationsV2)
-router.get('/courses-v2', getCoursesV2)
+router.get('/user-courses-v2', getCoursesV2)
+router.get('/user-organisations-v2', getUserOrganisationsV2)
router.get('/organisations/:code', getOrganisations)
router.get('/course-units/:code', getByCourseUnit)
router.get('/access', getAccessInfo)
diff --git a/src/server/services/summary/summaryV2.js b/src/server/services/summary/summaryV2.js
index ea20cbd6a..d0cea7244 100644
--- a/src/server/services/summary/summaryV2.js
+++ b/src/server/services/summary/summaryV2.js
@@ -325,9 +325,37 @@ const getTeacherSummary = async ({ startDate, endDate, user }) => {
return organisationsJson
}
+const getUserOrganisationSummaries = async ({ startDate, endDate, user }) => {
+ const organisationIds = await getSummaryAccessibleOrganisationIds(user)
+
+ const organisations = await Organisation.findAll({
+ attributes: ['id', 'name', 'code'],
+ where: {
+ id: {
+ [Op.in]: organisationIds,
+ [Op.notIn]: SUMMARY_EXCLUDED_ORG_IDS,
+ },
+ },
+ include: {
+ model: Summary.scope({ method: ['at', startDate, endDate] }),
+ as: 'summaries',
+ required: false,
+ },
+ })
+
+ const organisationsJson = organisations.map(org => {
+ org.summary = sumSummaries(org.summaries)
+ delete org.dataValues.summaries
+ return org.toJSON()
+ })
+
+ return organisationsJson
+}
+
module.exports = {
getOrganisationSummary,
getOrganisationSummaryWithChildOrganisations,
getOrganisationSummaryWithCourseUnits,
getTeacherSummary,
+ getUserOrganisationSummaries,
}