Skip to content

Commit

Permalink
fix: application rounds tab permission
Browse files Browse the repository at this point in the history
Filter queries by units the user has permissions, so we don't get
permission errors.
  • Loading branch information
joonatank committed Sep 5, 2024
1 parent b3440e4 commit fdceed5
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,24 @@ import { errorToast } from "common/src/common/toast";
import Loader from "@/component/Loader";
import { More } from "@/component/More";
import { useSort } from "@/hooks/useSort";
import { transformApplicantType } from "./utils";
import { getFilteredUnits, transformApplicantType } from "./utils";
import { useSearchParams } from "react-router-dom";
import { AllocatedEventsTable, SORT_KEYS } from "./AllocatedEventsTable";
import { transformWeekday, type Day } from "common/src/conversion";
import { getPermissionErrors } from "common/src/apolloUtils";

type Props = {
applicationRoundPk: number;
unitOptions: { nameFi: string; pk: number }[];
};

export function TimeSlotDataLoader({ applicationRoundPk }: Props): JSX.Element {
const [orderBy, handleSortChanged] = useSort(SORT_KEYS);
export function TimeSlotDataLoader({
unitOptions,
applicationRoundPk,
}: Props): JSX.Element {
const { t } = useTranslation();

const [orderBy, handleSortChanged] = useSort(SORT_KEYS);
const [searchParams] = useSearchParams();
const unitFilter = searchParams.getAll("unit");
const applicantFilter = searchParams.getAll("applicant");
Expand All @@ -34,7 +40,7 @@ export function TimeSlotDataLoader({ applicationRoundPk }: Props): JSX.Element {
const query = useAllocatedTimeSlotsQuery({
skip: !applicationRoundPk,
variables: {
allocatedUnit: unitFilter.map(Number).filter(Number.isFinite),
allocatedUnit: getFilteredUnits(unitFilter, unitOptions),
applicationRound: applicationRoundPk,
applicantType: transformApplicantType(applicantFilter),
applicationSectionStatus: [
Expand All @@ -54,17 +60,19 @@ export function TimeSlotDataLoader({ applicationRoundPk }: Props): JSX.Element {
orderBy: transformOrderBy(orderBy),
},
onError: (err: ApolloError) => {
errorToast({ text: err.message });
const permErrors = getPermissionErrors(err);
if (permErrors.length > 0) {
errorToast({ text: t("errors.noPermission") });
} else {
errorToast({ text: t("errors.errorFetchingData") });
}
},
fetchPolicy: "cache-and-network",
// TODO enable or no?
nextFetchPolicy: "cache-first",
});

const { fetchMore, previousData, loading, data } = query;

const { t } = useTranslation();

const dataToUse = data ?? previousData;
if (loading && !dataToUse) {
return <Loader />;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,21 @@ import { More } from "@/component/More";
import React from "react";
import Loader from "@/component/Loader";
import { filterNonNullable } from "common/src/helpers";
import { getPermissionErrors } from "common/src/apolloUtils";
import { useTranslation } from "next-i18next";
import { getFilteredUnits } from "./utils";

type Props = {
applicationRoundPk: number;
unitOptions: { nameFi: string; pk: number }[];
};

function RejectedOccurrencesDataLoader({
applicationRoundPk,
unitOptions,
}: Props): JSX.Element {
const { t } = useTranslation();

const [orderBy, handleSortChanged] = useSort(SORT_KEYS);
const [searchParams] = useSearchParams();
const unitFilter = searchParams.getAll("unit");
Expand All @@ -32,18 +39,22 @@ function RejectedOccurrencesDataLoader({
useRejectedOccurrencesQuery({
variables: {
applicationRound: applicationRoundPk,
unit: unitFilter.map(Number).filter(Number.isFinite),
unit: getFilteredUnits(unitFilter, unitOptions),
reservationUnit: reservationUnitFilter
.map(Number)
.filter(Number.isFinite),
orderBy: transformOrderBy(orderBy),
textSearch: nameFilter,
},
onError: (err: ApolloError) => {
errorToast({ text: err.message });
const permErrors = getPermissionErrors(err);
if (permErrors.length > 0) {
errorToast({ text: t("errors.noPermission") });
} else {
errorToast({ text: t("errors.errorFetchingData") });
}
},
fetchPolicy: "cache-and-network",
// TODO enable or no?
nextFetchPolicy: "cache-first",
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import { isApplicationRoundInProgress } from "@/helpers";
import { breakpoints } from "common";
import RejectedOccurrencesDataLoader from "./RejectedOccurrencesDataLoader";
import { errorToast } from "common/src/common/toast";
import { hasPermission } from "@/modules/permissionHelper";
import { useSession } from "@/hooks/auth";

const HeadingContainer = styled.div`
display: flex;
Expand Down Expand Up @@ -247,8 +249,13 @@ export function Review({
applicationRound?.reservationUnits?.flatMap((x) => x)
);

const ds = getUnitOptions(resUnits);
const unitPks = uniqBy(ds, (unit) => unit.pk).sort((a, b) =>
const { user } = useSession();

// need filtered list of units that the user has permission to view
const ds = getUnitOptions(resUnits).filter((unit) =>
hasPermission(user, UserPermissionChoice.CanViewApplications, unit.pk)
);
const unitOptions = uniqBy(ds, (unit) => unit.pk).sort((a, b) =>
a.nameFi.localeCompare(b.nameFi)
);

Expand Down Expand Up @@ -341,15 +348,19 @@ export function Review({
</Tabs.TabList>
<Tabs.TabPanel>
<TabContent>
<Filters units={unitPks} enableApplicant />
<Filters units={unitOptions} enableApplicant />
<ApplicationDataLoader
applicationRoundPk={applicationRound.pk ?? 0}
/>
</TabContent>
</Tabs.TabPanel>
<Tabs.TabPanel>
<TabContent>
<Filters units={unitPks} statusOption="event" enableApplicant />
<Filters
units={unitOptions}
statusOption="event"
enableApplicant
/>
<ApplicationEventDataLoader
applicationRoundPk={applicationRound.pk ?? 0}
/>
Expand All @@ -358,7 +369,7 @@ export function Review({
<Tabs.TabPanel>
<TabContent>
<Filters
units={unitPks}
units={unitOptions}
reservationUnits={reservationUnitOptions}
enableApplicant
enableWeekday
Expand All @@ -367,20 +378,22 @@ export function Review({
/>
<TimeSlotDataLoader
applicationRoundPk={applicationRound.pk ?? 0}
unitOptions={unitOptions}
/>
</TabContent>
</Tabs.TabPanel>
{isApplicationRoundEnded && (
<Tabs.TabPanel>
<TabContent>
<Filters
units={unitPks}
units={unitOptions}
reservationUnits={reservationUnitOptions}
enableReservationUnit
statusOption="eventShort"
/>
<RejectedOccurrencesDataLoader
applicationRoundPk={applicationRound.pk ?? 0}
unitOptions={unitOptions}
/>
</TabContent>
</Tabs.TabPanel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,13 @@ export function formatAppliedReservationTime(time: {
const { count, hours } = time;
return `${formatNumber(count, "")} / ${formatters.oneDecimal.format(hours)} t`;
}

/// Clean query param selection and filter by possible units
/// @return array of selected unit pks or all possible unit pks
export function getFilteredUnits(
unitFilter: string[],
possibleUnits: { nameFi: string; pk: number }[]
): number[] {
const units = unitFilter.map(Number).filter(Number.isFinite);
return units.length > 0 ? units : possibleUnits.map((u) => u.pk);
}

0 comments on commit fdceed5

Please sign in to comment.