diff --git a/package.json b/package.json index 06cb9a2115..4cae215c12 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "react-latex-next": "^2.1.0", "react-mde": "^11.5.0", "react-papaparse": "^4.0.2", + "react-qr-reader": "^3.0.0-beta-1", "react-redux": "^8.0.2", "react-responsive": "^9.0.0-beta.10", "react-router-dom": "^5.3.0", diff --git a/src/commons/sideContent/SideContentRemoteExecution.tsx b/src/commons/sideContent/SideContentRemoteExecution.tsx index e8910ce946..532fb3928f 100644 --- a/src/commons/sideContent/SideContentRemoteExecution.tsx +++ b/src/commons/sideContent/SideContentRemoteExecution.tsx @@ -9,7 +9,7 @@ import { Spinner } from '@blueprintjs/core'; import classNames from 'classnames'; -import React from 'react'; +import React, { SetStateAction } from 'react'; import { shallowEqual, useDispatch, useSelector } from 'react-redux'; import { NavLink } from 'react-router-dom'; import { Dispatch } from 'redux'; @@ -25,6 +25,8 @@ import { WorkspaceLocation } from '../workspace/WorkspaceTypes'; export interface SideContentRemoteExecutionProps { workspace: WorkspaceLocation; + secretParams?: string; + callbackFunction?: React.Dispatch>; } interface DeviceMenuItemButtonsProps { @@ -116,7 +118,10 @@ const DeviceContent = ({ session }: { session?: DeviceSession }) => { }; const SideContentRemoteExecution: React.FC = props => { - const [dialogState, setDialogState] = React.useState(undefined); + const [dialogState, setDialogState] = React.useState( + props.secretParams ? true : undefined + ); + const [secretParams, setSecretParams] = React.useState(props.secretParams); const [isLoggedIn, devices, currentSession]: [ boolean, @@ -212,7 +217,14 @@ const SideContentRemoteExecution: React.FC = pr setDialogState(undefined)} + defaultSecret={dialogState === true ? secretParams : undefined} + onClose={() => { + setDialogState(undefined); + setSecretParams(undefined); + if (props.callbackFunction) { + props.callbackFunction(undefined); + } + }} /> ); diff --git a/src/features/remoteExecution/RemoteExecutionDeviceDialog.tsx b/src/features/remoteExecution/RemoteExecutionDeviceDialog.tsx index b90944d1cc..4a9363a519 100644 --- a/src/features/remoteExecution/RemoteExecutionDeviceDialog.tsx +++ b/src/features/remoteExecution/RemoteExecutionDeviceDialog.tsx @@ -1,6 +1,16 @@ -import { Button, Callout, Classes, Dialog, FormGroup, HTMLSelect } from '@blueprintjs/core'; +import { + Button, + Callout, + Classes, + Dialog, + FormGroup, + HTMLSelect, + InputGroup +} from '@blueprintjs/core'; +import { Tooltip2 } from '@blueprintjs/popover2'; import classNames from 'classnames'; import React from 'react'; +import { QrReader } from 'react-qr-reader'; import { useDispatch } from 'react-redux'; import { editDevice, registerDevice } from '../../commons/sagas/RequestsSaga'; @@ -17,12 +27,14 @@ export interface RemoteExecutionDeviceDialogProps { isOpen: boolean; onClose: () => void; deviceToEdit?: Device; + defaultSecret?: string; } export default function RemoteExecutionDeviceDialog({ isOpen, onClose, - deviceToEdit + deviceToEdit, + defaultSecret }: RemoteExecutionDeviceDialogProps) { const dispatch = useDispatch(); const nameField = useField(validateNotEmpty); @@ -31,6 +43,7 @@ export default function RemoteExecutionDeviceDialog({ const [isSubmitting, setIsSubmitting] = React.useState(false); const [errorMessage, setErrorMessage] = React.useState(); + const [showScanner, setShowScanner] = React.useState(false); const onSubmit = async () => { const fields = collectFieldValues(nameField, typeField, secretField); @@ -59,6 +72,12 @@ export default function RemoteExecutionDeviceDialog({ setIsSubmitting(false); }; + const scanButton = ( + +