@seamapi/react 1.64.0 → 1.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -4
- package/dist/elements.js +6684 -6581
- package/dist/elements.js.map +1 -1
- package/dist/index.css +2 -4
- package/dist/index.css.map +1 -1
- package/dist/index.min.css +1 -1
- package/dist/index.min.css.map +1 -1
- package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.d.ts +1 -1
- package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.js +11 -13
- package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.js.map +1 -1
- package/lib/seam/components/AccessCodeTable/AccessCodeHealthBar.d.ts +4 -1
- package/lib/seam/components/AccessCodeTable/AccessCodeHealthBar.js +3 -2
- package/lib/seam/components/AccessCodeTable/AccessCodeHealthBar.js.map +1 -1
- package/lib/seam/components/AccessCodeTable/AccessCodeTable.d.ts +1 -1
- package/lib/seam/components/AccessCodeTable/AccessCodeTable.js +15 -11
- package/lib/seam/components/AccessCodeTable/AccessCodeTable.js.map +1 -1
- package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.d.ts +1 -1
- package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.js +2 -2
- package/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.js.map +1 -1
- package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.d.ts +1 -1
- package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.js +12 -7
- package/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.js.map +1 -1
- package/lib/seam/components/DeviceDetails/LockDeviceDetails.js +11 -4
- package/lib/seam/components/DeviceDetails/LockDeviceDetails.js.map +1 -1
- package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.d.ts +1 -1
- package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js +2 -2
- package/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.js.map +1 -1
- package/lib/seam/components/DeviceTable/DeviceHealthBar.d.ts +3 -1
- package/lib/seam/components/DeviceTable/DeviceHealthBar.js +4 -3
- package/lib/seam/components/DeviceTable/DeviceHealthBar.js.map +1 -1
- package/lib/seam/components/DeviceTable/DeviceTable.d.ts +1 -1
- package/lib/seam/components/DeviceTable/DeviceTable.js +14 -9
- package/lib/seam/components/DeviceTable/DeviceTable.js.map +1 -1
- package/lib/seam/components/SupportedDeviceTable/use-device-model.d.ts +7 -0
- package/lib/seam/components/SupportedDeviceTable/use-device-model.js +18 -0
- package/lib/seam/components/SupportedDeviceTable/use-device-model.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/use-device-models.d.ts +7 -0
- package/lib/seam/components/SupportedDeviceTable/use-device-models.js +17 -0
- package/lib/seam/components/SupportedDeviceTable/use-device-models.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/use-manufacturer.d.ts +7 -0
- package/lib/seam/components/SupportedDeviceTable/use-manufacturer.js +18 -0
- package/lib/seam/components/SupportedDeviceTable/use-manufacturer.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/use-manufacturers.d.ts +7 -0
- package/lib/seam/components/SupportedDeviceTable/use-manufacturers.js +17 -0
- package/lib/seam/components/SupportedDeviceTable/use-manufacturers.js.map +1 -0
- package/lib/seam/components/common-props.d.ts +3 -0
- package/lib/seam/components/common-props.js.map +1 -1
- package/lib/seam/filters.d.ts +8 -0
- package/lib/seam/filters.js +16 -0
- package/lib/seam/filters.js.map +1 -0
- package/lib/telemetry/client.js.map +1 -1
- package/lib/ui/Snackbar/Snackbar.d.ts +1 -1
- package/lib/ui/Snackbar/Snackbar.js +1 -1
- package/lib/ui/Snackbar/Snackbar.js.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +14 -4
- package/src/lib/element.tsx +2 -0
- package/src/lib/seam/components/AccessCodeDetails/AccessCodeDetails.tsx +24 -30
- package/src/lib/seam/components/AccessCodeTable/AccessCodeHealthBar.tsx +9 -1
- package/src/lib/seam/components/AccessCodeTable/AccessCodeTable.tsx +32 -5
- package/src/lib/seam/components/ClimateSettingScheduleDetails/ClimateSettingScheduleDetails.tsx +4 -0
- package/src/lib/seam/components/ClimateSettingScheduleTable/ClimateSettingScheduleTable.tsx +21 -5
- package/src/lib/seam/components/DeviceDetails/LockDeviceDetails.tsx +19 -8
- package/src/lib/seam/components/DeviceDetails/ThermostatDeviceDetails.tsx +4 -0
- package/src/lib/seam/components/DeviceTable/DeviceHealthBar.tsx +10 -2
- package/src/lib/seam/components/DeviceTable/DeviceTable.tsx +29 -7
- package/src/lib/seam/components/SupportedDeviceTable/use-device-model.ts +45 -0
- package/src/lib/seam/components/SupportedDeviceTable/use-device-models.ts +43 -0
- package/src/lib/seam/components/SupportedDeviceTable/use-manufacturer.ts +45 -0
- package/src/lib/seam/components/SupportedDeviceTable/use-manufacturers.ts +43 -0
- package/src/lib/seam/components/common-props.tsx +10 -0
- package/src/lib/seam/filters.ts +32 -0
- package/src/lib/telemetry/client.ts +3 -3
- package/src/lib/ui/Snackbar/Snackbar.tsx +2 -2
- package/src/lib/version.ts +1 -1
- package/src/styles/_device-details.scss +1 -2
- package/src/styles/_thermostat.scss +1 -2
|
@@ -7,6 +7,7 @@ import { NestedAccessCodeTable } from 'lib/seam/components/AccessCodeTable/Acces
|
|
|
7
7
|
import type { CommonProps } from 'lib/seam/components/common-props.js'
|
|
8
8
|
import { DeviceModel } from 'lib/seam/components/DeviceDetails/DeviceModel.js'
|
|
9
9
|
import { useToggleLock } from 'lib/seam/devices/use-toggle-lock.js'
|
|
10
|
+
import { deviceErrorFilter, deviceWarningFilter } from 'lib/seam/filters.js'
|
|
10
11
|
import { Alerts } from 'lib/ui/Alert/Alerts.js'
|
|
11
12
|
import { Button } from 'lib/ui/Button.js'
|
|
12
13
|
import { BatteryStatus } from 'lib/ui/device/BatteryStatus.js'
|
|
@@ -24,6 +25,8 @@ export function LockDeviceDetails(
|
|
|
24
25
|
): JSX.Element | null {
|
|
25
26
|
const {
|
|
26
27
|
device,
|
|
28
|
+
errorFilter = () => true,
|
|
29
|
+
warningFilter = () => true,
|
|
27
30
|
disableLockUnlock,
|
|
28
31
|
disableCreateAccessCode,
|
|
29
32
|
disableEditAccessCode,
|
|
@@ -52,6 +55,8 @@ export function LockDeviceDetails(
|
|
|
52
55
|
return (
|
|
53
56
|
<NestedAccessCodeTable
|
|
54
57
|
deviceId={device.device_id}
|
|
58
|
+
errorFilter={errorFilter}
|
|
59
|
+
warningFilter={warningFilter}
|
|
55
60
|
disableLockUnlock={disableLockUnlock}
|
|
56
61
|
disableCreateAccessCode={disableCreateAccessCode}
|
|
57
62
|
disableEditAccessCode={disableEditAccessCode}
|
|
@@ -64,14 +69,20 @@ export function LockDeviceDetails(
|
|
|
64
69
|
}
|
|
65
70
|
|
|
66
71
|
const alerts = [
|
|
67
|
-
...device.errors
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
...device.errors
|
|
73
|
+
.filter(deviceErrorFilter)
|
|
74
|
+
.filter(errorFilter)
|
|
75
|
+
.map((error) => ({
|
|
76
|
+
variant: 'error' as const,
|
|
77
|
+
message: error.message,
|
|
78
|
+
})),
|
|
79
|
+
...device.warnings
|
|
80
|
+
.filter(deviceWarningFilter)
|
|
81
|
+
.filter(warningFilter)
|
|
82
|
+
.map((warning) => ({
|
|
83
|
+
variant: 'warning' as const,
|
|
84
|
+
message: warning.message,
|
|
85
|
+
})),
|
|
75
86
|
]
|
|
76
87
|
|
|
77
88
|
return (
|
|
@@ -23,6 +23,8 @@ export function ThermostatDeviceDetails({
|
|
|
23
23
|
device,
|
|
24
24
|
onBack,
|
|
25
25
|
className,
|
|
26
|
+
errorFilter = () => true,
|
|
27
|
+
warningFilter = () => true,
|
|
26
28
|
disableLockUnlock,
|
|
27
29
|
disableCreateAccessCode,
|
|
28
30
|
disableEditAccessCode,
|
|
@@ -41,6 +43,8 @@ export function ThermostatDeviceDetails({
|
|
|
41
43
|
return (
|
|
42
44
|
<NestedClimateSettingScheduleTable
|
|
43
45
|
deviceId={device.device_id}
|
|
46
|
+
errorFilter={errorFilter}
|
|
47
|
+
warningFilter={warningFilter}
|
|
44
48
|
disableLockUnlock={disableLockUnlock}
|
|
45
49
|
disableCreateAccessCode={disableCreateAccessCode}
|
|
46
50
|
disableEditAccessCode={disableEditAccessCode}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
import type { ConnectedAccountError, DeviceError } from 'seamapi'
|
|
2
|
+
|
|
1
3
|
import { CheckIcon } from 'lib/icons/Check.js'
|
|
2
4
|
import { ExclamationCircleOutlineIcon } from 'lib/icons/ExclamationCircleOutline.js'
|
|
3
5
|
import { OnlineStatusAccountOfflineIcon } from 'lib/icons/OnlineStatusAccountOffline.js'
|
|
4
6
|
import type { UseDevicesData } from 'lib/seam/devices/use-devices.js'
|
|
7
|
+
import {
|
|
8
|
+
connectedAccountErrorFilter,
|
|
9
|
+
deviceErrorFilter,
|
|
10
|
+
} from 'lib/seam/filters.js'
|
|
5
11
|
import { TableFilterBar } from 'lib/ui/Table/TableFilterBar/TableFilterBar.js'
|
|
6
12
|
import { TableFilterItem } from 'lib/ui/Table/TableFilterBar/TableFilterItem.js'
|
|
7
13
|
|
|
@@ -12,22 +18,24 @@ interface DeviceHealthBarProps {
|
|
|
12
18
|
devices: Array<UseDevicesData[number]>
|
|
13
19
|
filter: AccountFilter | DeviceFilter | null
|
|
14
20
|
onFilterSelect: (filter: AccountFilter | DeviceFilter | null) => void
|
|
21
|
+
errorFilter: (error: DeviceError | ConnectedAccountError) => boolean
|
|
15
22
|
}
|
|
16
23
|
|
|
17
24
|
export function DeviceHealthBar({
|
|
18
25
|
devices,
|
|
19
26
|
filter,
|
|
20
27
|
onFilterSelect,
|
|
28
|
+
errorFilter,
|
|
21
29
|
}: DeviceHealthBarProps): JSX.Element {
|
|
22
30
|
const erroredAccounts = devices.filter((device) => {
|
|
23
31
|
return (
|
|
24
|
-
device.errors.filter((
|
|
32
|
+
device.errors.filter(errorFilter).filter(connectedAccountErrorFilter)
|
|
25
33
|
.length > 0
|
|
26
34
|
)
|
|
27
35
|
})
|
|
28
36
|
const erroredDevices = devices.filter((device) => {
|
|
29
37
|
return (
|
|
30
|
-
device.errors.filter((
|
|
38
|
+
device.errors.filter(errorFilter).filter(deviceErrorFilter).length > 0
|
|
31
39
|
)
|
|
32
40
|
})
|
|
33
41
|
const accountIssueCount = erroredAccounts.length
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
} from 'lib/seam/devices/use-devices.js'
|
|
23
23
|
import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
|
|
24
24
|
import { LoadingToast } from 'lib/ui/LoadingToast/LoadingToast.js'
|
|
25
|
+
import { Snackbar } from 'lib/ui/Snackbar/Snackbar.js'
|
|
25
26
|
import { EmptyPlaceholder } from 'lib/ui/Table/EmptyPlaceholder.js'
|
|
26
27
|
import { TableBody } from 'lib/ui/Table/TableBody.js'
|
|
27
28
|
import { TableHeader } from 'lib/ui/Table/TableHeader.js'
|
|
@@ -67,6 +68,8 @@ export function DeviceTable({
|
|
|
67
68
|
deviceComparator = compareByCreatedAtDesc,
|
|
68
69
|
heading = t.devices,
|
|
69
70
|
title = t.devices,
|
|
71
|
+
errorFilter = () => true,
|
|
72
|
+
warningFilter = () => true,
|
|
70
73
|
disableLockUnlock = false,
|
|
71
74
|
disableCreateAccessCode = false,
|
|
72
75
|
disableEditAccessCode = false,
|
|
@@ -77,7 +80,7 @@ export function DeviceTable({
|
|
|
77
80
|
}: DeviceTableProps = {}): JSX.Element {
|
|
78
81
|
useComponentTelemetry('DeviceTable')
|
|
79
82
|
|
|
80
|
-
const { devices, isInitialLoading, isError,
|
|
83
|
+
const { devices, isInitialLoading, isError, refetch } = useDevices({
|
|
81
84
|
device_ids: deviceIds,
|
|
82
85
|
connected_account_ids: connectedAccountIds,
|
|
83
86
|
})
|
|
@@ -107,6 +110,8 @@ export function DeviceTable({
|
|
|
107
110
|
return (
|
|
108
111
|
<NestedDeviceDetails
|
|
109
112
|
deviceId={selectedDeviceId}
|
|
113
|
+
errorFilter={errorFilter}
|
|
114
|
+
warningFilter={warningFilter}
|
|
110
115
|
disableLockUnlock={disableLockUnlock}
|
|
111
116
|
disableCreateAccessCode={disableCreateAccessCode}
|
|
112
117
|
disableEditAccessCode={disableEditAccessCode}
|
|
@@ -120,10 +125,6 @@ export function DeviceTable({
|
|
|
120
125
|
)
|
|
121
126
|
}
|
|
122
127
|
|
|
123
|
-
if (isError) {
|
|
124
|
-
return <p className={className}>{error?.message}</p>
|
|
125
|
-
}
|
|
126
|
-
|
|
127
128
|
return (
|
|
128
129
|
<div className={classNames('seam-device-table', className)}>
|
|
129
130
|
<ContentHeader onBack={onBack} />
|
|
@@ -152,8 +153,25 @@ export function DeviceTable({
|
|
|
152
153
|
)}
|
|
153
154
|
</TableHeader>
|
|
154
155
|
<TableBody>
|
|
155
|
-
<Content
|
|
156
|
+
<Content
|
|
157
|
+
devices={filteredDevices}
|
|
158
|
+
onDeviceClick={handleDeviceClick}
|
|
159
|
+
errorFilter={errorFilter}
|
|
160
|
+
/>
|
|
156
161
|
</TableBody>
|
|
162
|
+
|
|
163
|
+
<Snackbar
|
|
164
|
+
variant='error'
|
|
165
|
+
visible={isError}
|
|
166
|
+
message={t.fallbackErrorMessage}
|
|
167
|
+
action={{
|
|
168
|
+
label: t.tryAgain,
|
|
169
|
+
onClick: () => {
|
|
170
|
+
void refetch()
|
|
171
|
+
},
|
|
172
|
+
}}
|
|
173
|
+
disableCloseButton
|
|
174
|
+
/>
|
|
157
175
|
</div>
|
|
158
176
|
)
|
|
159
177
|
}
|
|
@@ -161,8 +179,9 @@ export function DeviceTable({
|
|
|
161
179
|
function Content(props: {
|
|
162
180
|
devices: Array<UseDevicesData[number]>
|
|
163
181
|
onDeviceClick: (deviceId: string) => void
|
|
182
|
+
errorFilter: (error: any) => boolean
|
|
164
183
|
}): JSX.Element {
|
|
165
|
-
const { devices, onDeviceClick } = props
|
|
184
|
+
const { devices, onDeviceClick, errorFilter } = props
|
|
166
185
|
const [filter, setFilter] = useState<AccountFilter | DeviceFilter | null>(
|
|
167
186
|
null
|
|
168
187
|
)
|
|
@@ -198,6 +217,7 @@ function Content(props: {
|
|
|
198
217
|
devices={devices}
|
|
199
218
|
filter={filter}
|
|
200
219
|
onFilterSelect={setFilter}
|
|
220
|
+
errorFilter={errorFilter}
|
|
201
221
|
/>
|
|
202
222
|
{filteredDevices.map((device) => (
|
|
203
223
|
<DeviceRow
|
|
@@ -216,4 +236,6 @@ const t = {
|
|
|
216
236
|
devices: 'Devices',
|
|
217
237
|
noDevicesMessage: 'Sorry, no devices were found',
|
|
218
238
|
loading: 'Loading devices',
|
|
239
|
+
tryAgain: 'Try again',
|
|
240
|
+
fallbackErrorMessage: 'Devices could not be loaded',
|
|
219
241
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DeviceModelV1,
|
|
3
|
+
RouteRequestParams,
|
|
4
|
+
RouteResponse,
|
|
5
|
+
} from '@seamapi/types/devicedb'
|
|
6
|
+
import { useQuery } from '@tanstack/react-query'
|
|
7
|
+
import type { SeamError } from 'seamapi'
|
|
8
|
+
|
|
9
|
+
import { useSeamClient } from 'lib/seam/use-seam-client.js'
|
|
10
|
+
import type { UseSeamQueryResult } from 'lib/seam/use-seam-query-result.js'
|
|
11
|
+
|
|
12
|
+
export type UseDeviceModelParams = DeviceModelsGetParams | string
|
|
13
|
+
export type UseDeviceModelData = DeviceModelV1 | null
|
|
14
|
+
|
|
15
|
+
export function useDeviceModel(
|
|
16
|
+
params?: UseDeviceModelParams
|
|
17
|
+
): UseSeamQueryResult<'deviceModel', UseDeviceModelData> {
|
|
18
|
+
const normalizedParams =
|
|
19
|
+
typeof params === 'string' ? { device_model_id: params } : params
|
|
20
|
+
|
|
21
|
+
const { client: seam } = useSeamClient()
|
|
22
|
+
const { data, ...rest } = useQuery<
|
|
23
|
+
DeviceModelsGetResponse['device_model'] | null,
|
|
24
|
+
SeamError
|
|
25
|
+
>({
|
|
26
|
+
enabled: seam != null,
|
|
27
|
+
queryKey: ['internal', 'device_models', 'get', normalizedParams],
|
|
28
|
+
queryFn: async () => {
|
|
29
|
+
if (seam == null) return null
|
|
30
|
+
const {
|
|
31
|
+
data: { device_model: deviceModel },
|
|
32
|
+
} = await seam.client.get<DeviceModelsGetResponse>(
|
|
33
|
+
'/internal/devicedb/v1/device_models/get',
|
|
34
|
+
{ params: normalizedParams }
|
|
35
|
+
)
|
|
36
|
+
return deviceModel
|
|
37
|
+
},
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
return { ...rest, deviceModel: data }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type DeviceModelsGetParams = RouteRequestParams<'/v1/device_models/get'>
|
|
44
|
+
|
|
45
|
+
type DeviceModelsGetResponse = RouteResponse<'/v1/device_models/get'>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DeviceModelV1,
|
|
3
|
+
RouteRequestParams,
|
|
4
|
+
RouteResponse,
|
|
5
|
+
} from '@seamapi/types/devicedb'
|
|
6
|
+
import { useQuery } from '@tanstack/react-query'
|
|
7
|
+
import type { SeamError } from 'seamapi'
|
|
8
|
+
|
|
9
|
+
import { useSeamClient } from 'lib/seam/use-seam-client.js'
|
|
10
|
+
import type { UseSeamQueryResult } from 'lib/seam/use-seam-query-result.js'
|
|
11
|
+
|
|
12
|
+
export type UseDeviceModelsParams = DeviceModelsListParams
|
|
13
|
+
export type UseDeviceModelsData = DeviceModelV1[]
|
|
14
|
+
|
|
15
|
+
export function useDeviceModels(
|
|
16
|
+
params?: UseDeviceModelsParams
|
|
17
|
+
): UseSeamQueryResult<'deviceModels', UseDeviceModelsData> {
|
|
18
|
+
const { client: seam } = useSeamClient()
|
|
19
|
+
|
|
20
|
+
const { data, ...rest } = useQuery<
|
|
21
|
+
DeviceModelsListResponse['device_models'],
|
|
22
|
+
SeamError
|
|
23
|
+
>({
|
|
24
|
+
enabled: seam != null,
|
|
25
|
+
queryKey: ['internal', 'device_models', 'list', params],
|
|
26
|
+
queryFn: async () => {
|
|
27
|
+
if (seam == null) return []
|
|
28
|
+
const {
|
|
29
|
+
data: { device_models: deviceModels },
|
|
30
|
+
} = await seam.client.get<DeviceModelsListResponse>(
|
|
31
|
+
'/internal/devicedb/v1/device_models/list',
|
|
32
|
+
{ params }
|
|
33
|
+
)
|
|
34
|
+
return deviceModels
|
|
35
|
+
},
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
return { ...rest, deviceModels: data }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type DeviceModelsListParams = RouteRequestParams<'/v1/device_models/list'>
|
|
42
|
+
|
|
43
|
+
type DeviceModelsListResponse = RouteResponse<'/v1/device_models/list'>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Manufacturer,
|
|
3
|
+
RouteRequestParams,
|
|
4
|
+
RouteResponse,
|
|
5
|
+
} from '@seamapi/types/devicedb'
|
|
6
|
+
import { useQuery } from '@tanstack/react-query'
|
|
7
|
+
import type { SeamError } from 'seamapi'
|
|
8
|
+
|
|
9
|
+
import { useSeamClient } from 'lib/seam/use-seam-client.js'
|
|
10
|
+
import type { UseSeamQueryResult } from 'lib/seam/use-seam-query-result.js'
|
|
11
|
+
|
|
12
|
+
export type UseManufacturerParams = ManufacturersGetParams | string
|
|
13
|
+
export type UseManufacturerData = Manufacturer | null
|
|
14
|
+
|
|
15
|
+
export function useManufacturer(
|
|
16
|
+
params?: UseManufacturerParams
|
|
17
|
+
): UseSeamQueryResult<'manufacturer', UseManufacturerData> {
|
|
18
|
+
const normalizedParams =
|
|
19
|
+
typeof params === 'string' ? { manufacturer_id: params } : params
|
|
20
|
+
|
|
21
|
+
const { client: seam } = useSeamClient()
|
|
22
|
+
const { data, ...rest } = useQuery<
|
|
23
|
+
ManufacturersGetResponse['manufacturer'] | null,
|
|
24
|
+
SeamError
|
|
25
|
+
>({
|
|
26
|
+
enabled: seam != null,
|
|
27
|
+
queryKey: ['internal', 'manufacturers', 'get', normalizedParams],
|
|
28
|
+
queryFn: async () => {
|
|
29
|
+
if (seam == null) return null
|
|
30
|
+
const {
|
|
31
|
+
data: { manufacturer },
|
|
32
|
+
} = await seam.client.get<ManufacturersGetResponse>(
|
|
33
|
+
'/internal/devicedb/v1/manufacturers/get',
|
|
34
|
+
{ params: normalizedParams }
|
|
35
|
+
)
|
|
36
|
+
return manufacturer
|
|
37
|
+
},
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
return { ...rest, manufacturer: data }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type ManufacturersGetParams = RouteRequestParams<'/v1/manufacturers/get'>
|
|
44
|
+
|
|
45
|
+
type ManufacturersGetResponse = RouteResponse<'/v1/manufacturers/get'>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Manufacturer,
|
|
3
|
+
RouteRequestParams,
|
|
4
|
+
RouteResponse,
|
|
5
|
+
} from '@seamapi/types/devicedb'
|
|
6
|
+
import { useQuery } from '@tanstack/react-query'
|
|
7
|
+
import type { SeamError } from 'seamapi'
|
|
8
|
+
|
|
9
|
+
import { useSeamClient } from 'lib/seam/use-seam-client.js'
|
|
10
|
+
import type { UseSeamQueryResult } from 'lib/seam/use-seam-query-result.js'
|
|
11
|
+
|
|
12
|
+
export type UseManufacturersParams = ManufacturersListParams
|
|
13
|
+
export type UseManufacturersData = Manufacturer[]
|
|
14
|
+
|
|
15
|
+
export function useManufacturers(
|
|
16
|
+
params?: UseManufacturersParams
|
|
17
|
+
): UseSeamQueryResult<'manufacturers', UseManufacturersData> {
|
|
18
|
+
const { client: seam } = useSeamClient()
|
|
19
|
+
|
|
20
|
+
const { data, ...rest } = useQuery<
|
|
21
|
+
ManufacturersListResponse['manufacturers'],
|
|
22
|
+
SeamError
|
|
23
|
+
>({
|
|
24
|
+
enabled: seam != null,
|
|
25
|
+
queryKey: ['internal', 'manufacturers', 'list', params],
|
|
26
|
+
queryFn: async () => {
|
|
27
|
+
if (seam == null) return []
|
|
28
|
+
const {
|
|
29
|
+
data: { manufacturers },
|
|
30
|
+
} = await seam.client.get<ManufacturersListResponse>(
|
|
31
|
+
'/internal/devicedb/v1/manufacturers/list',
|
|
32
|
+
{ params }
|
|
33
|
+
)
|
|
34
|
+
return manufacturers
|
|
35
|
+
},
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
return { ...rest, manufacturers: data }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type ManufacturersListParams = RouteRequestParams<'/v1/manufacturers/list'>
|
|
42
|
+
|
|
43
|
+
type ManufacturersListResponse = RouteResponse<'/v1/manufacturers/list'>
|
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
import type { ComponentType } from 'react'
|
|
2
|
+
import type {
|
|
3
|
+
AccessCodeError,
|
|
4
|
+
ConnectedAccountError,
|
|
5
|
+
DeviceError,
|
|
6
|
+
SeamWarning,
|
|
7
|
+
} from 'seamapi'
|
|
2
8
|
|
|
3
9
|
export interface RequiredCommonProps {
|
|
4
10
|
className: string | undefined
|
|
5
11
|
onBack: (() => void) | undefined
|
|
12
|
+
errorFilter: (
|
|
13
|
+
error: ConnectedAccountError | DeviceError | AccessCodeError
|
|
14
|
+
) => boolean
|
|
15
|
+
warningFilter: (warning: SeamWarning) => boolean
|
|
6
16
|
disableDeleteAccessCode: boolean | undefined
|
|
7
17
|
disableCreateAccessCode: boolean | undefined
|
|
8
18
|
disableEditAccessCode: boolean | undefined
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AccessCodeError,
|
|
3
|
+
ConnectedAccountError,
|
|
4
|
+
DeviceError,
|
|
5
|
+
SeamWarning,
|
|
6
|
+
} from 'seamapi'
|
|
7
|
+
|
|
8
|
+
type SeamCompositeError = ConnectedAccountError | DeviceError | AccessCodeError
|
|
9
|
+
|
|
10
|
+
export const accessCodeErrorFilter = (error: SeamCompositeError): boolean => {
|
|
11
|
+
return 'is_access_code_error' in error && error.is_access_code_error
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const accessCodeWarningFilter = (_: SeamWarning): boolean => {
|
|
15
|
+
return true
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const deviceErrorFilter = (error: SeamCompositeError): boolean => {
|
|
19
|
+
return 'is_device_error' in error && error.is_device_error
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const deviceWarningFilter = (_: SeamWarning): boolean => {
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const connectedAccountErrorFilter = (
|
|
27
|
+
error: SeamCompositeError
|
|
28
|
+
): boolean => {
|
|
29
|
+
return (
|
|
30
|
+
'is_connected_account_error' in error && error.is_connected_account_error
|
|
31
|
+
)
|
|
32
|
+
}
|
|
@@ -12,7 +12,7 @@ export interface TelemetryClientOptions {
|
|
|
12
12
|
// Implements a compatible Analytics 2.0 API with custom options.
|
|
13
13
|
// https://segment.com/docs/connections/sources/catalog/libraries/website/javascript/
|
|
14
14
|
export class TelemetryClient {
|
|
15
|
-
#queue: Queue
|
|
15
|
+
readonly #queue: Queue
|
|
16
16
|
#anonymousId: string | null
|
|
17
17
|
|
|
18
18
|
#endpoint: string
|
|
@@ -154,7 +154,7 @@ export class TelemetryClient {
|
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
#push = (message: Message): void => {
|
|
157
|
+
readonly #push = (message: Message): void => {
|
|
158
158
|
if (this.#disabled) return
|
|
159
159
|
this.#queue.push(async () => {
|
|
160
160
|
const payload: Payload = {
|
|
@@ -178,7 +178,7 @@ export class TelemetryClient {
|
|
|
178
178
|
})
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
#log = (
|
|
181
|
+
readonly #log = (
|
|
182
182
|
method: string,
|
|
183
183
|
...args: Array<string | Traits | Properties>
|
|
184
184
|
): void => {
|
|
@@ -11,7 +11,7 @@ interface SnackbarProps {
|
|
|
11
11
|
message: string
|
|
12
12
|
variant: SnackbarVariant
|
|
13
13
|
visible: boolean
|
|
14
|
-
onClose
|
|
14
|
+
onClose?: () => void
|
|
15
15
|
action?: {
|
|
16
16
|
label: string
|
|
17
17
|
onClick: () => void
|
|
@@ -29,7 +29,7 @@ export function Snackbar({
|
|
|
29
29
|
autoDismiss = false,
|
|
30
30
|
dismissAfterMs = 5000,
|
|
31
31
|
disableCloseButton = false,
|
|
32
|
-
onClose,
|
|
32
|
+
onClose = () => {},
|
|
33
33
|
}: SnackbarProps): JSX.Element {
|
|
34
34
|
const { label: actionLabel, onClick: handleActionClick } = action ?? {}
|
|
35
35
|
|
package/src/lib/version.ts
CHANGED