Skip to content

Commit

Permalink
Merge pull request #760 from yeatmanlab/ref/318/query-composables-lis…
Browse files Browse the repository at this point in the history
…t-orgs

Migrate List Organisations page to composable TanStack queries
  • Loading branch information
maximilianoertel authored Sep 9, 2024
2 parents 8a7dbac + 26aff29 commit bb16b11
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 50 deletions.
78 changes: 29 additions & 49 deletions src/components/ListOrgs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -117,20 +117,23 @@
import { ref, computed, onMounted, watch } from 'vue';
import * as Sentry from '@sentry/vue';
import { storeToRefs } from 'pinia';
import { useQuery } from '@tanstack/vue-query';
import { useToast } from 'primevue/usetoast';
import _get from 'lodash/get';
import _head from 'lodash/head';
import _isEmpty from 'lodash/isEmpty';
import _kebabCase from 'lodash/kebabCase';
import { useAuthStore } from '@/store/auth';
import { orgFetcher, orgFetchAll, orgPageFetcher } from '@/helpers/query/orgs';
import { orderByDefault, exportCsv, fetchDocById } from '@/helpers/query/utils';
import { orgFetchAll } from '@/helpers/query/orgs';
import { fetchUsersByOrg, countUsersByOrg } from '@/helpers/query/users';
import { orderByDefault, exportCsv, fetchDocById } from '@/helpers/query/utils';
import useUserType from '@/composables/useUserType';
import useUserClaimsQuery from '@/composables/queries/useUserClaimsQuery';
import useDistrictsQuery from '@/composables/queries/useDistrictsQuery';
import useDistrictSchoolsQuery from '@/composables/queries/useDistrictSchoolsQuery';
import useOrgsTableQuery from '@/composables/queries/useOrgsTableQuery';
import { CSV_EXPORT_MAX_RECORD_COUNT } from '@/constants/csvExport';
const initialized = ref(false);
const orgsQueryKeyIndex = ref(0);
const selectedDistrict = ref(undefined);
const selectedSchool = ref(undefined);
const orderBy = ref(orderByDefault);
Expand All @@ -152,16 +155,15 @@ const schoolPlaceholder = computed(() => {
return 'Select a school';
});
// Authstore and Sidebar
const authStore = useAuthStore();
const { roarfirekit, uid } = storeToRefs(authStore);
const { roarfirekit } = storeToRefs(authStore);
const { isLoading: isLoadingClaims, data: userClaims } = useUserClaimsQuery({
const { data: userClaims } = useUserClaimsQuery({
enabled: initialized,
});
const isSuperAdmin = computed(() => Boolean(userClaims.value?.claims?.super_admin));
const adminOrgs = computed(() => userClaims.value?.claims?.minimalAdminOrgs);
const { isSuperAdmin } = useUserType(userClaims);
const adminOrgs = computed(() => userClaims?.value?.claims?.minimalAdminOrgs);
const orgHeaders = computed(() => {
const headers = {
Expand Down Expand Up @@ -197,14 +199,26 @@ const activeOrgType = computed(() => {
return Object.keys(orgHeaders.value)[activeIndex.value];
});
const claimsLoaded = computed(() => !isLoadingClaims.value);
const claimsLoaded = computed(() => !_isEmpty(userClaims?.value?.claims));
const { isLoading: isLoadingDistricts, data: allDistricts } = useDistrictsQuery({
enabled: claimsLoaded,
});
const schoolQueryEnabled = computed(() => {
return claimsLoaded.value && !!selectedDistrict.value;
});
const { isLoading: isLoadingSchools, data: allSchools } = useDistrictSchoolsQuery(selectedDistrict, {
enabled: schoolQueryEnabled,
});
const { isLoading: isLoadingDistricts, data: allDistricts } = useQuery({
queryKey: ['districts', uid, orgsQueryKeyIndex],
queryFn: () => orgFetcher('districts', undefined, isSuperAdmin, adminOrgs),
keepPreviousData: true,
const {
isLoading,
isFetching,
data: orgData,
} = useOrgsTableQuery(activeOrgType, selectedDistrict, selectedSchool, orderBy, {
enabled: claimsLoaded,
staleTime: 5 * 60 * 1000, // 5 minutes
});
function copyToClipboard(text) {
Expand All @@ -228,40 +242,6 @@ function copyToClipboard(text) {
});
}
const schoolQueryEnabled = computed(() => {
return claimsLoaded.value && selectedDistrict.value !== undefined;
});
const { isLoading: isLoadingSchools, data: allSchools } = useQuery({
queryKey: ['schools', uid, selectedDistrict, orgsQueryKeyIndex],
queryFn: () => orgFetcher('schools', selectedDistrict, isSuperAdmin, adminOrgs),
keepPreviousData: true,
enabled: schoolQueryEnabled,
staleTime: 5 * 60 * 1000, // 5 minutes
});
const {
isLoading,
isFetching,
data: orgData,
} = useQuery({
queryKey: ['orgsPage', uid, activeOrgType, selectedDistrict, selectedSchool, orderBy, orgsQueryKeyIndex],
queryFn: () =>
orgPageFetcher(
activeOrgType,
selectedDistrict,
selectedSchool,
orderBy,
ref(100000),
ref(0),
isSuperAdmin,
adminOrgs,
),
keepPreviousData: true,
enabled: claimsLoaded,
staleTime: 5 * 60 * 1000, // 5 minutes
});
const exportAll = async () => {
const exportData = await orgFetchAll(
activeOrgType,
Expand Down
45 changes: 45 additions & 0 deletions src/composables/queries/useOrgsTableQuery.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { computed, ref } from 'vue';
import { useQuery } from '@tanstack/vue-query';
import useUserType from '@/composables/useUserType';
import useUserClaimsQuery from '@/composables/queries/useUserClaimsQuery';
import { orgPageFetcher } from '@/helpers/query/orgs';
import { ORGS_TABLE_QUERY_KEY } from '@/constants/queryKeys';
/**
* Orgs Table query.
*
* Fetches all orgs assigned to the current user account. This query is intended to be used by the List Orgs page that
* contains a tabbed data table with orgs (districts, schools, etc.) assigned to the user.
*
* @TODO: Explore the possibility of removing this query in favour of more granular queries for each org type.
*
* @param {String} activeOrgType – The active org type (district, school, etc.).
* @param {String} selectedDistrict – The selected district ID.
* @param {String} selectedSchool – The selected school ID.
* @param {String} orderBy – The order by field.
* @param {QueryOptions|undefined} queryOptions – Optional TanStack query options.
* @returns {UseQueryResult} The TanStack query result.
*/
const useOrgsTableQuery = (activeOrgType, selectedDistrict, selectedSchool, orderBy, queryOptions = undefined) => {
const { data: userClaims } = useUserClaimsQuery({ enabled: queryOptions?.enabled ?? true });
const { isSuperAdmin } = useUserType(userClaims);

const adminOrgs = computed(() => userClaims?.value?.claims?.minimalAdminOrgs);

return useQuery({
queryKey: [ORGS_TABLE_QUERY_KEY, activeOrgType, selectedDistrict, selectedSchool, orderBy],
queryFn: () =>
orgPageFetcher(
activeOrgType,
selectedDistrict,
selectedSchool,
orderBy,
ref(100000),
ref(0),
isSuperAdmin,
adminOrgs,
),
...queryOptions,
});
};

export default useOrgsTableQuery;
2 changes: 1 addition & 1 deletion src/constants/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ export const AUTH_SESSION_TIMEOUT_COUNTDOWN_DURATION =
export const AUTH_USER_TYPE = {
ADMIN: 'admin',
PARTICIPANT: 'participant',
SUPER_ADMIN: 'super_admin',
SUPER_ADMIN: 'super-admin',
};
1 change: 1 addition & 0 deletions src/constants/queryKeys.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export const DISTRICTS_QUERY_KEY = 'districts';
export const DISTRICT_SCHOOLS_QUERY_KEY = 'district-schools';
export const DSGF_ORGS_QUERY_KEY = 'dsgf-orgs';
export const ADMINITRATION_VARIANTS_QUERY_KEY = 'administration-variants';
export const ORGS_TABLE_QUERY_KEY = 'orgs-table';
1 change: 1 addition & 0 deletions src/helpers/query/orgs.js
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ export const orgPageFetcher = async (
}

const orgIds = adminOrgs.value[activeOrgType.value] ?? [];
// @TODO: Refactor to a single query for all orgs instead of multiple parallel queries.
const promises = orgIds.map((orgId) => fetchDocById(activeOrgType.value, orgId));
const orderField = (orderBy?.value ?? orderByDefault)[0].field.fieldPath;
const orderDirection = (orderBy?.value ?? orderByDefault)[0].direction;
Expand Down

0 comments on commit bb16b11

Please sign in to comment.