From 554e59134377b670d896659977d9d3c9c4f5aa44 Mon Sep 17 00:00:00 2001
From: Eric Rosenbaum <eric.rosenbaum@gmail.com>
Date: Thu, 14 Jun 2018 15:20:20 -0400
Subject: [PATCH] wip

---
 .../connection-modal/connected-step.jsx       | 29 ++++++++++
 .../connection-modal/connecting-step.jsx      | 29 ++++++++++
 .../connection-modal/connection-modal.css     | 45 ++------------
 .../connection-modal/connection-modal.jsx     | 29 +++++-----
 .../connection-modal/error-step.jsx           | 29 ++++++++++
 .../connection-modal/scanning-step.jsx        | 58 +++++++++++++++++++
 src/components/modal/modal.jsx                |  3 +-
 src/containers/blocks.jsx                     | 41 +++++++++----
 src/containers/connection-modal.jsx           | 16 ++++-
 src/containers/scanning-step.jsx              | 42 ++++++++++++++
 src/lib/libraries/extensions/index.jsx        |  6 +-
 11 files changed, 255 insertions(+), 72 deletions(-)
 create mode 100644 src/components/connection-modal/connected-step.jsx
 create mode 100644 src/components/connection-modal/connecting-step.jsx
 create mode 100644 src/components/connection-modal/error-step.jsx
 create mode 100644 src/components/connection-modal/scanning-step.jsx
 create mode 100644 src/containers/scanning-step.jsx

diff --git a/src/components/connection-modal/connected-step.jsx b/src/components/connection-modal/connected-step.jsx
new file mode 100644
index 000000000..03a70235e
--- /dev/null
+++ b/src/components/connection-modal/connected-step.jsx
@@ -0,0 +1,29 @@
+import {FormattedMessage} from 'react-intl';
+import PropTypes from 'prop-types';
+import React from 'react';
+
+import Box from '../box/box.jsx';
+
+import styles from './connection-modal.css';
+
+const ConnectedStep = props => (
+    <Box className={styles.body}>
+        <Box className={styles.buttonRow}>
+            <button
+                className={styles.searchButton}
+                onClick={props.onSearch}
+            >
+                <FormattedMessage
+                    defaultMessage="connected"
+                    description="Button in prompt for starting a search"
+                    id="gui.connection.search"
+                />
+            </button>
+        </Box>
+    </Box>
+);
+
+ConnectedStep.propTypes = {
+};
+
+export default ConnectedStep;
diff --git a/src/components/connection-modal/connecting-step.jsx b/src/components/connection-modal/connecting-step.jsx
new file mode 100644
index 000000000..b2b30cffb
--- /dev/null
+++ b/src/components/connection-modal/connecting-step.jsx
@@ -0,0 +1,29 @@
+import {FormattedMessage} from 'react-intl';
+import PropTypes from 'prop-types';
+import React from 'react';
+
+import Box from '../box/box.jsx';
+
+import styles from './connection-modal.css';
+
+const ConnectingStep = props => (
+    <Box className={styles.body}>
+        <Box className={styles.buttonRow}>
+            <button
+                className={styles.searchButton}
+                onClick={props.onSearch}
+            >
+                <FormattedMessage
+                    defaultMessage="connecting"
+                    description="Button in prompt for starting a search"
+                    id="gui.connection.search"
+                />
+            </button>
+        </Box>
+    </Box>
+);
+
+ConnectingStep.propTypes = {
+};
+
+export default ConnectingStep;
diff --git a/src/components/connection-modal/connection-modal.css b/src/components/connection-modal/connection-modal.css
index 34a8f5a21..d403af910 100644
--- a/src/components/connection-modal/connection-modal.css
+++ b/src/components/connection-modal/connection-modal.css
@@ -5,6 +5,10 @@
     width: 360px;
 }
 
+.header {
+    background-color: $pen-primary;
+}
+
 .body {
     background: $ui-white;
     padding: 1.5rem 2.25rem;
@@ -15,17 +19,6 @@
     margin: 0 0 0.75rem;
 }
 
-.input {
-    margin-bottom: 1.5rem;
-    width: 100%;
-    border: 1px solid $ui-black-transparent;
-    border-radius: 5px;
-    padding: 0 1rem;
-    height: 3rem;
-    color: $text-primary-transparent;
-    font-size: .875rem;
-}
-
 .button-row {
     font-weight: bolder;
     text-align: right;
@@ -49,33 +42,3 @@
 .button-row button + button {
     margin-left: 0.5rem;
 }
-
-.more-options {
-    border-top: 1px dashed hsla(0, 0%, 0%, .25);
-    overflow: visible;
-    padding: 1rem;
-    text-align: center;
-    margin: 0 0 1rem;
-}
-
-.hide-more-options {
-    display: none;
-}
-
-.more-options-accordion {
-    width: 60%;
-    margin: 0 auto;
-}
-
-.more-options-text {
-    opacity: .5;
-}
-
-.more-options-icon {
-    width: .75rem;
-    height: .75rem;
-    margin-left: .5rem;
-    vertical-align: middle;
-    padding-bottom: .2rem;
-    opacity: .5;
-}
diff --git a/src/components/connection-modal/connection-modal.jsx b/src/components/connection-modal/connection-modal.jsx
index e9ce818e8..73699b937 100644
--- a/src/components/connection-modal/connection-modal.jsx
+++ b/src/components/connection-modal/connection-modal.jsx
@@ -1,37 +1,40 @@
-import {FormattedMessage} from 'react-intl';
 import PropTypes from 'prop-types';
 import React from 'react';
 
 import Box from '../box/box.jsx';
 import Modal from '../modal/modal.jsx';
 
+import ScanningStep from '../../containers/scanning-step.jsx';
+import ConnectingStep from './connecting-step.jsx';
+import ConnectedStep from './connected-step.jsx';
+import ErrorStep from './error-step.jsx';
+
 import styles from './connection-modal.css';
 
+const phases = {
+    scanning: ScanningStep,
+    connecting: ConnectingStep,
+    connected: ConnectedStep,
+    error: ErrorStep
+};
+
 const ConnectionModalComponent = props => (
     <Modal
         className={styles.modalContent}
         contentLabel={props.title}
+        headerClassName={styles.header}
         onRequestClose={props.onCancel}
     >
         <Box className={styles.body}>
-            <Box className={styles.buttonRow}>
-                <button
-                    className={styles.cancelButton}
-                    onClick={props.onCancel}
-                >
-                    <FormattedMessage
-                        defaultMessage="cancel"
-                        description="Button in prompt for cancelling the dialog"
-                        id="gui.prompt.cancel"
-                    />
-                </button>
-            </Box>
+            {React.createElement(phases[props.phase], props)}
         </Box>
     </Modal>
 );
 
 ConnectionModalComponent.propTypes = {
     onCancel: PropTypes.func.isRequired,
+    onSearch: PropTypes.func.isRequired,
+    phase: PropTypes.string.isRequired,
     title: PropTypes.string.isRequired
 };
 
diff --git a/src/components/connection-modal/error-step.jsx b/src/components/connection-modal/error-step.jsx
new file mode 100644
index 000000000..451c7ab37
--- /dev/null
+++ b/src/components/connection-modal/error-step.jsx
@@ -0,0 +1,29 @@
+import {FormattedMessage} from 'react-intl';
+import PropTypes from 'prop-types';
+import React from 'react';
+
+import Box from '../box/box.jsx';
+
+import styles from './connection-modal.css';
+
+const ErrorStep = props => (
+    <Box className={styles.body}>
+        <Box className={styles.buttonRow}>
+            <button
+                className={styles.searchButton}
+                onClick={props.onSearch}
+            >
+                <FormattedMessage
+                    defaultMessage="error"
+                    description="Button in prompt for starting a search"
+                    id="gui.connection.search"
+                />
+            </button>
+        </Box>
+    </Box>
+);
+
+ErrorStep.propTypes = {
+};
+
+export default ErrorStep;
diff --git a/src/components/connection-modal/scanning-step.jsx b/src/components/connection-modal/scanning-step.jsx
new file mode 100644
index 000000000..c5fc4bbe6
--- /dev/null
+++ b/src/components/connection-modal/scanning-step.jsx
@@ -0,0 +1,58 @@
+import {FormattedMessage} from 'react-intl';
+import PropTypes from 'prop-types';
+import React from 'react';
+
+import Box from '../box/box.jsx';
+
+import styles from './connection-modal.css';
+
+const ScanningStep = props => (
+    <Box className={styles.body}>
+        <Box className={styles.activityArea}>
+            {props.searching ? (
+                props.devices.length === 0 ? (
+                    <div>search icon here</div>
+                ) : (
+                    props.devices.map(device => (
+                        <div>{device.name}</div>
+                    ))
+                )
+            ) : (
+                <div>No devices found, click on this hyperlink right now</div>
+            )}
+        </Box>
+        <Box className={styles.instructions}>
+            <FormattedMessage
+                defaultMessage="Select your device in the list above."
+                description=""
+                id="gui.connection.scanning.instructions"
+            />
+        </Box>
+        <Box className={styles.buttonRow}>
+            <button
+                className={styles.searchButton}
+                onClick={props.onSearch}
+            >
+                <FormattedMessage
+                    defaultMessage="scanning"
+                    description="Button in prompt for starting a search"
+                    id="gui.connection.search"
+                />
+            </button>
+        </Box>
+    </Box>
+);
+
+ScanningStep.propTypes = {
+    devices: PropTypes.arrayOf(PropTypes.shape({
+        name: PropTypes.string
+    })),
+    searching: PropTypes.bool.isRequired
+};
+
+ScanningStep.defaultProps = {
+    devices: [],
+    searching: true
+};
+
+export default ScanningStep;
diff --git a/src/components/modal/modal.jsx b/src/components/modal/modal.jsx
index dff3ce853..631e77261 100644
--- a/src/components/modal/modal.jsx
+++ b/src/components/modal/modal.jsx
@@ -26,7 +26,7 @@ const ModalComponent = props => (
             direction="column"
             grow={1}
         >
-            <div className={styles.header}>
+            <div className={classNames(styles.header, props.headerClassName)}>
                 <div
                     className={classNames(
                         styles.headerItem,
@@ -74,6 +74,7 @@ ModalComponent.propTypes = {
         PropTypes.object
     ]).isRequired,
     fullScreen: PropTypes.bool,
+    headerClassName: PropTypes.string,
     onRequestClose: PropTypes.func
 };
 
diff --git a/src/containers/blocks.jsx b/src/containers/blocks.jsx
index 13d87d9d4..30c7dd9e4 100644
--- a/src/containers/blocks.jsx
+++ b/src/containers/blocks.jsx
@@ -39,6 +39,8 @@ class Blocks extends React.Component {
             'attachVM',
             'detachVM',
             'handleCategorySelected',
+            'handleConnectionModalStart',
+            'handleConnectionModalClose',
             'handlePromptStart',
             'handlePromptCallback',
             'handlePromptClose',
@@ -57,12 +59,16 @@ class Blocks extends React.Component {
             'setLocale'
         ]);
         this.ScratchBlocks.prompt = this.handlePromptStart;
+        this.ScratchBlocks.statusButtonCallback = this.handleConnectionModalStart;
         this.state = {
             workspaceMetrics: {},
-            prompt: null
+            prompt: null,
+            connectionModal: null
         };
         this.onTargetsUpdate = debounce(this.onTargetsUpdate, 100);
         this.toolboxUpdateQueue = [];
+
+        this.state.connectionModal = true;
     }
     componentDidMount () {
         this.ScratchBlocks.FieldColourSlider.activateEyedropper_ = this.props.onActivateColorPicker;
@@ -95,6 +101,7 @@ class Blocks extends React.Component {
     shouldComponentUpdate (nextProps, nextState) {
         return (
             this.state.prompt !== nextState.prompt ||
+            this.state.connectionModal !== nextState.connectionModal ||
             this.props.isVisible !== nextProps.isVisible ||
             this.props.toolboxXML !== nextProps.toolboxXML ||
             this.props.extensionLibraryVisible !== nextProps.extensionLibraryVisible ||
@@ -327,6 +334,15 @@ class Blocks extends React.Component {
             optVarType !== this.ScratchBlocks.BROADCAST_MESSAGE_VARIABLE_TYPE;
         this.setState(p);
     }
+    handleConnectionModalStart (extensionId) {
+        const c = {connectionModal: {
+            id: extensionId
+        }};
+        this.setState(c);
+    }
+    handleConnectionModalClose () {
+        this.setState({connectionModal: null});
+    }
     handlePromptCallback (data) {
         this.state.prompt.callback(data);
         this.handlePromptClose();
@@ -366,17 +382,20 @@ class Blocks extends React.Component {
                     {...props}
                 />
                 {this.state.prompt ? (
-                    // <Prompt
-                    //     label={this.state.prompt.message}
-                    //     placeholder={this.state.prompt.defaultValue}
-                    //     showMoreOptions={this.state.prompt.showMoreOptions}
-                    //     title={this.state.prompt.title}
-                    //     onCancel={this.handlePromptClose}
-                    //     onOk={this.handlePromptCallback}
-                    // />
-                    <ConnectionModal
-                        title={'OMG a modal 😲 🔥 💯'}
+                    <Prompt
+                        label={this.state.prompt.message}
+                        placeholder={this.state.prompt.defaultValue}
+                        showMoreOptions={this.state.prompt.showMoreOptions}
+                        title={this.state.prompt.title}
                         onCancel={this.handlePromptClose}
+                        onOk={this.handlePromptCallback}
+                    />
+                ) : null}
+                {this.state.connectionModal ? (
+                    <ConnectionModal
+                        id={this.state.connectionModal.id}
+                        vm={vm}
+                        onCancel={this.handleConnectionModalClose}
                     />
                 ) : null}
                 {extensionLibraryVisible ? (
diff --git a/src/containers/connection-modal.jsx b/src/containers/connection-modal.jsx
index 460db8f96..0860b50b6 100644
--- a/src/containers/connection-modal.jsx
+++ b/src/containers/connection-modal.jsx
@@ -7,25 +7,35 @@ class ConnectionModal extends React.Component {
     constructor (props) {
         super(props);
         bindAll(this, [
-            'handleCancel'
+            'handleCancel',
+            'handleSearch'
         ]);
+        this.state = {
+            phase: 'scanning'
+        };
     }
     handleCancel () {
         this.props.onCancel();
     }
+    handleSearch () {
+        this.props.onSearch();
+    }
     render () {
         return (
             <ConnectionModalComponent
-                title={this.props.title}
+                title={this.props.id}
                 onCancel={this.handleCancel}
+                onSearch={this.handleSearch}
+                phase={this.state.phase}
             />
         );
     }
 }
 
 ConnectionModal.propTypes = {
+    id: PropTypes.string.isRequired,
     onCancel: PropTypes.func.isRequired,
-    title: PropTypes.string.isRequired
+    onSearch: PropTypes.func.isRequired
 };
 
 export default ConnectionModal;
diff --git a/src/containers/scanning-step.jsx b/src/containers/scanning-step.jsx
new file mode 100644
index 000000000..44d0c5781
--- /dev/null
+++ b/src/containers/scanning-step.jsx
@@ -0,0 +1,42 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import bindAll from 'lodash.bindall';
+import ScanningStepComponent from '../components/connection-modal/scanning-step.jsx';
+
+class ScanningStep extends React.Component {
+    constructor (props) {
+        super(props);
+        bindAll(this, [
+            'handleCancel',
+            'handleSearch'
+        ]);
+        this.state = {
+            searching: true,
+            devices: []
+        };
+    }
+    handleCancel () {
+        this.props.onCancel();
+    }
+    handleSearch () {
+        this.props.onSearch();
+    }
+    render () {
+        return (
+            <ScanningStepComponent
+                title={this.props.id}
+                onCancel={this.handleCancel}
+                onSearch={this.handleSearch}
+                phase={this.state.phase}
+            />
+        );
+    }
+}
+
+ScanningStep.propTypes = {
+    id: PropTypes.string.isRequired,
+    onCancel: PropTypes.func.isRequired,
+    onSearch: PropTypes.func.isRequired
+};
+
+export default ScanningStep;
diff --git a/src/lib/libraries/extensions/index.jsx b/src/lib/libraries/extensions/index.jsx
index 71404f8fb..82b5e67d9 100644
--- a/src/lib/libraries/extensions/index.jsx
+++ b/src/lib/libraries/extensions/index.jsx
@@ -120,7 +120,7 @@ export default [
             />
         ),
         featured: true,
-        disabled: true
+        disabled: false
     },
     {
         name: 'LEGO WeDo 2.0',
@@ -134,7 +134,7 @@ export default [
             />
         ),
         featured: true,
-        disabled: true
+        disabled: false
     },
     {
         name: 'LEGO MINDSTORMS EV3',
@@ -148,7 +148,7 @@ export default [
             />
         ),
         featured: true,
-        disabled: true
+        disabled: false
     },
     {
         name: 'LEGO Boost',
-- 
GitLab