Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Préavis - Affiche la durée de la dernière requête dans la liste #3729

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const DEFAULT_LIST_FILTER_VALUES: ListFilter = {
statuses: undefined
}

export const DEFAULT_PAGE_SIZE = 10
export const DEFAULT_PAGE_SIZE = 50

export const COMMUNITY_PRIOR_NOTIFICATION_TYPES = ['Préavis communautaire', 'Préavis navire tiers']
export const DESIGNATED_PORTS_PRIOR_NOTIFICATION_TYPE_PREFIX = 'Ports désignés'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@ import { useListSorting } from '@hooks/useListSorting'
import { useLoadingState } from '@hooks/useLoadingState'
import { useMainAppDispatch } from '@hooks/useMainAppDispatch'
import { useMainAppSelector } from '@hooks/useMainAppSelector'
import { customSentry, CustomSentryMeasurementName } from '@libs/customSentry'
import { DisplayedErrorKey } from '@libs/DisplayedError/constants'
import { Accent, Button, Icon, Size, TableWithSelectableRows, usePrevious } from '@mtes-mct/monitor-ui'
import { skipToken } from '@reduxjs/toolkit/query'
import { flexRender, getCoreRowModel, getExpandedRowModel, useReactTable } from '@tanstack/react-table'
import { isLegacyFirefox } from '@utils/isLegacyFirefox'
import { useIsSuperUser } from 'auth/hooks/useIsSuperUser'
import { useCallback, useEffect, useState } from 'react'
import { useCallback, useEffect, useRef, useState } from 'react'
import styled, { css } from 'styled-components'

import { getTableColumns } from './columns'
Expand All @@ -43,6 +42,8 @@ type PriorNotificationListProps = Readonly<{
isFromUrl: boolean
}>
export function PriorNotificationList({ isFromUrl }: PriorNotificationListProps) {
const lastFetchStartDateRef = useRef<number | undefined>(undefined)

const dispatch = useMainAppDispatch()
const listFilter = useMainAppSelector(state => state.priorNotification.listFilterValues)
const openedPriorNotificationDetail = useMainAppSelector(
Expand All @@ -54,6 +55,7 @@ export function PriorNotificationList({ isFromUrl }: PriorNotificationListProps)
const isSuperUser = useIsSuperUser()

const [rowSelection, setRowSelection] = useState({})
const [lastFetchDuration, setLastFetchDuration] = useState<number | undefined>(undefined)

const { apiPaginationParams, reactTablePaginationState, setReactTablePaginationState } = useListPagination(
DEFAULT_PAGE_SIZE,
Expand Down Expand Up @@ -145,12 +147,17 @@ export function PriorNotificationList({ isFromUrl }: PriorNotificationListProps)
}
}, [previousListFilter, listFilter, table])

if (isBodyLoaderVisible) {
customSentry.startMeasurement(CustomSentryMeasurementName.PRIOR_NOTIFICATION_LIST_BODY_LOADING, '0')
customSentry.startMeasurement(CustomSentryMeasurementName.PRIOR_NOTIFICATION_LIST_BODY_SPINNER, '0')
} else {
customSentry.endMeasurement(CustomSentryMeasurementName.PRIOR_NOTIFICATION_LIST_BODY_SPINNER, '0', 2000)
}
useEffect(() => {
if (isFetching) {
lastFetchStartDateRef.current = Date.now()

return
}

if (lastFetchStartDateRef.current) {
setLastFetchDuration(Date.now() - lastFetchStartDateRef.current)
}
}, [isFetching])

return (
<>
Expand All @@ -176,7 +183,7 @@ export function PriorNotificationList({ isFromUrl }: PriorNotificationListProps)
<TableTop $isFromUrl={isFromUrl}>
<TableLegend>{`${
isBodyLoaderVisible || isError || totalLength === undefined ? '...' : totalLength
} préavis (tous les horaires sont en UTC)`}</TableLegend>
} préavis (tous les horaires sont en UTC) en ${isBodyLoaderVisible || isError || lastFetchDuration === undefined ? '...' : `${lastFetchDuration / 1000}s`}`}</TableLegend>

{isSuperUser && (
<Button
Expand Down
17 changes: 16 additions & 1 deletion frontend/src/hooks/__tests__/useLoadingState.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,12 +124,27 @@ describe('hooks/useLoadingState()', () => {
})
})

// Next page fetch starts
act(() => {
rerender({
filterAndSortingState: { filter: 'initial' },
isFetching: true,
paginationState: { pageIndex: 1, pageSize: 10 }
})
})

expect(result.current).toEqual({
isLoadingNewPage: false,
isLoadingNextPage: true,
isReloading: false
})

// New page fetch starts
act(() => {
rerender({
filterAndSortingState: { filter: 'changed' },
isFetching: true,
paginationState: { pageIndex: 1, pageSize: 10 }
paginationState: { pageIndex: 0, pageSize: 10 }
})
})

Expand Down
62 changes: 24 additions & 38 deletions frontend/src/hooks/useLoadingState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,18 @@ export type LoadingState = {
isReloading: boolean
}

const NO_LOADING_STATE: LoadingState = {
isLoadingNewPage: false,
isLoadingNextPage: false,
isReloading: false
}

export function useLoadingState(
isFetching: boolean,
filterAndSortingState: AnyObject,
paginationState: AnyObject
): LoadingState {
const isFirstFetchRef = useRef<boolean | undefined>(isFetching || undefined)
const isFirstRenderRef = useRef(true)
const initialPaginationState = useRef(paginationState)
const lastLoadingStateRef = useRef<LoadingState>({
isLoadingNewPage: isFetching,
isLoadingNextPage: false,
Expand All @@ -38,49 +43,30 @@ export function useLoadingState(
const previousPaginationState = usePreviousIf(paginationState, isFetching)
const wasFetching = usePrevious(isFetching)

if (isFirstRenderRef.current) {
isFirstRenderRef.current = false
if (!isFetching) {
lastLoadingStateRef.current = NO_LOADING_STATE

return lastLoadingStateRef.current
}

if (!isFetching) {
if (isFirstFetchRef.current === true && !!wasFetching) {
isFirstFetchRef.current = false
}

lastLoadingStateRef.current = {
isLoadingNewPage: false,
isLoadingNextPage: false,
isReloading: false
}
} else {
const hasFilterAndSortingStateChanged =
isFirstFetchRef.current !== undefined && !isEqual(filterAndSortingState, previousFilterAndSortingState)
const hasPaginationStateChanged =
isFirstFetchRef.current !== undefined && !isEqual(paginationState, previousPaginationState)

if (isFirstFetchRef.current === undefined) {
isFirstFetchRef.current = true
} else if (isFirstFetchRef.current && (hasFilterAndSortingStateChanged || hasPaginationStateChanged)) {
isFirstFetchRef.current = false
}
const hasNewFilterAndSortingState = !isEqual(filterAndSortingState, previousFilterAndSortingState)
const hasNewPaginationState =
!isEqual(paginationState, previousPaginationState) && !isEqual(paginationState, initialPaginationState)

// If the data is still been fetched with the same filter/sorting & pagination states,
// while not being a first load, this means the loading state is the same as the last one.
if (!isFirstFetchRef.current && wasFetching && !hasFilterAndSortingStateChanged && !hasPaginationStateChanged) {
return lastLoadingStateRef.current
}
// If the data is still been fetched with the same filter/sorting & pagination states,
// while not being a first load, this means the loading state is the same as the last one.
if (wasFetching && !hasNewFilterAndSortingState && !hasNewPaginationState) {
return lastLoadingStateRef.current
}

const isLoadingNewPage = isFirstFetchRef.current || hasFilterAndSortingStateChanged
const isLoadingNextPage = !isLoadingNewPage && !hasFilterAndSortingStateChanged && hasPaginationStateChanged
const isReloading = !isFirstFetchRef.current && !hasFilterAndSortingStateChanged && !hasPaginationStateChanged
const isLoadingNewPage = hasNewFilterAndSortingState
const isReloading = !hasNewFilterAndSortingState && !hasNewPaginationState
const isLoadingNextPage = !isLoadingNewPage && !isReloading

lastLoadingStateRef.current = {
isLoadingNewPage,
isLoadingNextPage,
isReloading
}
lastLoadingStateRef.current = {
isLoadingNewPage,
isLoadingNextPage,
isReloading
}

return lastLoadingStateRef.current
Expand Down
4 changes: 1 addition & 3 deletions frontend/src/libs/customSentry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ export enum CustomSentryMeasurementName {
LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER = 'LOGBOOK_PRIOR_NOTIFICATION_FORM_SPINNER',
MANUAL_PRIOR_NOTIFICATION_FORM_LOADING = 'MANUAL_PRIOR_NOTIFICATION_FORM_LOADING',
MANUAL_PRIOR_NOTIFICATION_FORM_SPINNER = 'MANUAL_PRIOR_NOTIFICATION_FORM_SPINNER',
PRIOR_NOTIFICATION_CARD_DOWNLOAD_BUTTON = 'PRIOR_NOTIFICATION_CARD_DOWNLOAD_BUTTON',
PRIOR_NOTIFICATION_LIST_BODY_LOADING = 'PRIOR_NOTIFICATION_LIST_BODY_LOADING',
PRIOR_NOTIFICATION_LIST_BODY_SPINNER = 'PRIOR_NOTIFICATION_LIST_BODY_SPINNER'
PRIOR_NOTIFICATION_CARD_DOWNLOAD_BUTTON = 'PRIOR_NOTIFICATION_CARD_DOWNLOAD_BUTTON'
}

class CustomSentry {
Expand Down
Loading