Skip to content

Commit

Permalink
Migrate alerts and fleet segments apis to rtk
Browse files Browse the repository at this point in the history
  • Loading branch information
louptheron committed Jan 31, 2025
1 parent 26664f2 commit f57c7d0
Show file tree
Hide file tree
Showing 17 changed files with 171 additions and 248 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,16 @@ data class VesselRiskFactor(
val gearOnboard: List<Gear>? = listOf(),
val speciesOnboard: List<Species>? = listOf(),
val totalWeightOnboard: Double? = null,
val segments: List<String>,
val segments: List<String> = listOf(),
val probableSegments: List<String>? = listOf(),
val segmentHighestImpact: String? = null,
val segmentHighestPriority: String? = null,
val lastControlDatetime: ZonedDateTime? = null,
val postControlComments: String? = null,
val numberControlsLastFiveYears: Short,
val numberControlsLastThreeYears: Short,
val numberInfractionsLastFiveYears: Short,
val numberGearSeizuresLastFiveYears: Short,
val numberSpeciesSeizuresLastFiveYears: Short,
val numberVesselSeizuresLastFiveYears: Short,
val numberControlsLastFiveYears: Short = 0,
val numberControlsLastThreeYears: Short = 0,
val numberInfractionsLastFiveYears: Short = 0,
val numberGearSeizuresLastFiveYears: Short = 0,
val numberSpeciesSeizuresLastFiveYears: Short = 0,
val numberVesselSeizuresLastFiveYears: Short = 0,
)
132 changes: 40 additions & 92 deletions frontend/src/api/alert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { FrontendApiError } from '@libs/FrontendApiError'

import { monitorfishApi, monitorfishApiKy } from './api'
import { monitorfishApi } from './api'

import type {
LEGACY_PendingAlert,
Expand Down Expand Up @@ -41,97 +41,45 @@ export const alertApi = monitorfishApi.injectEndpoints({
url: `/operational_alerts/silenced`
}),
transformErrorResponse: response => new FrontendApiError(CREATE_SILENCED_ALERT_ERROR_MESSAGE, response)
}),
deleteSilencedAlert: builder.mutation<void, string>({
query: id => ({
method: 'DELETE',
url: `/operational_alerts/silenced/${id}`
}),
transformErrorResponse: response => new FrontendApiError(DELETE_SILENCED_ALERT_ERROR_MESSAGE, response)
}),
getOperationalAlerts: builder.query<LEGACY_PendingAlert[], void>({
query: () => '/bff/v1/operational_alerts',
transformErrorResponse: response => new FrontendApiError(ALERTS_ERROR_MESSAGE, response),
transformResponse: (response: PendingAlert[]) => response.map(normalizePendingAlert)
}),
getSilencedAlerts: builder.query<LEGACY_SilencedAlert[], void>({
query: () => '/operational_alerts/silenced',
transformErrorResponse: response => new FrontendApiError(ALERTS_ERROR_MESSAGE, response),
transformResponse: (response: SilencedAlert[]) => response
}),
silenceAlert: builder.mutation<
LEGACY_SilencedAlert,
{ id: string; silencedAlertPeriodRequest: SilencedAlertPeriodRequest }
>({
query: ({ id, silencedAlertPeriodRequest }) => ({
body: {
beforeDateTime: silencedAlertPeriodRequest.beforeDateTime?.toISOString() ?? '',
silencedAlertPeriod: silencedAlertPeriodRequest.silencedAlertPeriod ?? ''
},
method: 'PUT',
url: `/operational_alerts/${id}/silence`
}),
transformErrorResponse: response => new FrontendApiError(SILENCE_ALERT_ERROR_MESSAGE, response),
transformResponse: (response: SilencedAlert) => response
}),
validateAlert: builder.mutation<void, string>({
query: id => ({
method: 'PUT',
url: `/operational_alerts/${id}/validate`
}),
transformErrorResponse: response => new FrontendApiError(VALIDATE_ALERT_ERROR_MESSAGE, response)
})
})
})

export const { useCreateSilencedAlertMutation } = alertApi

/**
* Get operational alerts
*
* @throws {@link FrontendApiError}
*/
async function getOperationalAlertsFromAPI(): Promise<LEGACY_PendingAlert[]> {
try {
const data = await monitorfishApiKy.get('/bff/v1/operational_alerts').json<PendingAlert[]>()

return data.map(normalizePendingAlert)
} catch (err) {
throw new FrontendApiError(ALERTS_ERROR_MESSAGE, (err as FrontendApiError).originalError)
}
}

/**
* Validate an alert
*
* @throws {@link FrontendApiError}
*/
async function validateAlertFromAPI(id: string): Promise<void> {
try {
await monitorfishApiKy.put(`/bff/v1/operational_alerts/${id}/validate`)
} catch (err) {
throw new FrontendApiError(VALIDATE_ALERT_ERROR_MESSAGE, (err as FrontendApiError).originalError)
}
}

/**
* Silence an alert and returns the saved silenced alert
*
* @throws {@link FrontendApiError}
*/
async function silenceAlertFromAPI(
id: string,
silencedAlertPeriodRequest: SilencedAlertPeriodRequest
): Promise<LEGACY_SilencedAlert> {
// TODO Normalize this data before calling the api service rather than here.
const silencedAlertPeriod = silencedAlertPeriodRequest.silencedAlertPeriod ?? ''
const beforeDateTime = silencedAlertPeriodRequest.beforeDateTime?.toISOString() ?? ''

try {
return await monitorfishApiKy
.put(`/bff/v1/operational_alerts/${id}/silence`, {
json: {
beforeDateTime,
silencedAlertPeriod
}
})
.json<SilencedAlert>()
} catch (err) {
throw new FrontendApiError(SILENCE_ALERT_ERROR_MESSAGE, (err as FrontendApiError).originalError)
}
}

/**
* Get silenced alerts
*
* @throws {@link FrontendApiError}
*/
async function getSilencedAlertsFromAPI(): Promise<LEGACY_SilencedAlert[]> {
try {
return await monitorfishApiKy.get('/bff/v1/operational_alerts/silenced').json<SilencedAlert[]>()
} catch (err) {
throw new FrontendApiError(ALERTS_ERROR_MESSAGE, (err as FrontendApiError).originalError)
}
}

/**
* Delete a silenced alert
*
* @throws {@link FrontendApiError}
*/
async function deleteSilencedAlertFromAPI(id: string): Promise<void> {
try {
await monitorfishApiKy.delete(`/bff/v1/operational_alerts/silenced/${id}`)
} catch (err) {
throw new FrontendApiError(DELETE_SILENCED_ALERT_ERROR_MESSAGE, (err as FrontendApiError).originalError)
}
}

export {
getOperationalAlertsFromAPI,
validateAlertFromAPI,
silenceAlertFromAPI,
getSilencedAlertsFromAPI,
deleteSilencedAlertFromAPI
}
9 changes: 0 additions & 9 deletions frontend/src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { createApi, fetchBaseQuery, retry } from '@reduxjs/toolkit/query/react'
import { setMeasurement, startSpan } from '@sentry/react'
import { normalizeRtkBaseQuery } from '@utils/normalizeRtkBaseQuery'
import { sha256 } from '@utils/sha256'
import { undefinedize } from '@utils/undefinedize'
import ky, { HTTPError } from 'ky'

import { RTK_MAX_RETRIES, RtkCacheTagType } from './constants'
Expand Down Expand Up @@ -209,14 +208,6 @@ export const monitorfishPublicApi = createApi({

export const monitorfishApiKy = ky.extend({
hooks: {
afterResponse: [
async (_input, _options, response) => {
const responseData = await response.json()
const normalizedResponse = undefinedize(responseData)

return new Response(JSON.stringify(normalizedResponse), response)
}
],
beforeError: [
async error => {
const { request, response } = error
Expand Down
10 changes: 2 additions & 8 deletions frontend/src/domain/use_cases/alert/addSilencedAlert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,15 @@ import type { SilencedAlertData } from '@features/Alert/types'
export const addSilencedAlert =
(silencedAlert: SilencedAlertData): MainAppThunk =>
async (dispatch, getState) => {
// @ts-ignore
const previousSilencedAlerts = getState().alert.silencedAlerts

try {
/**
* TODO Why is there this TS type issue as `data` is part of the response :
* TS2339: Property 'data' does not exist on type '{ data: SilencedAlert; } | { error: FetchBaseQueryError | SerializedError; }'.
*/
// @ts-ignore
const { data: savedSilencedAlert, error: silencedAlertError } = await dispatch(
alertApi.endpoints.createSilencedAlert.initiate(silencedAlert)
)
if (silencedAlertError) {
// eslint-disable-next-line @typescript-eslint/no-throw-literal
throw silencedAlertError
}
const savedSilencedAlert = await dispatch(alertApi.endpoints.createSilencedAlert.initiate(silencedAlert)).unwrap()

const nextSilencedAlerts = [savedSilencedAlert, ...previousSilencedAlerts]
dispatch(setSilencedAlerts(nextSilencedAlerts))
Expand Down
23 changes: 13 additions & 10 deletions frontend/src/domain/use_cases/alert/getOperationalAlerts.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { alertApi } from '@api/alert'
import { RTK_FORCE_REFETCH_QUERY_OPTIONS } from '@api/constants'
import { setPendingAlerts } from '@features/Alert/components/SideWindowAlerts/slice'

import { getOperationalAlertsFromAPI } from '../../../api/alert'
import { setError } from '../../shared_slices/Global'

import type { MainAppThunk } from '../../../store'
import type { MainAppThunk } from '@store'

export const getOperationalAlerts = (): MainAppThunk => dispatch => {
getOperationalAlertsFromAPI()
.then(alerts => {
dispatch(setPendingAlerts(alerts))
})
.catch(error => {
dispatch(setError(error))
})
export const getOperationalAlerts = (): MainAppThunk => async dispatch => {
try {
const alerts = await dispatch(
alertApi.endpoints.getOperationalAlerts.initiate(undefined, RTK_FORCE_REFETCH_QUERY_OPTIONS)
).unwrap()

dispatch(setPendingAlerts(alerts))
} catch (error) {
dispatch(setError(error))
}
}
21 changes: 12 additions & 9 deletions frontend/src/domain/use_cases/alert/getSilencedAlerts.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { alertApi } from '@api/alert'
import { RTK_FORCE_REFETCH_QUERY_OPTIONS } from '@api/constants'
import { setSilencedAlerts } from '@features/Alert/components/SideWindowAlerts/slice'

import { getSilencedAlertsFromAPI } from '../../../api/alert'
import { setError } from '../../shared_slices/Global'

export const getSilencedAlerts = () => dispatch => {
getSilencedAlertsFromAPI()
.then(silencedAlerts => {
dispatch(setSilencedAlerts(silencedAlerts))
})
.catch(error => {
dispatch(setError(error))
})
export const getSilencedAlerts = () => async dispatch => {
try {
const silencedAlerts = await dispatch(
alertApi.endpoints.getSilencedAlerts.initiate(undefined, RTK_FORCE_REFETCH_QUERY_OPTIONS)
).unwrap()

dispatch(setSilencedAlerts(silencedAlerts))
} catch (error) {
dispatch(setError(error))
}
}
20 changes: 9 additions & 11 deletions frontend/src/domain/use_cases/alert/reactivateSilencedAlert.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { alertApi } from '@api/alert'
import { setSilencedAlerts } from '@features/Alert/components/SideWindowAlerts/slice'
import { deleteListItems } from '@utils/deleteListItems'
import { updateListItemsProp } from '@utils/updateListItemsProp'

import { deleteSilencedAlertFromAPI } from '../../../api/alert'
import { deleteListItems } from '../../../utils/deleteListItems'
import { updateListItemsProp } from '../../../utils/updateListItemsProp'
import { setError } from '../../shared_slices/Global'

import type { MainAppThunk } from '../../../store'
import type { LEGACY_SilencedAlert } from '@features/Alert/types'
import type { MainAppThunk } from '@store'

export const reactivateSilencedAlert =
(id: string): MainAppThunk =>
(dispatch, getState) => {
async (dispatch, getState) => {
const previousSilencedAlerts = getState().alert.silencedAlerts
const previousSilencedAlertsWithReactivatedFlag = setAlertAsReactivated(previousSilencedAlerts, id)
dispatch(setSilencedAlerts(previousSilencedAlertsWithReactivatedFlag))
Expand All @@ -20,19 +20,17 @@ export const reactivateSilencedAlert =
dispatch(setSilencedAlerts(previousSilencedAlertsWithoutReactivatedFlag))
}, 3200)

deleteSilencedAlertFromAPI(id).catch(error => {
try {
await dispatch(alertApi.endpoints.deleteSilencedAlert.initiate(id)).unwrap()
} catch (error) {
clearTimeout(timeout)
dispatch(setSilencedAlerts(previousSilencedAlerts))
dispatch(setError(error))
})
}
}

function setAlertAsReactivated(previousSilencedAlerts: LEGACY_SilencedAlert[], id: string) {
return updateListItemsProp(previousSilencedAlerts, 'id', id, {
isReactivated: true
})
}

export function removeAlert(previousAlerts: LEGACY_SilencedAlert[], id: string) {
return deleteListItems(previousAlerts, 'id', id)
}
11 changes: 7 additions & 4 deletions frontend/src/domain/use_cases/alert/silenceAlert.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { alertApi } from '@api/alert'
import {
addToPendingAlertsBeingSilenced,
removeFromSilencedAlertsQueue,
Expand All @@ -6,14 +7,13 @@ import {
} from '@features/Alert/components/SideWindowAlerts/slice'
import { removeVesselAlertAndUpdateReporting } from '@features/Vessel/slice'
import { renderVesselFeatures } from '@features/Vessel/useCases/renderVesselFeatures'
import { deleteListItems } from '@utils/deleteListItems'

import { silenceAlertFromAPI } from '../../../api/alert'
import { deleteListItems } from '../../../utils/deleteListItems'
import { VesselFeature } from '../../entities/vessel/vessel'
import { setError } from '../../shared_slices/Global'

import type { MainAppThunk } from '../../../store'
import type { SilencedAlertPeriodRequest } from '@features/Alert/types'
import type { MainAppThunk } from '@store'

/**
* Silence an alert
Expand All @@ -38,7 +38,10 @@ export const silenceAlert =
}, 3200)

try {
const silencedAlert = await silenceAlertFromAPI(pendingAlertId, silencedAlertPeriodRequest)
const silencedAlert = await dispatch(
alertApi.endpoints.silenceAlert.initiate({ id: pendingAlertId, silencedAlertPeriodRequest })
).unwrap()

dispatch(
removeVesselAlertAndUpdateReporting({
alertType: silencedAlert.value.type,
Expand Down
11 changes: 6 additions & 5 deletions frontend/src/domain/use_cases/alert/validateAlert.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { alertApi } from '@api/alert'
import { RtkCacheTagType } from '@api/constants'
import { setPendingAlerts } from '@features/Alert/components/SideWindowAlerts/slice'
import { removeVesselAlertAndUpdateReporting } from '@features/Vessel/slice'
import { renderVesselFeatures } from '@features/Vessel/useCases/renderVesselFeatures'
import { vesselApi } from '@features/Vessel/vesselApi'
import { deleteListItems } from '@utils/deleteListItems'
import { updateListItemsProp } from '@utils/updateListItemsProp'

import { validateAlertFromAPI } from '../../../api/alert'
import { deleteListItems } from '../../../utils/deleteListItems'
import { updateListItemsProp } from '../../../utils/updateListItemsProp'
import { VesselFeature } from '../../entities/vessel/vessel'
import { setError } from '../../shared_slices/Global'

import type { MainAppThunk } from '../../../store'
import type { LEGACY_PendingAlert } from '@features/Alert/types'
import type { MainAppThunk } from '@store'

export const validateAlert =
(id: string): MainAppThunk =>
Expand All @@ -26,7 +26,8 @@ export const validateAlert =
}, 3200)

try {
await validateAlertFromAPI(id)
await dispatch(alertApi.endpoints.validateAlert.initiate(id)).unwrap()

// We dispatch this action to update the reporting list
// since it depends on the alerts list that we just updated
dispatch(vesselApi.util.invalidateTags([RtkCacheTagType.Reportings]))
Expand Down
Loading

0 comments on commit f57c7d0

Please sign in to comment.