Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -28,6 +28,7 @@ import SubmitButton from '@ttn-lw/components/submit-button'
import toast from '@ttn-lw/components/toast'

import RequireRequest from '@ttn-lw/lib/components/require-request'
import Message from '@ttn-lw/lib/components/message'

import validationSchema from '@console/containers/gateway-managed-gateway/connection-settings/validation-schema'
import {
Expand Down Expand Up @@ -71,6 +72,9 @@ const m = defineMessages({
'You have just claimed a managed gateway. To connect it to WiFi or ethernet you can configure those connections here. The preprovisioned cellular backhaul typically connects automatically.',
updateSuccess: 'Connection settings updated',
updateFailure: 'There was an error updating these connection settings',
unavailable: 'Managed gateway connection settings unavailable',
unavailableDesc:
'The managed gateway connection settings are currently unavailable. Please try again later.',
})

const GatewayConnectionSettings = () => {
Expand Down Expand Up @@ -381,6 +385,17 @@ const GatewayConnectionSettings = () => {
],
)

if (selectedManagedGateway === 'unavailable') {
return (
<div className="item-12">
<div className="d-flex direction-column j-center al-center w-full text-center gap-cs-m mb-ls-m">
<Message content={m.unavailable} className="fw-bold fs-l lh-xs3" component="div" />
<Message content={m.unavailableDesc} className="c-text-neutral-light lh-xxs" />
</div>
</div>
)
}

return (
<RequireRequest requestAction={loadData}>
<div className="item-12 d-flex gap-ls-s md:direction-column">
Expand Down
23 changes: 18 additions & 5 deletions pkg/webui/console/containers/gateway-status-panel/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// Copyright © 2024 The Things Network Foundation, The Things Industries B.V.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -66,6 +66,8 @@
noConnection: 'This gateway has not made any connection attempts yet.',
noConnectionDescription:
'If you have recently registered this gateway, please wait for a few moments to allow the gateway to connect. Otherwise please refer to our <Link>gateway troubleshooting documentation</Link>.',
isUnavailable: 'Gateway status unavailable',
isUnavailableDesc: 'Gateway status is currently unavailable. Please try again later.',
})

const SectionTitle = ({ title, tooltip }) => (
Expand Down Expand Up @@ -117,7 +119,8 @@
[error],
)

const isUnavailable = Boolean(error) && Boolean(error.message)
const hasError = Boolean(error) && Boolean(error.message)
const isUnavailable = hasError && error.message === 'Unavailable'

const maxRoundTripTime = useMemo(
() =>
Expand Down Expand Up @@ -162,7 +165,7 @@
status={
isDisconnected
? 'bad'
: isFetching || isUnavailable || noConnectionYet
: isFetching || hasError || noConnectionYet
? 'mediocre'
: 'green'
}
Expand All @@ -172,11 +175,12 @@
/>
}
>
{isFetching ? (
{isFetching && (
<Spinner center inline>
<Message content={sharedMessages.fetching} />
</Spinner>
) : noConnectionYet ? (
)}
{noConnectionYet && (
<div className="d-flex j-center al-center flex-grow">
<div className="d-flex direction-column j-center al-center text-center w-60 gap-cs-m mb-ls-m">
<Message content={m.noConnection} className="fw-bold fs-l lh-xs3" component="div" />
Expand All @@ -193,7 +197,16 @@
/>
</div>
</div>
) : (
)}
{isUnavailable && (
<div className="d-flex j-center al-center flex-grow">
<div className="d-flex direction-column j-center al-center text-center w-60 gap-cs-m mb-ls-m">
<Message content={m.isUnavailable} className="fw-bold fs-l lh-xs3" component="div" />
<Message content={m.isUnavailableDesc} className="c-text-neutral-light lh-xxs" />
</div>
</div>
)}
{!isFetching && !noConnectionYet && !isUnavailable && (
<>
<div className={style.gtwStatusPanelUpperContainer}>
<div className="d-flex direction-column j-between w-full sm-md:j-start">
Expand Down
39 changes: 34 additions & 5 deletions pkg/webui/console/store/middleware/logics/gateways.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { selectGsConfig } from '@ttn-lw/lib/selectors/env'
import { getGatewayId } from '@ttn-lw/lib/selectors/id'
import getHostFromUrl from '@ttn-lw/lib/host-from-url'
import createRequestLogic from '@ttn-lw/lib/store/logics/create-request-logic'
import { isNotFoundError } from '@ttn-lw/lib/errors/utils'
import { isNetworkError, isNotFoundError, isTimeoutError } from '@ttn-lw/lib/errors/utils'

import * as gateways from '@console/store/actions/gateways'

Expand Down Expand Up @@ -61,7 +61,11 @@ const getGatewayLogic = createRequestLogic({
'ethernet_mac_address',
])
} catch (e) {
if (!isNotFoundError(e)) {
if (isNetworkError(e) || isTimeoutError(e)) {
managed = 'unavailable'
/* eslint-disable-next-line no-console */
console.error('Gateway request timed out', e)
} else if (!isNotFoundError(e)) {
throw e
}
}
Expand Down Expand Up @@ -137,12 +141,24 @@ const getGatewaysLogic = createRequestLogic({
const gatewayIds = entities.map(e => e.ids)
let gatewaysStats = null
if (gatewayIds.length) {
gatewaysStats = await tts.Gateways.getBatchStatistics(gatewayIds)
try {
gatewaysStats = await tts.Gateways.getBatchStatistics(gatewayIds)
} catch (error) {
if (isTimeoutError(error) || isNetworkError(error)) {
gatewaysStats = 'unknown'
/* eslint-disable-next-line no-console */
console.error(`Failed to fetch gateway statistics for ${gatewayIds.join(', ')}`, error)
}
}
}

entities = data.gateways.map(gateway => {
const gatewayServerAddress = getHostFromUrl(gateway.gateway_server_address)

if (gatewaysStats === 'unknown') {
return { ...gateway, status: 'unknown' }
}

if (!Boolean(gatewayServerAddress)) {
return { ...gateway, status: 'unknown' }
}
Expand Down Expand Up @@ -285,10 +301,23 @@ const startGatewayStatisticsLogic = createLogic({
const updateGatewayStatisticsLogic = createRequestLogic({
type: gateways.UPDATE_GTW_STATS,
throttle: 1000,
process: async ({ action }) => {
process: async ({ action }, dispatch) => {
const { id } = action.payload

const stats = await tts.Gateways.getStatisticsById(id)
let stats = null
try {
stats = await tts.Gateways.getStatisticsById(id)
} catch (error) {
if (isTimeoutError(error) || isNetworkError(error)) {
dispatch(
gateways.updateGatewayStatisticsFailure({
message: 'Unavailable',
}),
)
/* eslint-disable-next-line no-console */
console.error(`Failed to fetch gateway statistics for ${id}`, error)
}
}

return { stats }
},
Expand Down
23 changes: 19 additions & 4 deletions pkg/webui/console/store/middleware/logics/init.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// Copyright © 2024 The Things Network Foundation, The Things Industries B.V.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -25,8 +25,11 @@

import { getActiveUserSessionIdSuccess } from '@console/store/actions/sessions'
import * as user from '@console/store/actions/user'
import { getInboxNotifications } from '@console/store/actions/notifications'
import { getAllBookmarks } from '@console/store/actions/user-preferences'
import {
getInboxNotifications,
getInboxNotificationsSuccess,
} from '@console/store/actions/notifications'
import { getAllBookmarks, getAllBookmarksSuccess } from '@console/store/actions/user-preferences'

const consoleAppLogic = createRequestLogic({
type: init.INITIALIZE,
Expand Down Expand Up @@ -83,8 +86,20 @@
const initActions = []

initActions.push(
await dispatch(attachPromise(getInboxNotifications({ page: 1, limit: 3 }))),
await dispatch(attachPromise(getAllBookmarks(userId))),
dispatch(attachPromise(getInboxNotifications({ page: 1, limit: 3 }))).catch(error => {
// Ignore error, as it is not critical for the app to work and log it in the browser console.
// The inbox notifications will be empty in this case.
getInboxNotificationsSuccess({})
// eslint-disable-next-line no-console
console.error('Failed to fetch inbox notifications', error)
}),
dispatch(attachPromise(getAllBookmarks(userId))).catch(error => {
// Ignore error, as it is not critical for the app to work and log it in the browser console.
// The bookmarks will be empty in this case.
getAllBookmarksSuccess([])
// eslint-disable-next-line no-console
console.error('Failed to fetch bookmarks', error)
}),
statusPageUrl ? await dispatch(attachPromise(getNetworkStatusSummary())) : undefined,
)

Expand Down
4 changes: 3 additions & 1 deletion pkg/webui/lib/errors/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,9 @@ export const isNetworkError = error =>
* @returns {boolean} `true` if `error` is a timeout error, `false` otherwise.
*/
export const isTimeoutError = error =>
Boolean(error) && typeof error === 'object' && error.code === 'ECONNABORTED'
Boolean(error) &&
typeof error === 'object' &&
(error.code === 'ECONNABORTED' || error?.message?.includes('timeout'))

/**
* Returns whether `error` is a connection failure error that happens on the
Expand Down
4 changes: 4 additions & 0 deletions pkg/webui/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,8 @@
"console.containers.gateway-managed-gateway.connection-settings.index.firstNotification": "You have just claimed a managed gateway. To connect it to WiFi or ethernet you can configure those connections here. The preprovisioned cellular backhaul typically connects automatically.",
"console.containers.gateway-managed-gateway.connection-settings.index.updateSuccess": "Connection settings updated",
"console.containers.gateway-managed-gateway.connection-settings.index.updateFailure": "There was an error updating these connection settings",
"console.containers.gateway-managed-gateway.connection-settings.index.unavailable": "Managed gateway connection settings unavailable",
"console.containers.gateway-managed-gateway.connection-settings.index.unavailableDesc": "The managed gateway connection settings are currently unavailable. Please try again later.",
"console.containers.gateway-managed-gateway.connection-settings.wifi-settings-form-fields.settingsProfile": "Settings profile",
"console.containers.gateway-managed-gateway.connection-settings.wifi-settings-form-fields.profileDescription": "Connection settings profiles can be shared within the same organization",
"console.containers.gateway-managed-gateway.connection-settings.wifi-settings-form-fields.wifiConnection": "WiFi connection",
Expand Down Expand Up @@ -685,6 +687,8 @@
"console.containers.gateway-status-panel.index.unlockGraph": "Unlock uptime graph",
"console.containers.gateway-status-panel.index.noConnection": "This gateway has not made any connection attempts yet.",
"console.containers.gateway-status-panel.index.noConnectionDescription": "If you have recently registered this gateway, please wait for a few moments to allow the gateway to connect. Otherwise please refer to our <Link>gateway troubleshooting documentation</Link>.",
"console.containers.gateway-status-panel.index.isUnavailable": "Gateway status unavailable",
"console.containers.gateway-status-panel.index.isUnavailableDesc": "Gateway status is currently unavailable. Please try again later.",
"console.containers.gateway-status-panel.transmissions.noUplinks": "No uplinks yet",
"console.containers.gateway-status-panel.transmissions.noDownlinks": "No downlinks yet",
"console.containers.gateway-status-panel.transmissions.noStatus": "No status",
Expand Down
4 changes: 4 additions & 0 deletions pkg/webui/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,8 @@
"console.containers.gateway-managed-gateway.connection-settings.index.firstNotification": "",
"console.containers.gateway-managed-gateway.connection-settings.index.updateSuccess": "",
"console.containers.gateway-managed-gateway.connection-settings.index.updateFailure": "",
"console.containers.gateway-managed-gateway.connection-settings.index.unavailable": "",
"console.containers.gateway-managed-gateway.connection-settings.index.unavailableDesc": "",
"console.containers.gateway-managed-gateway.connection-settings.wifi-settings-form-fields.settingsProfile": "",
"console.containers.gateway-managed-gateway.connection-settings.wifi-settings-form-fields.profileDescription": "",
"console.containers.gateway-managed-gateway.connection-settings.wifi-settings-form-fields.wifiConnection": "",
Expand Down Expand Up @@ -685,6 +687,8 @@
"console.containers.gateway-status-panel.index.unlockGraph": "",
"console.containers.gateway-status-panel.index.noConnection": "",
"console.containers.gateway-status-panel.index.noConnectionDescription": "",
"console.containers.gateway-status-panel.index.isUnavailable": "",
"console.containers.gateway-status-panel.index.isUnavailableDesc": "",
"console.containers.gateway-status-panel.transmissions.noUplinks": "",
"console.containers.gateway-status-panel.transmissions.noDownlinks": "",
"console.containers.gateway-status-panel.transmissions.noStatus": "",
Expand Down
Loading