feature(ui) - assist ui changes
This commit is contained in:
parent
75a7950f61
commit
9bb78e89b4
9 changed files with 98 additions and 46 deletions
|
|
@ -1,13 +1,16 @@
|
|||
import React, { useState, useEffect, FC } from 'react';
|
||||
import VideoContainer from '../components/VideoContainer';
|
||||
import stl from './chatWindow.css';
|
||||
import { callPeer } from 'App/player';
|
||||
import React, { useState, useEffect, FC } from 'react'
|
||||
import VideoContainer from '../components/VideoContainer'
|
||||
import { Icon, Popup } from 'UI'
|
||||
import stl from './chatWindow.css'
|
||||
import { callPeer } from 'App/player'
|
||||
import cn from 'classnames'
|
||||
|
||||
export interface Props {
|
||||
// call: (oStream: MediaStream, cb: (iStream: MediaStream)=>void)=>void
|
||||
}
|
||||
|
||||
const ChatWindow: FC<Props> = function ChatWindow() {
|
||||
const [minimize, setMinimize] = useState(false)
|
||||
const [ inputStream, setInputStream ] = useState<MediaStream | null>(null);
|
||||
const [ outputStream, setOutputStream ] = useState<MediaStream | null>(null);
|
||||
|
||||
|
|
@ -26,11 +29,30 @@ const ChatWindow: FC<Props> = function ChatWindow() {
|
|||
.catch(console.log) // TODO: handle error in ui
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div
|
||||
className="fixed border radius bg-white z-50 shadow-xl mt-16"
|
||||
return (
|
||||
<div
|
||||
className="fixed border radius bg-white z-50 shadow-xl mt-16 p-2"
|
||||
style={{ width: '220px' }}
|
||||
>
|
||||
<div className="p-2">
|
||||
<div className="flex items-center">
|
||||
<div>
|
||||
<button onClick={() => setMinimize(!minimize)}>
|
||||
<Icon name={ minimize ? "plus" : "minus" } size="14" />
|
||||
</button>
|
||||
</div>
|
||||
<Popup
|
||||
trigger={
|
||||
<button className="flex items-center ml-auto">
|
||||
<Icon name="high-engagement" size="16"/>
|
||||
</button>
|
||||
}
|
||||
content={ `Remote Control` }
|
||||
size="tiny"
|
||||
inverted
|
||||
position="top center"
|
||||
/>
|
||||
</div>
|
||||
<div className={cn({'hidden' : minimize}, 'mt-2')}>
|
||||
<VideoContainer stream={ inputStream } />
|
||||
<div className="py-1" />
|
||||
<VideoContainer stream={ outputStream } muted/>
|
||||
|
|
|
|||
|
|
@ -27,15 +27,7 @@ function AssistActions({ toggleChatWindow }: Props) {
|
|||
size="tiny"
|
||||
inverted
|
||||
position="top center"
|
||||
/>
|
||||
<div className="mx-1" />
|
||||
<div
|
||||
role="button"
|
||||
className="flex items-center p-2 cursor-pointer"
|
||||
>
|
||||
<Icon name="controller" size="20" />
|
||||
<span className="ml-2">Request Control</span>
|
||||
</div>
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,13 @@ function VideoContainer({ stream, muted = false }: Props) {
|
|||
useEffect(() => {
|
||||
if (ref.current) {
|
||||
ref.current.srcObject = stream;
|
||||
|
||||
stream?.getAudioTracks().forEach(track => {
|
||||
console.log(track)
|
||||
track.addEventListener('unmute', function(e) {
|
||||
console.log(e)
|
||||
})
|
||||
});
|
||||
}
|
||||
}, [ ref.current, stream ])
|
||||
|
||||
|
|
@ -33,8 +40,10 @@ function VideoContainer({ stream, muted = false }: Props) {
|
|||
setVideoEnabled(vEn)
|
||||
}
|
||||
|
||||
// console.log(stream && stream.getAudioTracks())
|
||||
|
||||
return (
|
||||
<div className="relative bg-gray-light-shade" style={{ height: '152px', width: '200px' }}>
|
||||
<div className="relative bg-gray-light-shade" style={{ height: '152px' }}>
|
||||
<div className="absolute inset-0 flex justify-center border border-gray-300 bg-white radius bg-opacity-25">
|
||||
<video autoPlay ref={ ref } muted={ muted } />
|
||||
<div className={cn(stl.controls, "flex items-center absolute w-full justify-end bottom-0")}>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ const countryOptions = Object.keys(countries).map(i => ({ text: countries[i], va
|
|||
filters: state.getIn([ 'filters', 'appliedFilter', 'filters' ]),
|
||||
filterValues: state.get('filterValues'),
|
||||
filterOptions: state.getIn([ 'filters', 'filterOptions' ]),
|
||||
activeTab: state.getIn([ 'sessions', 'activeTab', 'type' ]),
|
||||
}), {
|
||||
addAttribute,
|
||||
})
|
||||
|
|
@ -45,10 +46,11 @@ class Attributes extends React.PureComponent {
|
|||
return options && options.size ? toOptions(options.filter(i => !!i)) : []
|
||||
}
|
||||
render() {
|
||||
const { filters } = this.props;
|
||||
const { filters, activeTab } = this.props;
|
||||
|
||||
return (
|
||||
<>
|
||||
{ filters.size > 0 &&
|
||||
{ filters.size > 0 && activeTab !== 'live' &&
|
||||
<div>
|
||||
<div className="py-1"><ListHeader title="Filters" /></div>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -141,8 +141,6 @@ export default class BugFinder extends React.PureComponent {
|
|||
const { activeFlow, activeTab } = this.props;
|
||||
const { showRehydratePanel } = this.state;
|
||||
|
||||
console.log('activeTab', activeTab)
|
||||
|
||||
return (
|
||||
<div className="page-margin container-90 flex relative">
|
||||
<div className="flex-1 flex">
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ const customFilterAutoCompleteKeys = ['METADATA', KEYS.CLICK, KEYS.USER_BROWSER,
|
|||
customFilters: state.getIn([ 'filters', 'customFilters' ]),
|
||||
variables: state.getIn([ 'customFields', 'list' ]),
|
||||
sources: state.getIn([ 'customFields', 'sources' ]),
|
||||
activeTab: state.getIn([ 'sessions', 'activeTab', 'type' ]),
|
||||
}), {
|
||||
applyFilter,
|
||||
setActiveKey,
|
||||
|
|
@ -81,10 +82,11 @@ export default class FilterModal extends React.PureComponent {
|
|||
};
|
||||
|
||||
renderList(type, list) {
|
||||
const { activeTab } = this.props;
|
||||
const blocks = [];
|
||||
for (let j = 0; j < list.length; j++) {
|
||||
blocks.push(
|
||||
<div key={`${ j }-block`} className="mr-5" >
|
||||
<div key={`${ j }-block`} className={cn("mr-5", { [stl.disabled]: activeTab === 'live' && list[j].key !== 'USERID' })} >
|
||||
{ list[ j ] && this.renderFilterItem(type, list[ j ]) }
|
||||
</div>
|
||||
);
|
||||
|
|
@ -136,6 +138,7 @@ export default class FilterModal extends React.PureComponent {
|
|||
loading = false,
|
||||
searchedEvents,
|
||||
searchQuery = '',
|
||||
activeTab,
|
||||
} = this.props;
|
||||
const { query } = this.state;
|
||||
const reg = getRE(query, 'i');
|
||||
|
|
@ -158,6 +161,8 @@ export default class FilterModal extends React.PureComponent {
|
|||
const staticFilters = preloadedFilters
|
||||
.filter(({ value, actualValue }) => !this.props.loading && this.test(actualValue || value))
|
||||
|
||||
// console.log('filteredList', filteredList);
|
||||
|
||||
return (!displayed ? null :
|
||||
<div className={ stl.modal }>
|
||||
{ loading &&
|
||||
|
|
@ -173,22 +178,26 @@ export default class FilterModal extends React.PureComponent {
|
|||
{ searchQuery &&
|
||||
<React.Fragment>
|
||||
{this.renderEventDropdownPart(TYPES.USERID, 'User Id')}
|
||||
{this.renderEventDropdownPart(TYPES.METADATA, 'Metadata')}
|
||||
{this.renderEventDropdownPart(TYPES.CONSOLE, 'Errors')}
|
||||
{this.renderEventDropdownPart(TYPES.CUSTOM, 'Custom Events')}
|
||||
{this.renderEventDropdownPart(KEYS.USER_COUNTRY, 'Country', _appliedFilterKeys)}
|
||||
{this.renderEventDropdownPart(KEYS.USER_BROWSER, 'Browser', _appliedFilterKeys)}
|
||||
{this.renderEventDropdownPart(KEYS.USER_DEVICE, 'Device', _appliedFilterKeys)}
|
||||
{this.renderEventDropdownPart(TYPES.LOCATION, 'Page')}
|
||||
{this.renderEventDropdownPart(TYPES.CLICK, 'Click')}
|
||||
{this.renderEventDropdownPart(TYPES.FETCH, 'Fetch')}
|
||||
{this.renderEventDropdownPart(TYPES.INPUT, 'Input')}
|
||||
|
||||
{this.renderEventDropdownPart(KEYS.USER_OS, 'Operating System', _appliedFilterKeys)}
|
||||
{this.renderEventDropdownPart(KEYS.REFERRER, 'Referrer', _appliedFilterKeys)}
|
||||
{this.renderEventDropdownPart(TYPES.GRAPHQL, 'GraphQL')}
|
||||
{this.renderEventDropdownPart(TYPES.STATEACTION, 'Store Action')}
|
||||
{this.renderEventDropdownPart(TYPES.REVID, 'Rev ID')}
|
||||
{activeTab !== 'live' && (
|
||||
<>
|
||||
{this.renderEventDropdownPart(TYPES.METADATA, 'Metadata')}
|
||||
{this.renderEventDropdownPart(TYPES.CONSOLE, 'Errors')}
|
||||
{this.renderEventDropdownPart(TYPES.CUSTOM, 'Custom Events')}
|
||||
{this.renderEventDropdownPart(KEYS.USER_COUNTRY, 'Country', _appliedFilterKeys)}
|
||||
{this.renderEventDropdownPart(KEYS.USER_BROWSER, 'Browser', _appliedFilterKeys)}
|
||||
{this.renderEventDropdownPart(KEYS.USER_DEVICE, 'Device', _appliedFilterKeys)}
|
||||
{this.renderEventDropdownPart(TYPES.LOCATION, 'Page')}
|
||||
{this.renderEventDropdownPart(TYPES.CLICK, 'Click')}
|
||||
{this.renderEventDropdownPart(TYPES.FETCH, 'Fetch')}
|
||||
{this.renderEventDropdownPart(TYPES.INPUT, 'Input')}
|
||||
|
||||
{this.renderEventDropdownPart(KEYS.USER_OS, 'Operating System', _appliedFilterKeys)}
|
||||
{this.renderEventDropdownPart(KEYS.REFERRER, 'Referrer', _appliedFilterKeys)}
|
||||
{this.renderEventDropdownPart(TYPES.GRAPHQL, 'GraphQL')}
|
||||
{this.renderEventDropdownPart(TYPES.STATEACTION, 'Store Action')}
|
||||
{this.renderEventDropdownPart(TYPES.REVID, 'Rev ID')}
|
||||
</>
|
||||
)}
|
||||
</React.Fragment>
|
||||
}
|
||||
</div>
|
||||
|
|
@ -201,7 +210,7 @@ export default class FilterModal extends React.PureComponent {
|
|||
<div className={ stl.list }>
|
||||
{ this.renderList(category.type, category.keys) }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -88,4 +88,9 @@ h5.title {
|
|||
& .filterGroup {
|
||||
width: 205px;
|
||||
}
|
||||
}
|
||||
|
||||
.disabled {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
|
@ -1,23 +1,37 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { fetchLiveList } from 'Duck/sessions';
|
||||
import { connect } from 'react-redux';
|
||||
import { NoContent, Loader } from 'UI';
|
||||
import { List } from 'immutable';
|
||||
import { List, Map } from 'immutable';
|
||||
import SessionItem from 'Shared/SessionItem';
|
||||
|
||||
interface Props {
|
||||
loading: Boolean,
|
||||
list?: List<any>,
|
||||
fetchLiveList: () => void
|
||||
fetchLiveList: () => void,
|
||||
filters: List<any>
|
||||
}
|
||||
|
||||
function LiveSessionList(props: Props) {
|
||||
const { loading, list } = props;
|
||||
const { loading, list, filters } = props;
|
||||
const [userId, setUserId] = useState(undefined)
|
||||
|
||||
useEffect(() => {
|
||||
props.fetchLiveList();
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
console.log(filters)
|
||||
if (filters) {
|
||||
const userIdFilter = filters.filter(i => i.key === 'USERID').first()
|
||||
if (userIdFilter)
|
||||
setUserId(userIdFilter.value[0])
|
||||
else
|
||||
setUserId(undefined)
|
||||
}
|
||||
}, [filters])
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
<NoContent
|
||||
|
|
@ -27,7 +41,7 @@ function LiveSessionList(props: Props) {
|
|||
show={ !loading && list && list.size === 0}
|
||||
>
|
||||
<Loader loading={ loading }>
|
||||
{list?.map(session => (
|
||||
{list?.filter(i => i.userId === userId).map(session => (
|
||||
<SessionItem
|
||||
key={ session.sessionId }
|
||||
session={ session }
|
||||
|
|
@ -44,4 +58,5 @@ function LiveSessionList(props: Props) {
|
|||
export default connect(state => ({
|
||||
list: state.getIn(['sessions', 'liveSessions']),
|
||||
loading: state.getIn([ 'sessions', 'loading' ]),
|
||||
filters: state.getIn([ 'filters', 'appliedFilter', 'filters' ]),
|
||||
}), { fetchLiveList })(LiveSessionList)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ interface Props {
|
|||
function Counter({ startTime }: Props) {
|
||||
return (
|
||||
<div className="mx-2">
|
||||
{startTime && Duration.fromMillis(startTime).toFormat('m:ss')}
|
||||
{startTime && Duration.fromMillis(startTime).toFormat('h:m:ss')}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue