Skip to content

Commit

Permalink
feat(summary-v2): Sortable flatlist :pepejam:
Browse files Browse the repository at this point in the history
  • Loading branch information
Veikkosuhonen committed Nov 2, 2023
1 parent bf12381 commit 49cea82
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 44 deletions.
47 changes: 25 additions & 22 deletions src/client/pages/CourseSummary/SummaryV2/MyOrganisations.js
Original file line number Diff line number Diff line change
@@ -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 (
<Box display="flex" flexDirection="column" alignItems="stretch" gap="0.4rem">
<SorterRow />
{rootOrganisations.map((organisation, i) => (
<OrganisationSummaryRow
key={organisation.id}
loadClosed
alwaysOpen={rootOrganisations.length === 1}
organisationId={organisation.id}
organisation={organisation}
startDate={dateRange.start}
endDate={dateRange.end}
hasSorter={i === 0}
/>
))}
{isLoading ? (
<LinearProgress />
) : (
orderedAndFilteredOrganisations.map(organisation => (
<OrganisationSummaryRow
key={organisation.id}
loadClosed
alwaysOpen={organisations.length === 1}
organisationId={organisation.id}
organisation={organisation}
startDate={dateRange.start}
endDate={dateRange.end}
/>
))
)}
</Box>
)
}
Expand Down
17 changes: 3 additions & 14 deletions src/client/pages/CourseSummary/SummaryV2/SummaryRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -257,31 +257,20 @@ const CourseUnitSummaryRow = ({ courseUnit, questions }) => {
}

const ChildOrganisationsList = ({ organisationId, startDate, endDate, questions }) => {
const { showSummariesWithNoFeedback, sortBy, sortFunction } = useSummaryContext()
const { organisation, isLoading } = useSummaries({
entityId: organisationId,
startDate,
endDate,
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 <Loader />
}

return filteredAndOrderedOrganisations?.map(org => (
return orderedAndFilteredOrganisations?.map(org => (
<OrganisationSummaryRow
key={org.id}
startDate={startDate}
Expand Down
1 change: 0 additions & 1 deletion src/client/pages/CourseSummary/SummaryV2/University.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ const University = () => {
alwaysOpen
startDate={dateRange.start}
endDate={dateRange.end}
hasSorter
/>
</>
)
Expand Down
41 changes: 40 additions & 1 deletion src/client/pages/CourseSummary/SummaryV2/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand Down Expand Up @@ -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,
Expand Down
10 changes: 6 additions & 4 deletions src/client/pages/CourseSummary/SummaryV2/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -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]])
Expand Down
18 changes: 18 additions & 0 deletions src/client/pages/CourseSummary/SummaryV2/utils.js
Original file line number Diff line number Diff line change
@@ -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()
Expand All @@ -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
}
20 changes: 18 additions & 2 deletions src/server/routes/courseSummary/courseSummaryController.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
const { Router } = require('express')
const { addYears, format } = require('date-fns')
const { Op } = require('sequelize')

const { CourseUnit, Organisation } = require('../../models')

Expand All @@ -17,6 +16,7 @@ const {
getOrganisationSummaryWithCourseUnits,
getOrganisationSummary,
getTeacherSummary,
getUserOrganisationSummaries,
} = require('../../services/summary/summaryV2')
const { startOfStudyYear, endOfStudyYear } = require('../../util/common')
const { inProduction } = require('../../util/config')
Expand Down Expand Up @@ -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)
Expand Down
28 changes: 28 additions & 0 deletions src/server/services/summary/summaryV2.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

0 comments on commit 49cea82

Please sign in to comment.