@seamapi/react 1.5.1 → 1.7.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 +7 -5
- package/dist/elements.js +25020 -0
- package/dist/elements.js.map +1 -0
- package/hooks.d.ts +1 -0
- package/hooks.js +2 -0
- package/hooks.js.map +1 -0
- package/index.css +6 -0
- package/index.css.map +1 -1
- package/index.min.css +1 -1
- package/index.min.css.map +1 -1
- package/lib/{sort-by.d.ts → dates.d.ts} +1 -1
- package/lib/{sort-by.js → dates.js} +2 -2
- package/lib/dates.js.map +1 -0
- package/lib/index.d.ts +2 -2
- package/lib/index.js +2 -2
- package/lib/index.js.map +1 -1
- package/lib/{SeamProvider.d.ts → seam/SeamProvider.d.ts} +9 -6
- package/lib/{SeamProvider.js → seam/SeamProvider.js} +29 -30
- package/lib/seam/SeamProvider.js.map +1 -0
- package/lib/seam/access-codes/use-access-codes.js +2 -2
- package/lib/seam/access-codes/use-access-codes.js.map +1 -1
- package/lib/{ui → seam/components}/AccessCodeDetails/AccessCodeDetails.js +5 -5
- package/lib/seam/components/AccessCodeDetails/AccessCodeDetails.js.map +1 -0
- package/lib/{ui → seam/components}/AccessCodeDetails/AccessCodeDevice.js +7 -7
- package/lib/seam/components/AccessCodeDetails/AccessCodeDevice.js.map +1 -0
- package/lib/seam/components/AccessCodeTable/AccessCodeTable.js +77 -0
- package/lib/seam/components/AccessCodeTable/AccessCodeTable.js.map +1 -0
- package/lib/{ui → seam/components}/AccessCodeTable/CodeDetails.js +3 -3
- package/lib/seam/components/AccessCodeTable/CodeDetails.js.map +1 -0
- package/lib/{ui → seam/components}/DeviceDetails/DeviceDetails.js +14 -14
- package/lib/seam/components/DeviceDetails/DeviceDetails.js.map +1 -0
- package/lib/seam/components/DeviceDetails/DeviceModel.js.map +1 -0
- package/lib/{ui → seam/components}/DeviceTable/DeviceHealthBar.d.ts +3 -2
- package/lib/{ui → seam/components}/DeviceTable/DeviceHealthBar.js +4 -4
- package/lib/seam/components/DeviceTable/DeviceHealthBar.js.map +1 -0
- package/lib/{ui → seam/components}/DeviceTable/DeviceRow.d.ts +1 -1
- package/lib/{ui → seam/components}/DeviceTable/DeviceRow.js +9 -9
- package/lib/seam/components/DeviceTable/DeviceRow.js.map +1 -0
- package/lib/{ui → seam/components}/DeviceTable/DeviceTable.d.ts +1 -1
- package/lib/{ui → seam/components}/DeviceTable/DeviceTable.js +11 -11
- package/lib/seam/components/DeviceTable/DeviceTable.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/FilterCategoryMenu.d.ts +20 -0
- package/lib/{ui → seam/components}/SupportedDeviceTable/FilterCategoryMenu.js +8 -5
- package/lib/seam/components/SupportedDeviceTable/FilterCategoryMenu.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.d.ts +9 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.js +39 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterArea.d.ts +9 -0
- package/lib/{ui → seam/components}/SupportedDeviceTable/SupportedDeviceFilterArea.js +33 -28
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceFilterArea.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceHeader.d.ts +2 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceHeader.js +12 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceHeader.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.d.ts +6 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.js +19 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.d.ts +5 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.js +16 -0
- package/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.js.map +1 -0
- package/lib/seam/components/SupportedDeviceTable/use-filtered-device-models.d.ts +7 -0
- package/lib/seam/components/SupportedDeviceTable/use-filtered-device-models.js +18 -0
- package/lib/seam/components/SupportedDeviceTable/use-filtered-device-models.js.map +1 -0
- package/lib/seam/components/index.js.map +1 -0
- package/lib/seam/device-models/use-device-models.d.ts +5 -0
- package/lib/seam/device-models/use-device-models.js +17 -0
- package/lib/seam/device-models/use-device-models.js.map +1 -0
- package/lib/seam/devices/use-devices.js +3 -3
- package/lib/seam/devices/use-devices.js.map +1 -1
- package/lib/seam/devices/use-toggle-lock.js +1 -1
- package/lib/seam/devices/use-toggle-lock.js.map +1 -1
- package/lib/seam/index.d.ts +1 -0
- package/lib/seam/index.js +1 -0
- package/lib/seam/index.js.map +1 -1
- package/lib/seam/use-seam-client.js +1 -1
- package/lib/seam/use-seam-client.js.map +1 -1
- package/lib/seam/use-seam-font.d.ts +1 -1
- package/lib/seam/use-seam-font.js +1 -1
- package/lib/seam/use-seam-font.js.map +1 -1
- package/lib/seam/use-seam-styles.js.map +1 -1
- package/lib/{capitalize.js → strings.js} +1 -1
- package/lib/strings.js.map +1 -0
- package/lib/ui/Menu/Menu.d.ts +1 -1
- package/lib/ui/Menu/Menu.js.map +1 -1
- package/lib/ui/Menu/MenuItem.d.ts +1 -1
- package/lib/ui/Menu/MoreActionsMenu.d.ts +1 -1
- package/lib/ui/Table/TableFilterBar/TableFilterBar.d.ts +2 -1
- package/lib/ui/Table/TableFilterBar/TableFilterItem.d.ts +2 -1
- package/lib/ui/TextField/SearchTextField.js.map +1 -1
- package/lib/{copy-to-clipboard.js → ui/clipboard.js} +1 -1
- package/lib/ui/clipboard.js.map +1 -0
- package/lib/ui/use-interval.js.map +1 -0
- package/lib/{use-is-date-in-past.js → ui/use-is-date-in-past.js} +1 -1
- package/lib/ui/use-is-date-in-past.js.map +1 -0
- package/lib/ui/use-toggle.js.map +1 -0
- package/lib/version.d.ts +2 -2
- package/lib/version.js +3 -1
- package/lib/version.js.map +1 -1
- package/package.json +21 -8
- package/src/elements.ts +27 -0
- package/src/hooks.ts +1 -0
- package/src/lib/{sort-by.ts → dates.ts} +1 -1
- package/src/lib/element.tsx +86 -0
- package/src/lib/index.ts +2 -2
- package/src/lib/{SeamProvider.tsx → seam/SeamProvider.tsx} +53 -46
- package/src/lib/seam/access-codes/use-access-codes.ts +2 -2
- package/src/lib/seam/components/AccessCodeDetails/AccessCodeDetails.element.ts +12 -0
- package/src/lib/{ui → seam/components}/AccessCodeDetails/AccessCodeDetails.tsx +4 -5
- package/src/lib/{ui → seam/components}/AccessCodeDetails/AccessCodeDevice.tsx +2 -2
- package/src/lib/seam/components/AccessCodeTable/AccessCodeTable.element.ts +12 -0
- package/src/lib/{ui → seam/components}/AccessCodeTable/AccessCodeTable.tsx +20 -5
- package/src/lib/{ui → seam/components}/AccessCodeTable/CodeDetails.tsx +2 -3
- package/src/lib/seam/components/DeviceDetails/DeviceDetails.element.ts +12 -0
- package/src/lib/{ui → seam/components}/DeviceDetails/DeviceDetails.tsx +8 -6
- package/src/lib/{ui → seam/components}/DeviceTable/DeviceHealthBar.tsx +1 -1
- package/src/lib/{ui → seam/components}/DeviceTable/DeviceRow.tsx +1 -1
- package/src/lib/seam/components/DeviceTable/DeviceTable.element.ts +11 -0
- package/src/lib/{ui → seam/components}/DeviceTable/DeviceTable.tsx +7 -7
- package/src/lib/{ui → seam/components}/SupportedDeviceTable/FilterCategoryMenu.tsx +26 -13
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceContent.tsx +120 -0
- package/src/lib/{ui → seam/components}/SupportedDeviceTable/SupportedDeviceFilterArea.tsx +43 -39
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceHeader.tsx +22 -0
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.tsx +48 -0
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.element.ts +11 -0
- package/src/lib/seam/components/SupportedDeviceTable/SupportedDeviceTable.tsx +40 -0
- package/src/lib/seam/components/SupportedDeviceTable/use-filtered-device-models.ts +35 -0
- package/src/lib/seam/components/elements.ts +5 -0
- package/src/lib/seam/device-models/use-device-models.ts +34 -0
- package/src/lib/seam/devices/use-devices.ts +3 -3
- package/src/lib/seam/devices/use-toggle-lock.ts +1 -2
- package/src/lib/seam/index.ts +1 -0
- package/src/lib/seam/use-seam-client.ts +1 -1
- package/src/lib/seam/use-seam-font.ts +5 -1
- package/src/lib/seam/use-seam-styles.ts +1 -1
- package/src/lib/ui/Menu/Menu.tsx +4 -4
- package/src/lib/ui/Menu/MenuItem.tsx +1 -1
- package/src/lib/ui/Menu/MoreActionsMenu.tsx +1 -1
- package/src/lib/ui/Table/TableFilterBar/TableFilterBar.tsx +2 -2
- package/src/lib/ui/Table/TableFilterBar/TableFilterItem.tsx +1 -1
- package/src/lib/ui/TextField/SearchTextField.tsx +3 -3
- package/src/lib/ui/clipboard.ts +3 -0
- package/src/lib/{use-interval.ts → ui/use-interval.ts} +1 -1
- package/src/lib/{use-is-date-in-past.ts → ui/use-is-date-in-past.ts} +1 -1
- package/src/lib/version.ts +3 -1
- package/src/styles/_access-code-table.scss +7 -0
- package/lib/SeamProvider.js.map +0 -1
- package/lib/capitalize.js.map +0 -1
- package/lib/copy-to-clipboard.js.map +0 -1
- package/lib/sort-by.js.map +0 -1
- package/lib/ui/AccessCodeDetails/AccessCodeDetails.js.map +0 -1
- package/lib/ui/AccessCodeDetails/AccessCodeDevice.js.map +0 -1
- package/lib/ui/AccessCodeTable/AccessCodeTable.js +0 -69
- package/lib/ui/AccessCodeTable/AccessCodeTable.js.map +0 -1
- package/lib/ui/AccessCodeTable/CodeDetails.js.map +0 -1
- package/lib/ui/DeviceDetails/DeviceDetails.js.map +0 -1
- package/lib/ui/DeviceDetails/DeviceModel.js.map +0 -1
- package/lib/ui/DeviceTable/DeviceHealthBar.js.map +0 -1
- package/lib/ui/DeviceTable/DeviceRow.js.map +0 -1
- package/lib/ui/DeviceTable/DeviceTable.js.map +0 -1
- package/lib/ui/SupportedDeviceTable/FilterCategoryMenu.d.ts +0 -15
- package/lib/ui/SupportedDeviceTable/FilterCategoryMenu.js.map +0 -1
- package/lib/ui/SupportedDeviceTable/SupportedDeviceContent.d.ts +0 -4
- package/lib/ui/SupportedDeviceTable/SupportedDeviceContent.js +0 -46
- package/lib/ui/SupportedDeviceTable/SupportedDeviceContent.js.map +0 -1
- package/lib/ui/SupportedDeviceTable/SupportedDeviceFilterArea.d.ts +0 -11
- package/lib/ui/SupportedDeviceTable/SupportedDeviceFilterArea.js.map +0 -1
- package/lib/ui/SupportedDeviceTable/SupportedDeviceHeader.d.ts +0 -1
- package/lib/ui/SupportedDeviceTable/SupportedDeviceHeader.js +0 -5
- package/lib/ui/SupportedDeviceTable/SupportedDeviceHeader.js.map +0 -1
- package/lib/ui/SupportedDeviceTable/SupportedDeviceRow.d.ts +0 -5
- package/lib/ui/SupportedDeviceTable/SupportedDeviceRow.js +0 -12
- package/lib/ui/SupportedDeviceTable/SupportedDeviceRow.js.map +0 -1
- package/lib/ui/SupportedDeviceTable/SupportedDeviceTable.d.ts +0 -3
- package/lib/ui/SupportedDeviceTable/SupportedDeviceTable.js +0 -8
- package/lib/ui/SupportedDeviceTable/SupportedDeviceTable.js.map +0 -1
- package/lib/ui/SupportedDeviceTable/types.d.ts +0 -15
- package/lib/ui/SupportedDeviceTable/types.js +0 -2
- package/lib/ui/SupportedDeviceTable/types.js.map +0 -1
- package/lib/ui/index.js.map +0 -1
- package/lib/use-interval.js.map +0 -1
- package/lib/use-is-date-in-past.js.map +0 -1
- package/lib/use-toggle.js.map +0 -1
- package/src/lib/copy-to-clipboard.ts +0 -3
- package/src/lib/ui/SupportedDeviceTable/SupportedDeviceContent.tsx +0 -135
- package/src/lib/ui/SupportedDeviceTable/SupportedDeviceHeader.tsx +0 -14
- package/src/lib/ui/SupportedDeviceTable/SupportedDeviceRow.tsx +0 -35
- package/src/lib/ui/SupportedDeviceTable/SupportedDeviceTable.tsx +0 -16
- package/src/lib/ui/SupportedDeviceTable/types.ts +0 -16
- /package/lib/{ui → seam/components}/AccessCodeDetails/AccessCodeDetails.d.ts +0 -0
- /package/lib/{ui → seam/components}/AccessCodeDetails/AccessCodeDevice.d.ts +0 -0
- /package/lib/{ui → seam/components}/AccessCodeTable/AccessCodeTable.d.ts +0 -0
- /package/lib/{ui → seam/components}/AccessCodeTable/CodeDetails.d.ts +0 -0
- /package/lib/{ui → seam/components}/DeviceDetails/DeviceDetails.d.ts +0 -0
- /package/lib/{ui → seam/components}/DeviceDetails/DeviceModel.d.ts +0 -0
- /package/lib/{ui → seam/components}/DeviceDetails/DeviceModel.js +0 -0
- /package/lib/{ui → seam/components}/index.d.ts +0 -0
- /package/lib/{ui → seam/components}/index.js +0 -0
- /package/lib/{capitalize.d.ts → strings.d.ts} +0 -0
- /package/lib/{copy-to-clipboard.d.ts → ui/clipboard.d.ts} +0 -0
- /package/lib/{use-interval.d.ts → ui/use-interval.d.ts} +0 -0
- /package/lib/{use-interval.js → ui/use-interval.js} +0 -0
- /package/lib/{use-is-date-in-past.d.ts → ui/use-is-date-in-past.d.ts} +0 -0
- /package/lib/{use-toggle.d.ts → ui/use-toggle.d.ts} +0 -0
- /package/lib/{use-toggle.js → ui/use-toggle.js} +0 -0
- /package/src/lib/{ui → seam/components}/DeviceDetails/DeviceModel.tsx +0 -0
- /package/src/lib/{ui → seam/components}/index.ts +0 -0
- /package/src/lib/{capitalize.ts → strings.ts} +0 -0
- /package/src/lib/{use-toggle.ts → ui/use-toggle.ts} +0 -0
|
@@ -6,9 +6,9 @@ import type {
|
|
|
6
6
|
SeamError,
|
|
7
7
|
} from 'seamapi'
|
|
8
8
|
|
|
9
|
+
import { compareByCreatedAtDesc } from 'lib/dates.js'
|
|
9
10
|
import { useSeamClient } from 'lib/seam/use-seam-client.js'
|
|
10
11
|
import type { UseSeamQueryResult } from 'lib/seam/use-seam-query-result.js'
|
|
11
|
-
import { byCreatedAt } from 'lib/sort-by.js'
|
|
12
12
|
|
|
13
13
|
export type UseAccessCodesParams = AccessCodesListRequest | string
|
|
14
14
|
export type UseAccessCodesData = AccessCode[]
|
|
@@ -29,7 +29,7 @@ export function useAccessCodes(
|
|
|
29
29
|
queryFn: async () => {
|
|
30
30
|
if (client == null) return []
|
|
31
31
|
const accessCodes = await client?.accessCodes.list(normalizedParams)
|
|
32
|
-
return accessCodes.sort(
|
|
32
|
+
return accessCodes.sort(compareByCreatedAtDesc)
|
|
33
33
|
},
|
|
34
34
|
})
|
|
35
35
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ElementProps } from 'lib/element.js'
|
|
2
|
+
|
|
3
|
+
import type { AccessCodeDetailsProps } from './AccessCodeDetails.js'
|
|
4
|
+
|
|
5
|
+
export const name = 'seam-access-code-details'
|
|
6
|
+
|
|
7
|
+
export const props: ElementProps<AccessCodeDetailsProps> = {
|
|
8
|
+
accessCodeId: 'string',
|
|
9
|
+
onBack: 'function',
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { AccessCodeDetails as Component } from './AccessCodeDetails.js'
|
|
@@ -2,12 +2,11 @@ import { DateTime } from 'luxon'
|
|
|
2
2
|
import { useState } from 'react'
|
|
3
3
|
import type { AccessCode } from 'seamapi'
|
|
4
4
|
|
|
5
|
-
import { useAccessCode } from 'lib/
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
import { DeviceDetails } from 'lib/ui/DeviceDetails/DeviceDetails.js'
|
|
5
|
+
import { useAccessCode } from 'lib/seam/access-codes/use-access-code.js'
|
|
6
|
+
import { AccessCodeDevice } from 'lib/seam/components/AccessCodeDetails/AccessCodeDevice.js'
|
|
7
|
+
import { DeviceDetails } from 'lib/seam/components/DeviceDetails/DeviceDetails.js'
|
|
9
8
|
import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
|
|
10
|
-
import { useIsDateInPast } from 'lib/use-is-date-in-past.js'
|
|
9
|
+
import { useIsDateInPast } from 'lib/ui/use-is-date-in-past.js'
|
|
11
10
|
|
|
12
11
|
export interface AccessCodeDetailsProps {
|
|
13
12
|
accessCodeId: string
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { LockDevice } from 'seamapi'
|
|
2
2
|
|
|
3
|
+
import { getDeviceModel } from 'lib/seam/components/DeviceDetails/DeviceModel.js'
|
|
3
4
|
import { isLockDevice } from 'lib/seam/devices/types.js'
|
|
4
5
|
import { useDevice } from 'lib/seam/devices/use-device.js'
|
|
5
6
|
import { useToggleLock } from 'lib/seam/devices/use-toggle-lock.js'
|
|
6
7
|
import { Button } from 'lib/ui/Button.js'
|
|
7
8
|
import { DeviceImage } from 'lib/ui/device/DeviceImage.js'
|
|
8
|
-
import { getDeviceModel } from 'lib/ui/DeviceDetails/DeviceModel.js'
|
|
9
9
|
import { TextButton } from 'lib/ui/TextButton.js'
|
|
10
10
|
|
|
11
11
|
export function AccessCodeDevice({
|
|
@@ -27,7 +27,7 @@ export function AccessCodeDevice({
|
|
|
27
27
|
function LockDeviceDetails(props: {
|
|
28
28
|
device: LockDevice
|
|
29
29
|
onSelectDevice: (deviceId: string) => void
|
|
30
|
-
}) {
|
|
30
|
+
}): JSX.Element {
|
|
31
31
|
const { device, onSelectDevice } = props
|
|
32
32
|
const toggleLock = useToggleLock(device)
|
|
33
33
|
const model = getDeviceModel(device)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ElementProps } from 'lib/element.js'
|
|
2
|
+
|
|
3
|
+
import type { AccessCodeTableProps } from './AccessCodeTable.js'
|
|
4
|
+
|
|
5
|
+
export const name = 'seam-access-code-table'
|
|
6
|
+
|
|
7
|
+
export const props: ElementProps<AccessCodeTableProps> = {
|
|
8
|
+
deviceId: 'string',
|
|
9
|
+
onBack: 'function',
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { AccessCodeTable as Component } from './AccessCodeTable.js'
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { useState } from 'react'
|
|
2
2
|
import type { AccessCode } from 'seamapi'
|
|
3
3
|
|
|
4
|
-
import { copyToClipboard } from 'lib/copy-to-clipboard.js'
|
|
5
4
|
import { AccessCodeKeyIcon } from 'lib/icons/AccessCodeKey.js'
|
|
6
5
|
import { CopyIcon } from 'lib/icons/Copy.js'
|
|
6
|
+
import { ExclamationCircleOutlineIcon } from 'lib/icons/ExclamationCircleOutline.js'
|
|
7
7
|
import {
|
|
8
8
|
useAccessCodes,
|
|
9
9
|
type UseAccessCodesData,
|
|
10
10
|
} from 'lib/seam/access-codes/use-access-codes.js'
|
|
11
|
-
import { AccessCodeDetails } from 'lib/
|
|
12
|
-
import { CodeDetails } from 'lib/
|
|
11
|
+
import { AccessCodeDetails } from 'lib/seam/components/AccessCodeDetails/AccessCodeDetails.js'
|
|
12
|
+
import { CodeDetails } from 'lib/seam/components/AccessCodeTable/CodeDetails.js'
|
|
13
|
+
import { copyToClipboard } from 'lib/ui/clipboard.js'
|
|
13
14
|
import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
|
|
14
15
|
import { MenuItem } from 'lib/ui/Menu/MenuItem.js'
|
|
15
16
|
import { MoreActionsMenu } from 'lib/ui/Menu/MoreActionsMenu.js'
|
|
@@ -89,7 +90,7 @@ export function AccessCodeTable(
|
|
|
89
90
|
function Body(props: {
|
|
90
91
|
accessCodes: Array<UseAccessCodesData[number]>
|
|
91
92
|
selectAccessCode: (accessCode: AccessCode) => void
|
|
92
|
-
}) {
|
|
93
|
+
}): JSX.Element {
|
|
93
94
|
const { accessCodes, selectAccessCode } = props
|
|
94
95
|
|
|
95
96
|
if (accessCodes.length === 0) {
|
|
@@ -114,8 +115,15 @@ function Body(props: {
|
|
|
114
115
|
function AccessCodeRow(props: {
|
|
115
116
|
accessCode: UseAccessCodesData[number]
|
|
116
117
|
onClick: () => void
|
|
117
|
-
}) {
|
|
118
|
+
}): JSX.Element {
|
|
118
119
|
const { onClick, accessCode } = props
|
|
120
|
+
|
|
121
|
+
const errorCount = accessCode.errors?.length ?? 0
|
|
122
|
+
const isPlural = errorCount === 0 || errorCount > 1
|
|
123
|
+
const issueIconTitle = isPlural
|
|
124
|
+
? `${errorCount} ${t.codeIssues}`
|
|
125
|
+
: `${errorCount} ${t.codeIssue}`
|
|
126
|
+
|
|
119
127
|
return (
|
|
120
128
|
<TableRow key={accessCode.access_code_id} onClick={onClick}>
|
|
121
129
|
<TableCell className='seam-icon-cell'>
|
|
@@ -128,6 +136,11 @@ function AccessCodeRow(props: {
|
|
|
128
136
|
<CodeDetails accessCode={accessCode} />
|
|
129
137
|
</TableCell>
|
|
130
138
|
<TableCell className='seam-action-cell'>
|
|
139
|
+
{errorCount > 0 && (
|
|
140
|
+
<div className='seam-code-issue-icon-wrap' title={issueIconTitle}>
|
|
141
|
+
<ExclamationCircleOutlineIcon />
|
|
142
|
+
</div>
|
|
143
|
+
)}
|
|
131
144
|
<MoreActionsMenu
|
|
132
145
|
menuProps={{
|
|
133
146
|
backgroundProps: {
|
|
@@ -157,4 +170,6 @@ const t = {
|
|
|
157
170
|
accessCodes: 'Access Codes',
|
|
158
171
|
copyCode: 'Copy code',
|
|
159
172
|
noAccessCodesMessage: 'Sorry, no access codes were found',
|
|
173
|
+
codeIssue: 'code issue',
|
|
174
|
+
codeIssues: 'code issues',
|
|
160
175
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { DateTime } from 'luxon'
|
|
2
2
|
import type { AccessCode } from 'seamapi'
|
|
3
3
|
|
|
4
|
-
import { useDevice } from 'lib/
|
|
5
|
-
|
|
4
|
+
import { useDevice } from 'lib/seam/devices/use-device.js'
|
|
6
5
|
import { DotDivider } from 'lib/ui/layout/DotDivider.js'
|
|
7
|
-
import { useIsDateInPast } from 'lib/use-is-date-in-past.js'
|
|
6
|
+
import { useIsDateInPast } from 'lib/ui/use-is-date-in-past.js'
|
|
8
7
|
|
|
9
8
|
export function CodeDetails(props: { accessCode: AccessCode }): JSX.Element {
|
|
10
9
|
const { accessCode } = props
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ElementProps } from 'lib/element.js'
|
|
2
|
+
|
|
3
|
+
import type { DeviceDetailsProps } from './DeviceDetails.js'
|
|
4
|
+
|
|
5
|
+
export const name = 'seam-device-details'
|
|
6
|
+
|
|
7
|
+
export const props: ElementProps<DeviceDetailsProps> = {
|
|
8
|
+
deviceId: 'string',
|
|
9
|
+
onBack: 'function',
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { DeviceDetails as Component } from './DeviceDetails.js'
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import type { LockDevice } from 'seamapi'
|
|
2
2
|
|
|
3
|
-
import { useDevice } from 'lib/index.js'
|
|
4
|
-
|
|
5
3
|
import { ChevronRightIcon } from 'lib/icons/ChevronRight.js'
|
|
6
4
|
import { useAccessCodes } from 'lib/seam/access-codes/use-access-codes.js'
|
|
5
|
+
import { AccessCodeTable } from 'lib/seam/components/AccessCodeTable/AccessCodeTable.js'
|
|
6
|
+
import { DeviceModel } from 'lib/seam/components/DeviceDetails/DeviceModel.js'
|
|
7
7
|
import { isLockDevice } from 'lib/seam/devices/types.js'
|
|
8
|
+
import { useDevice } from 'lib/seam/devices/use-device.js'
|
|
8
9
|
import { useToggleLock } from 'lib/seam/devices/use-toggle-lock.js'
|
|
9
|
-
import { AccessCodeTable } from 'lib/ui/AccessCodeTable/AccessCodeTable.js'
|
|
10
10
|
import { Alerts } from 'lib/ui/Alert/Alerts.js'
|
|
11
11
|
import { Button } from 'lib/ui/Button.js'
|
|
12
12
|
import { BatteryStatus } from 'lib/ui/device/BatteryStatus.js'
|
|
13
13
|
import { DeviceImage } from 'lib/ui/device/DeviceImage.js'
|
|
14
14
|
import { OnlineStatus } from 'lib/ui/device/OnlineStatus.js'
|
|
15
|
-
import { DeviceModel } from 'lib/ui/DeviceDetails/DeviceModel.js'
|
|
16
15
|
import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
|
|
17
|
-
import { useToggle } from 'lib/use-toggle.js'
|
|
16
|
+
import { useToggle } from 'lib/ui/use-toggle.js'
|
|
18
17
|
|
|
19
18
|
export interface DeviceDetailsProps {
|
|
20
19
|
deviceId: string
|
|
@@ -39,7 +38,10 @@ export function DeviceDetails(props: DeviceDetailsProps): JSX.Element | null {
|
|
|
39
38
|
return <LockDeviceDetails device={device} onBack={onBack} />
|
|
40
39
|
}
|
|
41
40
|
|
|
42
|
-
function LockDeviceDetails(props: {
|
|
41
|
+
function LockDeviceDetails(props: {
|
|
42
|
+
device: LockDevice
|
|
43
|
+
onBack?: () => void
|
|
44
|
+
}): JSX.Element | null {
|
|
43
45
|
const { device, onBack } = props
|
|
44
46
|
|
|
45
47
|
const [accessCodesOpen, toggleAccessCodesOpen] = useToggle()
|
|
@@ -16,7 +16,7 @@ export function DeviceHealthBar({
|
|
|
16
16
|
devices,
|
|
17
17
|
filter,
|
|
18
18
|
onFilterSelect,
|
|
19
|
-
}: DeviceHealthBarProps) {
|
|
19
|
+
}: DeviceHealthBarProps): JSX.Element {
|
|
20
20
|
const erroredDevices = devices.filter((device) => device.errors.length > 0)
|
|
21
21
|
const issueCount = erroredDevices.length
|
|
22
22
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getDeviceModel } from 'lib/seam/components/DeviceDetails/DeviceModel.js'
|
|
1
2
|
import { isLockDevice } from 'lib/seam/devices/types.js'
|
|
2
3
|
import type {
|
|
3
4
|
UseDevicesData,
|
|
@@ -7,7 +8,6 @@ import { BatteryStatus } from 'lib/ui/device/BatteryStatus.js'
|
|
|
7
8
|
import { DeviceImage } from 'lib/ui/device/DeviceImage.js'
|
|
8
9
|
import { LockStatus } from 'lib/ui/device/LockStatus.js'
|
|
9
10
|
import { OnlineStatus } from 'lib/ui/device/OnlineStatus.js'
|
|
10
|
-
import { getDeviceModel } from 'lib/ui/DeviceDetails/DeviceModel.js'
|
|
11
11
|
import { TableCell } from 'lib/ui/Table/TableCell.js'
|
|
12
12
|
import { TableRow } from 'lib/ui/Table/TableRow.js'
|
|
13
13
|
import { Title } from 'lib/ui/typography/Title.js'
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ElementProps } from 'lib/element.js'
|
|
2
|
+
|
|
3
|
+
import type { DeviceTableProps } from './DeviceTable.js'
|
|
4
|
+
|
|
5
|
+
export const name = 'seam-device-table'
|
|
6
|
+
|
|
7
|
+
export const props: ElementProps<DeviceTableProps> = {
|
|
8
|
+
onBack: 'function',
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export { DeviceTable as Component } from './DeviceTable.js'
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { useState } from 'react'
|
|
2
2
|
|
|
3
|
+
import { DeviceDetails } from 'lib/seam/components/DeviceDetails/DeviceDetails.js'
|
|
4
|
+
import {
|
|
5
|
+
type DeviceFilter,
|
|
6
|
+
DeviceHealthBar,
|
|
7
|
+
} from 'lib/seam/components/DeviceTable/DeviceHealthBar.js'
|
|
8
|
+
import { DeviceRow } from 'lib/seam/components/DeviceTable/DeviceRow.js'
|
|
3
9
|
import {
|
|
4
10
|
useDevices,
|
|
5
11
|
type UseDevicesData,
|
|
6
12
|
type UseDevicesParams,
|
|
7
13
|
} from 'lib/seam/devices/use-devices.js'
|
|
8
|
-
import { DeviceDetails } from 'lib/ui/DeviceDetails/DeviceDetails.js'
|
|
9
|
-
import {
|
|
10
|
-
type DeviceFilter,
|
|
11
|
-
DeviceHealthBar,
|
|
12
|
-
} from 'lib/ui/DeviceTable/DeviceHealthBar.js'
|
|
13
|
-
import { DeviceRow } from 'lib/ui/DeviceTable/DeviceRow.js'
|
|
14
14
|
import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
|
|
15
15
|
import { EmptyPlaceholder } from 'lib/ui/Table/EmptyPlaceholder.js'
|
|
16
16
|
import { TableBody } from 'lib/ui/Table/TableBody.js'
|
|
@@ -90,7 +90,7 @@ export function DeviceTable({
|
|
|
90
90
|
function Body(props: {
|
|
91
91
|
devices: Array<UseDevicesData[number]>
|
|
92
92
|
selectDevice: (id: string) => void
|
|
93
|
-
}) {
|
|
93
|
+
}): JSX.Element {
|
|
94
94
|
const { devices, selectDevice } = props
|
|
95
95
|
const [filter, setFilter] = useState<DeviceFilter | null>(null)
|
|
96
96
|
|
|
@@ -2,6 +2,24 @@ import { ChevronDownIcon } from 'lib/icons/ChevronDown.js'
|
|
|
2
2
|
import { Menu } from 'lib/ui/Menu/Menu.js'
|
|
3
3
|
import { MenuItem } from 'lib/ui/Menu/MenuItem.js'
|
|
4
4
|
|
|
5
|
+
export type FilterCategoryMenuProps =
|
|
6
|
+
| FilterCategoryMenuPropsWithAllOption
|
|
7
|
+
| FilterCategoryMenuPropsWithoutAllOption
|
|
8
|
+
|
|
9
|
+
interface FilterCategoryMenuPropsWithAllOption
|
|
10
|
+
extends FilterCategoryMenuBaseProps {
|
|
11
|
+
hideAllOption?: false
|
|
12
|
+
allLabel: string
|
|
13
|
+
onAllOptionSelect: () => void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface FilterCategoryMenuPropsWithoutAllOption
|
|
17
|
+
extends FilterCategoryMenuBaseProps {
|
|
18
|
+
hideAllOption: true
|
|
19
|
+
allLabel: never
|
|
20
|
+
onAllOptionSelect?: never
|
|
21
|
+
}
|
|
22
|
+
|
|
5
23
|
interface FilterCategoryMenuBaseProps {
|
|
6
24
|
label: string
|
|
7
25
|
options: string[]
|
|
@@ -9,24 +27,15 @@ interface FilterCategoryMenuBaseProps {
|
|
|
9
27
|
buttonLabel?: string
|
|
10
28
|
}
|
|
11
29
|
|
|
12
|
-
export type FilterCategoryMenuProps =
|
|
13
|
-
| (FilterCategoryMenuBaseProps & {
|
|
14
|
-
hideAllOption?: false
|
|
15
|
-
onAllOptionSelect: () => void
|
|
16
|
-
})
|
|
17
|
-
| (FilterCategoryMenuBaseProps & {
|
|
18
|
-
hideAllOption: true
|
|
19
|
-
onAllOptionSelect?: never
|
|
20
|
-
})
|
|
21
|
-
|
|
22
30
|
export function FilterCategoryMenu({
|
|
23
|
-
label =
|
|
31
|
+
label = t.filter,
|
|
32
|
+
allLabel,
|
|
24
33
|
options,
|
|
25
34
|
hideAllOption = false,
|
|
26
35
|
onSelect,
|
|
27
36
|
onAllOptionSelect,
|
|
28
37
|
buttonLabel,
|
|
29
|
-
}: FilterCategoryMenuProps) {
|
|
38
|
+
}: FilterCategoryMenuProps): JSX.Element {
|
|
30
39
|
const usableOptions = hideAllOption ? options : ['All', ...options]
|
|
31
40
|
|
|
32
41
|
return (
|
|
@@ -44,7 +53,7 @@ export function FilterCategoryMenu({
|
|
|
44
53
|
<MenuItem
|
|
45
54
|
key={`${index}:${option}`}
|
|
46
55
|
onClick={() => {
|
|
47
|
-
if (option ===
|
|
56
|
+
if (option === allLabel) {
|
|
48
57
|
onAllOptionSelect?.()
|
|
49
58
|
} else {
|
|
50
59
|
onSelect(option)
|
|
@@ -58,3 +67,7 @@ export function FilterCategoryMenu({
|
|
|
58
67
|
</div>
|
|
59
68
|
)
|
|
60
69
|
}
|
|
70
|
+
|
|
71
|
+
const t = {
|
|
72
|
+
filter: 'Filter',
|
|
73
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { SupportedDeviceHeader } from 'lib/seam/components/SupportedDeviceTable/SupportedDeviceHeader.js'
|
|
2
|
+
import { SupportedDeviceRow } from 'lib/seam/components/SupportedDeviceTable/SupportedDeviceRow.js'
|
|
3
|
+
import {
|
|
4
|
+
type DeviceModelFilters,
|
|
5
|
+
useFilteredDeviceModels,
|
|
6
|
+
} from 'lib/seam/components/SupportedDeviceTable/use-filtered-device-models.js'
|
|
7
|
+
import { Button } from 'lib/ui/Button.js'
|
|
8
|
+
|
|
9
|
+
interface SupportedDeviceContentProps {
|
|
10
|
+
filterValue: string
|
|
11
|
+
resetFilterValue: () => void
|
|
12
|
+
filters: DeviceModelFilters
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function SupportedDeviceContent({
|
|
16
|
+
resetFilterValue,
|
|
17
|
+
filterValue,
|
|
18
|
+
filters,
|
|
19
|
+
}: SupportedDeviceContentProps): JSX.Element | null {
|
|
20
|
+
const { deviceModels, isLoading, isError, refetch } = useFilteredDeviceModels(
|
|
21
|
+
filterValue,
|
|
22
|
+
filters
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
if (isLoading) {
|
|
26
|
+
return (
|
|
27
|
+
<div className='seam-supported-device-table-content-state-block'>
|
|
28
|
+
<p>{t.loading}</p>
|
|
29
|
+
</div>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (isError) {
|
|
34
|
+
return (
|
|
35
|
+
<div className='seam-supported-device-table-content-state-block'>
|
|
36
|
+
<p>{t.error}</p>
|
|
37
|
+
<Button
|
|
38
|
+
variant='solid'
|
|
39
|
+
size='small'
|
|
40
|
+
onClick={() => {
|
|
41
|
+
void refetch()
|
|
42
|
+
}}
|
|
43
|
+
>
|
|
44
|
+
{t.retry}
|
|
45
|
+
</Button>
|
|
46
|
+
</div>
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (deviceModels == null) {
|
|
51
|
+
return null
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<table className='seam-supported-device-table-content'>
|
|
56
|
+
<SupportedDeviceHeader />
|
|
57
|
+
<tbody>
|
|
58
|
+
{deviceModels.map((deviceModel, index) => (
|
|
59
|
+
<SupportedDeviceRow
|
|
60
|
+
key={[
|
|
61
|
+
deviceModel.main_category,
|
|
62
|
+
deviceModel.brand,
|
|
63
|
+
deviceModel.model_name,
|
|
64
|
+
deviceModel.manufacturer_model_id,
|
|
65
|
+
index,
|
|
66
|
+
].join(':')}
|
|
67
|
+
deviceModel={deviceModel}
|
|
68
|
+
/>
|
|
69
|
+
))}
|
|
70
|
+
{deviceModels.length === 0 && (
|
|
71
|
+
<EmptyResult
|
|
72
|
+
filterValue={filterValue}
|
|
73
|
+
resetFilterValue={resetFilterValue}
|
|
74
|
+
/>
|
|
75
|
+
)}
|
|
76
|
+
</tbody>
|
|
77
|
+
</table>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function EmptyResult({
|
|
82
|
+
filterValue,
|
|
83
|
+
resetFilterValue,
|
|
84
|
+
}: Pick<
|
|
85
|
+
SupportedDeviceContentProps,
|
|
86
|
+
'filterValue' | 'resetFilterValue'
|
|
87
|
+
>): JSX.Element {
|
|
88
|
+
const noMatchingRows = (
|
|
89
|
+
<>
|
|
90
|
+
<p>{t.noMatch}</p>
|
|
91
|
+
<Button
|
|
92
|
+
variant='outline'
|
|
93
|
+
size='small'
|
|
94
|
+
onClick={resetFilterValue}
|
|
95
|
+
className='seam-supported-device-table-content-message-clear-search'
|
|
96
|
+
>
|
|
97
|
+
{t.clear}
|
|
98
|
+
</Button>
|
|
99
|
+
</>
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
return (
|
|
103
|
+
<tr className='seam-supported-device-table-content-message-row'>
|
|
104
|
+
<td colSpan={6}>
|
|
105
|
+
<div className='seam-supported-device-table-content-message'>
|
|
106
|
+
{filterValue.length === 0 ? <p>{t.noneFound}</p> : noMatchingRows}
|
|
107
|
+
</div>
|
|
108
|
+
</td>
|
|
109
|
+
</tr>
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const t = {
|
|
114
|
+
loading: 'Loading device models...',
|
|
115
|
+
retry: 'Retry',
|
|
116
|
+
error: 'There was an error fetching device models.',
|
|
117
|
+
noneFound: 'No device models found.',
|
|
118
|
+
noMatch: 'No device models matched your search.',
|
|
119
|
+
clear: 'Clear search terms',
|
|
120
|
+
}
|
|
@@ -1,58 +1,45 @@
|
|
|
1
1
|
import type { Dispatch, SetStateAction } from 'react'
|
|
2
|
+
import type { DeviceModel } from 'seamapi'
|
|
2
3
|
|
|
3
|
-
import {
|
|
4
|
+
import { FilterCategoryMenu } from 'lib/seam/components/SupportedDeviceTable/FilterCategoryMenu.js'
|
|
5
|
+
import type { DeviceModelFilters } from 'lib/seam/components/SupportedDeviceTable/use-filtered-device-models.js'
|
|
6
|
+
import { useDeviceModels } from 'lib/seam/device-models/use-device-models.js'
|
|
7
|
+
import { capitalize } from 'lib/strings.js'
|
|
4
8
|
import { Button } from 'lib/ui/Button.js'
|
|
5
9
|
import { Menu } from 'lib/ui/Menu/Menu.js'
|
|
6
|
-
import { FilterCategoryMenu } from 'lib/ui/SupportedDeviceTable/FilterCategoryMenu.js'
|
|
7
|
-
import type { DeviceModel, Filters } from 'lib/ui/SupportedDeviceTable/types.js'
|
|
8
10
|
import { SearchTextField } from 'lib/ui/TextField/SearchTextField.js'
|
|
9
11
|
|
|
10
|
-
interface SupportedDeviceFilterAreaProps {
|
|
11
|
-
deviceModels: DeviceModel[]
|
|
12
|
+
export interface SupportedDeviceFilterAreaProps {
|
|
12
13
|
filterValue: string
|
|
13
14
|
setFilterValue: (filter: string) => void
|
|
14
|
-
filters:
|
|
15
|
-
setFilters: Dispatch<SetStateAction<
|
|
15
|
+
filters: DeviceModelFilters
|
|
16
|
+
setFilters: Dispatch<SetStateAction<DeviceModelFilters>>
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
export function SupportedDeviceFilterArea({
|
|
19
|
-
deviceModels,
|
|
20
20
|
filterValue,
|
|
21
21
|
setFilterValue,
|
|
22
22
|
filters,
|
|
23
23
|
setFilters,
|
|
24
|
-
}: SupportedDeviceFilterAreaProps) {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
filterProperty !== undefined &&
|
|
29
|
-
filterProperty !== null &&
|
|
30
|
-
filterProperty !== false
|
|
31
|
-
)
|
|
32
|
-
})
|
|
33
|
-
const appliedFiltersCount = appliedFilters.length
|
|
24
|
+
}: SupportedDeviceFilterAreaProps): JSX.Element {
|
|
25
|
+
const appliedFiltersCount = Object.values(filters).filter(
|
|
26
|
+
(v) => v != null && v !== false
|
|
27
|
+
).length
|
|
34
28
|
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
) => {
|
|
38
|
-
const properties = new Set<string>()
|
|
39
|
-
deviceModels.forEach((deviceModel) => {
|
|
40
|
-
properties.add(capitalize(deviceModel[property]))
|
|
41
|
-
})
|
|
42
|
-
return Array.from(properties)
|
|
43
|
-
}
|
|
29
|
+
const filterProperty = 'brand'
|
|
30
|
+
const availableProperties = useAvailableProperties(filterProperty)
|
|
44
31
|
|
|
45
|
-
const resetFilter = (filterType: keyof
|
|
32
|
+
const resetFilter = (filterType: keyof DeviceModelFilters): void => {
|
|
46
33
|
setFilters((filters) => ({
|
|
47
34
|
...filters,
|
|
48
35
|
[filterType]: null,
|
|
49
36
|
}))
|
|
50
37
|
}
|
|
51
38
|
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
39
|
+
const filterButtonLabel =
|
|
40
|
+
appliedFiltersCount > 0 ? `${t.filters} (${appliedFiltersCount})` : t.filter
|
|
41
|
+
|
|
42
|
+
const allLabel = t.all
|
|
56
43
|
|
|
57
44
|
return (
|
|
58
45
|
<div className='seam-supported-device-table-filter-area'>
|
|
@@ -77,27 +64,27 @@ export function SupportedDeviceFilterArea({
|
|
|
77
64
|
>
|
|
78
65
|
<div className='seam-filter-menu-row'>
|
|
79
66
|
<FilterCategoryMenu
|
|
80
|
-
label=
|
|
81
|
-
|
|
67
|
+
label={t.brand}
|
|
68
|
+
allLabel={allLabel}
|
|
69
|
+
options={availableProperties}
|
|
82
70
|
onSelect={(brand: string) => {
|
|
83
71
|
setFilters((filters) => ({
|
|
84
72
|
...filters,
|
|
85
73
|
brand,
|
|
86
74
|
}))
|
|
87
75
|
}}
|
|
88
|
-
buttonLabel={filters.brand ??
|
|
76
|
+
buttonLabel={filters.brand ?? allLabel}
|
|
89
77
|
onAllOptionSelect={() => {
|
|
90
|
-
resetFilter(
|
|
78
|
+
resetFilter(filterProperty)
|
|
91
79
|
}}
|
|
92
80
|
/>
|
|
93
81
|
</div>
|
|
94
|
-
|
|
95
82
|
<div className='seam-filter-menu-row'>
|
|
96
83
|
<label
|
|
97
84
|
htmlFor='supportedOnly'
|
|
98
85
|
className='seam-filter-checkbox-label'
|
|
99
86
|
>
|
|
100
|
-
<p>
|
|
87
|
+
<p>{t.supported}</p>
|
|
101
88
|
<input
|
|
102
89
|
id='supportedOnly'
|
|
103
90
|
name='supportedOnly'
|
|
@@ -115,7 +102,6 @@ export function SupportedDeviceFilterArea({
|
|
|
115
102
|
</div>
|
|
116
103
|
</div>
|
|
117
104
|
</Menu>
|
|
118
|
-
|
|
119
105
|
<div className='seam-supported-device-table-filter-area-search-bar-wrap'>
|
|
120
106
|
<SearchTextField
|
|
121
107
|
value={filterValue}
|
|
@@ -129,3 +115,21 @@ export function SupportedDeviceFilterArea({
|
|
|
129
115
|
</div>
|
|
130
116
|
)
|
|
131
117
|
}
|
|
118
|
+
|
|
119
|
+
const useAvailableProperties = (property: keyof DeviceModel): string[] => {
|
|
120
|
+
const { deviceModels } = useDeviceModels()
|
|
121
|
+
if (deviceModels == null) return []
|
|
122
|
+
const properties = new Set<string>()
|
|
123
|
+
for (const deviceModel of deviceModels) {
|
|
124
|
+
properties.add(capitalize(deviceModel[property]))
|
|
125
|
+
}
|
|
126
|
+
return Array.from(properties)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const t = {
|
|
130
|
+
all: 'All',
|
|
131
|
+
brand: 'Brand',
|
|
132
|
+
supported: 'Supported',
|
|
133
|
+
filter: 'Filter',
|
|
134
|
+
filters: 'Filters',
|
|
135
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function SupportedDeviceHeader(): JSX.Element {
|
|
2
|
+
return (
|
|
3
|
+
<thead>
|
|
4
|
+
<tr>
|
|
5
|
+
<th />
|
|
6
|
+
<th>{t.category}</th>
|
|
7
|
+
<th>{t.modelName}</th>
|
|
8
|
+
<th>{t.manufacturerModelId}</th>
|
|
9
|
+
<th>{t.connectionType}</th>
|
|
10
|
+
<th>{t.status}</th>
|
|
11
|
+
</tr>
|
|
12
|
+
</thead>
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const t = {
|
|
17
|
+
category: 'Category',
|
|
18
|
+
modelName: 'Model Name',
|
|
19
|
+
manufacturerModelId: 'Manufacturer Model ID',
|
|
20
|
+
connectionType: 'Connection Type',
|
|
21
|
+
status: 'Status',
|
|
22
|
+
}
|