@seamapi/react 0.15.0 → 0.15.1
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/lib/hooks/use-access-codes.d.ts +5 -0
- package/lib/hooks/use-access-codes.js +16 -0
- package/lib/hooks/use-access-codes.js.map +1 -0
- package/lib/hooks/use-device.d.ts +5 -0
- package/lib/hooks/use-device.js +17 -0
- package/lib/hooks/use-device.js.map +1 -0
- package/lib/hooks/use-devices.d.ts +1 -0
- package/lib/hooks/use-devices.js +2 -0
- package/lib/hooks/use-devices.js.map +1 -0
- package/lib/hooks/use-seam-client.d.ts +1 -0
- package/lib/hooks/use-seam-client.js +2 -0
- package/lib/hooks/use-seam-client.js.map +1 -0
- package/lib/seam/use-seam-client.js +13 -26
- package/lib/seam/use-seam-client.js.map +1 -1
- package/lib/types/use-seam-query-result.d.ts +5 -0
- package/lib/types/use-seam-query-result.js +2 -0
- package/lib/types/use-seam-query-result.js.map +1 -0
- package/lib/ui/AccessCodeTable/AccessCodeTable.d.ts +3 -5
- package/lib/ui/AccessCodeTable/AccessCodeTable.js +8 -2
- package/lib/ui/AccessCodeTable/AccessCodeTable.js.map +1 -1
- package/lib/ui/DeviceDetails/DeviceDetails.js +1 -3
- package/lib/ui/DeviceDetails/DeviceDetails.js.map +1 -1
- package/package.json +4 -3
- package/src/lib/hooks/use-access-codes.ts +21 -0
- package/src/lib/hooks/use-device.ts +26 -0
- package/src/lib/hooks/use-devices.ts +1 -0
- package/src/lib/hooks/use-seam-client.ts +1 -0
- package/src/lib/seam/use-seam-client.ts +21 -39
- package/src/lib/types/use-seam-query-result.ts +7 -0
- package/src/lib/ui/AccessCodeTable/AccessCodeTable.tsx +9 -7
- package/src/lib/ui/DeviceDetails/DeviceDetails.tsx +2 -5
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useQuery } from '@tanstack/react-query';
|
|
2
|
+
import { useSeamClient } from '../../lib/seam/use-seam-client.js';
|
|
3
|
+
export function useAccessCodes(params) {
|
|
4
|
+
const { client } = useSeamClient();
|
|
5
|
+
const { data, ...rest } = useQuery({
|
|
6
|
+
enabled: client != null,
|
|
7
|
+
queryKey: ['access_codes', 'list', params],
|
|
8
|
+
queryFn: async () => {
|
|
9
|
+
if (client == null)
|
|
10
|
+
return [];
|
|
11
|
+
return await client?.accessCodes.list(params);
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
return { ...rest, accessCodes: data };
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=use-access-codes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-access-codes.js","sourceRoot":"","sources":["../../src/lib/hooks/use-access-codes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAGhD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAG3D,MAAM,UAAU,cAAc,CAAC,MAE9B;IACC,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAAA;IAClC,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAiB;QACjD,OAAO,EAAE,MAAM,IAAI,IAAI;QACvB,QAAQ,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,CAAC;QAC1C,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,IAAI,MAAM,IAAI,IAAI;gBAAE,OAAO,EAAE,CAAA;YAC7B,OAAO,MAAM,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC/C,CAAC;KACF,CAAC,CAAA;IAEF,OAAO,EAAE,GAAG,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAA;AACvC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useQuery } from '@tanstack/react-query';
|
|
2
|
+
import { useSeamClient } from '../../lib/seam/use-seam-client.js';
|
|
3
|
+
export function useDevice(params) {
|
|
4
|
+
const objParams = typeof params === 'string' ? { device_id: params } : params;
|
|
5
|
+
const { client } = useSeamClient();
|
|
6
|
+
const { data, ...rest } = useQuery({
|
|
7
|
+
enabled: client != null,
|
|
8
|
+
queryKey: ['devices', 'get', params],
|
|
9
|
+
queryFn: async () => {
|
|
10
|
+
if (client == null)
|
|
11
|
+
return [];
|
|
12
|
+
return await client?.devices.get(objParams);
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
return { ...rest, device: data };
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=use-device.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-device.js","sourceRoot":"","sources":["../../src/lib/hooks/use-device.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAGhD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAG3D,MAAM,UAAU,SAAS,CACvB,MAIU;IAEV,MAAM,SAAS,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAA;IAC7E,MAAM,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAAA;IAClC,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,CAAiB;QACjD,OAAO,EAAE,MAAM,IAAI,IAAI;QACvB,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC;QACpC,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,IAAI,MAAM,IAAI,IAAI;gBAAE,OAAO,EAAE,CAAA;YAC7B,OAAO,MAAM,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QAC7C,CAAC;KACF,CAAC,CAAA;IAEF,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA;AAClC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useDevices } from '../../lib/seam/devices/use-devices.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-devices.js","sourceRoot":"","sources":["../../src/lib/hooks/use-devices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useSeamClient } from '../../lib/seam/use-seam-client.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-seam-client.js","sourceRoot":"","sources":["../../src/lib/hooks/use-seam-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA"}
|
|
@@ -4,22 +4,15 @@ import { v4 as uuidv4 } from 'uuid';
|
|
|
4
4
|
import { useSeamContext } from '../../lib/SeamProvider.js';
|
|
5
5
|
export function useSeamClient() {
|
|
6
6
|
const { client, clientOptions, publishableKey, ...context } = useSeamContext();
|
|
7
|
-
const
|
|
8
|
-
const userIdentifierKey = useUserIdentifierKey(context.userIdentifierKey);
|
|
7
|
+
const userIdentifierKey = useUserIdentifierKeyOrFingerprint(context.userIdentifierKey);
|
|
9
8
|
const { isLoading, isError, error, data } = useQuery({
|
|
10
|
-
queryKey: ['client', { client,
|
|
9
|
+
queryKey: ['client', { client, userIdentifierKey }],
|
|
11
10
|
queryFn: async () => {
|
|
12
11
|
if (client != null)
|
|
13
12
|
return client;
|
|
14
13
|
if (publishableKey == null) {
|
|
15
14
|
throw new Error('Missing publishableKey');
|
|
16
15
|
}
|
|
17
|
-
if (clientSession != null) {
|
|
18
|
-
return new Seam({
|
|
19
|
-
...clientOptions,
|
|
20
|
-
clientSessionToken: clientSession.token,
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
16
|
const res = await Seam.getClientSessionToken({
|
|
24
17
|
...clientOptions,
|
|
25
18
|
publishableKey,
|
|
@@ -28,7 +21,6 @@ export function useSeamClient() {
|
|
|
28
21
|
if (!res.ok || res.client_session?.token == null) {
|
|
29
22
|
throw new Error('Failed to get client access token');
|
|
30
23
|
}
|
|
31
|
-
setClientSession(res.client_session);
|
|
32
24
|
return new Seam({
|
|
33
25
|
...clientOptions,
|
|
34
26
|
clientSessionToken: res.client_session.token,
|
|
@@ -37,24 +29,19 @@ export function useSeamClient() {
|
|
|
37
29
|
});
|
|
38
30
|
return { client: data ?? null, isLoading, isError, error };
|
|
39
31
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
cachedClientSession != null ? JSON.parse(cachedClientSession) : null,
|
|
48
|
-
setClientSession,
|
|
49
|
-
];
|
|
50
|
-
}
|
|
51
|
-
function useUserIdentifierKey(userIdentifierKey) {
|
|
32
|
+
/**
|
|
33
|
+
* You'll almost always want to supply a user identifier key, but if you don't
|
|
34
|
+
* we'll automatically pick a fingerprint for this user. The user interface
|
|
35
|
+
* will show warnings when you use a fingerprint because this client session
|
|
36
|
+
* is bound to this machine, and is effectively ephemeral.
|
|
37
|
+
*/
|
|
38
|
+
function useUserIdentifierKeyOrFingerprint(userIdentifierKey) {
|
|
52
39
|
if (userIdentifierKey != null) {
|
|
53
40
|
return userIdentifierKey;
|
|
54
41
|
}
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
globalThis?.localStorage?.setItem(
|
|
58
|
-
return
|
|
42
|
+
const fingerprintValue = globalThis?.localStorage?.getItem('seam_user_fingerprint') ??
|
|
43
|
+
`fingerprint_${uuidv4()}`;
|
|
44
|
+
globalThis?.localStorage?.setItem('seam_user_fingerprint', fingerprintValue);
|
|
45
|
+
return fingerprintValue;
|
|
59
46
|
}
|
|
60
47
|
//# sourceMappingURL=use-seam-client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-seam-client.js","sourceRoot":"","sources":["../../src/lib/seam/use-seam-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAChD,OAAO,
|
|
1
|
+
{"version":3,"file":"use-seam-client.js","sourceRoot":"","sources":["../../src/lib/seam/use-seam-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAC9B,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAA;AAEnC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAEpD,MAAM,UAAU,aAAa;IAM3B,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,GAAG,OAAO,EAAE,GAAG,cAAc,EAAE,CAAA;IAC9E,MAAM,iBAAiB,GAAG,iCAAiC,CACzD,OAAO,CAAC,iBAAiB,CAC1B,CAAA;IAED,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAO;QACzD,QAAQ,EAAE,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;QACnD,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,IAAI,MAAM,IAAI,IAAI;gBAAE,OAAO,MAAM,CAAA;YAEjC,IAAI,cAAc,IAAI,IAAI,EAAE;gBAC1B,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAA;aAC1C;YAED,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC;gBAC3C,GAAG,aAAa;gBAChB,cAAc;gBACd,iBAAiB;aAClB,CAAC,CAAA;YAEF,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,cAAc,EAAE,KAAK,IAAI,IAAI,EAAE;gBAChD,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAA;aACrD;YAED,OAAO,IAAI,IAAI,CAAC;gBACd,GAAG,aAAa;gBAChB,kBAAkB,EAAE,GAAG,CAAC,cAAc,CAAC,KAAK;aAC7C,CAAC,CAAA;QACJ,CAAC;KACF,CAAC,CAAA;IAEF,OAAO,EAAE,MAAM,EAAE,IAAI,IAAI,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;AAC5D,CAAC;AAED;;;;;GAKG;AACH,SAAS,iCAAiC,CACxC,iBAAqC;IAErC,IAAI,iBAAiB,IAAI,IAAI,EAAE;QAC7B,OAAO,iBAAiB,CAAA;KACzB;IAED,MAAM,gBAAgB,GACpB,UAAU,EAAE,YAAY,EAAE,OAAO,CAAC,uBAAuB,CAAC;QAC1D,eAAe,MAAM,EAAE,EAAE,CAAA;IAE3B,UAAU,EAAE,YAAY,EAAE,OAAO,CAAC,uBAAuB,EAAE,gBAAgB,CAAC,CAAA;IAE5E,OAAO,gBAAgB,CAAA;AACzB,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { UseQueryResult } from '@tanstack/react-query';
|
|
2
|
+
import type { SeamError } from 'seamapi';
|
|
3
|
+
export type UseSeamQueryResult<Field extends string, ResponsePayload> = Omit<UseQueryResult<ResponsePayload, SeamError>, 'data'> & {
|
|
4
|
+
[key in Field]?: ResponsePayload;
|
|
5
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-seam-query-result.js","sourceRoot":"","sources":["../../src/lib/types/use-seam-query-result.ts"],"names":[],"mappings":""}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
accessCodes: AccessCode[];
|
|
1
|
+
export declare function AccessCodeTable(props: {
|
|
2
|
+
deviceId: string;
|
|
4
3
|
onClickBack?: () => void;
|
|
5
|
-
}
|
|
6
|
-
export declare function AccessCodeTable(props: AccessCodeTableProps): JSX.Element;
|
|
4
|
+
}): JSX.Element;
|
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { TableBody, TableCell, TableHeader, TableRow, TableTitle, } from '../../../lib/ui/Table/index.js';
|
|
3
|
+
import { useAccessCodes } from '../../../lib/hooks/use-access-codes.js';
|
|
3
4
|
import { AccessCodeKeyIcon } from '../../../lib/icons/AccessCodeKey.js';
|
|
4
5
|
import { CodeDetails } from '../../../lib/ui/AccessCodeTable/CodeDetails.js';
|
|
5
6
|
import { ContentHeader } from '../../../lib/ui/layout/ContentHeader.js';
|
|
6
7
|
import { Caption } from '../../../lib/ui/typography/Caption.js';
|
|
7
8
|
import { Title } from '../../../lib/ui/typography/Title.js';
|
|
8
9
|
export function AccessCodeTable(props) {
|
|
9
|
-
const { accessCodes
|
|
10
|
+
const { accessCodes } = useAccessCodes({
|
|
11
|
+
device_id: props.deviceId,
|
|
12
|
+
});
|
|
13
|
+
const { onClickBack } = props;
|
|
14
|
+
if (!accessCodes)
|
|
15
|
+
return _jsx(_Fragment, { children: null });
|
|
10
16
|
return (_jsxs("div", { className: 'seam-access-code-table', children: [_jsx(ContentHeader, { onClickBack: onClickBack }), _jsx(TableHeader, { children: _jsxs(TableTitle, { children: [t.accessCodes, " ", _jsxs(Caption, { children: ["(", accessCodes.length, ")"] })] }) }), _jsx(TableBody, { children: accessCodes.map((code) => (_jsxs(TableRow, { children: [_jsx(TableCell, { className: 'seam-icon-cell', children: _jsx("div", { children: _jsx(AccessCodeKeyIcon, {}) }) }), _jsxs(TableCell, { className: 'seam-name-cell', children: [_jsx(Title, { children: code.name }), _jsx(CodeDetails, { accessCode: code })] }), _jsx(TableCell, { className: 'seam-action-cell' })] }, code.access_code_id))) })] }));
|
|
11
17
|
}
|
|
12
18
|
const t = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AccessCodeTable.js","sourceRoot":"","sources":["../../../src/lib/ui/AccessCodeTable/AccessCodeTable.tsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"AccessCodeTable.js","sourceRoot":"","sources":["../../../src/lib/ui/AccessCodeTable/AccessCodeTable.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,SAAS,EACT,SAAS,EACT,WAAW,EACX,QAAQ,EACR,UAAU,GACX,MAAM,uBAAuB,CAAA;AAE9B,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAA;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAA;AACtD,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAA;AAElD,MAAM,UAAU,eAAe,CAAC,KAG/B;IACC,MAAM,EAAE,WAAW,EAAE,GAAG,cAAc,CAAC;QACrC,SAAS,EAAE,KAAK,CAAC,QAAQ;KAC1B,CAAC,CAAA;IACF,MAAM,EAAE,WAAW,EAAE,GAAG,KAAK,CAAA;IAE7B,IAAI,CAAC,WAAW;QAAE,OAAO,4BAAG,IAAI,GAAI,CAAA;IAEpC,OAAO,CACL,eAAK,SAAS,EAAC,wBAAwB,aACrC,KAAC,aAAa,IAAC,WAAW,EAAE,WAAW,GAAI,EAC3C,KAAC,WAAW,cACV,MAAC,UAAU,eACR,CAAC,CAAC,WAAW,OAAE,MAAC,OAAO,oBAAG,WAAW,CAAC,MAAM,SAAY,IAC9C,GACD,EACd,KAAC,SAAS,cACP,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACzB,MAAC,QAAQ,eACP,KAAC,SAAS,IAAC,SAAS,EAAC,gBAAgB,YACnC,wBACE,KAAC,iBAAiB,KAAG,GACjB,GACI,EACZ,MAAC,SAAS,IAAC,SAAS,EAAC,gBAAgB,aACnC,KAAC,KAAK,cAAE,IAAI,CAAC,IAAI,GAAS,EAC1B,KAAC,WAAW,IAAC,UAAU,EAAE,IAAI,GAAI,IACvB,EACZ,KAAC,SAAS,IAAC,SAAS,EAAC,kBAAkB,GAI3B,KAdC,IAAI,CAAC,cAAc,CAevB,CACZ,CAAC,GACQ,IACR,CACP,CAAA;AACH,CAAC;AAED,MAAM,CAAC,GAAG;IACR,WAAW,EAAE,cAAc;CAC5B,CAAA"}
|
|
@@ -12,11 +12,9 @@ export function DeviceDetails(props) {
|
|
|
12
12
|
const { device } = props;
|
|
13
13
|
const lockStatus = device.properties.locked ? t.locked : t.unlocked;
|
|
14
14
|
const accessCodeLength = device.properties?.schlage_metadata?.access_code_length;
|
|
15
|
-
// TODO : Fetch access codes
|
|
16
|
-
const accessCodes = [];
|
|
17
15
|
const [showingAccessCodes, toggleAccessCodes] = useToggle();
|
|
18
16
|
if (showingAccessCodes) {
|
|
19
|
-
return (_jsx(AccessCodeTable, {
|
|
17
|
+
return (_jsx(AccessCodeTable, { deviceId: device.device_id, onClickBack: toggleAccessCodes }));
|
|
20
18
|
}
|
|
21
19
|
return (_jsxs("div", { className: 'seam-device-details', children: [_jsx(ContentHeader, { title: 'Device' }), _jsxs("div", { className: 'seam-body', children: [_jsx("div", { className: 'seam-summary', children: _jsxs("div", { className: 'seam-content', children: [_jsx("div", { className: 'seam-image', children: _jsx(DeviceImage, { device: device }) }), _jsxs("div", { className: 'seam-info', children: [_jsx("h4", { className: 'seam-device-name', children: device.properties.name }), _jsxs("div", { className: 'seam-properties', children: [_jsx(OnlineStatus, { device: device }), _jsx(BatteryStatus, { device: device }), _jsx(ModelStatus, { device: device })] })] })] }) }), _jsx("div", { className: 'seam-box', children: _jsxs("div", { className: 'seam-content seam-access-codes', onClick: toggleAccessCodes, children: [_jsxs("span", { className: 'seam-value', children: ["49 ", t.accessCodes] }), _jsx(ChevronRightIcon, {})] }) }), _jsxs("div", { className: 'seam-box', children: [_jsxs("div", { className: 'seam-content', children: [_jsx("span", { className: 'seam-label', children: t.lockStatus }), _jsx("span", { className: 'seam-value', children: lockStatus })] }), _jsx(AccessCodeLength, { accessCodeLength: accessCodeLength })] })] })] }));
|
|
22
20
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeviceDetails.js","sourceRoot":"","sources":["../../../src/lib/ui/DeviceDetails/DeviceDetails.tsx"],"names":[],"mappings":";AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"DeviceDetails.js","sourceRoot":"","sources":["../../../src/lib/ui/DeviceDetails/DeviceDetails.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seamapi/react",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "Seam React component library.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -93,17 +93,17 @@
|
|
|
93
93
|
"@tanstack/react-query": "^4.28.0",
|
|
94
94
|
"classnames": "^2.3.2",
|
|
95
95
|
"luxon": "^3.3.0",
|
|
96
|
-
"seamapi": "^5.19.0-alpha.
|
|
96
|
+
"seamapi": "^5.19.0-alpha.3",
|
|
97
97
|
"uuid": "^9.0.0"
|
|
98
98
|
},
|
|
99
99
|
"devDependencies": {
|
|
100
100
|
"@babel/preset-env": "^7.21.4",
|
|
101
101
|
"@babel/preset-react": "^7.18.6",
|
|
102
102
|
"@babel/preset-typescript": "^7.21.4",
|
|
103
|
-
"@seamapi/fake-seam-connect": "^0.3.0-alpha.5",
|
|
104
103
|
"@emotion/styled": "^11.10.6",
|
|
105
104
|
"@mui/icons-material": "^5.11.16",
|
|
106
105
|
"@mui/material": "^5.12.2",
|
|
106
|
+
"@seamapi/fake-seam-connect": "^0.3.0-alpha.5",
|
|
107
107
|
"@storybook/addon-essentials": "^7.0.2",
|
|
108
108
|
"@storybook/addon-interactions": "^7.0.2",
|
|
109
109
|
"@storybook/addon-links": "^7.0.2",
|
|
@@ -135,6 +135,7 @@
|
|
|
135
135
|
"eslint-plugin-unused-imports": "^2.0.0",
|
|
136
136
|
"fast-glob": "^3.2.12",
|
|
137
137
|
"http-proxy-middleware": "^2.0.6",
|
|
138
|
+
"isomorphic-fetch": "^3.0.0",
|
|
138
139
|
"jest": "^29.5.0",
|
|
139
140
|
"jest-environment-jsdom": "^29.5.0",
|
|
140
141
|
"prettier": "^2.3.0",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useQuery } from '@tanstack/react-query'
|
|
2
|
+
import type { AccessCode, SeamError } from 'seamapi'
|
|
3
|
+
|
|
4
|
+
import { useSeamClient } from 'lib/seam/use-seam-client.js'
|
|
5
|
+
import type { UseSeamQueryResult } from 'lib/types/use-seam-query-result.js'
|
|
6
|
+
|
|
7
|
+
export function useAccessCodes(params: {
|
|
8
|
+
device_id: string
|
|
9
|
+
}): UseSeamQueryResult<'accessCodes', AccessCode[]> {
|
|
10
|
+
const { client } = useSeamClient()
|
|
11
|
+
const { data, ...rest } = useQuery<any, SeamError>({
|
|
12
|
+
enabled: client != null,
|
|
13
|
+
queryKey: ['access_codes', 'list', params],
|
|
14
|
+
queryFn: async () => {
|
|
15
|
+
if (client == null) return []
|
|
16
|
+
return await client?.accessCodes.list(params)
|
|
17
|
+
},
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
return { ...rest, accessCodes: data }
|
|
21
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useQuery } from '@tanstack/react-query'
|
|
2
|
+
import type { Device, SeamError } from 'seamapi'
|
|
3
|
+
|
|
4
|
+
import { useSeamClient } from 'lib/seam/use-seam-client.js'
|
|
5
|
+
import type { UseSeamQueryResult } from 'lib/types/use-seam-query-result.js'
|
|
6
|
+
|
|
7
|
+
export function useDevice(
|
|
8
|
+
params:
|
|
9
|
+
| {
|
|
10
|
+
device_id: string
|
|
11
|
+
}
|
|
12
|
+
| string
|
|
13
|
+
): UseSeamQueryResult<'device', Device<any>> {
|
|
14
|
+
const objParams = typeof params === 'string' ? { device_id: params } : params
|
|
15
|
+
const { client } = useSeamClient()
|
|
16
|
+
const { data, ...rest } = useQuery<any, SeamError>({
|
|
17
|
+
enabled: client != null,
|
|
18
|
+
queryKey: ['devices', 'get', params],
|
|
19
|
+
queryFn: async () => {
|
|
20
|
+
if (client == null) return []
|
|
21
|
+
return await client?.devices.get(objParams)
|
|
22
|
+
},
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
return { ...rest, device: data }
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useDevices } from 'lib/seam/devices/use-devices.js'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useSeamClient } from 'lib/seam/use-seam-client.js'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useQuery } from '@tanstack/react-query'
|
|
2
|
-
import {
|
|
2
|
+
import { Seam } from 'seamapi'
|
|
3
3
|
import { v4 as uuidv4 } from 'uuid'
|
|
4
4
|
|
|
5
5
|
import { useSeamContext } from 'lib/SeamProvider.js'
|
|
@@ -11,11 +11,12 @@ export function useSeamClient(): {
|
|
|
11
11
|
error: unknown
|
|
12
12
|
} {
|
|
13
13
|
const { client, clientOptions, publishableKey, ...context } = useSeamContext()
|
|
14
|
-
const
|
|
15
|
-
|
|
14
|
+
const userIdentifierKey = useUserIdentifierKeyOrFingerprint(
|
|
15
|
+
context.userIdentifierKey
|
|
16
|
+
)
|
|
16
17
|
|
|
17
18
|
const { isLoading, isError, error, data } = useQuery<Seam>({
|
|
18
|
-
queryKey: ['client', { client,
|
|
19
|
+
queryKey: ['client', { client, userIdentifierKey }],
|
|
19
20
|
queryFn: async () => {
|
|
20
21
|
if (client != null) return client
|
|
21
22
|
|
|
@@ -23,13 +24,6 @@ export function useSeamClient(): {
|
|
|
23
24
|
throw new Error('Missing publishableKey')
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
if (clientSession != null) {
|
|
27
|
-
return new Seam({
|
|
28
|
-
...clientOptions,
|
|
29
|
-
clientSessionToken: clientSession.token,
|
|
30
|
-
})
|
|
31
|
-
}
|
|
32
|
-
|
|
33
27
|
const res = await Seam.getClientSessionToken({
|
|
34
28
|
...clientOptions,
|
|
35
29
|
publishableKey,
|
|
@@ -40,8 +34,6 @@ export function useSeamClient(): {
|
|
|
40
34
|
throw new Error('Failed to get client access token')
|
|
41
35
|
}
|
|
42
36
|
|
|
43
|
-
setClientSession(res.client_session)
|
|
44
|
-
|
|
45
37
|
return new Seam({
|
|
46
38
|
...clientOptions,
|
|
47
39
|
clientSessionToken: res.client_session.token,
|
|
@@ -52,34 +44,24 @@ export function useSeamClient(): {
|
|
|
52
44
|
return { client: data ?? null, isLoading, isError, error }
|
|
53
45
|
}
|
|
54
46
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
JSON.stringify(clientSession)
|
|
65
|
-
)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const cachedClientSession = globalThis?.localStorage?.getItem(localStorageKey)
|
|
69
|
-
|
|
70
|
-
return [
|
|
71
|
-
cachedClientSession != null ? JSON.parse(cachedClientSession) : null,
|
|
72
|
-
setClientSession,
|
|
73
|
-
]
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function useUserIdentifierKey(userIdentifierKey: string | undefined): string {
|
|
47
|
+
/**
|
|
48
|
+
* You'll almost always want to supply a user identifier key, but if you don't
|
|
49
|
+
* we'll automatically pick a fingerprint for this user. The user interface
|
|
50
|
+
* will show warnings when you use a fingerprint because this client session
|
|
51
|
+
* is bound to this machine, and is effectively ephemeral.
|
|
52
|
+
*/
|
|
53
|
+
function useUserIdentifierKeyOrFingerprint(
|
|
54
|
+
userIdentifierKey: string | undefined
|
|
55
|
+
): string {
|
|
77
56
|
if (userIdentifierKey != null) {
|
|
78
57
|
return userIdentifierKey
|
|
79
58
|
}
|
|
80
59
|
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
60
|
+
const fingerprintValue =
|
|
61
|
+
globalThis?.localStorage?.getItem('seam_user_fingerprint') ??
|
|
62
|
+
`fingerprint_${uuidv4()}`
|
|
63
|
+
|
|
64
|
+
globalThis?.localStorage?.setItem('seam_user_fingerprint', fingerprintValue)
|
|
65
|
+
|
|
66
|
+
return fingerprintValue
|
|
85
67
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { UseQueryResult } from '@tanstack/react-query'
|
|
2
|
+
import type { SeamError } from 'seamapi'
|
|
3
|
+
|
|
4
|
+
export type UseSeamQueryResult<Field extends string, ResponsePayload> = Omit<
|
|
5
|
+
UseQueryResult<ResponsePayload, SeamError>,
|
|
6
|
+
'data'
|
|
7
|
+
> & { [key in Field]?: ResponsePayload }
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import type { AccessCode } from 'seamapi'
|
|
2
|
-
|
|
3
1
|
import {
|
|
4
2
|
TableBody,
|
|
5
3
|
TableCell,
|
|
@@ -8,19 +6,23 @@ import {
|
|
|
8
6
|
TableTitle,
|
|
9
7
|
} from 'lib/ui/Table/index.js'
|
|
10
8
|
|
|
9
|
+
import { useAccessCodes } from 'lib/hooks/use-access-codes.js'
|
|
11
10
|
import { AccessCodeKeyIcon } from 'lib/icons/AccessCodeKey.js'
|
|
12
11
|
import { CodeDetails } from 'lib/ui/AccessCodeTable/CodeDetails.js'
|
|
13
12
|
import { ContentHeader } from 'lib/ui/layout/ContentHeader.js'
|
|
14
13
|
import { Caption } from 'lib/ui/typography/Caption.js'
|
|
15
14
|
import { Title } from 'lib/ui/typography/Title.js'
|
|
16
15
|
|
|
17
|
-
export
|
|
18
|
-
|
|
16
|
+
export function AccessCodeTable(props: {
|
|
17
|
+
deviceId: string
|
|
19
18
|
onClickBack?: () => void
|
|
20
|
-
}
|
|
19
|
+
}): JSX.Element {
|
|
20
|
+
const { accessCodes } = useAccessCodes({
|
|
21
|
+
device_id: props.deviceId,
|
|
22
|
+
})
|
|
23
|
+
const { onClickBack } = props
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
const { accessCodes, onClickBack } = props
|
|
25
|
+
if (!accessCodes) return <>{null}</>
|
|
24
26
|
|
|
25
27
|
return (
|
|
26
28
|
<div className='seam-access-code-table'>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type LockDevice } from 'seamapi'
|
|
2
2
|
|
|
3
3
|
import { ChevronRightIcon } from 'lib/icons/ChevronRight.js'
|
|
4
4
|
import { AccessCodeTable } from 'lib/ui/AccessCodeTable/AccessCodeTable.js'
|
|
@@ -21,15 +21,12 @@ export function DeviceDetails(props: DeviceDetailsProps): JSX.Element {
|
|
|
21
21
|
const accessCodeLength =
|
|
22
22
|
device.properties?.schlage_metadata?.access_code_length
|
|
23
23
|
|
|
24
|
-
// TODO : Fetch access codes
|
|
25
|
-
const accessCodes: AccessCode[] = []
|
|
26
|
-
|
|
27
24
|
const [showingAccessCodes, toggleAccessCodes] = useToggle()
|
|
28
25
|
|
|
29
26
|
if (showingAccessCodes) {
|
|
30
27
|
return (
|
|
31
28
|
<AccessCodeTable
|
|
32
|
-
|
|
29
|
+
deviceId={device.device_id}
|
|
33
30
|
onClickBack={toggleAccessCodes}
|
|
34
31
|
/>
|
|
35
32
|
)
|