onUpdateRowValue(id, newFilter, labelUpdate)}
/>
diff --git a/assets/js/dashboard/stats/modals/filter-modal-props-row.js b/assets/js/dashboard/stats/modals/filter-modal-props-row.js
index 09fb3e77ab076..b3c26c22af101 100644
--- a/assets/js/dashboard/stats/modals/filter-modal-props-row.js
+++ b/assets/js/dashboard/stats/modals/filter-modal-props-row.js
@@ -6,16 +6,18 @@ import Combobox from '../../components/combobox'
import { apiPath } from '../../util/url'
import { EVENT_PROPS_PREFIX, FILTER_OPERATIONS, fetchSuggestions, getPropertyKeyFromFilterKey } from '../../util/filters'
+import { useQueryContext } from "../../query-context"
+import { useSiteContext } from "../../site-context"
export default function FilterModalPropsRow({
- site,
- query,
filter,
showDelete,
disabledOptions,
onUpdate,
onDelete,
}) {
+ const { query } = useQueryContext()
+ const site = useSiteContext()
const [operation, filterKey, clauses] = filter
const propKey = useMemo(
@@ -33,7 +35,7 @@ export default function FilterModalPropsRow({
}
function fetchPropValueOptions(input) {
- if ([FILTER_OPERATIONS.contains, FILTER_OPERATIONS.does_not_contain].includes(operation)) {return Promise.resolve([])}
+ if ([FILTER_OPERATIONS.contains, FILTER_OPERATIONS.does_not_contain].includes(operation)) { return Promise.resolve([]) }
return fetchSuggestions(apiPath(site, `/suggestions/prop_value`), query, input, [
FILTER_OPERATIONS.isNot, filterKey, ['(none)']
])
diff --git a/assets/js/dashboard/stats/modals/filter-modal-row.js b/assets/js/dashboard/stats/modals/filter-modal-row.js
index dc4f85555f455..89cc983e4e207 100644
--- a/assets/js/dashboard/stats/modals/filter-modal-row.js
+++ b/assets/js/dashboard/stats/modals/filter-modal-row.js
@@ -6,14 +6,16 @@ import Combobox from '../../components/combobox'
import { FILTER_OPERATIONS, fetchSuggestions, isFreeChoiceFilter } from "../../util/filters"
import { apiPath } from '../../util/url'
import { getLabel, formattedFilters } from '../../util/filters'
+import { useQueryContext } from "../../query-context"
+import { useSiteContext } from "../../site-context"
export default function FilterModalRow({
- site,
- query,
filter,
labels,
onUpdate
}) {
+ const { query } = useQueryContext();
+ const site = useSiteContext();
const [operation, filterKey, clauses] = filter
const selectedClauses = useMemo(
diff --git a/assets/js/dashboard/stats/modals/filter-modal.js b/assets/js/dashboard/stats/modals/filter-modal.js
index 8d3ccd1758613..a1984a33cc930 100644
--- a/assets/js/dashboard/stats/modals/filter-modal.js
+++ b/assets/js/dashboard/stats/modals/filter-modal.js
@@ -1,13 +1,13 @@
import React from "react";
-import { withRouter } from 'react-router-dom'
+import { withRouter } from 'react-router-dom';
-import Modal from './modal'
-import { EVENT_PROPS_PREFIX, FILTER_GROUP_TO_MODAL_TYPE, formatFilterGroup, FILTER_OPERATIONS, getFilterGroup, FILTER_MODAL_TO_FILTER_GROUP } from '../../util/filters'
-import { parseQuery } from '../../query'
-import { updatedQuery } from '../../util/url'
-import { shouldIgnoreKeypress } from '../../keybinding'
-import { cleanLabels } from "../../util/filters"
-import FilterModalGroup from "./filter-modal-group"
+import Modal from './modal';
+import { EVENT_PROPS_PREFIX, FILTER_GROUP_TO_MODAL_TYPE, formatFilterGroup, FILTER_OPERATIONS, getFilterGroup, FILTER_MODAL_TO_FILTER_GROUP } from '../../util/filters';
+import { parseQuery } from '../../query';
+import { updatedQuery } from '../../util/url';
+import { shouldIgnoreKeypress } from '../../keybinding';
+import { cleanLabels } from "../../util/filters";
+import FilterModalGroup from "./filter-modal-group";
function partitionFilters(modalType, filters) {
const otherFilters = []
@@ -145,8 +145,6 @@ class FilterModal extends React.Component {
filterGroup={filterGroup}
filterState={this.state.filterState}
labels={this.state.labelState}
- site={this.props.site}
- query={this.state.query}
onUpdateRowValue={this.onUpdateRowValue.bind(this)}
onAddRow={this.onAddRow.bind(this)}
onDeleteRow={this.onDeleteRow.bind(this)}
diff --git a/assets/js/dashboard/stats/pages/index.js b/assets/js/dashboard/stats/pages/index.js
index c7354099e5d82..20d573a7da917 100644
--- a/assets/js/dashboard/stats/pages/index.js
+++ b/assets/js/dashboard/stats/pages/index.js
@@ -1,16 +1,18 @@
import React, { useEffect, useState } from 'react';
-import * as storage from '../../util/storage'
-import * as url from '../../util/url'
-import * as api from '../../api'
-import ListReport from './../reports/list'
-import * as metrics from './../reports/metrics'
+import * as storage from '../../util/storage';
+import * as url from '../../util/url';
+import * as api from '../../api';
+import ListReport from './../reports/list';
+import * as metrics from './../reports/metrics';
import ImportedQueryUnsupportedWarning from '../imported-query-unsupported-warning';
import { hasGoalFilter } from '../../util/filters';
import { useQueryContext } from '../../query-context';
import { useSiteContext } from '../../site-context';
-function EntryPages({ query, site, afterFetchData }) {
+function EntryPages({ afterFetchData }) {
+ const { query } = useQueryContext();
+ const site = useSiteContext();
function fetchData() {
return api.get(url.apiPath(site, '/entry-pages'), query, { limit: 9 })
}
@@ -41,14 +43,15 @@ function EntryPages({ query, site, afterFetchData }) {
keyLabel="Entry page"
metrics={chooseMetrics()}
detailsLink={url.sitePath('entry-pages')}
- query={query}
externalLinkDest={externalLinkDest}
color="bg-orange-50"
/>
)
}
-function ExitPages({ query, site, afterFetchData }) {
+function ExitPages({ afterFetchData }) {
+ const site = useSiteContext();
+ const { query } = useQueryContext();
function fetchData() {
return api.get(url.apiPath(site, '/exit-pages'), query, { limit: 9 })
}
@@ -79,14 +82,15 @@ function ExitPages({ query, site, afterFetchData }) {
keyLabel="Exit page"
metrics={chooseMetrics()}
detailsLink={url.sitePath('exit-pages')}
- query={query}
externalLinkDest={externalLinkDest}
color="bg-orange-50"
/>
)
}
-function TopPages({ query, site, afterFetchData }) {
+function TopPages({ afterFetchData }) {
+ const { query } = useQueryContext();
+ const site = useSiteContext();
function fetchData() {
return api.get(url.apiPath(site, '/pages'), query, { limit: 9 })
}
@@ -117,7 +121,6 @@ function TopPages({ query, site, afterFetchData }) {
keyLabel="Page"
metrics={chooseMetrics()}
detailsLink={url.sitePath('pages')}
- query={query}
externalLinkDest={externalLinkDest}
color="bg-orange-50"
/>
@@ -133,7 +136,7 @@ const labelFor = {
export default function Pages() {
const { query } = useQueryContext();
const site = useSiteContext();
-
+
const tabKey = `pageTab__${site.domain}`
const storedTab = storage.getItem(tabKey)
const [mode, setMode] = useState(storedTab || 'pages')
@@ -155,12 +158,12 @@ export default function Pages() {
function renderContent() {
switch (mode) {
case "entry-pages":
- return
+ return
case "exit-pages":
- return
+ return
case "pages":
default:
- return
+ return
}
}
@@ -196,7 +199,7 @@ export default function Pages() {
{labelFor[mode] || 'Page Visits'}
-
+
{renderPill('Top Pages', 'pages')}
diff --git a/assets/js/dashboard/stats/reports/list.js b/assets/js/dashboard/stats/reports/list.js
index ef40c1a0c2197..e607b1d43f93d 100644
--- a/assets/js/dashboard/stats/reports/list.js
+++ b/assets/js/dashboard/stats/reports/list.js
@@ -1,14 +1,16 @@
import React, { useState, useEffect, useCallback } from 'react';
-import { Link } from 'react-router-dom'
+import { Link } from 'react-router-dom';
import FlipMove from 'react-flip-move';
-import FadeIn from '../../fade-in'
-import MoreLink from '../more-link'
-import Bar from '../bar'
-import LazyLoader from '../../components/lazy-loader'
-import classNames from 'classnames'
-import { trimURL, updatedQuery } from '../../util/url'
-import { cleanLabels, hasGoalFilter, replaceFilterByPrefix } from '../../util/filters'
+import FadeIn from '../../fade-in';
+import MoreLink from '../more-link';
+import Bar from '../bar';
+import LazyLoader from '../../components/lazy-loader';
+import classNames from 'classnames';
+import { trimURL, updatedQuery } from '../../util/url';
+import { cleanLabels, replaceFilterByPrefix, isRealTimeDashboard, hasGoalFilter } from '../../util/filters';
+import { useQueryContext } from '../../query-context';
+
const MAX_ITEMS = 9
export const MIN_HEIGHT = 380
const ROW_HEIGHT = 32
@@ -16,15 +18,16 @@ const ROW_GAP_HEIGHT = 4
const DATA_CONTAINER_HEIGHT = (ROW_HEIGHT + ROW_GAP_HEIGHT) * (MAX_ITEMS - 1) + ROW_HEIGHT
const COL_MIN_WIDTH = 70
-export function FilterLink({ pathname, query, filterInfo, onClick, children, extraClass }) {
+export function FilterLink({ pathname, filterInfo, onClick, children, extraClass }) {
+ const { query } = useQueryContext();
const className = classNames(`${extraClass}`, { 'hover:underline': !!filterInfo })
if (filterInfo) {
- const {prefix, filter, labels} = filterInfo
+ const { prefix, filter, labels } = filterInfo
const newFilters = replaceFilterByPrefix(query, prefix, filter)
const newLabels = cleanLabels(newFilters, query.labels, filter[1], labels)
const filterQuery = updatedQuery({ filters: newFilters, labels: newLabels })
-
+
let linkTo = { search: filterQuery.toString() }
if (pathname) { linkTo.pathname = pathname }
@@ -56,90 +59,73 @@ function ExternalLink({ item, externalLinkDest }) {
return null
}
-// The main function component for rendering list reports and making them react to what
-// is happening on the dashboard.
-
-// A `fetchData` function must be passed through props. This function defines the data
-// to be rendered, and should return a list of objects under a `results` key. Think of
-// these objects as rows. The number of columns that are **actually rendered** is also
-// configurable through the `metrics` prop, which also defines the keys under which
-// column values are read, and how they're rendered. For example:
-
-// | keyLabel | METRIC_1.renderLabel(query) | METRIC_1.renderLabel(query) | ...
-// |--------------------|-----------------------------|-----------------------------| ---
-// | LISTITEM_1.name | LISTITEM_1[METRIC_1.key] | LISTITEM_1[METRIC_2.key] | ...
-// | LISTITEM_2.name | LISTITEM_2[METRIC_1.key] | LISTITEM_2[METRIC_2.key] | ...
-
-// Further configuration of the report is possible through optional props.
-
-// REQUIRED PROPS:
-
-// * `keyLabel` - What each entry in the list represents (for UI only).
-
-// * `query` - The query object representing the current state of the dashboard.
-
-// * `fetchData` - a function that returns an `api.get` promise that will resolve to an
-// object containing a `results` key.
-
-// * `metrics` - a list `Metric` class objects, containing at least the `key,`
-// `renderLabel`, and `renderValue` fields. Optionally, a Metric object can contain
-// the keys `meta.plot` and `meta.hiddenOnMobile` to represent additional behaviour
-// for this metric in the ListReport.
-
-// * `getFilterFor` - a function that takes a list item and returns [prefix, filter, labels]
-// that should be applied when the list item is clicked. All existing filters matching prefix
-// are removed. If a list item is not supposed to be clickable, this function should
-// return `null` for that list item.
-
-// OPTIONAL PROPS:
-
-// * `onClick` - function with additional action to be taken when a list entry is clicked.
-
-// * `detailsLink` - the pathname to the detailed view of this report. E.g.:
-// `/dummy.site/pages`. If this is given as input to the ListReport, the Details button
-// will always be rendered.
-
-// * `maybeHideDetails` - set this to `true` if the details button should be hidden on
-// the condition that there are less than MAX_ITEMS entries in the list. (i.e . nothing
-// more to show)
-
-// * `externalLinkDest` - a function that takes a list item and returns an external url
-// to navigate to. If this prop is given, an additional icon is rendered upon hovering
-// the entry.
-
-// * `renderIcon` - a function that takes a list item and returns the
-// HTML of an icon (such as a flag, favicon, or a screen size icon) for a listItem.
-
-// * `color` - color of the comparison bars in light-mode
-
-// * `afterFetchData` - a function to be called directly after `fetchData`. Receives the,
-// raw API response as an argument. The return value is ignored by ListReport. Allows
-// hooking into the request lifecycle and doing actions with returned metadata. For
-// example, the parent component might want to control what happens when imported data
-// is included or not.
-
-export default function ListReport(props) {
+/**
+ *
+ * REQUIRED PROPS
+ *
+ * @param {Function} fetchData - A function that defines the data
+ * to be rendered, and should return a list of objects under a `results` key. Think of
+ * these objects as rows. The number of columns that are **actually rendered** is also
+ * configurable through the `metrics` prop, which also defines the keys under which
+ * column values are read, and how they're rendered.
+ * @param {*} keyLabel - What each entry in the list represents (for UI only).
+ * @param {Array.} metrics - A list of `Metric` class objects, containing at least the `key,`
+ * `renderLabel`, and `renderValue` fields. Optionally, a Metric object can contain
+ * the keys `meta.plot` and `meta.hiddenOnMobile` to represent additional behavior
+ * for this metric in the ListReport.
+ * @param {Function} getFilterFor - A function that takes a list item and returns [prefix, filter, labels]
+ * that should be applied when the list item is clicked. All existing filters matching prefix
+ * are removed. If a list item is not supposed to be clickable, this function should
+ * return `null` for that list item.
+ *
+ * OPTIONAL PROPS
+ *
+ * @param {Function} [onClick] - Function with additional action to be taken when a list entry is clicked.
+ * @param {string} [detailsLink] - The pathname to the detailed view of this report. E.g.:
+ * `/dummy.site/pages`. If this is given as input to the ListReport, the Details button
+ * will always be rendered.
+ * @param {boolean} [maybeHideDetails] - Set this to `true` if the details button should be hidden on
+ * the condition that there are less than MAX_ITEMS entries in the list (i.e. nothing
+ * more to show).
+ * @param {Function} [externalLinkDest] - A function that takes a list item and returns an external URL
+ * to navigate to. If this prop is given, an additional icon is rendered upon hovering
+ * the entry.
+ * @param {Function} [renderIcon] - A function that takes a list item and returns the
+ * HTML of an icon (such as a flag, favicon, or a screen size icon) for a list item.
+ * @param {string} [color] - Color of the comparison bars in light-mode.
+ * @param {Function} [afterFetchData] - A function to be called directly after `fetchData`. Receives the
+ * raw API response as an argument. The return value is ignored by ListReport. Allows
+ * hooking into the request lifecycle and doing actions with returned metadata. For
+ * example, the parent component might want to control what happens when imported data
+ * is included or not.
+ *
+ * @returns {HTMLElement} Table of metrics, in the following format:
+ * | keyLabel | METRIC_1.renderLabel(query) | METRIC_2.renderLabel(query) | ...
+ * |--------------------|-----------------------------|-----------------------------| ---
+ * | LISTITEM_1.name | LISTITEM_1[METRIC_1.key] | LISTITEM_1[METRIC_2.key] | ...
+ * | LISTITEM_2.name | LISTITEM_2[METRIC_1.key] | LISTITEM_2[METRIC_2.key] | ...
+ */
+export default function ListReport({ keyLabel, metrics, colMinWidth = COL_MIN_WIDTH, afterFetchData, detailsLink, maybeHideDetails, onClick, color, getFilterFor, renderIcon, externalLinkDest, fetchData }) {
+ const { query } = useQueryContext();
const [state, setState] = useState({ loading: true, list: null })
const [visible, setVisible] = useState(false)
- const metrics = props.metrics
- const colMinWidth = props.colMinWidth || COL_MIN_WIDTH
- const isRealtime = props.query.period === 'realtime'
- const goalFilterApplied = hasGoalFilter(props.query)
+ const isRealtime = isRealTimeDashboard(query);
+ const goalFilterApplied = hasGoalFilter(query);
- const fetchData = useCallback(() => {
+ const getData = useCallback(() => {
if (!isRealtime) {
setState({ loading: true, list: null })
}
- props.fetchData()
+ fetchData()
.then((response) => {
- if (props.afterFetchData) {
- props.afterFetchData(response)
+ if (afterFetchData) {
+ afterFetchData(response)
}
setState({ loading: false, list: response.results })
})
- }, [props.keyLabel, props.query])
+ }, [keyLabel, query])
const onVisible = () => { setVisible(true) }
@@ -154,12 +140,12 @@ export default function ListReport(props) {
useEffect(() => {
if (visible) {
- if (isRealtime) { document.addEventListener('tick', fetchData) }
- fetchData()
+ if (isRealtime) { document.addEventListener('tick', getData) }
+ getData()
}
- return () => { document.removeEventListener('tick', fetchData) }
- }, [props.keyLabel, props.query, visible]);
+ return () => { document.removeEventListener('tick', getData) }
+ }, [keyLabel, query, visible]);
// returns a filtered `metrics` list. Since currently, the backend can return different
// metrics based on filters and existing data, this function validates that the metrics
@@ -205,14 +191,14 @@ export default function ListReport(props) {
className={`${metric.key} text-right ${hiddenOnMobileClass(metric)}`}
style={{ minWidth: colMinWidth }}
>
- { metric.renderLabel(props.query) }
+ {metric.renderLabel(query)}
)
})
return (
- {props.keyLabel}
+ {keyLabel}
{metricLabels}
)
@@ -238,7 +224,7 @@ export default function ListReport(props) {
}
function renderBarFor(listItem) {
- const lightBackground = props.color || 'bg-green-50'
+ const lightBackground = color || 'bg-green-50'
const metricToPlot = metrics.find(metric => metric.meta.plot).key
return (
@@ -251,9 +237,8 @@ export default function ListReport(props) {
>
{maybeRenderIconFor(listItem)}
@@ -262,7 +247,7 @@ export default function ListReport(props) {
{trimURL(listItem.name, colMinWidth)}
-
+
@@ -270,8 +255,8 @@ export default function ListReport(props) {
}
function maybeRenderIconFor(listItem) {
- if (props.renderIcon) {
- return props.renderIcon(listItem)
+ if (renderIcon) {
+ return renderIcon(listItem)
}
}
@@ -284,7 +269,7 @@ export default function ListReport(props) {
style={{ width: colMinWidth, minWidth: colMinWidth }}
>
- { metric.renderValue(listItem[metric.key]) }
+ {metric.renderValue(listItem[metric.key])}
)
@@ -309,10 +294,10 @@ export default function ListReport(props) {
function maybeRenderDetailsLink() {
const moreResultsAvailable = state.list.length >= MAX_ITEMS
- const hideDetails = props.maybeHideDetails && !moreResultsAvailable
+ const hideDetails = maybeHideDetails && !moreResultsAvailable
- const showDetails = props.detailsLink && !state.loading && !hideDetails
- return showDetails &&
+ const showDetails = detailsLink && !state.loading && !hideDetails
+ return showDetails &&
}
return (
diff --git a/assets/js/dashboard/stats/sources/index.js b/assets/js/dashboard/stats/sources/index.js
index b8121b002d906..5cb2bc95cb265 100644
--- a/assets/js/dashboard/stats/sources/index.js
+++ b/assets/js/dashboard/stats/sources/index.js
@@ -1,12 +1,11 @@
import React from 'react';
-import SearchTerms from './search-terms'
-import SourceList from './source-list'
-import ReferrerList from './referrer-list'
-import { getFiltersByKeyPrefix, isFilteringOnFixedValue } from '../../util/filters'
+import SearchTerms from './search-terms';
+import SourceList from './source-list';
+import ReferrerList from './referrer-list';
+import { getFiltersByKeyPrefix, isFilteringOnFixedValue } from '../../util/filters';
import { useQueryContext } from '../../query-context';
import { useSiteContext } from '../../site-context';
-
export default function Sources() {
const { query } = useQueryContext();
const site = useSiteContext();
@@ -14,8 +13,8 @@ export default function Sources() {
return
} else if (isFilteringOnFixedValue(query, 'source')) {
const [[_operation, _filterKey, clauses]] = getFiltersByKeyPrefix(query, "source")
- return
+ return
} else {
- return
+ return
}
}
diff --git a/assets/js/dashboard/stats/sources/referrer-list.js b/assets/js/dashboard/stats/sources/referrer-list.js
index 06c9c375d6d99..caa7d2cdb0400 100644
--- a/assets/js/dashboard/stats/sources/referrer-list.js
+++ b/assets/js/dashboard/stats/sources/referrer-list.js
@@ -1,12 +1,16 @@
import React, { useEffect, useState } from 'react';
-import * as api from '../../api'
-import * as url from '../../util/url'
-import * as metrics from '../reports/metrics'
-import { hasGoalFilter } from "../../util/filters"
-import ListReport from '../reports/list'
-import ImportedQueryUnsupportedWarning from '../../stats/imported-query-unsupported-warning'
+import * as api from '../../api';
+import * as url from '../../util/url';
+import * as metrics from '../reports/metrics';
+import { hasGoalFilter } from "../../util/filters";
+import ListReport from '../reports/list';
+import ImportedQueryUnsupportedWarning from '../../stats/imported-query-unsupported-warning';
+import { useQueryContext } from '../../query-context';
+import { useSiteContext } from '../../site-context';
-export default function Referrers({ source, site, query }) {
+export default function Referrers({ source }) {
+ const { query } = useQueryContext();
+ const site = useSiteContext()
const [skipImportedReason, setSkipImportedReason] = useState(null)
const [loading, setLoading] = useState(true)
@@ -47,7 +51,7 @@ export default function Referrers({ source, site, query }) {
function chooseMetrics() {
return [
- metrics.createVisitors({meta: {plot: true}}),
+ metrics.createVisitors({ meta: { plot: true } }),
hasGoalFilter(query) && metrics.createConversionRate(),
].filter(metric => !!metric)
}
@@ -56,7 +60,7 @@ export default function Referrers({ source, site, query }) {
Top Referrers
-
+
!!metric)
}
@@ -52,21 +55,21 @@ function AllSources(props) {
return (
)
}
-function UTMSources(props) {
- const { site, query } = props
- const utmTag = UTM_TAGS[props.tab]
+function UTMSources({ tab, afterFetchData }) {
+ const { query } = useQueryContext();
+ const site = useSiteContext();
+ const utmTag = UTM_TAGS[tab]
function fetchData() {
return api.get(url.apiPath(site, utmTag.endpoint), query, { limit: 9 })
@@ -74,14 +77,14 @@ function UTMSources(props) {
function getFilterFor(listItem) {
return {
- prefix: props.tab,
- filter: ["is", props.tab, [listItem['name']]]
+ prefix: tab,
+ filter: ["is", tab, [listItem['name']]]
}
}
function chooseMetrics() {
return [
- metrics.createVisitors({meta: {plot: true}}),
+ metrics.createVisitors({ meta: { plot: true } }),
hasGoalFilter(query) && metrics.createConversionRate(),
].filter(metric => !!metric)
}
@@ -89,20 +92,20 @@ function UTMSources(props) {
return (
)
}
-export default function SourceList(props) {
- const { site, query } = props
- const tabKey = 'sourceTab__' + props.site.domain
+export default function SourceList() {
+ const site = useSiteContext();
+ const { query } = useQueryContext();
+ const tabKey = 'sourceTab__' + site.domain
const storedTab = storage.getItem(tabKey)
const [currentTab, setCurrentTab] = useState(storedTab || 'all')
const [loading, setLoading] = useState(true)
@@ -174,9 +177,9 @@ export default function SourceList(props) {
function renderContent() {
if (currentTab === 'all') {
- return
+ return
} else {
- return
+ return
}
}
@@ -193,7 +196,7 @@ export default function SourceList(props) {
Top Sources
-
+
{renderTabs()}
diff --git a/assets/js/dashboard/util/filters.js b/assets/js/dashboard/util/filters.js
index 92611f955b0a2..a57a724f5786c 100644
--- a/assets/js/dashboard/util/filters.js
+++ b/assets/js/dashboard/util/filters.js
@@ -1,4 +1,6 @@
+import { useMemo } from "react"
import * as api from '../api'
+import { useQueryContext } from '../query-context'
export const FILTER_MODAL_TO_FILTER_GROUP = {
'page': ['page', 'entry_page', 'exit_page'],
@@ -99,10 +101,21 @@ export function hasGoalFilter(query) {
return getFiltersByKeyPrefix(query, "goal").length > 0
}
+export function useHasGoalFilter() {
+ const { query: { filters } } = useQueryContext();
+ return useMemo(() => getFiltersByKeyPrefix({ filters }, "goal").length > 0, [filters]);
+}
+
export function isRealTimeDashboard(query) {
return query?.period === 'realtime'
}
+export function useIsRealtimeDashboard() {
+ const { query: { period } } = useQueryContext();
+ return useMemo(() => isRealTimeDashboard({ period }), [period]);
+}
+
+
// Note: Currently only a single goal filter can be applied at a time.
export function getGoalFilter(query) {
return getFiltersByKeyPrefix(query, "goal")[0] || null