Skip to content

Commit

Permalink
refactor(supernova): refactor localItems, client.js, serviceApi, and …
Browse files Browse the repository at this point in the history
…processingStatus to use React Query (#680)

* refactor(supernova): reactQuery expire silence

* refactor(supernova): recreate and createSilence with reactQuery

* refactor(supernova): scheduledSilences are now ReactQuery

* feat(supernova):  make messages dismissable and instant close messages

* refactor(supernova): rollback to message in modal through lack of sticky message

* refactor(supernova): delete apiService, Client, states, and localitems

* fix(supernova): fix loading silences

* chore(supernova): bump version

* chore(supernova): reduce duplicates in Store

* refactor(supernova): optimistic expire

* feat(supernova): optimistic updates Recreate Silence and Expire Silence

* feat(supernova): optimistic updates

* fix(supernova): fix scheduledSilence

* fix(supernova): getMappingSilences are working again

* fix(supernova): fix get mapping state

* fix(supernova): correct padding

* chore(supernova): del pending

* refactor(supernova): useEndlessScrollList instead of own implementation

* chore(supernova): messages are now lasting

* refactor(supernova): name change

* fix(supernova): Allow pending silences to expire

* refactor(supernova): change MessageProvider

* chore(supernova): decouples alerts list from alerts detail view

* fix(supernova): give the error response to the messageprovider for clearer messages

---------

Co-authored-by: Arturo Reuschenbach Puncernau <[email protected]>
  • Loading branch information
TilmanHaupt and ArtieReus authored Dec 20, 2024
1 parent 2191270 commit 92719cf
Show file tree
Hide file tree
Showing 33 changed files with 837 additions and 1,891 deletions.
5 changes: 5 additions & 0 deletions .changeset/rare-llamas-occur.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cloudoperators/juno-app-supernova": minor
---

Refactored fetch with ReactQuery and minor UI improvements
69 changes: 9 additions & 60 deletions apps/supernova/src/AppContent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,82 +4,31 @@
*/

import React from "react"
import { useActions, Messages } from "@cloudoperators/juno-messages-provider"
import { Container, Stack, Spinner } from "@cloudoperators/juno-ui-components"
import { useAlertsUpdatedAt, useAlertsTotalCounts, useGlobalsActiveSelectedTab } from "./components/StoreProvider"
import AlertsList from "./components/alerts/AlertsList"
import { Messages, MessagesProvider } from "@cloudoperators/juno-messages-provider"
import { Container } from "@cloudoperators/juno-ui-components"
import { useGlobalsActiveSelectedTab } from "./components/StoreProvider"
import RegionsList from "./components/regions/RegionsList"
import StatusBar from "./components/status/StatusBar"
import Filters from "./components/filters/Filters"
import { parseError } from "./helpers"
import AlertDetail from "./components/alerts/AlertDetail"
import PredefinedFilters from "./components/filters/PredefinedFilters"
import SilencesList from "./components/silences/SilencesList"

import { useBoundQuery } from "./hooks/useBoundQuery"
import AlertsTab from "./components/alerts/AlertsTab"

const AppContent = () => {
const { addMessage } = useActions()

// alerts
const totalCounts = useAlertsTotalCounts()
const updatedAt = useAlertsUpdatedAt()

const activeSelectedTab = useGlobalsActiveSelectedTab()

const { error: alertsError, isLoading: isAlertsLoading } = useBoundQuery("alerts")
const { error: silencesError, isLoading: isSilencesLoading } = useBoundQuery("silences")
// since the API call is done in a web worker and not logging aware, we need to show the error just in case the user is logged in
if (silencesError) {
addMessage({
variant: "error",
text: parseError(alertsError),
})
}

// since the API call is done in a web worker and not logging aware, we need to show the error just in case the user is logged in
if (alertsError) {
addMessage({
variant: "error",
text: parseError(silencesError),
})
}

return (
<Container px py className="h-full">
<Messages className="pb-6" />

{activeSelectedTab === "alerts" && (
<>
<AlertDetail />
<MessagesProvider>
<AlertDetail />
</MessagesProvider>
<RegionsList />
{isAlertsLoading ? (
<Stack gap="2">
<span>Loading</span>
<Spinner variant="primary" />
</Stack>
) : (
<>
<PredefinedFilters />
<Filters />
<StatusBar totalCounts={totalCounts} isUpdating={isAlertsLoading} updatedAt={updatedAt} />
<AlertsList />
</>
)}
</>
)}
{activeSelectedTab === "silences" && (
<>
{isSilencesLoading ? (
<Stack gap="2">
<span>Loading</span>
<Spinner variant="primary" />
</Stack>
) : (
<SilencesList />
)}
<AlertsTab />
</>
)}
{activeSelectedTab === "silences" && <SilencesList />}
</Container>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { sortAlerts, countAlerts } from "../utils"
import { sortAlerts, countAlerts } from "../lib/utils"
let compareAlertString

export const fetchAlerts = async (endpoint) => {
Expand Down
100 changes: 0 additions & 100 deletions apps/supernova/src/api/apiService.js

This file was deleted.

54 changes: 0 additions & 54 deletions apps/supernova/src/api/client.js

This file was deleted.

6 changes: 6 additions & 0 deletions apps/supernova/src/api/mutationFunctions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { deleteSilences, createSilences } from "./silences"

export const MUTATION_FUNCTIONS = {
deleteSilences: deleteSilences,
createSilences: createSilences,
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { fetchAlerts } from "./alertsQueries"
import { fetchSilences } from "./silencesQueries"
import { fetchAlerts } from "./alerts"
import { fetchSilences } from "./silences"

export const QUERY_FUNCTIONS = {
alerts: fetchAlerts,
Expand Down
75 changes: 75 additions & 0 deletions apps/supernova/src/api/silences.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Greenhouse contributors
* SPDX-License-Identifier: Apache-2.0
*/

export const fetchSilences = async (endpoint) => {
try {
const response = await fetch(`${endpoint}/silences`)

if (!response.ok) {
// Parse the error object from the response body
const errorObject = await response.json().catch(() => {
throw new Error(`Unexpected error: Unable to parse error response.`)
})

// Throw the error object directly
throw errorObject
}

const items = await response.json() // Parse JSON data

// Return the structured result
return {
silences: items,
}
} catch (error) {
console.error(error)
throw error // Let React Query handle the error
}
}

export const deleteSilences = async (variables) => {
try {
const response = await fetch(`${variables.endpoint}/silence/${variables.id}`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
})

if (!response.ok) {
const errorDetails = await response.json().catch(() => null)
const errorMessage = errorDetails?.message || errorDetails || `Error ${response.status}: ${response.statusText}`
throw new Error(errorMessage)
}
return await response
} catch (error) {
console.error(error)
throw error // Let React Query handle the error
}
}

export const createSilences = async (variables) => {
try {
const response = await fetch(`${variables.endpoint}/silences`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify(variables.silence),
})

if (!response.ok) {
const errorDetails = await response.json().catch(() => null)
const errorMessage = errorDetails?.message || errorDetails || `Error ${response.status}: ${response.statusText}`
throw new Error(errorMessage)
}
return await response.json()
} catch (error) {
console.error(error)
throw error // Let React Query handle the error
}
}
2 changes: 0 additions & 2 deletions apps/supernova/src/components/StoreProvider.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,9 @@ export const useFilterActions = () => useAppStore((state) => state.filters.actio

// Silences exports
export const useSilencesItems = () => useAppStore((state) => state.silences.items)
export const useSilencesItemsHash = () => useAppStore((state) => state.silences.itemsHash)
export const useSilencesExcludedLabels = () => useAppStore((state) => state.silences.excludedLabels)
export const useSilencesIsUpdating = () => useAppStore((state) => state.silences.isUpdating)
export const useSilencesUpdatedAt = () => useAppStore((state) => state.silences.updatedAt)
export const useSilencesLocalItems = () => useAppStore((state) => state.silences.localItems)
export const useShowDetailsForSilence = () => useAppStore((state) => state.silences.showDetailsForSilence)
export const useSilencesStatus = () => useAppStore((state) => state.silences.status)
export const useSilencesRegEx = () => useAppStore((state) => state.silences.regEx)
Expand Down
4 changes: 2 additions & 2 deletions apps/supernova/src/components/alerts/Alert.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { DataGridCell, DataGridRow } from "@cloudoperators/juno-ui-components"
import { useGlobalsActions, useShowDetailsFor } from "../StoreProvider"
import AlertLabels from "./shared/AlertLabels"
import AlertLinks from "./shared/AlertLinks"
import SilenceNew from "../silences/SilenceNew"
import CreateSilence from "../silences/CreateSilence"
import AlertIcon from "./shared/AlertIcon"
import AlertDescription from "./shared/AlertDescription"
import AlertTimestamp from "./shared/AlertTimestamp"
Expand Down Expand Up @@ -93,7 +93,7 @@ const Alert = ({ alert }, ref) => {
<AlertStatus alert={alert} />
</DataGridCell>
<DataGridCell>
<SilenceNew alert={alert} size="small" />
<CreateSilence alert={alert} size="small" />
</DataGridCell>
</DataGridRow>
)
Expand Down
Loading

0 comments on commit 92719cf

Please sign in to comment.