Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Score Reports Not Populating Correctly #895

Merged
merged 7 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 36 additions & 21 deletions src/composables/useFilteredTableData.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,51 @@
import { ref, watch } from 'vue';
import _once from 'lodash/once';

import _cloneDeep from 'lodash/cloneDeep';

let initialTableData = null;
const setInitialTableData = _once((data) => {
initialTableData = data;
});

/**
* A composable function that manages filtered table data based on provided school and grade filters.
*
* @param {Ref<Array>} tableData - A reactive reference to the table data that will be filtered.
* @returns {Object} - An object containing the filtered table data and a function to update the filters.
* @property {Ref<Array>} filteredTableData - A reactive reference to the filtered table data.
* @property {Function} updateFilters - A function to update the filters applied to the table data.
*
* The `updateFilters` function expects two arrays as arguments:
* - `filterSchools`: An array of school names to filter the data by. Default is an empty array.
* - `filterGrades`: An array of grades to filter the data by. Default is an empty array.
*
* The function creates a deep clone of the initial table data to avoid mutating the original data.
* It then filters the data based on the provided school names and grades.
* If no filters are applied, it resets the table data to the initial state.
*
* The `watch` function observes changes to the `tableData` and updates the `filteredTableData` accordingly.
* It also snapshots the data once before any filters are applied if the table data is not empty.
*/
export function useFilteredTableData(tableData) {
// Snapshot the data once before any filters are applied
let data = null;
const setData = _once(() => {
data = tableData.value;
});

// Create a reactive reference to the table data
const filteredTableData = ref(tableData);

// Expects an unwrapped array for each filter
const updateFilters = (filterSchools, filterGrades) => {
let filteredData = tableData.value;
const updateFilters = (filterSchools = [], filterGrades = []) => {
const filteredData = ref(_cloneDeep(initialTableData) ?? []);

if (filterSchools.length > 0) {
filteredData = filteredData.filter((item) => filterSchools.includes(item.user.schoolName));
if (filterSchools.length) {
filteredData.value = filteredData.value.filter((item) => filterSchools.includes(item?.user.schoolName));
}
if (filterGrades.length > 0) {
filteredData = filteredData.filter((item) => filterGrades.includes(item.user.grade));
if (filterGrades.length) {
filteredData.value = filteredData.value.filter((item) => filterGrades.includes(String(item?.user.grade)));
}

// Update the filteredTableData with the filtered data, or the original data if no filters are applied
filteredTableData.value = filterSchools.length === 0 && filterGrades.length === 0 ? data : filteredData;
filteredTableData.value = !filterSchools.length && !filterGrades.length ? initialTableData : filteredData.value;
};

// Watch for changes to the table data and update the filteredTableData
// setData() is called only once to snapshot the data before any filters are applied
watch(tableData, (newValue) => {
setData();

if (!initialTableData && newValue?.length) {
setInitialTableData(newValue);
}
filteredTableData.value = newValue;
});

Expand Down
2 changes: 1 addition & 1 deletion src/pages/HomeSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ const isLoading = computed(() => {
// @NOTE: In addition to the loading states, we also check if user data and user claims are loaded as due to the
// current application initialization flow, the userData and userClaims queries initially reset. Once this is improved
// these additional checks can be removed.
return !initialized || isLoadingUserData.value || isLoadingClaims.value || !userData.value || !userClaims.value;
return !initialized.value || isLoadingUserData.value || isLoadingClaims.value || !userData.value || !userClaims.value;
});

const showConsent = ref(false);
Expand Down
18 changes: 10 additions & 8 deletions src/pages/ScoreReport.vue
Original file line number Diff line number Diff line change
Expand Up @@ -135,12 +135,11 @@
:loading="isLoadingAssignments || isFetchingAssignments"
:groupheaders="true"
data-cy="roar-data-table"
@reset-filters="resetFilters"
@export-all="exportData({ selectedRows: $event })"
@export-selected="exportData({ selectedRows: $event })"
>
<template #filterbar>
<FilterBar :schools="schoolsInfo" :grades="gradeOptions" :update-filters="updateFilters" />
<FilterBar :schools="schoolOptions" :grades="gradeOptions" :update-filters="updateFilters" />
</template>
<span>
<label for="view-columns" class="view-label">View</label>
Expand Down Expand Up @@ -477,6 +476,10 @@ const schoolNameDictionary = computed(() => {
);
});

const schoolOptions = computed(() => {
return Object.values(schoolNameDictionary.value).map((name) => ({ name: name, label: name }));
});

// Return a faded color if assessment is not reliable
function returnColorByReliability(assessment, rawScore, support_level, tag_color) {
if (assessment.reliable !== undefined && !assessment.reliable && assessment.engagementFlags !== undefined) {
Expand Down Expand Up @@ -841,17 +844,16 @@ const computeAssignmentAndRunData = computed(() => {
}
});

// Composable to filter table data using FilterBar.vue component which is passed in as a slot to RoarDataTable
// This composable manages the data which is passed into the FilterBar component slot for filtering
const filteredTableData = ref([]);
const { updateFilters } = useFilteredTableData(filteredTableData);

// Watch for changes in assignmentTableData and update filteredTableData
// This will snapshot the assignmentTableData and filter it based on the current filters
watch(
() => computeAssignmentAndRunData.value.assignmentTableData,
(newTableData) => {
filteredTableData.value = newTableData;
computeAssignmentAndRunData,
(newValue) => {
filteredTableData.value = newValue.assignmentTableData;
},
{ immediate: true, deep: true },
);

const viewMode = ref('color');
Expand Down