From 552319dadbe1c71e4d21fc212ccaaf1d2a296e64 Mon Sep 17 00:00:00 2001 From: araddcc002 Date: Mon, 30 Sep 2024 08:34:44 +0000 Subject: [PATCH 01/12] wip for pagination --- .../src/routes/v2/model/getModelsSearch.ts | 5 +- backend/src/services/model.ts | 1 + frontend/actions/model.ts | 2 + frontend/pages/index.tsx | 63 +++++++++++++------ frontend/src/common/PaginationSelector.tsx | 39 ++++++++++++ 5 files changed, 89 insertions(+), 21 deletions(-) create mode 100644 frontend/src/common/PaginationSelector.tsx diff --git a/backend/src/routes/v2/model/getModelsSearch.ts b/backend/src/routes/v2/model/getModelsSearch.ts index b961ff52c..94e74e313 100644 --- a/backend/src/routes/v2/model/getModelsSearch.ts +++ b/backend/src/routes/v2/model/getModelsSearch.ts @@ -20,6 +20,7 @@ export const getModelsSearchSchema = z.object({ search: z.string().optional().default(''), allowTemplating: strictCoerceBoolean(z.boolean().optional()), schemaId: z.string().optional(), + currentPage: z.string().optional(), }), }) @@ -44,6 +45,7 @@ registerPath({ kind: z.string().openapi({ example: EntryKind.Model }), allowTemplating: z.boolean().openapi({ example: true }), schemaId: z.string().optional(), + currentPage: z.string().optional(), }), ), }), @@ -70,7 +72,7 @@ export const getModelsSearch = [ async (req: Request, res: Response) => { req.audit = AuditInfo.SearchModels const { - query: { kind, libraries, filters, search, task, allowTemplating, schemaId }, + query: { kind, libraries, filters, search, task, allowTemplating, schemaId, currentPage }, } = parse(req, getModelsSearchSchema) const foundModels = await searchModels( @@ -82,6 +84,7 @@ export const getModelsSearch = [ task, allowTemplating, schemaId, + currentPage, ) const models = foundModels.map((model) => ({ id: model.id, diff --git a/backend/src/services/model.ts b/backend/src/services/model.ts index df4f6b659..42d7bc866 100644 --- a/backend/src/services/model.ts +++ b/backend/src/services/model.ts @@ -113,6 +113,7 @@ export async function searchModels( task?: string, allowTemplating?: boolean, schemaId?: string, + _currentPage?: string, ): Promise> { const query: any = {} diff --git a/frontend/actions/model.ts b/frontend/actions/model.ts index 3eb6a8868..101ac65c9 100644 --- a/frontend/actions/model.ts +++ b/frontend/actions/model.ts @@ -26,6 +26,7 @@ export function useListModels( search = '', allowTemplating?: boolean, schemaId?: string, + currentPage?: number | string, ) { const queryParams = { ...(kind && { kind }), @@ -35,6 +36,7 @@ export function useListModels( ...(search && { search }), ...(allowTemplating && { allowTemplating }), ...(schemaId && { schemaId }), + ...(currentPage && { currentPage }), } const { data, isLoading, error, mutate } = useSWR< { diff --git a/frontend/pages/index.tsx b/frontend/pages/index.tsx index 22fc42e8a..a4a2838d5 100644 --- a/frontend/pages/index.tsx +++ b/frontend/pages/index.tsx @@ -20,6 +20,7 @@ import { useRouter } from 'next/router' import React, { ChangeEvent, Fragment, useCallback, useEffect, useState } from 'react' import ChipSelector from 'src/common/ChipSelector' import Loading from 'src/common/Loading' +import PaginationSelector from 'src/common/PaginationSelector' import Title from 'src/common/Title' import useDebounce from 'src/hooks/useDebounce' import EntryList from 'src/marketplace/EntryList' @@ -39,6 +40,7 @@ export default function Marketplace() { const [selectedTask, setSelectedTask] = useState('') const [selectedTypes, setSelectedTypes] = useState([]) const [selectedTab, setSelectedTab] = useState(EntryKind.MODEL) + const [currentPage, setCurrentPage] = useState(1) const debouncedFilter = useDebounce(filter, 250) const { models, isModelsError, isModelsLoading } = useListModels( @@ -47,6 +49,9 @@ export default function Marketplace() { selectedTask, selectedLibraries, debouncedFilter, + undefined, + undefined, + currentPage, ) const { @@ -98,6 +103,14 @@ export default function Marketplace() { [router], ) + const handleCurrentPageChange = useCallback( + (newPage: number | string) => { + setCurrentPage(newPage) + updateQueryParams('currentPage', newPage as string) + }, + [updateQueryParams], + ) + const handleFilterChange = useCallback( (e: ChangeEvent) => { setFilter(e.target.value) @@ -233,26 +246,36 @@ export default function Marketplace() { {isModelsLoading && } - {!isModelsLoading && selectedTab === EntryKind.MODEL && ( -
- -
- )} - {!isDataCardsLoading && selectedTab === EntryKind.DATA_CARD && ( -
- -
- )} + + handleCurrentPageChange(newValue)} + /> + {!isModelsLoading && selectedTab === EntryKind.MODEL && ( +
+ +
+ )} + {!isDataCardsLoading && selectedTab === EntryKind.DATA_CARD && ( +
+ +
+ )} + handleCurrentPageChange(newValue)} + /> +
diff --git a/frontend/src/common/PaginationSelector.tsx b/frontend/src/common/PaginationSelector.tsx new file mode 100644 index 000000000..60f1a8ea9 --- /dev/null +++ b/frontend/src/common/PaginationSelector.tsx @@ -0,0 +1,39 @@ +import { ArrowBack, ArrowForward } from '@mui/icons-material' +import { IconButton, Stack, TextField } from '@mui/material' +import { useCallback } from 'react' + +interface PaginationSelectorProps { + currentPage: number | string + onChange: (newValue: number | string) => void +} + +export default function PaginationSelector({ currentPage, onChange }: PaginationSelectorProps) { + const handleBackPage = useCallback(() => { + if (currentPage > 1) { + onChange(parseInt(currentPage as string) - 1) + } + }, [currentPage, onChange]) + + const handleForwardPage = useCallback(() => { + onChange(parseInt(currentPage as string) + 1) + }, [currentPage, onChange]) + + const handleManualPageChange = useCallback( + (newValue: string) => { + onChange(parseInt(newValue) || '') + }, + [onChange], + ) + + return ( + + + + + handleManualPageChange(e.target.value)} /> + + + + + ) +} From cc2f0b7ba6d40a866ce07ab4cd01e5c438294e3f Mon Sep 17 00:00:00 2001 From: araddcc002 Date: Fri, 18 Oct 2024 15:27:37 +0000 Subject: [PATCH 02/12] improvements to the ui pagination component and implementation of the backend --- .../src/routes/v2/model/getModelsSearch.ts | 10 ++-- backend/src/services/model.ts | 32 ++++++------ frontend/actions/model.ts | 16 +++--- frontend/pages/index.tsx | 4 +- frontend/src/common/PaginationSelector.tsx | 49 +++++++++++++++---- 5 files changed, 76 insertions(+), 35 deletions(-) diff --git a/backend/src/routes/v2/model/getModelsSearch.ts b/backend/src/routes/v2/model/getModelsSearch.ts index 94e74e313..25a52e02d 100644 --- a/backend/src/routes/v2/model/getModelsSearch.ts +++ b/backend/src/routes/v2/model/getModelsSearch.ts @@ -48,6 +48,7 @@ registerPath({ currentPage: z.string().optional(), }), ), + totalEntries: z.number(), }), }, }, @@ -65,6 +66,7 @@ export interface ModelSearchResult { interface GetModelsResponse { models: Array + totalEntries: number } export const getModelsSearch = [ @@ -72,7 +74,7 @@ export const getModelsSearch = [ async (req: Request, res: Response) => { req.audit = AuditInfo.SearchModels const { - query: { kind, libraries, filters, search, task, allowTemplating, schemaId, currentPage }, + query: { kind, libraries, filters, search, task, allowTemplating, schemaId, currentPage = '0' }, } = parse(req, getModelsSearchSchema) const foundModels = await searchModels( @@ -84,9 +86,9 @@ export const getModelsSearch = [ task, allowTemplating, schemaId, - currentPage, + parseInt(currentPage) || 0, ) - const models = foundModels.map((model) => ({ + const models = foundModels.results.map((model) => ({ id: model.id, name: model.name, description: model.description, @@ -96,6 +98,6 @@ export const getModelsSearch = [ await audit.onSearchModel(req, models) - return res.json({ models }) + return res.json({ models, totalEntries: foundModels.totalEntries }) }, ] diff --git a/backend/src/services/model.ts b/backend/src/services/model.ts index d0bcde10d..17953df1f 100644 --- a/backend/src/services/model.ts +++ b/backend/src/services/model.ts @@ -30,6 +30,12 @@ export type CreateModelParams = Pick< ModelInterface, 'name' | 'teamId' | 'description' | 'visibility' | 'settings' | 'kind' | 'collaborators' > + +type ModelSearchResult = { + results: Array + totalEntries: number +} + export async function createModel(user: UserInterface, modelParams: CreateModelParams) { const modelId = convertStringToId(modelParams.name) @@ -115,8 +121,8 @@ export async function searchModels( task?: string, allowTemplating?: boolean, schemaId?: string, - _currentPage?: string, -): Promise> { + currentPage: number = 0, +): Promise { const query: any = {} if (kind) { @@ -166,21 +172,17 @@ export async function searchModels( } } - let cursor = ModelModel - // Find only matching documents - .find(query) - - if (!search) { - // Sort by last updated - cursor = cursor.sort({ updatedAt: -1 }) - } else { - // Sort by text search - cursor = cursor.sort({ score: { $meta: 'textScore' } }) - } + const promise = Promise.all([ + ModelModel.find(query) + .limit(10) + .skip(10 * currentPage) + .sort(!search ? { updatedAt: -1 } : { score: { $meta: 'textScore' } }), + ModelModel.find(query).countDocuments(), + ]) + const [results, count] = await promise - const results = await cursor const auths = await authorisation.models(user, results, ModelAction.View) - return results.filter((_, i) => auths[i].success) + return { results: results.filter((_, i) => auths[i].success), totalEntries: count } } export async function getModelCard( diff --git a/frontend/actions/model.ts b/frontend/actions/model.ts index 101ac65c9..cf8aaa6d7 100644 --- a/frontend/actions/model.ts +++ b/frontend/actions/model.ts @@ -6,6 +6,11 @@ import { ErrorInfo, fetcher } from '../utils/fetcher' const emptyModelList = [] +export interface EntrySearchResults { + models: EntrySearchResult[] + totalEntries: number +} + export interface EntrySearchResult { id: string name: string @@ -38,16 +43,15 @@ export function useListModels( ...(schemaId && { schemaId }), ...(currentPage && { currentPage }), } - const { data, isLoading, error, mutate } = useSWR< - { - models: EntrySearchResult[] - }, - ErrorInfo - >(Object.entries(queryParams).length > 0 ? `/api/v2/models/search?${qs.stringify(queryParams)}` : null, fetcher) + const { data, isLoading, error, mutate } = useSWR( + Object.entries(queryParams).length > 0 ? `/api/v2/models/search?${qs.stringify(queryParams)}` : null, + fetcher, + ) return { mutateModels: mutate, models: data ? data.models : emptyModelList, + totalModels: data ? data.totalEntries : 0, isModelsLoading: isLoading, isModelsError: error, } diff --git a/frontend/pages/index.tsx b/frontend/pages/index.tsx index a4a2838d5..3992fd0f6 100644 --- a/frontend/pages/index.tsx +++ b/frontend/pages/index.tsx @@ -43,7 +43,7 @@ export default function Marketplace() { const [currentPage, setCurrentPage] = useState(1) const debouncedFilter = useDebounce(filter, 250) - const { models, isModelsError, isModelsLoading } = useListModels( + const { models, totalModels, isModelsError, isModelsLoading } = useListModels( EntryKind.MODEL, selectedTypes, selectedTask, @@ -250,6 +250,7 @@ export default function Marketplace() { handleCurrentPageChange(newValue)} + totalEntries={totalModels} /> {!isModelsLoading && selectedTab === EntryKind.MODEL && (
@@ -274,6 +275,7 @@ export default function Marketplace() { handleCurrentPageChange(newValue)} + totalEntries={totalModels} /> diff --git a/frontend/src/common/PaginationSelector.tsx b/frontend/src/common/PaginationSelector.tsx index 60f1a8ea9..1b9b77ba0 100644 --- a/frontend/src/common/PaginationSelector.tsx +++ b/frontend/src/common/PaginationSelector.tsx @@ -1,13 +1,18 @@ import { ArrowBack, ArrowForward } from '@mui/icons-material' -import { IconButton, Stack, TextField } from '@mui/material' -import { useCallback } from 'react' +import { IconButton, MenuItem, Select, SelectChangeEvent, Stack, Typography } from '@mui/material' +import { useCallback, useMemo } from 'react' interface PaginationSelectorProps { currentPage: number | string onChange: (newValue: number | string) => void + totalEntries: number } -export default function PaginationSelector({ currentPage, onChange }: PaginationSelectorProps) { +export default function PaginationSelector({ currentPage, onChange, totalEntries }: PaginationSelectorProps) { + const lastPage = useMemo(() => { + return totalEntries / 10 + }, [totalEntries]) + const handleBackPage = useCallback(() => { if (currentPage > 1) { onChange(parseInt(currentPage as string) - 1) @@ -15,22 +20,48 @@ export default function PaginationSelector({ currentPage, onChange }: Pagination }, [currentPage, onChange]) const handleForwardPage = useCallback(() => { - onChange(parseInt(currentPage as string) + 1) - }, [currentPage, onChange]) + if (currentPage < lastPage - 1) { + onChange(parseInt(currentPage as string) + 1) + } + }, [currentPage, lastPage, onChange]) const handleManualPageChange = useCallback( - (newValue: string) => { - onChange(parseInt(newValue) || '') + (event: SelectChangeEvent) => { + onChange(parseInt(event.target.value) || '') }, [onChange], ) + const menuItems = useMemo(() => { + return [...Array(lastPage | 0)].map((_, i) => { + return ( + + {i + 1} + + ) + }) + }, [lastPage]) + return ( - + - handleManualPageChange(e.target.value)} /> + Page: + + of {Math.round(lastPage)} From 2101f0b44989635aed74af475a0dde99cf9722d9 Mon Sep 17 00:00:00 2001 From: araddcc002 Date: Fri, 18 Oct 2024 16:27:04 +0000 Subject: [PATCH 03/12] further improvements --- .../src/routes/v2/model/getModelsSearch.ts | 5 +- backend/src/services/model.ts | 5 +- frontend/actions/model.ts | 2 + frontend/pages/index.tsx | 35 ++++++++++-- frontend/src/common/PaginationSelector.tsx | 56 +++++++++++++++---- 5 files changed, 82 insertions(+), 21 deletions(-) diff --git a/backend/src/routes/v2/model/getModelsSearch.ts b/backend/src/routes/v2/model/getModelsSearch.ts index 25a52e02d..1f7e50ac3 100644 --- a/backend/src/routes/v2/model/getModelsSearch.ts +++ b/backend/src/routes/v2/model/getModelsSearch.ts @@ -21,6 +21,7 @@ export const getModelsSearchSchema = z.object({ allowTemplating: strictCoerceBoolean(z.boolean().optional()), schemaId: z.string().optional(), currentPage: z.string().optional(), + pageSize: z.string().optional(), }), }) @@ -45,7 +46,6 @@ registerPath({ kind: z.string().openapi({ example: EntryKind.Model }), allowTemplating: z.boolean().openapi({ example: true }), schemaId: z.string().optional(), - currentPage: z.string().optional(), }), ), totalEntries: z.number(), @@ -74,7 +74,7 @@ export const getModelsSearch = [ async (req: Request, res: Response) => { req.audit = AuditInfo.SearchModels const { - query: { kind, libraries, filters, search, task, allowTemplating, schemaId, currentPage = '0' }, + query: { kind, libraries, filters, search, task, allowTemplating, schemaId, currentPage = '0', pageSize = '10' }, } = parse(req, getModelsSearchSchema) const foundModels = await searchModels( @@ -87,6 +87,7 @@ export const getModelsSearch = [ allowTemplating, schemaId, parseInt(currentPage) || 0, + parseInt(pageSize) || 10, ) const models = foundModels.results.map((model) => ({ id: model.id, diff --git a/backend/src/services/model.ts b/backend/src/services/model.ts index 17953df1f..bc8627385 100644 --- a/backend/src/services/model.ts +++ b/backend/src/services/model.ts @@ -122,6 +122,7 @@ export async function searchModels( allowTemplating?: boolean, schemaId?: string, currentPage: number = 0, + pageSize: number = 10, ): Promise { const query: any = {} @@ -174,8 +175,8 @@ export async function searchModels( const promise = Promise.all([ ModelModel.find(query) - .limit(10) - .skip(10 * currentPage) + .limit(pageSize) + .skip((currentPage - 1) * pageSize) .sort(!search ? { updatedAt: -1 } : { score: { $meta: 'textScore' } }), ModelModel.find(query).countDocuments(), ]) diff --git a/frontend/actions/model.ts b/frontend/actions/model.ts index cf8aaa6d7..25acd8fbc 100644 --- a/frontend/actions/model.ts +++ b/frontend/actions/model.ts @@ -32,6 +32,7 @@ export function useListModels( allowTemplating?: boolean, schemaId?: string, currentPage?: number | string, + pageSize?: number | string, ) { const queryParams = { ...(kind && { kind }), @@ -42,6 +43,7 @@ export function useListModels( ...(allowTemplating && { allowTemplating }), ...(schemaId && { schemaId }), ...(currentPage && { currentPage }), + ...(pageSize && { pageSize }), } const { data, isLoading, error, mutate } = useSWR( Object.entries(queryParams).length > 0 ? `/api/v2/models/search?${qs.stringify(queryParams)}` : null, diff --git a/frontend/pages/index.tsx b/frontend/pages/index.tsx index 3992fd0f6..4f579f364 100644 --- a/frontend/pages/index.tsx +++ b/frontend/pages/index.tsx @@ -41,6 +41,7 @@ export default function Marketplace() { const [selectedTypes, setSelectedTypes] = useState([]) const [selectedTab, setSelectedTab] = useState(EntryKind.MODEL) const [currentPage, setCurrentPage] = useState(1) + const [pageSize, setPageSize] = useState(10) const debouncedFilter = useDebounce(filter, 250) const { models, totalModels, isModelsError, isModelsLoading } = useListModels( @@ -52,13 +53,25 @@ export default function Marketplace() { undefined, undefined, currentPage, + pageSize, ) const { models: dataCards, + totalModels: totalDataCards, isModelsError: isDataCardsError, isModelsLoading: isDataCardsLoading, - } = useListModels(EntryKind.DATA_CARD, selectedTypes, selectedTask, selectedLibraries, debouncedFilter) + } = useListModels( + EntryKind.DATA_CARD, + selectedTypes, + selectedTask, + selectedLibraries, + debouncedFilter, + undefined, + undefined, + currentPage, + pageSize, + ) const theme = useTheme() const router = useRouter() @@ -111,6 +124,14 @@ export default function Marketplace() { [updateQueryParams], ) + const handlePageSizeChange = useCallback( + (newValue: number | string) => { + setPageSize(newValue) + updateQueryParams('pageSize', newValue as string) + }, + [updateQueryParams], + ) + const handleFilterChange = useCallback( (e: ChangeEvent) => { setFilter(e.target.value) @@ -234,12 +255,12 @@ export default function Marketplace() { setSelectedTab(EntryKind.MODEL)} /> setSelectedTab(EntryKind.DATA_CARD)} /> @@ -249,8 +270,10 @@ export default function Marketplace() { handleCurrentPageChange(newValue)} + currentPageOnChange={(newValue) => handleCurrentPageChange(newValue)} totalEntries={totalModels} + pageSize={pageSize} + pageSizeOnChange={(newValue) => handlePageSizeChange(newValue)} /> {!isModelsLoading && selectedTab === EntryKind.MODEL && (
@@ -274,8 +297,10 @@ export default function Marketplace() { )} handleCurrentPageChange(newValue)} + currentPageOnChange={(newValue) => handleCurrentPageChange(newValue)} totalEntries={totalModels} + pageSize={pageSize} + pageSizeOnChange={(newValue) => handlePageSizeChange(newValue)} /> diff --git a/frontend/src/common/PaginationSelector.tsx b/frontend/src/common/PaginationSelector.tsx index 1b9b77ba0..70faa50eb 100644 --- a/frontend/src/common/PaginationSelector.tsx +++ b/frontend/src/common/PaginationSelector.tsx @@ -1,35 +1,52 @@ import { ArrowBack, ArrowForward } from '@mui/icons-material' -import { IconButton, MenuItem, Select, SelectChangeEvent, Stack, Typography } from '@mui/material' +import { + FormControl, + IconButton, + InputLabel, + MenuItem, + Select, + SelectChangeEvent, + Stack, + Typography, +} from '@mui/material' import { useCallback, useMemo } from 'react' interface PaginationSelectorProps { currentPage: number | string - onChange: (newValue: number | string) => void + currentPageOnChange: (newValue: number | string) => void totalEntries: number + pageSize: number | string + pageSizeOnChange: (newValue: number | string) => void } -export default function PaginationSelector({ currentPage, onChange, totalEntries }: PaginationSelectorProps) { +export default function PaginationSelector({ + currentPage, + currentPageOnChange, + totalEntries, + pageSize, + pageSizeOnChange, +}: PaginationSelectorProps) { const lastPage = useMemo(() => { - return totalEntries / 10 - }, [totalEntries]) + return Math.ceil(totalEntries / parseInt(pageSize as string)) + }, [pageSize, totalEntries]) const handleBackPage = useCallback(() => { if (currentPage > 1) { - onChange(parseInt(currentPage as string) - 1) + currentPageOnChange(parseInt(currentPage as string) - 1) } - }, [currentPage, onChange]) + }, [currentPage, currentPageOnChange]) const handleForwardPage = useCallback(() => { - if (currentPage < lastPage - 1) { - onChange(parseInt(currentPage as string) + 1) + if (currentPage < lastPage) { + currentPageOnChange(parseInt(currentPage as string) + 1) } - }, [currentPage, lastPage, onChange]) + }, [currentPage, lastPage, currentPageOnChange]) const handleManualPageChange = useCallback( (event: SelectChangeEvent) => { - onChange(parseInt(event.target.value) || '') + currentPageOnChange(parseInt(event.target.value) || '') }, - [onChange], + [currentPageOnChange], ) const menuItems = useMemo(() => { @@ -62,6 +79,21 @@ export default function PaginationSelector({ currentPage, onChange, totalEntries {menuItems} of {Math.round(lastPage)} + + Page size + + From 2640cfe1106a06df0b7fe09de02c323bd33ef108 Mon Sep 17 00:00:00 2001 From: araddcc002 Date: Fri, 1 Nov 2024 08:15:21 +0000 Subject: [PATCH 04/12] wip --- backend/src/routes/v2/model/getModelsSearch.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/routes/v2/model/getModelsSearch.ts b/backend/src/routes/v2/model/getModelsSearch.ts index 1f7e50ac3..96eec093a 100644 --- a/backend/src/routes/v2/model/getModelsSearch.ts +++ b/backend/src/routes/v2/model/getModelsSearch.ts @@ -20,8 +20,8 @@ export const getModelsSearchSchema = z.object({ search: z.string().optional().default(''), allowTemplating: strictCoerceBoolean(z.boolean().optional()), schemaId: z.string().optional(), - currentPage: z.string().optional(), - pageSize: z.string().optional(), + currentPage: z.coerce.number().optional(), + pageSize: z.coerce.number().optional(), }), }) @@ -74,7 +74,7 @@ export const getModelsSearch = [ async (req: Request, res: Response) => { req.audit = AuditInfo.SearchModels const { - query: { kind, libraries, filters, search, task, allowTemplating, schemaId, currentPage = '0', pageSize = '10' }, + query: { kind, libraries, filters, search, task, allowTemplating, schemaId, currentPage = 0, pageSize = 10 }, } = parse(req, getModelsSearchSchema) const foundModels = await searchModels( @@ -86,8 +86,8 @@ export const getModelsSearch = [ task, allowTemplating, schemaId, - parseInt(currentPage) || 0, - parseInt(pageSize) || 10, + currentPage, + pageSize, ) const models = foundModels.results.map((model) => ({ id: model.id, From d85964c582d318c57c566221d796badfecb630f5 Mon Sep 17 00:00:00 2001 From: araddcc002 Date: Fri, 1 Nov 2024 14:26:04 +0000 Subject: [PATCH 05/12] improvements to pagination --- backend/src/services/model.ts | 15 +++--- frontend/actions/model.ts | 4 +- frontend/pages/index.tsx | 38 ++++++++------ frontend/src/Form/EditableFormHeading.tsx | 4 +- frontend/src/common/PaginationSelector.tsx | 61 +++++++++++++--------- 5 files changed, 70 insertions(+), 52 deletions(-) diff --git a/backend/src/services/model.ts b/backend/src/services/model.ts index bc8627385..5bc521ea2 100644 --- a/backend/src/services/model.ts +++ b/backend/src/services/model.ts @@ -173,17 +173,14 @@ export async function searchModels( } } - const promise = Promise.all([ - ModelModel.find(query) - .limit(pageSize) - .skip((currentPage - 1) * pageSize) - .sort(!search ? { updatedAt: -1 } : { score: { $meta: 'textScore' } }), - ModelModel.find(query).countDocuments(), - ]) - const [results, count] = await promise + const results = await ModelModel.find(query).sort(!search ? { updatedAt: -1 } : { score: { $meta: 'textScore' } }) + // As we need to authenticate which models the user has permission to, we need to fetch all models that + // match the query first, and then filter them based on pagination. const auths = await authorisation.models(user, results, ModelAction.View) - return { results: results.filter((_, i) => auths[i].success), totalEntries: count } + const authorisedResults = results.filter((_, i) => auths[i].success) + const paginatedResults = authorisedResults.slice((currentPage - 1) * pageSize, currentPage * pageSize) + return { results: paginatedResults, totalEntries: authorisedResults.length } } export async function getModelCard( diff --git a/frontend/actions/model.ts b/frontend/actions/model.ts index 25acd8fbc..aa0931d1a 100644 --- a/frontend/actions/model.ts +++ b/frontend/actions/model.ts @@ -31,8 +31,8 @@ export function useListModels( search = '', allowTemplating?: boolean, schemaId?: string, - currentPage?: number | string, - pageSize?: number | string, + currentPage?: number, + pageSize?: number, ) { const queryParams = { ...(kind && { kind }), diff --git a/frontend/pages/index.tsx b/frontend/pages/index.tsx index 4f579f364..f88634578 100644 --- a/frontend/pages/index.tsx +++ b/frontend/pages/index.tsx @@ -40,8 +40,8 @@ export default function Marketplace() { const [selectedTask, setSelectedTask] = useState('') const [selectedTypes, setSelectedTypes] = useState([]) const [selectedTab, setSelectedTab] = useState(EntryKind.MODEL) - const [currentPage, setCurrentPage] = useState(1) - const [pageSize, setPageSize] = useState(10) + const [currentPage, setCurrentPage] = useState(1) + const [pageSize, setPageSize] = useState(10) const debouncedFilter = useDebounce(filter, 250) const { models, totalModels, isModelsError, isModelsLoading } = useListModels( @@ -76,11 +76,19 @@ export default function Marketplace() { const theme = useTheme() const router = useRouter() - const { filter: filterFromQuery, task: taskFromQuery, libraries: librariesFromQuery } = router.query + const { + filter: filterFromQuery, + task: taskFromQuery, + libraries: librariesFromQuery, + currentPage: currentPageFromQuery, + pageSize: pageSizeFromQuery, + } = router.query useEffect(() => { - if (filterFromQuery) setFilter(filterFromQuery as string) - if (taskFromQuery) setSelectedTask(taskFromQuery as string) + if (filterFromQuery && typeof filterFromQuery === 'string') setFilter(filterFromQuery) + if (taskFromQuery && typeof taskFromQuery === 'string') setSelectedTask(taskFromQuery) + if (currentPageFromQuery && typeof currentPageFromQuery === 'string') setCurrentPage(parseInt(currentPageFromQuery)) + if (pageSizeFromQuery && typeof pageSizeFromQuery === 'string') setPageSize(parseInt(pageSizeFromQuery)) if (librariesFromQuery) { let librariesAsArray: string[] = [] if (typeof librariesFromQuery === 'string') { @@ -90,7 +98,7 @@ export default function Marketplace() { } setSelectedLibraries([...librariesAsArray]) } - }, [filterFromQuery, taskFromQuery, librariesFromQuery]) + }, [filterFromQuery, taskFromQuery, librariesFromQuery, currentPageFromQuery, pageSizeFromQuery]) const handleSelectedTypesOnChange = useCallback((selected: string[]) => { if (selected.length > 0) { @@ -117,17 +125,17 @@ export default function Marketplace() { ) const handleCurrentPageChange = useCallback( - (newPage: number | string) => { + (newPage: number) => { setCurrentPage(newPage) - updateQueryParams('currentPage', newPage as string) + updateQueryParams('currentPage', newPage.toString()) }, [updateQueryParams], ) const handlePageSizeChange = useCallback( - (newValue: number | string) => { + (newValue: number) => { setPageSize(newValue) - updateQueryParams('pageSize', newValue as string) + updateQueryParams('pageSize', newValue.toString()) }, [updateQueryParams], ) @@ -266,15 +274,15 @@ export default function Marketplace() { /> - {isModelsLoading && } handleCurrentPageChange(newValue)} + onCurrentPageChange={(newValue) => handleCurrentPageChange(newValue)} totalEntries={totalModels} pageSize={pageSize} - pageSizeOnChange={(newValue) => handlePageSizeChange(newValue)} + onPageSizeChange={(newValue) => handlePageSizeChange(newValue)} /> + {(isModelsLoading || isDataCardsLoading) && } {!isModelsLoading && selectedTab === EntryKind.MODEL && (
handleCurrentPageChange(newValue)} + onCurrentPageChange={(newValue) => handleCurrentPageChange(newValue)} totalEntries={totalModels} pageSize={pageSize} - pageSizeOnChange={(newValue) => handlePageSizeChange(newValue)} + onPageSizeChange={(newValue) => handlePageSizeChange(newValue)} /> diff --git a/frontend/src/Form/EditableFormHeading.tsx b/frontend/src/Form/EditableFormHeading.tsx index 9735f1b89..71ce18e45 100644 --- a/frontend/src/Form/EditableFormHeading.tsx +++ b/frontend/src/Form/EditableFormHeading.tsx @@ -8,8 +8,8 @@ type EditableFormHeadingProps = { editButtonText: string isEdit: boolean isLoading: boolean - canUserEditOrDelete: boolean - actionButtonsTooltip: string + canUserEditOrDelete?: boolean + actionButtonsTooltip?: string onEdit: () => void onCancel: () => void onSubmit: () => void diff --git a/frontend/src/common/PaginationSelector.tsx b/frontend/src/common/PaginationSelector.tsx index 70faa50eb..9a13b967a 100644 --- a/frontend/src/common/PaginationSelector.tsx +++ b/frontend/src/common/PaginationSelector.tsx @@ -9,51 +9,64 @@ import { Stack, Typography, } from '@mui/material' -import { useCallback, useMemo } from 'react' +import { useCallback, useEffect, useMemo } from 'react' interface PaginationSelectorProps { - currentPage: number | string - currentPageOnChange: (newValue: number | string) => void + currentPage: number + onCurrentPageChange: (newValue: number) => void totalEntries: number - pageSize: number | string - pageSizeOnChange: (newValue: number | string) => void + pageSize: number + onPageSizeChange: (newValue: number) => void } export default function PaginationSelector({ currentPage, - currentPageOnChange, + onCurrentPageChange, totalEntries, pageSize, - pageSizeOnChange, + onPageSizeChange, }: PaginationSelectorProps) { const lastPage = useMemo(() => { - return Math.ceil(totalEntries / parseInt(pageSize as string)) + return Math.ceil(totalEntries / parseInt(pageSize.toString())) }, [pageSize, totalEntries]) + useEffect(() => { + if (currentPage > lastPage) { + onCurrentPageChange(lastPage) + } + }, [currentPage, lastPage, onCurrentPageChange]) + const handleBackPage = useCallback(() => { if (currentPage > 1) { - currentPageOnChange(parseInt(currentPage as string) - 1) + onCurrentPageChange(currentPage - 1) } - }, [currentPage, currentPageOnChange]) + }, [currentPage, onCurrentPageChange]) const handleForwardPage = useCallback(() => { if (currentPage < lastPage) { - currentPageOnChange(parseInt(currentPage as string) + 1) + onCurrentPageChange(currentPage + 1) } - }, [currentPage, lastPage, currentPageOnChange]) + }, [currentPage, lastPage, onCurrentPageChange]) const handleManualPageChange = useCallback( (event: SelectChangeEvent) => { - currentPageOnChange(parseInt(event.target.value) || '') + onCurrentPageChange(parseInt(event.target.value)) + }, + [onCurrentPageChange], + ) + + const handlePageSizeChange = useCallback( + (event: SelectChangeEvent) => { + onPageSizeChange(parseInt(event.target.value)) }, - [currentPageOnChange], + [onPageSizeChange], ) - const menuItems = useMemo(() => { - return [...Array(lastPage | 0)].map((_, i) => { + const pageNumberOptions = useMemo(() => { + return [...Array(lastPage | 0)].map((_, index) => { return ( - - {i + 1} + + {index + 1} ) }) @@ -67,16 +80,16 @@ export default function PaginationSelector({ Page: of {Math.round(lastPage)} @@ -85,8 +98,8 @@ export default function PaginationSelector({ labelId='page-size-selector' label='Page size' size='small' - value={pageSize} - onChange={(event) => pageSizeOnChange(event.target.value)} + value={`${pageSize}`} + onChange={handlePageSizeChange} > 10 20 From 891195abc2241160240cd2073fbc5bd8d1da4c41 Mon Sep 17 00:00:00 2001 From: araddcc002 Date: Fri, 1 Nov 2024 17:27:34 +0000 Subject: [PATCH 06/12] fixed unit tests --- .../src/routes/v2/model/getModelsSearch.ts | 12 +++++----- .../getModelsSearch.spec.ts.snap | 6 +++-- .../test/routes/model/getModelsSearch.spec.ts | 22 ++++++++++++++++--- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/backend/src/routes/v2/model/getModelsSearch.ts b/backend/src/routes/v2/model/getModelsSearch.ts index 96eec093a..93317b0eb 100644 --- a/backend/src/routes/v2/model/getModelsSearch.ts +++ b/backend/src/routes/v2/model/getModelsSearch.ts @@ -37,7 +37,7 @@ registerPath({ content: { 'application/json': { schema: z.object({ - models: z.array( + results: z.array( z.object({ id: z.string().openapi({ example: 'yolo-abcdef' }), name: z.string().openapi({ example: 'Yolo v4' }), @@ -64,8 +64,8 @@ export interface ModelSearchResult { kind: EntryKindKeys } -interface GetModelsResponse { - models: Array +export interface GetModelsResponse { + results: Array totalEntries: number } @@ -89,7 +89,7 @@ export const getModelsSearch = [ currentPage, pageSize, ) - const models = foundModels.results.map((model) => ({ + const results = foundModels.results.map((model) => ({ id: model.id, name: model.name, description: model.description, @@ -97,8 +97,8 @@ export const getModelsSearch = [ kind: model.kind, })) - await audit.onSearchModel(req, models) + await audit.onSearchModel(req, results) - return res.json({ models, totalEntries: foundModels.totalEntries }) + return res.json({ results, totalEntries: foundModels.totalEntries }) }, ] diff --git a/backend/test/routes/model/__snapshots__/getModelsSearch.spec.ts.snap b/backend/test/routes/model/__snapshots__/getModelsSearch.spec.ts.snap index 52d6454d8..e9e40678c 100644 --- a/backend/test/routes/model/__snapshots__/getModelsSearch.spec.ts.snap +++ b/backend/test/routes/model/__snapshots__/getModelsSearch.spec.ts.snap @@ -2,14 +2,16 @@ exports[`routes > model > getModelsSearch > 200 > ok 1`] = ` { - "models": [ + "results": [ { "description": "description", "id": "test", + "kind": "model", "name": "name", "tags": [], }, ], + "totalEntries": 1, } `; @@ -18,7 +20,7 @@ exports[`routes > model > getModelsSearch > audit > expected call 1`] = ` { "description": "description", "id": "test", - "kind": undefined, + "kind": "model", "name": "name", "tags": [], }, diff --git a/backend/test/routes/model/getModelsSearch.spec.ts b/backend/test/routes/model/getModelsSearch.spec.ts index b770903a8..e9446bc69 100644 --- a/backend/test/routes/model/getModelsSearch.spec.ts +++ b/backend/test/routes/model/getModelsSearch.spec.ts @@ -2,21 +2,37 @@ import qs from 'qs' import { describe, expect, test, vi } from 'vitest' import audit from '../../../src/connectors/audit/__mocks__/index.js' -import { getModelsSearchSchema } from '../../../src/routes/v2/model/getModelsSearch.js' +import { EntryKind } from '../../../src/models/Model.js' +import { + GetModelsResponse, + getModelsSearchSchema, + ModelSearchResult, +} from '../../../src/routes/v2/model/getModelsSearch.js' import { createFixture, testGet } from '../../testUtils/routes.js' vi.mock('../../../src/utils/user.js') vi.mock('../../../src/connectors/audit/index.js') +const mockedModelResult: ModelSearchResult = { + id: 'test', + name: 'name', + description: 'description', + tags: ['tag'], + kind: EntryKind.Model, +} +const mockedResults: GetModelsResponse = { + results: [mockedModelResult], + totalEntries: 1, +} + vi.mock('../../../src/services/model.js', () => ({ - searchModels: vi.fn(() => [{ id: 'test', name: 'name', description: 'description', tags: ['tag'] }]), + searchModels: vi.fn(() => mockedResults), })) describe('routes > model > getModelsSearch', () => { test('200 > ok', async () => { const fixture = createFixture(getModelsSearchSchema) const res = await testGet(`/api/v2/models/search?${qs.stringify(fixture)}`) - expect(res.statusCode).toBe(200) expect(res.body).matchSnapshot() }) From 5dda34015b2187cfa276cfdfbaa51dbc604c7f06 Mon Sep 17 00:00:00 2001 From: araddcc002 Date: Fri, 10 Jan 2025 13:51:51 +0000 Subject: [PATCH 07/12] merged main --- backend/src/routes/v2/model/getModelsSearch.ts | 2 +- frontend/actions/model.ts | 4 ++-- frontend/pages/index.tsx | 13 ++++--------- frontend/src/common/PaginationSelector.tsx | 8 +++++++- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/backend/src/routes/v2/model/getModelsSearch.ts b/backend/src/routes/v2/model/getModelsSearch.ts index 93317b0eb..c7420aaaf 100644 --- a/backend/src/routes/v2/model/getModelsSearch.ts +++ b/backend/src/routes/v2/model/getModelsSearch.ts @@ -74,7 +74,7 @@ export const getModelsSearch = [ async (req: Request, res: Response) => { req.audit = AuditInfo.SearchModels const { - query: { kind, libraries, filters, search, task, allowTemplating, schemaId, currentPage = 0, pageSize = 10 }, + query: { kind, libraries, filters, search, task, allowTemplating, schemaId, currentPage = 1, pageSize = 10 }, } = parse(req, getModelsSearchSchema) const foundModels = await searchModels( diff --git a/frontend/actions/model.ts b/frontend/actions/model.ts index 4a01c2a29..15ad052f4 100644 --- a/frontend/actions/model.ts +++ b/frontend/actions/model.ts @@ -7,7 +7,7 @@ import { ErrorInfo, fetcher } from '../utils/fetcher' const emptyModelList = [] export interface EntrySearchResults { - models: EntrySearchResult[] + results: EntrySearchResult[] totalEntries: number } @@ -52,7 +52,7 @@ export function useListModels( return { mutateModels: mutate, - models: data ? data.models : emptyModelList, + models: data ? data.results : emptyModelList, totalModels: data ? data.totalEntries : 0, isModelsLoading: isLoading, isModelsError: error, diff --git a/frontend/pages/index.tsx b/frontend/pages/index.tsx index f88634578..f20669d2e 100644 --- a/frontend/pages/index.tsx +++ b/frontend/pages/index.tsx @@ -126,8 +126,10 @@ export default function Marketplace() { const handleCurrentPageChange = useCallback( (newPage: number) => { - setCurrentPage(newPage) - updateQueryParams('currentPage', newPage.toString()) + if (newPage > 0) { + setCurrentPage(newPage) + updateQueryParams('currentPage', newPage.toString()) + } }, [updateQueryParams], ) @@ -275,13 +277,6 @@ export default function Marketplace() { - handleCurrentPageChange(newValue)} - totalEntries={totalModels} - pageSize={pageSize} - onPageSizeChange={(newValue) => handlePageSizeChange(newValue)} - /> {(isModelsLoading || isDataCardsLoading) && } {!isModelsLoading && selectedTab === EntryKind.MODEL && (
diff --git a/frontend/src/common/PaginationSelector.tsx b/frontend/src/common/PaginationSelector.tsx index 9a13b967a..c43028ba1 100644 --- a/frontend/src/common/PaginationSelector.tsx +++ b/frontend/src/common/PaginationSelector.tsx @@ -73,7 +73,13 @@ export default function PaginationSelector({ }, [lastPage]) return ( - + From b339ea5c24f5f35acf0e492aee53e761217a4ded Mon Sep 17 00:00:00 2001 From: araddcc002 Date: Fri, 10 Jan 2025 14:16:17 +0000 Subject: [PATCH 08/12] added a backend check where if currentpage or pagesize isnt set for list models it will return the full list --- backend/src/routes/v2/model/getModelsSearch.ts | 2 +- backend/src/services/model.ts | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/backend/src/routes/v2/model/getModelsSearch.ts b/backend/src/routes/v2/model/getModelsSearch.ts index c7420aaaf..09d906bb7 100644 --- a/backend/src/routes/v2/model/getModelsSearch.ts +++ b/backend/src/routes/v2/model/getModelsSearch.ts @@ -74,7 +74,7 @@ export const getModelsSearch = [ async (req: Request, res: Response) => { req.audit = AuditInfo.SearchModels const { - query: { kind, libraries, filters, search, task, allowTemplating, schemaId, currentPage = 1, pageSize = 10 }, + query: { kind, libraries, filters, search, task, allowTemplating, schemaId, currentPage, pageSize }, } = parse(req, getModelsSearchSchema) const foundModels = await searchModels( diff --git a/backend/src/services/model.ts b/backend/src/services/model.ts index f4fc536be..077a9482c 100644 --- a/backend/src/services/model.ts +++ b/backend/src/services/model.ts @@ -123,8 +123,8 @@ export async function searchModels( task?: string, allowTemplating?: boolean, schemaId?: string, - currentPage: number = 0, - pageSize: number = 10, + currentPage?: number, + pageSize?: number, ): Promise { const query: any = {} @@ -181,6 +181,9 @@ export async function searchModels( // match the query first, and then filter them based on pagination. const auths = await authorisation.models(user, results, ModelAction.View) const authorisedResults = results.filter((_, i) => auths[i].success) + if (!pageSize || !currentPage) { + return { results: authorisedResults, totalEntries: authorisedResults.length } + } const paginatedResults = authorisedResults.slice((currentPage - 1) * pageSize, currentPage * pageSize) return { results: paginatedResults, totalEntries: authorisedResults.length } } From f0727420516b493de98e09d1928a645173d6e41a Mon Sep 17 00:00:00 2001 From: araddcc002 Date: Fri, 10 Jan 2025 14:32:47 +0000 Subject: [PATCH 09/12] reverted model search response object name --- backend/src/routes/v2/model/getModelsSearch.ts | 8 ++++---- backend/src/services/model.ts | 6 +++--- .../model/__snapshots__/getModelsSearch.spec.ts.snap | 2 +- backend/test/routes/model/getModelsSearch.spec.ts | 2 +- frontend/actions/model.ts | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/backend/src/routes/v2/model/getModelsSearch.ts b/backend/src/routes/v2/model/getModelsSearch.ts index 09d906bb7..e5cb98ca5 100644 --- a/backend/src/routes/v2/model/getModelsSearch.ts +++ b/backend/src/routes/v2/model/getModelsSearch.ts @@ -65,7 +65,7 @@ export interface ModelSearchResult { } export interface GetModelsResponse { - results: Array + models: Array totalEntries: number } @@ -89,7 +89,7 @@ export const getModelsSearch = [ currentPage, pageSize, ) - const results = foundModels.results.map((model) => ({ + const models = foundModels.models.map((model) => ({ id: model.id, name: model.name, description: model.description, @@ -97,8 +97,8 @@ export const getModelsSearch = [ kind: model.kind, })) - await audit.onSearchModel(req, results) + await audit.onSearchModel(req, models) - return res.json({ results, totalEntries: foundModels.totalEntries }) + return res.json({ models, totalEntries: foundModels.totalEntries }) }, ] diff --git a/backend/src/services/model.ts b/backend/src/services/model.ts index 077a9482c..4bfc59714 100644 --- a/backend/src/services/model.ts +++ b/backend/src/services/model.ts @@ -32,7 +32,7 @@ export type CreateModelParams = Pick< > type ModelSearchResult = { - results: Array + models: Array totalEntries: number } @@ -182,10 +182,10 @@ export async function searchModels( const auths = await authorisation.models(user, results, ModelAction.View) const authorisedResults = results.filter((_, i) => auths[i].success) if (!pageSize || !currentPage) { - return { results: authorisedResults, totalEntries: authorisedResults.length } + return { models: authorisedResults, totalEntries: authorisedResults.length } } const paginatedResults = authorisedResults.slice((currentPage - 1) * pageSize, currentPage * pageSize) - return { results: paginatedResults, totalEntries: authorisedResults.length } + return { models: paginatedResults, totalEntries: authorisedResults.length } } export async function getModelCard( diff --git a/backend/test/routes/model/__snapshots__/getModelsSearch.spec.ts.snap b/backend/test/routes/model/__snapshots__/getModelsSearch.spec.ts.snap index e9e40678c..1b578deab 100644 --- a/backend/test/routes/model/__snapshots__/getModelsSearch.spec.ts.snap +++ b/backend/test/routes/model/__snapshots__/getModelsSearch.spec.ts.snap @@ -2,7 +2,7 @@ exports[`routes > model > getModelsSearch > 200 > ok 1`] = ` { - "results": [ + "models": [ { "description": "description", "id": "test", diff --git a/backend/test/routes/model/getModelsSearch.spec.ts b/backend/test/routes/model/getModelsSearch.spec.ts index e9446bc69..035c7184f 100644 --- a/backend/test/routes/model/getModelsSearch.spec.ts +++ b/backend/test/routes/model/getModelsSearch.spec.ts @@ -21,7 +21,7 @@ const mockedModelResult: ModelSearchResult = { kind: EntryKind.Model, } const mockedResults: GetModelsResponse = { - results: [mockedModelResult], + models: [mockedModelResult], totalEntries: 1, } diff --git a/frontend/actions/model.ts b/frontend/actions/model.ts index 15ad052f4..4a01c2a29 100644 --- a/frontend/actions/model.ts +++ b/frontend/actions/model.ts @@ -7,7 +7,7 @@ import { ErrorInfo, fetcher } from '../utils/fetcher' const emptyModelList = [] export interface EntrySearchResults { - results: EntrySearchResult[] + models: EntrySearchResult[] totalEntries: number } @@ -52,7 +52,7 @@ export function useListModels( return { mutateModels: mutate, - models: data ? data.results : emptyModelList, + models: data ? data.models : emptyModelList, totalModels: data ? data.totalEntries : 0, isModelsLoading: isLoading, isModelsError: error, From 8c3ef8458bb683d257e78f584a0aa2a66d5ea031 Mon Sep 17 00:00:00 2001 From: araddcc002 Date: Fri, 10 Jan 2025 16:08:07 +0000 Subject: [PATCH 10/12] logging for e2e --- .../e2e/bailo/make-and-review-access-request.cy.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/frontend/cypress/e2e/bailo/make-and-review-access-request.cy.ts b/frontend/cypress/e2e/bailo/make-and-review-access-request.cy.ts index 2e8cd1d76..1256bbf3d 100644 --- a/frontend/cypress/e2e/bailo/make-and-review-access-request.cy.ts +++ b/frontend/cypress/e2e/bailo/make-and-review-access-request.cy.ts @@ -3,6 +3,11 @@ let accessRequestUuid = '' const modelName = 'Test Model' const schemaId = 'minimal-access-request-general-v10' const accessRequestName = 'Test access request' +let spy + +Cypress.on('window:before:load', (win) => { + spy = cy.spy(win.console, 'error') // can be other methods - log, warn, etc +}) describe('Make and approve an access request', () => { before(() => { @@ -44,7 +49,11 @@ describe('Make and approve an access request', () => { }) cy.log('Creating the access request') - cy.get('body').contains('Select a different schema') + + cy.wrap({}).should(() => { + cy.get('body').contains('Select a different schema') + expect(spy).not.to.be.called + }) cy.get('[data-test=entitySelector]').contains('Joe Bloggs') cy.get('#root_name-label').contains('What is the name of the access request?') cy.get('#root_name').type(accessRequestName) From 8f4d5e421c730fc11926fb57e0354f6c411eeca9 Mon Sep 17 00:00:00 2001 From: araddcc002 Date: Fri, 10 Jan 2025 16:22:27 +0000 Subject: [PATCH 11/12] logging for e2e --- frontend/cypress/e2e/bailo/make-and-review-access-request.cy.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/cypress/e2e/bailo/make-and-review-access-request.cy.ts b/frontend/cypress/e2e/bailo/make-and-review-access-request.cy.ts index 1256bbf3d..cecf327c7 100644 --- a/frontend/cypress/e2e/bailo/make-and-review-access-request.cy.ts +++ b/frontend/cypress/e2e/bailo/make-and-review-access-request.cy.ts @@ -51,8 +51,8 @@ describe('Make and approve an access request', () => { cy.log('Creating the access request') cy.wrap({}).should(() => { - cy.get('body').contains('Select a different schema') expect(spy).not.to.be.called + cy.get('body').contains('Select a different schema') }) cy.get('[data-test=entitySelector]').contains('Joe Bloggs') cy.get('#root_name-label').contains('What is the name of the access request?') From 1e7be5f46c6c608464636605bc71fe4f287af523 Mon Sep 17 00:00:00 2001 From: araddcc002 Date: Fri, 10 Jan 2025 16:54:52 +0000 Subject: [PATCH 12/12] logging for e2e --- .../e2e/bailo/make-and-review-access-request.cy.ts | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/frontend/cypress/e2e/bailo/make-and-review-access-request.cy.ts b/frontend/cypress/e2e/bailo/make-and-review-access-request.cy.ts index cecf327c7..2e8cd1d76 100644 --- a/frontend/cypress/e2e/bailo/make-and-review-access-request.cy.ts +++ b/frontend/cypress/e2e/bailo/make-and-review-access-request.cy.ts @@ -3,11 +3,6 @@ let accessRequestUuid = '' const modelName = 'Test Model' const schemaId = 'minimal-access-request-general-v10' const accessRequestName = 'Test access request' -let spy - -Cypress.on('window:before:load', (win) => { - spy = cy.spy(win.console, 'error') // can be other methods - log, warn, etc -}) describe('Make and approve an access request', () => { before(() => { @@ -49,11 +44,7 @@ describe('Make and approve an access request', () => { }) cy.log('Creating the access request') - - cy.wrap({}).should(() => { - expect(spy).not.to.be.called - cy.get('body').contains('Select a different schema') - }) + cy.get('body').contains('Select a different schema') cy.get('[data-test=entitySelector]').contains('Joe Bloggs') cy.get('#root_name-label').contains('What is the name of the access request?') cy.get('#root_name').type(accessRequestName)