Skip to content

Commit

Permalink
fix(CentralIdentity): instructor reqs pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
jakeaturner committed Aug 21, 2024
1 parent 6180fad commit 3c78894
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 132 deletions.
13 changes: 13 additions & 0 deletions client/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
CentralIdentityLicense,
CentralIdentityOrg,
CentralIdentityUser,
CentralIdentityVerificationRequest,
CollectionResource,
ConductorBaseResponse,
ConductorSearchResponse,
Expand Down Expand Up @@ -403,6 +404,18 @@ class API {
return res;
}

async getCentralIdentityVerificationRequests(queryParams: { page?: number; limit?: number }) {
const res = await axios.get<
{
requests: CentralIdentityVerificationRequest[];
totalCount: number;
} & ConductorBaseResponse
>("/central-identity/verification-requests", {
params: queryParams,
});
return res;
}

// Commons
async getCommonsCatalog(paramsObj?: { activePage?: number; limit?: number }) {
const res = await axios.get<
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useEffect } from "react";
import { useState } from "react";
import { Link } from "react-router-dom";
import {
Header,
Expand All @@ -8,38 +8,29 @@ import {
Table,
Icon,
Button,
Dropdown,
} from "semantic-ui-react";
import { CentralIdentityVerificationRequest } from "../../../../types";
import axios from "axios";
import useGlobalError from "../../../../components/error/ErrorHooks";
import { PaginationWithItemsSelect } from "../../../../components/util/PaginationWithItemsSelect";
import {
getPrettyVerficationStatus,
verificationRequestStatusOptions,
} from "../../../../utils/centralIdentityHelpers";
import ManageVerificationRequestModal from "../../../../components/controlpanel/CentralIdentity/ManageVerificationRequestModal";
import { format as formatDate, parseISO } from "date-fns";
import { useQuery } from "@tanstack/react-query";
import api from "../../../../api";
import LoadingSpinner from "../../../../components/LoadingSpinner";
import { useModals } from "../../../../context/ModalContext";

const CentralIdentityInstructorVerifications = () => {
//Global State & Hooks
const { handleGlobalError } = useGlobalError();
const { openModal, closeAllModals } = useModals();

const [page, setPage] = useState<number>(1);
const [limit, setLimit] = useState<number>(10);
const { data, isFetching, refetch } = useQuery<{ requests: CentralIdentityVerificationRequest[], totalCount: number }>({
queryKey: ['central-identity-verification-requests', page, limit],
queryFn: () => loadData(),
})

//Data & UI
const [requests, setRequests] = useState<
CentralIdentityVerificationRequest[]
>([]);
const [loading, setLoading] = useState<boolean>(false);
const [activePage, setActivePage] = useState<number>(1);
const [totalItems, setTotalItems] = useState<number>(0);
const [totalPages, setTotalPages] = useState<number>(1);
const [itemsPerPage, setItemsPerPage] = useState<number>(10);
const [statusChoice, setStatusChoice] = useState<string | undefined>(
undefined
);
const [showManageModal, setShowManageModal] = useState<boolean>(false);
const [selectedRequest, setSelectedRequest] =
useState<CentralIdentityVerificationRequest | null>(null);
const TABLE_COLS = [
{ key: "firstName", text: "First Name" },
{ key: "lastName", text: "Last Name" },
Expand All @@ -48,53 +39,36 @@ const CentralIdentityInstructorVerifications = () => {
{ key: "Actions", text: "Actions" },
];

//Effects
useEffect(() => {
getRequests();
}, [activePage, itemsPerPage]);

// Handlers & Methods
async function getRequests(searchString?: string) {
async function loadData() {
try {
setLoading(true);

const res = await axios.get("/central-identity/verification-requests", {
params: {
activePage,
limit: itemsPerPage,
query: searchString,
status: 'open',
},
});

if (
res.data.err ||
!res.data.requests ||
!Array.isArray(res.data.requests) ||
res.data.totalCount === undefined
) {
throw new Error("Error retrieving users");
const response = await api.getCentralIdentityVerificationRequests({ page, limit });
if (response.data.err) {
console.error(response.data.errMsg);
throw new Error(response.data.errMsg);
}

setRequests(res.data.requests);
setTotalItems(res.data.totalCount);
setTotalPages(Math.ceil(res.data.totalCount / itemsPerPage));
return response.data;
} catch (err) {
handleGlobalError(err);
} finally {
setLoading(false);
return { requests: [], totalCount: 0 };
}
}

// Handlers & Methods
function handleSelectRequest(request: CentralIdentityVerificationRequest) {
setSelectedRequest(request);
setShowManageModal(true);
openModal(
<ManageVerificationRequestModal
show={true}
requestId={request.id.toString()}
userId={request.user_id.toString()}
onClose={handleCloseManageModal}
onSave={handleCloseManageModal}
/>
)
}

function handleCloseManageModal() {
setShowManageModal(false);
setSelectedRequest(null);
getRequests();
closeAllModals();
refetch();
}

return (
Expand Down Expand Up @@ -124,39 +98,20 @@ const CentralIdentityInstructorVerifications = () => {
</Breadcrumb.Section>
</Breadcrumb>
</Segment>
{/*
{
isFetching && <LoadingSpinner />
}
<Segment>
<Grid>
<Grid.Row>
<Grid.Column width="16">
<Dropdown
placeholder="Status..."
floating
selection
button
options={verificationRequestStatusOptions}
onChange={(_e, { value }) => {
setStatusChoice(value as string);
}}
value={statusChoice}
/>
</Grid.Column>
</Grid.Row>
</Grid>
</Segment>
*/}
<Segment loading={loading}>
<PaginationWithItemsSelect
activePage={activePage}
totalPages={totalPages}
itemsPerPage={itemsPerPage}
setItemsPerPageFn={setItemsPerPage}
setActivePageFn={setActivePage}
totalLength={totalItems}
activePage={page}
totalPages={data?.totalCount ? Math.ceil(data?.totalCount / limit) : 1}
itemsPerPage={limit}
setItemsPerPageFn={setLimit}
setActivePageFn={setPage}
totalLength={data?.totalCount ?? 0}
/>
</Segment>
<Segment loading={loading}>
<Segment>
<Table striped celled selectable>
<Table.Header>
<Table.Row>
Expand All @@ -168,8 +123,8 @@ const CentralIdentityInstructorVerifications = () => {
</Table.Row>
</Table.Header>
<Table.Body>
{requests.length > 0 &&
requests.map((req) => {
{data && data.requests.length > 0 &&
data.requests.map((req) => {
return (
<Table.Row key={req.id} className="word-break-all">
<Table.Cell>
Expand Down Expand Up @@ -201,7 +156,7 @@ const CentralIdentityInstructorVerifications = () => {
</Table.Row>
);
})}
{requests.length === 0 && (
{data && data.requests.length === 0 && (
<Table.Row>
<Table.Cell colSpan={TABLE_COLS.length + 1}>
<p className="text-center">
Expand All @@ -213,26 +168,17 @@ const CentralIdentityInstructorVerifications = () => {
</Table.Body>
</Table>
</Segment>
<Segment loading={loading}>
<Segment>
<PaginationWithItemsSelect
activePage={activePage}
totalPages={totalPages}
itemsPerPage={itemsPerPage}
setItemsPerPageFn={setItemsPerPage}
setActivePageFn={setActivePage}
totalLength={totalItems}
activePage={page}
totalPages={data?.totalCount ? Math.ceil(data?.totalCount / limit) : 1}
itemsPerPage={limit}
setItemsPerPageFn={setLimit}
setActivePageFn={setPage}
totalLength={data?.totalCount ?? 0}
/>
</Segment>
</Segment.Group>
{selectedRequest && (
<ManageVerificationRequestModal
show={showManageModal}
requestId={selectedRequest.id.toString()}
userId={selectedRequest.user_id.toString()}
onClose={handleCloseManageModal}
onSave={handleCloseManageModal}
/>
)}
</Grid.Column>
</Grid.Row>
</Grid>
Expand Down
3 changes: 1 addition & 2 deletions server/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,7 @@ router.route('/central-identity/verification-requests').get(
authAPI.verifyRequest,
authAPI.getUserAttributes,
authAPI.checkHasRoleMiddleware('libretexts', 'superadmin'),
centralIdentityAPI.validate('getVerificationRequests'),
middleware.checkValidationErrors,
middleware.validateZod(centralIdentityValidators.GetVerificationRequestsSchema),
centralIdentityAPI.getVerificationRequests,
);

Expand Down
29 changes: 5 additions & 24 deletions server/api/central-identity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
NewUserWebhookValidator,
CheckUserApplicationAccessValidator,
VerificationStatusUpdateWebhookValidator,
GetVerificationRequestsSchema,
} from "./validators/central-identity.js";
import Project, { ProjectInterface } from "../models/project.js";
import { getSubdomainFromLibrary } from "../util/librariesclient.js";
Expand Down Expand Up @@ -731,26 +732,17 @@ async function getServices(
}

async function getVerificationRequests(
req: TypedReqQuery<{
activePage?: number;
limit?: number;
status?: CentralIdentityVerificationRequestStatus;
}>,
req: z.infer<typeof GetVerificationRequestsSchema>,
res: Response<{
err: boolean;
requests: CentralIdentityVerificationRequest[];
totalCount: number;
}>
) {
try {
let page = 1;
let limit = req.query.limit || 25;
if (
req.query.activePage &&
Number.isInteger(parseInt(req.query.activePage.toString()))
) {
page = req.query.activePage;
}
const page = parseInt(req.query.page?.toString()) || 1;
const limit = parseInt(req.query.limit?.toString()) || 10;

const offset = getPaginationOffset(page, limit);

const requestsRes = await useCentralIdentityAxios(false).get(
Expand All @@ -759,7 +751,6 @@ async function getVerificationRequests(
params: {
offset,
limit,
status: req.query.status ? req.query.status : undefined,
},
}
);
Expand Down Expand Up @@ -1058,16 +1049,6 @@ function validate(method: string) {
case "updateUser": {
return [param("id", conductorErrors.err1).exists().isUUID()];
}
case "getVerificationRequests": {
return [
param("activePage", conductorErrors.err1).optional().isInt(),
param("limit", conductorErrors.err1).optional().isInt(),
param("status", conductorErrors.err1)
.optional()
.isString()
.custom(validateVerificationRequestStatus),
];
}
case "getOrgs": {
return [
param("activePage", conductorErrors.err1).optional().isInt(),
Expand Down
7 changes: 7 additions & 0 deletions server/api/validators/central-identity.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { query } from "express";
import { z } from "zod";
import { PaginationSchema } from "./misc";

export const NewUserWebhookValidator = z.object({
body: z.object({
Expand Down Expand Up @@ -30,3 +32,8 @@ export const CheckUserApplicationAccessValidator = z.object({
applicationId: z.coerce.number().positive().int(),
}),
});


export const GetVerificationRequestsSchema = z.object({
query: PaginationSchema,
})

0 comments on commit 3c78894

Please sign in to comment.