Skip to content

Commit

Permalink
Add cursor-based pagination for environment listings
Browse files Browse the repository at this point in the history
  • Loading branch information
peytondmurray committed Jan 20, 2025
1 parent b202f4f commit 65c3853
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 21 deletions.
12 changes: 11 additions & 1 deletion src/common/interfaces/ApiResponse.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
export interface IApiResponse<T = unknown> {
interface IApiResponse<T = unknown> {
data: T;
message: string | null;
page: number;
size: number;
count: number;
status: string;
}

interface ICursorPaginatedApiResponse<T = unknown> {
data: T;
status: string;
message: string | null;
cursor: string | null;
count: number;
}

export { IApiResponse, ICursorPaginatedApiResponse };
23 changes: 15 additions & 8 deletions src/features/environments/components/Environments.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const BaseEnvironments = ({
const { palette } = useTheme();
const version: string = process.env.REACT_APP_VERSION as string;
const environmentsState = useAppSelector(state => state.environments);
// const environmentsState = useAppSelector(state => state.environments);
const namespacesState = useAppSelector(state => state.namespaces);

const dispatch = useAppDispatch();
Expand Down Expand Up @@ -99,8 +100,8 @@ const BaseEnvironments = ({

const getEnvironments = async () => {
const { data: environmentsData } = await triggerQuery({
page: environmentsState.page,
size,
cursor: environmentsState.cursor,
limit: size,
search: environmentsState.search
});

Expand All @@ -115,31 +116,37 @@ const BaseEnvironments = ({
};

const handleChange = debounce(async (value: string) => {
const { data } = await triggerQuery({ page: 1, size, search: value });
const { data } = await triggerQuery({
cursor: null,
limit: size,
search: value
});

if (data) {
dispatch(
environmentsSlice.actions.searched({
data: data.data,
count: data.count,
search: value
search: value,
cursor: environmentsState.cursor
})
);
}
}, 500);

const next = async () => {
const { data } = await triggerQuery({
page: environmentsState.page + 1,
size,
cursor: environmentsState.cursor,
limit: size,
search: environmentsState.search
});

if (data) {
dispatch(
environmentsSlice.actions.nextFetched({
data: data.data,
count: data.count
count: data.count,
cursor: environmentsState.cursor
})
);
}
Expand Down Expand Up @@ -184,7 +191,7 @@ const BaseEnvironments = ({
{environmentsState.data && (
<EnvironmentsList
next={next}
hasMore={size * environmentsState.page < environmentsState.count}
hasMore={environmentsState.data.length < environmentsState.count}
environmentsList={environmentsState.data}
namespacesList={namespacesState.data}
search={environmentsState.search}
Expand Down
18 changes: 13 additions & 5 deletions src/features/environments/environmentsApiSlice.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import { IApiResponse } from "../../common/interfaces";
import { ICursorPaginatedApiResponse } from "../../common/interfaces";
import { Environment } from "../../common/models";
import { apiSlice } from "../api";

export const environmentsApiSlice = apiSlice.injectEndpoints({
endpoints: builder => ({
fetchEnvironments: builder.query<
IApiResponse<Environment[]>,
{ page: number; size: number; search: string }
ICursorPaginatedApiResponse<Environment[]>,
{ limit: number; cursor: string | null; search: string }
>({
query: dto =>
`/api/v1/environment/?page=${dto.page}&size=${dto.size}&search=${dto.search}`
query: ({ cursor, limit, search }) => {
const parameters = [
cursor !== null ? `cursor=${cursor}` : "",
`limit=${limit}`,
`search=${search}`
];
const queryParams =
parameters.length > 0 ? `?${parameters.join("&")}` : "";
return `/api/v1/environment/${queryParams}`;
}
})
})
});
Expand Down
18 changes: 11 additions & 7 deletions src/features/environments/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { Environment } from "../../common/models";

export interface IEnvironmentsState {
page: number;
cursor: string | null;
data: Environment[];
count: number;
search: string;
}

export const initialState: IEnvironmentsState = {
page: 1,
cursor: null,
data: [],
count: 0,
search: ""
Expand All @@ -33,24 +33,28 @@ export const environmentsSlice = createSlice({
data: Environment[];
count: number;
search: string;
cursor: string | null;
}>
) => {
return { ...action.payload, page: 1 };
return { ...action.payload, cursor: null };
},
nextFetched: (
state: IEnvironmentsState,
action: PayloadAction<{ data: Environment[]; count: number }>
action: PayloadAction<{
data: Environment[];
count: number;
cursor: string | null;
}>
) => {
const { data, count } = action.payload;
const { data, count, cursor } = action.payload;

const newData = state.data?.concat(data);
const nextPage = state.page + 1;

return {
...state,
data: newData,
count: count,
page: nextPage
cursor: cursor
};
}
}
Expand Down

0 comments on commit 65c3853

Please sign in to comment.