+
+
+
+
+ {error.message}
+
+
+
+
+
-
-
-
-
-
-
Over the past 30 days
+
+ Over the past 30 days
-
-
-
-
-
Last session with this error
- {resentOrDate(error.lastOccurrence)}
-
-
-
- {error.customTags.length > 0 ? (
-
-
- More Info (most recent call)
-
-
- {error.customTags.map((tag) => (
-
-
{Object.entries(tag)[0][0]}
{Object.entries(tag)[0][1]}
-
- ))}
-
-
- ) : null}
-
-
-
-
-
-
-
- );
- }
+
+
+
+
+
+ Last session with this error
+
+
+ {resentOrDate(error.lastOccurrence)}
+
+
+
+
+ {error.customTags.length > 0 ? (
+
+
+ More Info{' '}
+ (most recent call)
+
+
+ {error.customTags.map((tag) => (
+
+
+ {Object.entries(tag)[0][0]}
+
{' '}
+
+ {Object.entries(tag)[0][1]}
+
+
+ ))}
+
+
+ ) : null}
+
+
+
+
+
+
+
+
+ );
}
+
+export default withRouter(
+ connect(null, { addFilterByKeyAndValue })(observer(MainSection))
+);
diff --git a/frontend/app/components/Errors/Errors.js b/frontend/app/components/Errors/Errors.js
deleted file mode 100644
index b9ec178b5..000000000
--- a/frontend/app/components/Errors/Errors.js
+++ /dev/null
@@ -1,154 +0,0 @@
-import React from 'react';
-import { connect } from 'react-redux';
-import withSiteIdRouter from 'HOCs/withSiteIdRouter';
-import withPermissions from 'HOCs/withPermissions'
-import { UNRESOLVED, RESOLVED, IGNORED, BOOKMARK } from "Types/errorInfo";
-import { fetchBookmarks, editOptions } from "Duck/errors";
-import { applyFilter } from 'Duck/search';
-import { errors as errorsRoute, isRoute } from "App/routes";
-import withPageTitle from 'HOCs/withPageTitle';
-import cn from 'classnames';
-import SelectDateRange from 'Shared/SelectDateRange';
-import Period from 'Types/app/period';
-
-import List from './List/List';
-import ErrorInfo from './Error/ErrorInfo';
-import Header from './Header';
-import SideMenuSection from './SideMenu/SideMenuSection';
-import SideMenuDividedItem from './SideMenu/SideMenuDividedItem';
-
-const ERRORS_ROUTE = errorsRoute();
-
-function getStatusLabel(status) {
- switch(status) {
- case UNRESOLVED:
- return "Unresolved";
- case RESOLVED:
- return "Resolved";
- case IGNORED:
- return "Ignored";
- default:
- return "";
- }
-}
-
-@withPermissions(['ERRORS'], 'page-margin container-90')
-@withSiteIdRouter
-@connect(state => ({
- list: state.getIn([ "errors", "list" ]),
- status: state.getIn([ "errors", "options", "status" ]),
- filter: state.getIn([ 'search', 'instance' ]),
-}), {
- fetchBookmarks,
- applyFilter,
- editOptions,
-})
-@withPageTitle("Errors - OpenReplay")
-export default class Errors extends React.PureComponent {
- constructor(props) {
- super(props)
- this.state = {
- filter: '',
- }
- }
-
- ensureErrorsPage() {
- const { history } = this.props;
- if (!isRoute(ERRORS_ROUTE, history.location.pathname)) {
- history.push(ERRORS_ROUTE);
- }
- }
-
- onStatusItemClick = ({ key }) => {
- this.props.editOptions({ status: key });
- }
-
- onBookmarksClick = () => {
- this.props.editOptions({ status: BOOKMARK });
- }
-
- onDateChange = (e) => {
- const dateValues = e.toJSON();
- this.props.applyFilter(dateValues);
- };
-
- render() {
- const {
- count,
- match: {
- params: { errorId }
- },
- status,
- list,
- history,
- filter,
- } = this.props;
-
- const { startDate, endDate, rangeValue } = filter;
- const period = new Period({ start: startDate, end: endDate, rangeName: rangeValue });
-
- return (
-
-
-
-
-
-
-
- { errorId == null ?
- <>
-
-
- >
- :
-
- }
-
-
- );
- }
-}
\ No newline at end of file
diff --git a/frontend/app/components/Errors/Header.js b/frontend/app/components/Errors/Header.js
deleted file mode 100644
index 283eb599b..000000000
--- a/frontend/app/components/Errors/Header.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import React from 'react';
-function Header({ text, count }) {
- return (
-
- { text }
- { count != null && { count } }
-
- );
-}
-
-Header.displayName = "Header";
-
-export default Header;
-
\ No newline at end of file
diff --git a/frontend/app/components/Errors/List/List.js b/frontend/app/components/Errors/List/List.js
deleted file mode 100644
index a51a3c2b0..000000000
--- a/frontend/app/components/Errors/List/List.js
+++ /dev/null
@@ -1,259 +0,0 @@
-import React from 'react';
-import { connect } from 'react-redux';
-import { Set } from "immutable";
-import { NoContent, Loader, Checkbox, IconButton, Input, Pagination } from 'UI';
-import { merge, resolve, unresolve, ignore, updateCurrentPage, editOptions } from "Duck/errors";
-import { applyFilter } from 'Duck/filters';
-import { IGNORED, UNRESOLVED } from 'Types/errorInfo';
-import Divider from 'Components/Errors/ui/Divider';
-import ListItem from './ListItem/ListItem';
-import { debounce } from 'App/utils';
-import Select from 'Shared/Select';
-import EmptyStateSvg from '../../../svg/no-results.svg';
-
-const sortOptionsMap = {
- 'occurrence-desc': 'Last Occurrence',
- 'occurrence-desc': 'First Occurrence',
- 'sessions-asc': 'Sessions Ascending',
- 'sessions-desc': 'Sessions Descending',
- 'users-asc': 'Users Ascending',
- 'users-desc': 'Users Descending',
-};
-const sortOptions = Object.entries(sortOptionsMap)
- .map(([ value, label ]) => ({ value, label }));
-
-@connect(state => ({
- loading: state.getIn([ "errors", "loading" ]),
- resolveToggleLoading: state.getIn(["errors", "resolve", "loading"]) ||
- state.getIn(["errors", "unresolve", "loading"]),
- ignoreLoading: state.getIn([ "errors", "ignore", "loading" ]),
- mergeLoading: state.getIn([ "errors", "merge", "loading" ]),
- currentPage: state.getIn(["errors", "currentPage"]),
- limit: state.getIn(["errors", "limit"]),
- total: state.getIn([ 'errors', 'totalCount' ]),
- sort: state.getIn([ 'errors', 'options', 'sort' ]),
- order: state.getIn([ 'errors', 'options', 'order' ]),
- query: state.getIn([ "errors", "options", "query" ]),
-}), {
- merge,
- resolve,
- unresolve,
- ignore,
- applyFilter,
- updateCurrentPage,
- editOptions,
-})
-export default class List extends React.PureComponent {
- constructor(props) {
- super(props)
- this.state = {
- checkedAll: false,
- checkedIds: Set(),
- query: props.query,
- }
- this.debounceFetch = debounce(this.props.editOptions, 1000);
- }
-
- componentDidMount() {
- this.props.applyFilter({ });
- }
-
- check = ({ errorId }) => {
- const { checkedIds } = this.state;
- const newCheckedIds = checkedIds.contains(errorId)
- ? checkedIds.remove(errorId)
- : checkedIds.add(errorId);
- this.setState({
- checkedAll: newCheckedIds.size === this.props.list.size,
- checkedIds: newCheckedIds
- });
- }
-
- checkAll = () => {
- if (this.state.checkedAll) {
- this.setState({
- checkedAll: false,
- checkedIds: Set(),
- });
- } else {
- this.setState({
- checkedAll: true,
- checkedIds: this.props.list.map(({ errorId }) => errorId).toSet(),
- });
- }
- }
-
- resetChecked = () => {
- this.setState({
- checkedAll: false,
- checkedIds: Set(),
- });
- }
-
- currentCheckedIds() {
- return this.state.checkedIds
- .intersect(this.props.list.map(({ errorId }) => errorId).toSet());
- }
-
- merge = () => {
- this.props.merge(currentCheckedIds().toJS()).then(this.resetChecked);
- }
-
- applyToAllChecked(f) {
- return Promise.all(this.currentCheckedIds().map(f).toJS()).then(this.resetChecked);
- }
-
- resolve = () => {
- this.applyToAllChecked(this.props.resolve);
- }
-
- unresolve = () => {
- this.applyToAllChecked(this.props.unresolve);
- }
-
- ignore = () => {
- this.applyToAllChecked(this.props.ignore);
- }
-
- addPage = () => this.props.updateCurrentPage(this.props.currentPage + 1)
-
- writeOption = ({ name, value }) => {
- const [ sort, order ] = value.split('-');
- if (name === 'sort') {
- this.props.editOptions({ sort, order });
- }
- }
-
- // onQueryChange = ({ target: { value, name } }) => props.edit({ [ name ]: value })
-
- onQueryChange = ({ target: { value, name } }) => {
- this.setState({ query: value });
- this.debounceFetch({ query: value });
- }
-
- render() {
- const {
- list,
- status,
- loading,
- ignoreLoading,
- resolveToggleLoading,
- mergeLoading,
- currentPage,
- total,
- sort,
- order,
- limit,
- } = this.props;
- const {
- checkedAll,
- checkedIds,
- query,
- } = this.state;
- const someLoading = loading || ignoreLoading || resolveToggleLoading || mergeLoading;
- const currentCheckedIds = this.currentCheckedIds();
-
- return (
-
-
-
-
- { status === UNRESOLVED
- ?
- :
- }
- { status !== IGNORED &&
-
- }
-
-
- Sort By
-
-
-
-
-
-
-
- No Errors Found!
-
- }
- subtext="Please try to change your search parameters."
- // animatedIcon="empty-state"
- show={ !loading && list.size === 0}
- >
-
- { list.map(e =>
-
- )}
-
-
this.props.updateCurrentPage(page)}
- limit={limit}
- debounceRequest={500}
- />
-
-
-
-
- );
- }
-}
diff --git a/frontend/app/components/Errors/List/ListItem/ListItem.js b/frontend/app/components/Errors/List/ListItem/ListItem.js
deleted file mode 100644
index 0e4474567..000000000
--- a/frontend/app/components/Errors/List/ListItem/ListItem.js
+++ /dev/null
@@ -1,87 +0,0 @@
-import React from 'react';
-import { BarChart, Bar, YAxis, Tooltip, XAxis } from 'recharts';
-import cn from 'classnames';
-import { DateTime } from 'luxon'
-import { diffFromNowString } from 'App/date';
-import { error as errorRoute } from 'App/routes';
-import { IGNORED, RESOLVED } from 'Types/errorInfo';
-import { Checkbox, Link } from 'UI';
-import ErrorName from 'Components/Errors/ui/ErrorName';
-import Label from 'Components/Errors/ui/Label';
-import stl from './listItem.module.css';
-import { Styles } from '../../../Dashboard/Widgets/common';
-
-const CustomTooltip = ({ active, payload, label }) => {
- if (active) {
- const p = payload[0].payload;
- const dateStr = p.timestamp ? DateTime.fromMillis(p.timestamp).toFormat('l') : ''
- return (
-
- );
- }
-
- return null;
-};
-
-function ListItem({ className, onCheck, checked, error, disabled }) {
-
- const getDateFormat = val => {
- const d = new Date(val);
- return (d.getMonth()+ 1) + '/' + d.getDate()
- }
-
- return (
-
- );
-}
-
-
-ListItem.displayName = "ListItem";
-export default ListItem;
\ No newline at end of file
diff --git a/frontend/app/components/Errors/List/ListItem/listItem.module.css b/frontend/app/components/Errors/List/ListItem/listItem.module.css
deleted file mode 100644
index c9f7589b9..000000000
--- a/frontend/app/components/Errors/List/ListItem/listItem.module.css
+++ /dev/null
@@ -1,16 +0,0 @@
-.name {
- min-width: 55%;
-}
-
-.sessions {
- width: 6%;
-}
-
-.users {
- width: 5%;
-}
-
-.occurrence {
- width: 15%;
- min-width: 152px;
-}
diff --git a/frontend/app/components/Errors/SideMenu/SideMenuDividedItem.js b/frontend/app/components/Errors/SideMenu/SideMenuDividedItem.js
deleted file mode 100644
index 9efa63ed4..000000000
--- a/frontend/app/components/Errors/SideMenu/SideMenuDividedItem.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import React from 'react';
-import { SideMenuitem } from "UI";
-import Divider from 'Components/Errors/ui/Divider';
-function SideMenuDividedItem({ className, noTopDivider = false, noBottomDivider = false, ...props }) {
- return (
-
- );
-}
-
-SideMenuDividedItem.displayName = "SideMenuDividedItem";
-
-export default SideMenuDividedItem;
-
diff --git a/frontend/app/components/Errors/SideMenu/SideMenuHeader.js b/frontend/app/components/Errors/SideMenu/SideMenuHeader.js
deleted file mode 100644
index 32f1f7fc6..000000000
--- a/frontend/app/components/Errors/SideMenu/SideMenuHeader.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import React from 'react';
-import cn from 'classnames';
-import stl from './sideMenuHeader.module.css';
-
-function SideMenuHeader({ text, className }) {
- return (
-
- )
-}
-
-SideMenuHeader.displayName = "SideMenuHeader";
-export default SideMenuHeader;
diff --git a/frontend/app/components/Errors/SideMenu/SideMenuSection.js b/frontend/app/components/Errors/SideMenu/SideMenuSection.js
deleted file mode 100644
index f2d6732f2..000000000
--- a/frontend/app/components/Errors/SideMenu/SideMenuSection.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import React from 'react';
-import { SideMenuitem } from 'UI';
-import SideMenuHeader from './SideMenuHeader';
-
-function SideMenuSection({ title, items, onItemClick }) {
- return (
- <>
-