diff --git a/frontend/app/components/Assist/Assist.tsx b/frontend/app/components/Assist/Assist.tsx
index c59b32d03..9c8156631 100644
--- a/frontend/app/components/Assist/Assist.tsx
+++ b/frontend/app/components/Assist/Assist.tsx
@@ -1,5 +1,5 @@
import React from 'react'
-import ChatWindow from './components/ChatWindow/ChatWindow'
+import ChatWindow from './ChatWindow/ChatWindow'
import ScreenSharing from './ScreenSharing/ScreenSharing'
function Assist() {
diff --git a/frontend/app/components/Assist/ChatWindow/ChatWindow.tsx b/frontend/app/components/Assist/ChatWindow/ChatWindow.tsx
new file mode 100644
index 000000000..b142cd3a2
--- /dev/null
+++ b/frontend/app/components/Assist/ChatWindow/ChatWindow.tsx
@@ -0,0 +1,17 @@
+import React from 'react'
+import VideoContainer from '../components/VideoContainer/VideoContainer'
+// import stl from './chatWindow.css';
+
+function ChatWindow() {
+ return (
+
+ )
+}
+
+export default ChatWindow
diff --git a/frontend/app/components/Assist/components/ChatWindow/chatWindow.css b/frontend/app/components/Assist/ChatWindow/chatWindow.css
similarity index 77%
rename from frontend/app/components/Assist/components/ChatWindow/chatWindow.css
rename to frontend/app/components/Assist/ChatWindow/chatWindow.css
index 0d84b5bc4..48e7501bc 100644
--- a/frontend/app/components/Assist/components/ChatWindow/chatWindow.css
+++ b/frontend/app/components/Assist/ChatWindow/chatWindow.css
@@ -1,6 +1,6 @@
.wrapepr {
background-color: white;
- border: solid thin $gray-medium
+ border: solid thin #CCC;
border-radius: 3px;
position: fixed;
height: 400px;
diff --git a/frontend/app/components/Assist/components/ChatWindow/index.js b/frontend/app/components/Assist/ChatWindow/index.js
similarity index 100%
rename from frontend/app/components/Assist/components/ChatWindow/index.js
rename to frontend/app/components/Assist/ChatWindow/index.js
diff --git a/frontend/app/components/Assist/components/AssistActions/AassistActions.css b/frontend/app/components/Assist/components/AssistActions/AassistActions.css
new file mode 100644
index 000000000..aacce0805
--- /dev/null
+++ b/frontend/app/components/Assist/components/AssistActions/AassistActions.css
@@ -0,0 +1,3 @@
+.btn {
+
+}
\ No newline at end of file
diff --git a/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx b/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx
new file mode 100644
index 000000000..6b2b89279
--- /dev/null
+++ b/frontend/app/components/Assist/components/AssistActions/AssistActions.tsx
@@ -0,0 +1,24 @@
+import React from 'react'
+import { Button, Icon } from 'UI'
+import cn from 'classnames'
+// import stl from './AassistActions.css'
+
+interface Props {
+ isLive: false;
+}
+
+function AssistActions({ }: Props) {
+ return (
+
+
+
+
+
+
+ Request Control
+
+
+ )
+}
+
+export default AssistActions
diff --git a/frontend/app/components/Assist/components/AssistActions/index.js b/frontend/app/components/Assist/components/AssistActions/index.js
new file mode 100644
index 000000000..3e5108198
--- /dev/null
+++ b/frontend/app/components/Assist/components/AssistActions/index.js
@@ -0,0 +1 @@
+export { default } from './AssistActions'
\ No newline at end of file
diff --git a/frontend/app/components/Assist/components/ChatWindow/ChatWindow.tsx b/frontend/app/components/Assist/components/ChatWindow/ChatWindow.tsx
deleted file mode 100644
index 5bf91e812..000000000
--- a/frontend/app/components/Assist/components/ChatWindow/ChatWindow.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import React from 'react'
-import VideoContainer from '../VideoContainer/VideoContainer'
-// impdort stl from './chatWindow.css'
-
-function ChatWindow() {
- return (
-
- )
-}
-
-export default ChatWindow
diff --git a/frontend/app/components/Assist/components/VideoContainer/VideoContainer.tsx b/frontend/app/components/Assist/components/VideoContainer/VideoContainer.tsx
index d9b805464..cab7d5af4 100644
--- a/frontend/app/components/Assist/components/VideoContainer/VideoContainer.tsx
+++ b/frontend/app/components/Assist/components/VideoContainer/VideoContainer.tsx
@@ -1,50 +1,19 @@
import React, { useEffect } from 'react'
import { Button, Icon } from 'UI'
-function VideoContainer() {
- const constraints = {
- 'video': true,
- 'audio': true
- }
-
- async function playVideoFromCamera() {
- try {
- const constraints = {'video': true, 'audio': true};
- const stream = await navigator.mediaDevices.getUserMedia(constraints);
- const videoElement = document.querySelector('video#localVideo');
- // videoElement.srcObject = stream;
- } catch(error) {
- console.error('Error opening video camera.', error);
- }
-}
-
- function getConnectedDevices(type, callback) {
- navigator.mediaDevices.enumerateDevices()
- .then(devices => {
- const filtered = devices.filter(device => device.kind === type);
- callback(filtered);
- });
- }
-
+function VideoContainer() {
useEffect(() => {
- getConnectedDevices('videoinput', cameras => console.log('Cameras found', cameras));
- navigator.mediaDevices.getUserMedia(constraints)
- .then(stream => {
- console.log('Got MediaStream:', stream);
- })
- .catch(error => {
- console.error('Error accessing media devices.', error);
- });
+ // TODO check for video stream and display
}, [])
return (
-
diff --git a/frontend/app/components/BugFinder/BugFinder.js b/frontend/app/components/BugFinder/BugFinder.js
index e5d07f6d6..a5d5d87ed 100644
--- a/frontend/app/components/BugFinder/BugFinder.js
+++ b/frontend/app/components/BugFinder/BugFinder.js
@@ -25,7 +25,7 @@ import { LAST_7_DAYS } from 'Types/app/period';
import { resetFunnel } from 'Duck/funnels';
import { resetFunnelFilters } from 'Duck/funnelFilters'
import NoSessionsMessage from '../shared/NoSessionsMessage';
-import Assist from 'Components/Assist'
+import LiveSessionList from './LiveSessionList'
const AUTOREFRESH_INTERVAL = 10 * 60 * 1000;
@@ -135,16 +135,16 @@ export default class BugFinder extends React.PureComponent {
setActiveTab = tab => {
this.props.setActiveTab(tab);
-
}
render() {
const { activeFlow, activeTab } = this.props;
const { showRehydratePanel } = this.state;
+ console.log('activeTab', activeTab)
+
return (
-
-
- {activeFlow && activeFlow.type === 'flows' ?
-
- :
-
- }
+
+ { activeFlow && activeFlow.type === 'flows' &&
}
+ { activeTab.type !== 'live' &&
}
+ { activeTab.type === 'live' &&
}
+}
+
+function LiveSessionList({ loading, list }: Props ) {
+ return (
+
+
+
+
+
+ )
+}
+
+export default connect(state => ({
+
+}), { })(LiveSessionList)
diff --git a/frontend/app/components/BugFinder/LiveSessionList/index.js b/frontend/app/components/BugFinder/LiveSessionList/index.js
new file mode 100644
index 000000000..eb38fa3e7
--- /dev/null
+++ b/frontend/app/components/BugFinder/LiveSessionList/index.js
@@ -0,0 +1 @@
+export { default } from './LiveSessionList'
\ No newline at end of file
diff --git a/frontend/app/components/BugFinder/SessionList/SessionList.js b/frontend/app/components/BugFinder/SessionList/SessionList.js
index 13ddf9baa..7d4048782 100644
--- a/frontend/app/components/BugFinder/SessionList/SessionList.js
+++ b/frontend/app/components/BugFinder/SessionList/SessionList.js
@@ -123,7 +123,7 @@ export default class SessionList extends React.PureComponent {
const { activeTab, allList, total } = this.props;
var filteredList;
- if (activeTab.type !== ALL && activeTab.type !== 'bookmark') { // Watchdog sessions
+ if (activeTab.type !== ALL && activeTab.type !== 'bookmark' && activeTab.type !== 'live') { // Watchdog sessions
filteredList = allList.filter(session => activeTab.fits(session))
} else {
filteredList = allList
diff --git a/frontend/app/components/BugFinder/SessionsMenu/SessionsMenu.js b/frontend/app/components/BugFinder/SessionsMenu/SessionsMenu.js
index af5adf937..f01b88f24 100644
--- a/frontend/app/components/BugFinder/SessionsMenu/SessionsMenu.js
+++ b/frontend/app/components/BugFinder/SessionsMenu/SessionsMenu.js
@@ -81,6 +81,16 @@ function SessionsMenu(props) {
onClick={() => onMenuItemClick({ name: 'Bookmarks', type: 'bookmark' })}
/>
+
+
+ onMenuItemClick({ name: 'Assist', type: 'live' })}
+ />
+
+
diff --git a/frontend/app/components/Session/LivePlayer.js b/frontend/app/components/Session/LivePlayer.js
new file mode 100644
index 000000000..7c26c3c95
--- /dev/null
+++ b/frontend/app/components/Session/LivePlayer.js
@@ -0,0 +1,66 @@
+import { useEffect } from 'react';
+import { connect } from 'react-redux';
+import { Loader } from 'UI';
+import { toggleFullscreen, closeBottomBlock } from 'Duck/components/player';
+import {
+ PlayerProvider,
+ connectPlayer,
+ init as initPlayer,
+ clean as cleanPlayer,
+} from 'Player';
+import { Controls as PlayerControls } from 'Player';
+import Assist from 'Components/Assist'
+
+
+import PlayerBlockHeader from '../Session_/PlayerBlockHeader';
+import EventsBlock from '../Session_/EventsBlock';
+import PlayerBlock from '../Session_/PlayerBlock';
+import styles from '../Session_/session.css';
+
+
+
+const EventsBlockConnected = connectPlayer(state => ({
+ currentTimeEventIndex: state.eventListNow.length > 0 ? state.eventListNow.length - 1 : 0,
+ playing: state.playing,
+}))(EventsBlock)
+
+
+const InitLoader = connectPlayer(state => ({
+ loading: !state.initialized
+}))(Loader);
+
+
+function WebPlayer ({ session, toggleFullscreen, closeBottomBlock, live, fullscreen, jwt }) {
+ useEffect(() => {
+ initPlayer(session, jwt);
+ return () => cleanPlayer()
+ }, [ session.sessionId ]);
+
+ // LAYOUT (TODO: local layout state - useContext or something..)
+ useEffect(() => () => {
+ toggleFullscreen(false);
+ closeBottomBlock();
+ }, [])
+ return (
+
+
+
+
+
+
+
+ );
+}
+
+
+export default connect(state => ({
+ session: state.getIn([ 'sessions', 'current' ]),
+ jwt: state.get('jwt'),
+ fullscreen: state.getIn([ 'components', 'player', 'fullscreen' ]),
+}), {
+ toggleFullscreen,
+ closeBottomBlock,
+})(WebPlayer)
+
diff --git a/frontend/app/components/Session/Session.js b/frontend/app/components/Session/Session.js
index 27c87875c..5f921bc38 100644
--- a/frontend/app/components/Session/Session.js
+++ b/frontend/app/components/Session/Session.js
@@ -6,6 +6,7 @@ import { fetchList as fetchSlackList } from 'Duck/integrations/slack';
import { Link, NoContent, Loader } from 'UI';
import { sessions as sessionsRoute } from 'App/routes';
+import LivePlayer from './LivePlayer';
import WebPlayer from './WebPlayer';
import IOSPlayer from './IOSPlayer';
@@ -48,7 +49,7 @@ function Session({
{ session.isIOS
?
- :
+ :
}
diff --git a/frontend/app/components/Session_/PlayerBlockHeader.js b/frontend/app/components/Session_/PlayerBlockHeader.js
index 60773b57a..639c163f8 100644
--- a/frontend/app/components/Session_/PlayerBlockHeader.js
+++ b/frontend/app/components/Session_/PlayerBlockHeader.js
@@ -14,6 +14,7 @@ import { fetchList as fetchListIntegration } from 'Duck/integrations/actions';
import cls from './playerBlockHeader.css';
import Issues from './Issues/Issues';
import Autoplay from './Autoplay';
+import AssistActions from '../Assist/components/AssistActions';
const SESSIONS_ROUTE = sessionsRoute();
@@ -89,7 +90,7 @@ export default class PlayerBlockHeader extends React.PureComponent {
live,
disabled,
jiraConfig,
- fullscreen
+ fullscreen,
} = this.props;
return (
@@ -112,31 +113,36 @@ export default class PlayerBlockHeader extends React.PureComponent {
-
-
-
-
}
+ { live && (
+ <>
+
+
- }
- />
+
+ }
+ />
+ >
+ )}
{ !live && jiraConfig && jiraConfig.token &&
}