change(ui) - fixes in metric session list and other chanegs

This commit is contained in:
Shekar Siri 2022-02-09 18:39:33 +01:00
parent b33d05f1e6
commit 696f23b2ba
9 changed files with 106 additions and 59 deletions

View file

@ -26,6 +26,7 @@ import TrackerUpdateMessage from 'Shared/TrackerUpdateMessage';
import LiveSessionList from './LiveSessionList'
import SessionSearch from 'Shared/SessionSearch';
import MainSearchBar from 'Shared/MainSearchBar';
import LiveSearchBar from 'Shared/LiveSearchBar';
import { clearSearch } from 'Duck/search';
const weakEqual = (val1, val2) => {
@ -168,15 +169,28 @@ export default class BugFinder extends React.PureComponent {
<div className={cn("side-menu-margined", stl.searchWrapper) }>
<TrackerUpdateMessage />
<NoSessionsMessage />
<div
data-hidden={ activeTab === 'live' || activeTab === 'favorite' }
className="mb-5"
>
<MainSearchBar />
<SessionSearch />
</div>
{ activeTab.type !== 'live' && <SessionList onMenuItemClick={this.setActiveTab} /> }
{ activeTab.type === 'live' && <LiveSessionList /> }
{/* Recorde Sessions */}
{ activeTab.type !== 'live' && (
<>
<div className="mb-5">
<MainSearchBar />
<SessionSearch />
</div>
{ activeTab.type !== 'live' && <SessionList onMenuItemClick={this.setActiveTab} /> }
</>
)}
{/* Live Sessions */}
{ activeTab.type === 'live' && (
<>
<div className="mb-5">
<LiveSearchBar />
<SessionSearch />
</div>
{ activeTab.type === 'live' && <LiveSessionList /> }
</>
)}
</div>
</div>
<RehydrateSlidePanel

View file

@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
import { SlideModal, NoContent, Dropdown, Icon, TimezoneDropdown } from 'UI';
import { SlideModal, NoContent, Dropdown, Icon, TimezoneDropdown, Loader } from 'UI';
import SessionItem from 'Shared/SessionItem';
import stl from './SessionListModal.css';
import { connect } from 'react-redux';
@ -40,11 +40,26 @@ function SessionListModal(props: Props) {
]);
}, [list]);
const writeOption = (e, { name, value }) => setActiveSeries(value);
const getListSessionsBySeries = (seriesId) => {
const arr: any = []
list.forEach(element => {
if (seriesId === 'all') {
const sessionIds = arr.map(i => i.sessionId);
arr.push(...element.sessions.filter(i => !sessionIds.includes(i.sessionId)));
} else {
if (element.seriesId === seriesId) {
arr.push(...element.sessions)
}
}
});
return arr;
}
const filteredSessions = activeSeries === 'all' ? list.reduce((a, b) => a.concat(b.sessions), []) : list.filter(item => item.seriesId === activeSeries).reduce((a, b) => a.concat(b.sessions), []);
const startTime = new DateTime(activeWidget.startTimestamp).toFormat('LLL dd, yyyy HH:mm a');
const endTime = new DateTime(activeWidget.endTimestamp).toFormat('LLL dd, yyyy HH:mm a');
const writeOption = (e, { name, value }) => setActiveSeries(value);
const filteredSessions = getListSessionsBySeries(activeSeries);
const startTime = DateTime.fromMillis(activeWidget.startTimestamp).toFormat('LLL dd, yyyy HH:mm a');
const endTime = DateTime.fromMillis(activeWidget.endTimestamp).toFormat('LLL dd, yyyy HH:mm a');
return (
<SlideModal
title={ activeWidget && (
@ -80,13 +95,15 @@ function SessionListModal(props: Props) {
{/* <span className="mr-2 color-gray-medium">Series</span> */}
</div>
</div>
<NoContent
show={ !loading && (filteredSessions.length === 0 || filteredSessions.size === 0 )}
title="No recordings found!"
icon="exclamation-circle"
>
{ filteredSessions.map(session => <SessionItem key={ session.sessionId } session={ session } />) }
</NoContent>
<Loader loading={loading}>
<NoContent
show={ !loading && (filteredSessions.length === 0 )}
title="No recordings found!"
icon="exclamation-circle"
>
{ filteredSessions.map(session => <SessionItem key={ session.sessionId } session={ session } />) }
</NoContent>
</Loader>
</div>
)}
/>
@ -94,7 +111,7 @@ function SessionListModal(props: Props) {
}
export default connect(state => ({
loading: state.getIn(['customMetrics', 'sessionListRequest', 'loading']),
loading: state.getIn(['customMetrics', 'fetchSessionList', 'loading']),
list: state.getIn(['customMetrics', 'sessionList']),
// activeWidget: state.getIn(['customMetrics', 'activeWidget']),
}), { fetchSessionList, setActiveWidget })(SessionListModal);

View file

@ -4,7 +4,6 @@ import { connect } from 'react-redux';
import cn from 'classnames';
import stl from './FilterModal.css';
import { filtersMap, getMetaDataFilter } from 'Types/filter/newFilter';
// import { FilterKey, FilterType } from 'Types/filter/filterType';
interface Props {
filters: any,
@ -25,7 +24,6 @@ function FilterModal(props: Props) {
fetchingFilterSearchList,
searchQuery = '',
} = props;
// const hasFilerSearchList = filterSearchList && Object.keys(filterSearchList).length > 0;
const hasSearchQuery = searchQuery && searchQuery.length > 0;
const showSearchList = isMainSearch && searchQuery.length > 0;

View file

@ -0,0 +1,43 @@
import React from 'react';
import SessionSearchField from 'Shared/SessionSearchField';
import SavedSearch from 'Shared/SavedSearch';
import { Button, Popup } from 'UI';
import { clearSearch } from 'Duck/search';
import { connect } from 'react-redux';
interface Props {
clearSearch: () => void;
appliedFilter: any;
}
const LiveSearchBar = (props: Props) => {
const { appliedFilter } = props;
const hasFilters = appliedFilter && appliedFilter.filters && appliedFilter.filters.size > 0;
return (
<div className="flex items-center">
<div style={{ width: "80%", marginRight: "10px"}}>
<SessionSearchField />
</div>
<div className="flex items-center" style={{ width: "20%"}}>
<Popup
trigger={
<Button
plain
disabled={!hasFilters}
className="ml-auto"
onClick={() => props.clearSearch()}
>
<span className="font-medium">Clear</span>
</Button>
}
content={'Clear Steps'}
size="tiny"
inverted
position="top right"
/>
</div>
</div>
)
}
export default connect(state => ({
appliedFilter: state.getIn(['search', 'instance']),
}), { clearSearch })(LiveSearchBar);

View file

@ -0,0 +1 @@
export { default } from './LiveSearchBar';

View file

@ -1,26 +1,18 @@
import React, { useRef, useState } from 'react';
import React, { useState } from 'react';
import { connect } from 'react-redux';
import stl from './SessionSearchField.css';
import { Input } from 'UI';
import FilterModal from 'Shared/Filters/FilterModal';
// import { fetchList as fetchFilterSearch } from 'Duck/events';
import { fetchFilterSearch } from 'Duck/search';
import { debounce } from 'App/utils';
import { edit as editFilter } from 'Duck/search';
import {
addEvent, applyFilter, moveEvent, clearEvents,
addCustomFilter, addAttribute, setActiveFlow, setFilterOption
} from 'Duck/filters';
import { edit as editFilter, addFilterByKeyAndValue } from 'Duck/search';
interface Props {
// setSearchQuery: (query: string) => void;
fetchFilterSearch: (query: any) => void;
// searchQuery: string;
appliedFilter: any;
editFilter: typeof editFilter;
addFilterByKeyAndValue: (key: string, value: string) => void;
}
function SessionSearchField(props: Props) {
const { appliedFilter } = props;
const debounceFetchFilterSearch = debounce(props.fetchFilterSearch, 1000)
const [showModal, setShowModal] = useState(false)
const [searchQuery, setSearchQuery] = useState('')
@ -31,12 +23,7 @@ function SessionSearchField(props: Props) {
}
const onAddFilter = (filter) => {
filter.value = filter.value ? filter.value : [""]
const newFilters = appliedFilter.filters.concat(filter);
props.editFilter({
...appliedFilter.filter,
filters: newFilters,
});
props.addFilterByKeyAndValue(filter.key, filter.value)
}
return (
@ -46,10 +33,7 @@ function SessionSearchField(props: Props) {
className={stl.searchField}
onFocus={ () => setShowModal(true) }
onBlur={ () => setTimeout(setShowModal, 200, false) }
// ref={ this.inputRef }
onChange={ onSearchChange }
// onKeyUp={this.onKeyUp}
// value={props.searchQuery}
icon="search"
iconPosition="left"
placeholder={ 'Search sessions using any captured event (click, input, page, error...)'}
@ -72,14 +56,4 @@ function SessionSearchField(props: Props) {
);
}
export default connect(state => ({
events: state.getIn([ 'filters', 'appliedFilter', 'events' ]),
// searchQuery: state.getIn([ 'filters', 'searchQuery' ]),
appliedFilterKeys: state.getIn([ 'filters', 'appliedFilter', 'filters' ])
.map(({type}) => type).toJS(),
searchedEvents: state.getIn([ 'events', 'list' ]),
loading: state.getIn([ 'events', 'loading' ]),
strict: state.getIn([ 'filters', 'appliedFilter', 'strict' ]),
blink: state.getIn([ 'funnels', 'blink' ]),
appliedFilter: state.getIn(['search', 'instance']),
}), { fetchFilterSearch, editFilter })(SessionSearchField);
export default connect(null, { fetchFilterSearch, editFilter, addFilterByKeyAndValue })(SessionSearchField);

View file

@ -20,9 +20,9 @@ class SegmentSelection extends React.Component {
>
{ list.map(item => (
<Popup
key={ item.name }
trigger={
<div
key={ item.name }
className={ cn(styles.item, { 'opacity-25 cursor-default' : item.disabled }) }
data-active={ this.props.value && this.props.value.value === item.value }
onClick={ () => !item.disabled && this.setActiveItem(item) }

View file

@ -43,7 +43,7 @@ export const getChartFormatter = period => (data = []) =>
export const getStartAndEndTimestampsByDensity = (current, start, end, density) => {
const diff = end - start;
const step = diff / density;
const step = Math.floor(diff / density);
const currentIndex = Math.floor((current - start) / step);
const startTimestamp = parseInt(start + currentIndex * step);
const endTimestamp = parseInt(startTimestamp + step);

View file

@ -6,8 +6,8 @@ export const issues_types = List([
{ 'type': 'js_exception', 'visible': true, 'order': 0, 'name': 'Errors', 'icon': 'funnel/exclamation-circle' },
{ 'type': 'bad_request', 'visible': true, 'order': 1, 'name': 'Bad Requests', 'icon': 'funnel/file-medical-alt' },
{ 'type': 'missing_resource', 'visible': true, 'order': 2, 'name': 'Missing Images', 'icon': 'funnel/image' },
{ 'type': 'click_rage', 'visible': true, 'order': 3, 'name': 'Click Rage', 'icon': 'funnel/dizzy' },
{ 'type': 'dead_click', 'visible': true, 'order': 4, 'name': 'Dead Clicks', 'icon': 'funnel/emoji-angry' },
{ 'type': 'click_rage', 'visible': true, 'order': 3, 'name': 'Click Rage', 'icon': 'funnel/emoji-angry' },
{ 'type': 'dead_click', 'visible': true, 'order': 4, 'name': 'Dead Clicks', 'icon': 'funnel/dizzy' },
{ 'type': 'memory', 'visible': true, 'order': 5, 'name': 'High Memory', 'icon': 'funnel/sd-card' },
{ 'type': 'cpu', 'visible': true, 'order': 6, 'name': 'High CPU', 'icon': 'funnel/cpu' },
{ 'type': 'crash', 'visible': true, 'order': 7, 'name': 'Crashes', 'icon': 'funnel/file-earmark-break' },