diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.tsx
index 6d1cd01e4..76b8697c1 100644
--- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.tsx
+++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricPieChart/CustomMetricPieChart.tsx
@@ -9,8 +9,6 @@ import { numberWithCommas } from 'App/utils';
interface Props {
metric: any,
data: any;
- params: any;
- // seriesMap: any;
colors: any;
onClick?: (filters) => void;
}
diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableSessions/CustomMetricTableSessions.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableSessions/CustomMetricTableSessions.tsx
new file mode 100644
index 000000000..4bd4cb983
--- /dev/null
+++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableSessions/CustomMetricTableSessions.tsx
@@ -0,0 +1,16 @@
+import React from 'react';
+
+interface Props {
+ data: any
+ metric?: any
+ isTemplate?: boolean;
+}
+function CustomMetricTableSessions(props: Props) {
+ return (
+
+
+
+ );
+}
+
+export default CustomMetricTableSessions;
\ No newline at end of file
diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableSessions/index.ts b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableSessions/index.ts
new file mode 100644
index 000000000..46889345c
--- /dev/null
+++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricTableSessions/index.ts
@@ -0,0 +1 @@
+export { default } from './CustomMetricTableSessions';
\ No newline at end of file
diff --git a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidgetPreview/CustomMetricWidgetPreview.tsx b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidgetPreview/CustomMetricWidgetPreview.tsx
index 5f90e01ac..f248fbc89 100644
--- a/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidgetPreview/CustomMetricWidgetPreview.tsx
+++ b/frontend/app/components/Dashboard/Widgets/CustomMetricsWidgets/CustomMetricWidgetPreview/CustomMetricWidgetPreview.tsx
@@ -1,28 +1,24 @@
import React, { useEffect, useState, useRef } from 'react';
import { connect } from 'react-redux';
-import { Loader, NoContent, SegmentSelection, Icon } from 'UI';
+import { Loader, NoContent, SegmentSelection } from 'UI';
import { Styles } from '../../common';
-// import { ResponsiveContainer, XAxis, YAxis, CartesianGrid, Tooltip, LineChart, Line, Legend } from 'recharts';
-import Period, { LAST_24_HOURS, LAST_30_MINUTES, YESTERDAY, LAST_7_DAYS } from 'Types/app/period';
+import Period from 'Types/app/period';
import stl from './CustomMetricWidgetPreview.module.css';
-import { getChartFormatter } from 'Types/dashboard/helper';
import { remove } from 'Duck/customMetrics';
import DateRange from 'Shared/DateRange';
import { edit } from 'Duck/customMetrics';
import CustomMetriLineChart from '../CustomMetriLineChart';
import CustomMetricPercentage from '../CustomMetricPercentage';
import CustomMetricTable from '../CustomMetricTable';
-
-import APIClient from 'App/api_client';
import CustomMetricPieChart from '../CustomMetricPieChart';
-const customParams = rangeName => {
+const customParams = (rangeName: string) => {
const params = { density: 70 }
- if (rangeName === LAST_24_HOURS) params.density = 70
- if (rangeName === LAST_30_MINUTES) params.density = 70
- if (rangeName === YESTERDAY) params.density = 70
- if (rangeName === LAST_7_DAYS) params.density = 70
+ // if (rangeName === LAST_24_HOURS) params.density = 70
+ // if (rangeName === LAST_30_MINUTES) params.density = 70
+ // if (rangeName === YESTERDAY) params.density = 70
+ // if (rangeName === LAST_7_DAYS) params.density = 70
return params
}
@@ -30,23 +26,18 @@ const customParams = rangeName => {
interface Props {
metric: any;
data?: any;
- showSync?: boolean;
- // compare?: boolean;
onClickEdit?: (e) => void;
remove: (id) => void;
edit: (metric) => void;
}
function CustomMetricWidget(props: Props) {
- const { metric, showSync } = props;
+ const { metric } = props;
const [loading, setLoading] = useState(false)
const [data, setData] = useState({ chart: [{}] })
- const [seriesMap, setSeriesMap] = useState([]);
const [period, setPeriod] = useState(Period({ rangeName: metric.rangeName, startDate: metric.startDate, endDate: metric.endDate }));
const colors = Styles.customMetricColors;
const params = customParams(period.rangeName)
- const gradientDef = Styles.gradientDef();
- const metricParams = { ...params, metricId: metric.metricId, viewType: 'lineChart' }
const prevMetricRef = useRef();
const isTimeSeries = metric.metricType === 'timeseries';
const isTable = metric.metricType === 'table';
@@ -59,29 +50,6 @@ function CustomMetricWidget(props: Props) {
};
prevMetricRef.current = metric;
setLoading(true);
-
- // fetch new data for the widget preview
- // new APIClient()['post']('/custom_metrics/try', { ...metricParams, ...metric.toSaveData() })
- // .then(response => response.json())
- // .then(({ errors, data }) => {
- // if (errors) {
- // console.log('err', errors)
- // } else {
- // const namesMap = data
- // .map(i => Object.keys(i))
- // .flat()
- // .filter(i => i !== 'time' && i !== 'timestamp')
- // .reduce((unique: any, item: any) => {
- // if (!unique.includes(item)) {
- // unique.push(item);
- // }
- // return unique;
- // }, []);
-
- // setSeriesMap(namesMap);
- // setData(getChartFormatter(period)(data));
- // }
- // }).finally(() => setLoading(false));
}, [metric])
const onDateChange = (changedDates) => {
@@ -185,7 +153,6 @@ function CustomMetricWidget(props: Props) {
metric={metric}
data={data[0]}
colors={colors}
- params={params}
/>
)}
>
diff --git a/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx b/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx
index 0ba99c29d..9d95fc503 100644
--- a/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx
+++ b/frontend/app/components/Dashboard/components/WidgetForm/WidgetForm.tsx
@@ -36,17 +36,22 @@ function WidgetForm(props: Props) {
// const write = ({ target: { value, name } }) => metricStore.merge({ [ name ]: value });
const writeOption = ({ value, name }: any) => {
- value = value.value
+ value = Array.isArray(value) ? value : value.value
const obj: any = { [ name ]: value };
if (name === 'metricValue') {
- obj['metricValue'] = [value];
+ obj['metricValue'] = value;
+
+ // handle issues (remove all when other option is selected)
+ if (Array.isArray(obj['metricValue']) && obj['metricValue'].length > 1) {
+ obj['metricValue'] = obj['metricValue'].filter(i => i.value !== 'all');
+ }
}
if (name === 'metricOf') {
- if (value === FilterKey.ISSUE) {
- obj['metricValue'] = ['all'];
- }
+ // if (value === FilterKey.ISSUE) {
+ // obj['metricValue'] = [{ value: 'all', label: 'All' }];
+ // }
}
if (name === 'metricType') {
@@ -71,7 +76,6 @@ function WidgetForm(props: Props) {
} else {
history.replace(withSiteId(metricDetails(metric.metricId), siteId));
}
-
}
});
}
@@ -131,9 +135,11 @@ function WidgetForm(props: Props) {
issue type
>
)}
diff --git a/frontend/app/components/shared/Select/Select.tsx b/frontend/app/components/shared/Select/Select.tsx
index 6122df577..1f02b476d 100644
--- a/frontend/app/components/shared/Select/Select.tsx
+++ b/frontend/app/components/shared/Select/Select.tsx
@@ -2,6 +2,7 @@ import React from 'react';
import Select, { components, DropdownIndicatorProps } from 'react-select';
import { Icon } from 'UI';
import colors from 'App/theme/colors';
+const { ValueContainer } = components;
interface Props {
options: any[];
@@ -84,6 +85,7 @@ export default function({ name = '', onChange, right = false, plain = false, opt
},
indicatorsContainer: (provided: any) => ({
...provided,
+ maxHeight: '34px',
padding: 0,
}),
valueContainer: (provided: any) => ({
@@ -112,6 +114,7 @@ export default function({ name = '', onChange, right = false, plain = false, opt
components={{
IndicatorSeparator: () => null,
DropdownIndicator,
+ ValueContainer: CustomValueContainer,
...components,
}}
onChange={(value) => onChange({ name, value: value })}
@@ -138,4 +141,22 @@ const DropdownIndicator = (
);
- };
\ No newline at end of file
+ };
+
+const CustomValueContainer = ({ children, ...rest }: any) => {
+ const selectedCount = rest.getValue().length
+ const conditional = (selectedCount < 3)
+
+ let firstChild: any = []
+
+ if (!conditional) {
+ firstChild = [children[0].shift(), children[1]]
+ }
+
+ return (
+
+ {conditional ? children : firstChild}
+ {!conditional && ` and ${selectedCount - 1} others`}
+
+ )
+ }
\ No newline at end of file
diff --git a/frontend/app/constants/filterOptions.js b/frontend/app/constants/filterOptions.js
index bcb2297fd..dbed5d32c 100644
--- a/frontend/app/constants/filterOptions.js
+++ b/frontend/app/constants/filterOptions.js
@@ -63,8 +63,8 @@ export const metricTypes = [
{ text: 'Timeseries', label: 'Timeseries', value: 'timeseries' },
{ text: 'Table', label: 'Table', value: 'table' },
{ label: 'Funnel', value: 'funnel' },
- { label: 'Errors', value: 'errors' },
- { label: 'Sessions', value: 'sessions' },
+ // { label: 'Errors', value: 'errors' },
+ // { label: 'Sessions', value: 'sessions' },
];
export const tableColumnName = {
@@ -79,6 +79,7 @@ export const tableColumnName = {
export const metricOf = [
{ text: 'Session Count', label: 'Session Count', value: 'sessionCount', type: 'timeseries' },
{ text: 'Users', label: 'Users', value: FilterKey.USERID, type: 'table' },
+ { text: 'Sessions', label: 'Sessions', value: FilterKey.SESSIONS, type: 'table' },
{ text: 'Issues', label: 'Issues', value: FilterKey.ISSUE, type: 'table' },
{ text: 'Browsers', label: 'Browsers', value: FilterKey.USER_BROWSER, type: 'table' },
{ text: 'Devices', label: 'Devices', value: FilterKey.USER_DEVICE, type: 'table' },
diff --git a/frontend/app/mstore/dashboardStore.ts b/frontend/app/mstore/dashboardStore.ts
index a89be0b99..1a0aa181a 100644
--- a/frontend/app/mstore/dashboardStore.ts
+++ b/frontend/app/mstore/dashboardStore.ts
@@ -79,7 +79,7 @@ export default class DashboardStore implements IDashboardSotre {
currentWidget: Widget = new Widget()
widgetCategories: any[] = []
widgets: Widget[] = []
- period: Period = Period({ rangeName: LAST_7_DAYS })
+ period: Period = Period({ rangeName: LAST_24_HOURS })
drillDownFilter: Filter = new Filter()
startTimestamp: number = 0
endTimestamp: number = 0
@@ -131,7 +131,7 @@ export default class DashboardStore implements IDashboardSotre {
fetchMetricChartData: action
})
- const drillDownPeriod = Period({ rangeName: LAST_7_DAYS }).toTimestamps();
+ const drillDownPeriod = Period({ rangeName: LAST_24_HOURS }).toTimestamps();
this.drillDownFilter.updateKey('startTimestamp', drillDownPeriod.startTimestamp)
this.drillDownFilter.updateKey('endTimestamp', drillDownPeriod.endTimestamp)
}
diff --git a/frontend/app/mstore/metricStore.ts b/frontend/app/mstore/metricStore.ts
index 8a9ec96f7..8763bcee0 100644
--- a/frontend/app/mstore/metricStore.ts
+++ b/frontend/app/mstore/metricStore.ts
@@ -90,7 +90,6 @@ export default class MetricStore implements IMetricStore {
// State Actions
init(metric?: IWidget|null) {
- console.log('metric', metric);
// const _metric = new Widget().fromJson(sampleJsonErrors)
// this.instance.update(metric || _metric)
@@ -141,23 +140,26 @@ export default class MetricStore implements IMetricStore {
save(metric: IWidget, dashboardId?: string): Promise {
const wasCreating = !metric.exists()
this.isSaving = true
- return metricService.saveMetric(metric, dashboardId)
- .then((metric: any) => {
- const _metric = new Widget().fromJson(metric)
- if (wasCreating) {
- toast.success('Metric created successfully')
- this.addToList(_metric)
- this.instance = _metric
- } else {
- toast.success('Metric updated successfully')
- this.updateInList(_metric)
- }
- return _metric
- }).catch(() => {
- toast.error('Error saving metric')
- }).finally(() => {
- this.isSaving = false
- })
+ return new Promise((resolve, reject) => {
+ metricService.saveMetric(metric, dashboardId)
+ .then((metric: any) => {
+ const _metric = new Widget().fromJson(metric)
+ if (wasCreating) {
+ toast.success('Metric created successfully')
+ this.addToList(_metric)
+ this.instance = _metric
+ } else {
+ toast.success('Metric updated successfully')
+ this.updateInList(_metric)
+ }
+ resolve(_metric)
+ }).catch(() => {
+ toast.error('Error saving metric')
+ reject()
+ }).finally(() => {
+ this.isSaving = false
+ })
+ })
}
fetchList() {
diff --git a/frontend/app/mstore/types/widget.ts b/frontend/app/mstore/types/widget.ts
index 782c46150..dac811619 100644
--- a/frontend/app/mstore/types/widget.ts
+++ b/frontend/app/mstore/types/widget.ts
@@ -1,10 +1,10 @@
-import { makeAutoObservable, runInAction, observable, action, reaction, computed } from "mobx"
+import { makeAutoObservable, runInAction, observable, action } from "mobx"
import FilterSeries from "./filterSeries";
import { DateTime } from 'luxon';
-import { IFilter } from "./filter";
import { metricService } from "App/services";
-import Session, { ISession } from "App/mstore/types/session";
+import Session from "App/mstore/types/session";
import Funnelissue from 'App/mstore/types/funnelIssue';
+import { issueOptions } from 'App/constants/filterOptions';
export interface IWidget {
metricId: any
@@ -54,7 +54,8 @@ export default class Widget implements IWidget {
metricId: any = undefined
widgetId: any = undefined
name: string = "New Metric"
- metricType: string = "timeseries"
+ // metricType: string = "timeseries"
+ metricType: string = "table"
metricOf: string = "sessionCount"
metricValue: string = ""
viewType: string = "lineChart"
@@ -132,7 +133,7 @@ export default class Widget implements IWidget {
runInAction(() => {
this.metricId = json.metricId
this.widgetId = json.widgetId
- this.metricValue = json.metricValue
+ this.metricValue = this.metricValueFromArray(json.metricValue)
this.metricOf = json.metricOf
this.metricType = json.metricType
this.metricFormat = json.metricFormat
@@ -168,7 +169,7 @@ export default class Widget implements IWidget {
metricId: this.metricId,
widgetId: this.widgetId,
metricOf: this.metricOf,
- metricValue: this.metricValue,
+ metricValue: this.metricValueToArray(this.metricValue),
metricType: this.metricType,
metricFormat: this.metricFormat,
viewType: this.viewType,
@@ -238,4 +239,14 @@ export default class Widget implements IWidget {
})
})
}
+
+ private metricValueFromArray(metricValue: any) {
+ if (!Array.isArray(metricValue)) return metricValue;
+ return issueOptions.filter((i: any) => metricValue.includes(i.value))
+ }
+
+ private metricValueToArray(metricValue: any) {
+ if (!Array.isArray(metricValue)) return metricValue;
+ return metricValue.map((i: any) => i.value)
+ }
}
\ No newline at end of file
diff --git a/frontend/app/services/MetricService.ts b/frontend/app/services/MetricService.ts
index 26b47aefb..e01d9291b 100644
--- a/frontend/app/services/MetricService.ts
+++ b/frontend/app/services/MetricService.ts
@@ -60,7 +60,7 @@ export default class MetricService implements IMetricService {
const url = isCreating ? '/metrics' : '/metrics/' + data[Widget.ID_KEY];
return this.client[method](url, data)
.then((response: { json: () => any; }) => response.json())
- .then((response: { data: any; }) => response.data || {});
+ .then((response: { data: any; }) => response.data || {});
}
/**
diff --git a/frontend/app/types/filter/filter.js b/frontend/app/types/filter/filter.js
index 06cab8d14..d9b73c224 100644
--- a/frontend/app/types/filter/filter.js
+++ b/frontend/app/types/filter/filter.js
@@ -12,7 +12,7 @@ import Event from './event';
// import CustomFilter from './customFilter';
import NewFilter from './newFilter';
-const rangeValue = DATE_RANGE_VALUES.LAST_7_DAYS;
+const rangeValue = DATE_RANGE_VALUES.LAST_24_HOURS;
const range = getDateRangeFromValue(rangeValue);
const startDate = range.start.unix() * 1000;
const endDate = range.end.unix() * 1000;
diff --git a/frontend/app/types/filter/filterType.ts b/frontend/app/types/filter/filterType.ts
index f77d15a11..f91f15dd5 100644
--- a/frontend/app/types/filter/filterType.ts
+++ b/frontend/app/types/filter/filterType.ts
@@ -91,4 +91,6 @@ export enum FilterKey {
GRAPHQL_METHOD = "GRAPHQL_METHOD",
GRAPHQL_REQUEST_BODY = "GRAPHQL_REQUEST_BODY",
GRAPHQL_RESPONSE_BODY = "GRAPHQL_RESPONSE_BODY",
+
+ SESSIONS = 'SESSIONS'
}
\ No newline at end of file