From 1f00bf27f0091249582f10559f7640b543c349e8 Mon Sep 17 00:00:00 2001
From: Angel Penchev <26301867+angel-penchev@users.noreply.github.com>
Date: Tue, 26 Oct 2021 15:25:53 +0300
Subject: [PATCH] [Feat] BluetoothConnectionOptions
Created a button which opens a dialog for bluetooth device choice.
References #24, #27.
---
.../BluetoothConnectDialog.lazy.tsx | 15 ++++++
.../BluetoothConnectDialog.module.scss | 1 +
.../BluetoothConnectDialog.stories.tsx | 12 +++++
.../BluetoothConnectDialog.test.tsx | 14 ++++++
.../BluetoothConnectDialog.tsx | 48 +++++++++++++++++++
.../BluetoothConnectionOptions.lazy.tsx | 11 +++++
.../BluetoothConnectionOptions.module.scss | 1 +
.../BluetoothConnectionOptions.stories.tsx | 12 +++++
.../BluetoothConnectionOptions.test.tsx | 14 ++++++
.../BluetoothConnectionOptions.tsx | 48 +++++++++++++++++++
.../BluetoothDeviceSelection.tsx | 19 ++++----
.../HeadsetMonitor/HeadsetMonitor.lazy.tsx | 11 +++++
.../HeadsetMonitor/HeadsetMonitor.module.scss | 1 +
.../HeadsetMonitor/HeadsetMonitor.stories.tsx | 12 +++++
.../HeadsetMonitor/HeadsetMonitor.test.tsx | 14 ++++++
.../HeadsetMonitor/HeadsetMonitor.tsx | 14 ++++++
.../UnsupportedPlatform.lazy.tsx | 11 +++++
.../UnsupportedPlatform.module.scss | 1 +
.../UnsupportedPlatform.stories.tsx | 12 +++++
.../UnsupportedPlatform.test.tsx | 14 ++++++
.../UnsupportedPlatform.tsx | 19 ++++++++
21 files changed, 296 insertions(+), 8 deletions(-)
create mode 100644 client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.lazy.tsx
create mode 100644 client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.module.scss
create mode 100644 client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.stories.tsx
create mode 100644 client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.test.tsx
create mode 100644 client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.tsx
create mode 100644 client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.lazy.tsx
create mode 100644 client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.module.scss
create mode 100644 client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.stories.tsx
create mode 100644 client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.test.tsx
create mode 100644 client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.tsx
create mode 100644 client/src/components/HeadsetMonitor/HeadsetMonitor.lazy.tsx
create mode 100644 client/src/components/HeadsetMonitor/HeadsetMonitor.module.scss
create mode 100644 client/src/components/HeadsetMonitor/HeadsetMonitor.stories.tsx
create mode 100644 client/src/components/HeadsetMonitor/HeadsetMonitor.test.tsx
create mode 100644 client/src/components/HeadsetMonitor/HeadsetMonitor.tsx
create mode 100644 client/src/components/UnsupportedPlatform/UnsupportedPlatform.lazy.tsx
create mode 100644 client/src/components/UnsupportedPlatform/UnsupportedPlatform.module.scss
create mode 100644 client/src/components/UnsupportedPlatform/UnsupportedPlatform.stories.tsx
create mode 100644 client/src/components/UnsupportedPlatform/UnsupportedPlatform.test.tsx
create mode 100644 client/src/components/UnsupportedPlatform/UnsupportedPlatform.tsx
diff --git a/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.lazy.tsx b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.lazy.tsx
new file mode 100644
index 0000000..954c7fa
--- /dev/null
+++ b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.lazy.tsx
@@ -0,0 +1,15 @@
+import React, { lazy, Suspense } from 'react';
+
+const LazyBluetoothConnectDialog = lazy(
+ () => import('./BluetoothConnectDialog'),
+);
+
+const BluetoothConnectDialog = (
+ props: JSX.IntrinsicAttributes & { children?: React.ReactNode },
+) => (
+
+
+
+);
+
+export default BluetoothConnectDialog;
diff --git a/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.module.scss b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.module.scss
new file mode 100644
index 0000000..8006276
--- /dev/null
+++ b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.module.scss
@@ -0,0 +1 @@
+.BluetoothConnectDialog {}
\ No newline at end of file
diff --git a/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.stories.tsx b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.stories.tsx
new file mode 100644
index 0000000..acb4caf
--- /dev/null
+++ b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.stories.tsx
@@ -0,0 +1,12 @@
+/* eslint-disable */
+import BluetoothConnectDialog from './BluetoothConnectDialog';
+
+export default {
+ title: "BluetoothConnectDialog",
+};
+
+export const Default = () => ;
+
+Default.story = {
+ name: 'default',
+};
diff --git a/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.test.tsx b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.test.tsx
new file mode 100644
index 0000000..59b18d2
--- /dev/null
+++ b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.test.tsx
@@ -0,0 +1,14 @@
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect';
+import BluetoothConnectDialog from './BluetoothConnectDialog';
+
+describe('', () => {
+ test('it should mount', () => {
+ render();
+
+ const bluetoothConnectDialog = screen.getByTestId('BluetoothConnectDialog');
+
+ expect(bluetoothConnectDialog).toBeInTheDocument();
+ });
+});
diff --git a/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.tsx b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.tsx
new file mode 100644
index 0000000..2892357
--- /dev/null
+++ b/client/src/components/BluetoothConnectDialog/BluetoothConnectDialog.tsx
@@ -0,0 +1,48 @@
+import { Container, Dialog, DialogTitle } from '@mui/material';
+import React, { FC, useEffect, useState } from 'react';
+import styles from './BluetoothConnectDialog.module.scss';
+import BluetoothDeviceSelection from '../BluetoothDeviceSelection/BluetoothDeviceSelection';
+import UnsupportedPlatform from '../UnsupportedPlatform/UnsupportedPlatform';
+
+interface BluetoothConnectDialogProps {
+ open: boolean;
+ onClose: (device: BluetoothDevice) => void;
+}
+
+const BluetoothConnectDialog: FC = (
+ props: BluetoothConnectDialogProps,
+) => {
+ const { onClose, open } = props;
+ const [supportsBluetooth, setSupportsBluetooth] = useState(false);
+
+ useEffect(() => {
+ if (navigator.bluetooth) {
+ navigator.bluetooth
+ .getAvailability()
+ .then((isAvailable) => setSupportsBluetooth(isAvailable))
+ .catch(() => setSupportsBluetooth(false));
+ }
+ }, []);
+
+ const handleClose = (device: BluetoothDevice) => {
+ onClose(device);
+ };
+
+ return (
+
+
+
+ );
+};
+
+export default BluetoothConnectDialog;
diff --git a/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.lazy.tsx b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.lazy.tsx
new file mode 100644
index 0000000..4c61a03
--- /dev/null
+++ b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.lazy.tsx
@@ -0,0 +1,11 @@
+import React, { lazy, Suspense } from 'react';
+
+const LazyBluetoothConnectionOptions = lazy(() => import('./BluetoothConnectionOptions'));
+
+const BluetoothConnectionOptions = (props: JSX.IntrinsicAttributes & { children?: React.ReactNode; }) => (
+
+
+
+);
+
+export default BluetoothConnectionOptions;
diff --git a/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.module.scss b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.module.scss
new file mode 100644
index 0000000..c12c47d
--- /dev/null
+++ b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.module.scss
@@ -0,0 +1 @@
+.BluetoothConnectionOptions {}
\ No newline at end of file
diff --git a/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.stories.tsx b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.stories.tsx
new file mode 100644
index 0000000..514b3b9
--- /dev/null
+++ b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.stories.tsx
@@ -0,0 +1,12 @@
+/* eslint-disable */
+import BluetoothConnectionOptions from './BluetoothConnectionOptions';
+
+export default {
+ title: "BluetoothConnectionOptions",
+};
+
+export const Default = () => ;
+
+Default.story = {
+ name: 'default',
+};
diff --git a/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.test.tsx b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.test.tsx
new file mode 100644
index 0000000..d4e6cad
--- /dev/null
+++ b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.test.tsx
@@ -0,0 +1,14 @@
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect';
+import BluetoothConnectionOptions from './BluetoothConnectionOptions';
+
+describe('', () => {
+ test('it should mount', () => {
+ render();
+
+ const bluetoothConnectionOptions = screen.getByTestId('BluetoothConnectionOptions');
+
+ expect(bluetoothConnectionOptions).toBeInTheDocument();
+ });
+});
\ No newline at end of file
diff --git a/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.tsx b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.tsx
new file mode 100644
index 0000000..b367f02
--- /dev/null
+++ b/client/src/components/BluetoothConnectionOptions/BluetoothConnectionOptions.tsx
@@ -0,0 +1,48 @@
+import React, { FC, useContext } from 'react';
+import { Button, Container } from '@mui/material';
+import styles from './BluetoothConnectionOptions.module.scss';
+import { BluetoothSearching, BluetoothDisabled } from '@mui/icons-material';
+import BluetoothConnectDialog from '../BluetoothConnectDialog/BluetoothConnectDialog';
+import { HeadsetContext } from '../../contexts/HeadsetContext';
+
+const BluetoothConnectionOptions: FC<{}> = () => {
+ const { headset, setHeadset } = useContext(HeadsetContext);
+ const [open, setOpen] = React.useState(false);
+
+ const handleOpen = () => {
+ setOpen(true);
+ };
+
+ const handleClose = (device: BluetoothDevice) => {
+ setOpen(false);
+ connectDevice(device);
+ };
+
+ const connectDevice = (device: BluetoothDevice) => {
+ setHeadset(device);
+ };
+
+ const disconnectDevice = () => {
+ setHeadset(undefined);
+ };
+
+ return (
+
+ {!headset ? (
+
+ ) : (
+
+ )}
+
+
+ );
+};
+
+export default BluetoothConnectionOptions;
diff --git a/client/src/components/BluetoothDeviceSelection/BluetoothDeviceSelection.tsx b/client/src/components/BluetoothDeviceSelection/BluetoothDeviceSelection.tsx
index c57196f..fdb6ddd 100644
--- a/client/src/components/BluetoothDeviceSelection/BluetoothDeviceSelection.tsx
+++ b/client/src/components/BluetoothDeviceSelection/BluetoothDeviceSelection.tsx
@@ -8,16 +8,24 @@ import {
ListItemText,
Typography,
} from '@mui/material';
-import React, { FC, useState } from 'react';
+import React, { FC, useContext, useState } from 'react';
import styles from './BluetoothDeviceSelection.module.scss';
import { Bluetooth, Refresh } from '@mui/icons-material';
+import { HeadsetContext } from '../../contexts/HeadsetContext';
interface DevicesTable {
[key: string]: BluetoothDevice;
}
-const BluetoothDeviceSelection: FC<{}> = () => {
+interface BluetoothDeviceSelectionProps {
+ handleDeviceClick: (device: BluetoothDevice) => void;
+}
+
+const BluetoothDeviceSelection: FC = (
+ props: BluetoothDeviceSelectionProps,
+) => {
const [devices, setDevices] = useState({});
+ const { setHeadset } = useContext(HeadsetContext);
const refreshDevices = async () => {
const requestDeviceOptions = {
@@ -44,23 +52,18 @@ const BluetoothDeviceSelection: FC<{}> = () => {
setDevices(result);
};
- const connectDevice = (device: BluetoothDevice) => {
- console.log(device);
- };
-
return (
- Select a bluetooth device
{Object.values(devices).map((device) => (
- connectDevice(device)}>
+ props.handleDeviceClick(device)}>
diff --git a/client/src/components/HeadsetMonitor/HeadsetMonitor.lazy.tsx b/client/src/components/HeadsetMonitor/HeadsetMonitor.lazy.tsx
new file mode 100644
index 0000000..af2b07e
--- /dev/null
+++ b/client/src/components/HeadsetMonitor/HeadsetMonitor.lazy.tsx
@@ -0,0 +1,11 @@
+import React, { lazy, Suspense } from 'react';
+
+const LazyHeadsetMonitor = lazy(() => import('./HeadsetMonitor'));
+
+const HeadsetMonitor = (props: JSX.IntrinsicAttributes & { children?: React.ReactNode; }) => (
+
+
+
+);
+
+export default HeadsetMonitor;
diff --git a/client/src/components/HeadsetMonitor/HeadsetMonitor.module.scss b/client/src/components/HeadsetMonitor/HeadsetMonitor.module.scss
new file mode 100644
index 0000000..aa2f096
--- /dev/null
+++ b/client/src/components/HeadsetMonitor/HeadsetMonitor.module.scss
@@ -0,0 +1 @@
+.HeadsetMonitor {}
\ No newline at end of file
diff --git a/client/src/components/HeadsetMonitor/HeadsetMonitor.stories.tsx b/client/src/components/HeadsetMonitor/HeadsetMonitor.stories.tsx
new file mode 100644
index 0000000..335fa85
--- /dev/null
+++ b/client/src/components/HeadsetMonitor/HeadsetMonitor.stories.tsx
@@ -0,0 +1,12 @@
+/* eslint-disable */
+import HeadsetMonitor from './HeadsetMonitor';
+
+export default {
+ title: "HeadsetMonitor",
+};
+
+export const Default = () => ;
+
+Default.story = {
+ name: 'default',
+};
diff --git a/client/src/components/HeadsetMonitor/HeadsetMonitor.test.tsx b/client/src/components/HeadsetMonitor/HeadsetMonitor.test.tsx
new file mode 100644
index 0000000..d1cedc1
--- /dev/null
+++ b/client/src/components/HeadsetMonitor/HeadsetMonitor.test.tsx
@@ -0,0 +1,14 @@
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect';
+import HeadsetMonitor from './HeadsetMonitor';
+
+describe('', () => {
+ test('it should mount', () => {
+ render();
+
+ const headsetMonitor = screen.getByTestId('HeadsetMonitor');
+
+ expect(headsetMonitor).toBeInTheDocument();
+ });
+});
\ No newline at end of file
diff --git a/client/src/components/HeadsetMonitor/HeadsetMonitor.tsx b/client/src/components/HeadsetMonitor/HeadsetMonitor.tsx
new file mode 100644
index 0000000..e492cf1
--- /dev/null
+++ b/client/src/components/HeadsetMonitor/HeadsetMonitor.tsx
@@ -0,0 +1,14 @@
+import { Container } from '@mui/material';
+import React, { FC } from 'react';
+import BluetoothConnectionOptions from '../BluetoothConnectionOptions/BluetoothConnectionOptions';
+import styles from './HeadsetMonitor.module.scss';
+
+const HeadsetMonitor: FC<{}> = () => {
+ return (
+
+
+
+ );
+};
+
+export default HeadsetMonitor;
diff --git a/client/src/components/UnsupportedPlatform/UnsupportedPlatform.lazy.tsx b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.lazy.tsx
new file mode 100644
index 0000000..0b19910
--- /dev/null
+++ b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.lazy.tsx
@@ -0,0 +1,11 @@
+import React, { lazy, Suspense } from 'react';
+
+const LazyUnsupportedPlatform = lazy(() => import('./UnsupportedPlatform'));
+
+const UnsupportedPlatform = (props: JSX.IntrinsicAttributes & { children?: React.ReactNode; }) => (
+
+
+
+);
+
+export default UnsupportedPlatform;
diff --git a/client/src/components/UnsupportedPlatform/UnsupportedPlatform.module.scss b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.module.scss
new file mode 100644
index 0000000..030e476
--- /dev/null
+++ b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.module.scss
@@ -0,0 +1 @@
+.UnsupportedPlatform {}
\ No newline at end of file
diff --git a/client/src/components/UnsupportedPlatform/UnsupportedPlatform.stories.tsx b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.stories.tsx
new file mode 100644
index 0000000..bbcc320
--- /dev/null
+++ b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.stories.tsx
@@ -0,0 +1,12 @@
+/* eslint-disable */
+import UnsupportedPlatform from './UnsupportedPlatform';
+
+export default {
+ title: "UnsupportedPlatform",
+};
+
+export const Default = () => ;
+
+Default.story = {
+ name: 'default',
+};
diff --git a/client/src/components/UnsupportedPlatform/UnsupportedPlatform.test.tsx b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.test.tsx
new file mode 100644
index 0000000..0c1c4ea
--- /dev/null
+++ b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.test.tsx
@@ -0,0 +1,14 @@
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import '@testing-library/jest-dom/extend-expect';
+import UnsupportedPlatform from './UnsupportedPlatform';
+
+describe('', () => {
+ test('it should mount', () => {
+ render();
+
+ const unsupportedPlatform = screen.getByTestId('UnsupportedPlatform');
+
+ expect(unsupportedPlatform).toBeInTheDocument();
+ });
+});
\ No newline at end of file
diff --git a/client/src/components/UnsupportedPlatform/UnsupportedPlatform.tsx b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.tsx
new file mode 100644
index 0000000..8d6f98a
--- /dev/null
+++ b/client/src/components/UnsupportedPlatform/UnsupportedPlatform.tsx
@@ -0,0 +1,19 @@
+import { Container, Typography } from '@mui/material';
+import React, { FC } from 'react';
+import styles from './UnsupportedPlatform.module.scss';
+
+const UnsupportedPlatform: FC<{}> = () => {
+ return (
+
+
+ Sadly, the platform you are running this application on is currently
+ unsupported.
+
+
+ );
+};
+
+export default UnsupportedPlatform;