mirror of
https://github.com/plausible/analytics.git
synced 2024-12-23 09:33:19 +03:00
Support using matches/contains for most filters (#3721)
* Support using matches/contains for most filters * Change behavior where we auto-zoom to specific browser/os/source to only do so if filtering on a single value * No contains filtering on `location` * Update CHANGELOG.md * Fix merge conflict
This commit is contained in:
parent
ac7da6a9d4
commit
0065cd3052
@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
- IP Block List in Site Settings
|
- IP Block List in Site Settings
|
||||||
|
- Allow filtering with `contains`/`matches` operator for Sources, Browsers and Operating Systems.
|
||||||
- Allow filtering by multiple custom properties
|
- Allow filtering by multiple custom properties
|
||||||
- Wildcard and member filtering on the Stats API `event:goal` property
|
- Wildcard and member filtering on the Stats API `event:goal` property
|
||||||
- Allow filtering with `contains`/`matches` operator for custom properties
|
- Allow filtering with `contains`/`matches` operator for custom properties
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import * as storage from '../../util/storage'
|
import * as storage from '../../util/storage'
|
||||||
|
import { isFilteringOnFixedValue } from '../../util/filters'
|
||||||
import ListReport from '../reports/list'
|
import ListReport from '../reports/list'
|
||||||
import * as api from '../../api'
|
import * as api from '../../api'
|
||||||
import * as url from '../../util/url'
|
import * as url from '../../util/url'
|
||||||
@ -161,12 +162,12 @@ export default class Devices extends React.Component {
|
|||||||
renderContent() {
|
renderContent() {
|
||||||
switch (this.state.mode) {
|
switch (this.state.mode) {
|
||||||
case 'browser':
|
case 'browser':
|
||||||
if (this.props.query.filters.browser) {
|
if (isFilteringOnFixedValue(this.props.query, 'browser')) {
|
||||||
return <BrowserVersions site={this.props.site} query={this.props.query} />
|
return <BrowserVersions site={this.props.site} query={this.props.query} />
|
||||||
}
|
}
|
||||||
return <Browsers site={this.props.site} query={this.props.query} />
|
return <Browsers site={this.props.site} query={this.props.query} />
|
||||||
case 'os':
|
case 'os':
|
||||||
if (this.props.query.filters.os) {
|
if (isFilteringOnFixedValue(this.props.query, 'os')) {
|
||||||
return <OperatingSystemVersions site={this.props.site} query={this.props.query} />
|
return <OperatingSystemVersions site={this.props.site} query={this.props.query} />
|
||||||
}
|
}
|
||||||
return <OperatingSystems site={this.props.site} query={this.props.query} />
|
return <OperatingSystems site={this.props.site} query={this.props.query} />
|
||||||
|
@ -2,11 +2,13 @@ import React from 'react';
|
|||||||
import SearchTerms from './search-terms'
|
import SearchTerms from './search-terms'
|
||||||
import SourceList from './source-list'
|
import SourceList from './source-list'
|
||||||
import ReferrerList from './referrer-list'
|
import ReferrerList from './referrer-list'
|
||||||
|
import { isFilteringOnFixedValue } from '../../util/filters'
|
||||||
|
|
||||||
|
|
||||||
export default function Sources(props) {
|
export default function Sources(props) {
|
||||||
if (props.query.filters.source === 'Google') {
|
if (props.query.filters.source === 'Google') {
|
||||||
return <SearchTerms {...props} />
|
return <SearchTerms {...props} />
|
||||||
} else if (props.query.filters.source) {
|
} else if (isFilteringOnFixedValue(props.query, 'source')) {
|
||||||
return <ReferrerList {...props} />
|
return <ReferrerList {...props} />
|
||||||
} else {
|
} else {
|
||||||
return <SourceList {...props} />
|
return <SourceList {...props} />
|
||||||
|
@ -10,9 +10,7 @@ export const FILTER_GROUPS = {
|
|||||||
'props': ['prop_key', 'prop_value']
|
'props': ['prop_key', 'prop_value']
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ALLOW_FREE_CHOICE = new Set(
|
export const NO_CONTAINS_OPERATOR = new Set(['goal', 'screen'].concat(FILTER_GROUPS['location']))
|
||||||
FILTER_GROUPS['page'].concat(FILTER_GROUPS['utm']).concat(['prop_value'])
|
|
||||||
)
|
|
||||||
|
|
||||||
export const FILTER_OPERATIONS = {
|
export const FILTER_OPERATIONS = {
|
||||||
isNot: 'is not',
|
isNot: 'is not',
|
||||||
@ -31,7 +29,7 @@ export function supportsIsNot(filterName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function isFreeChoiceFilter(filterName) {
|
export function isFreeChoiceFilter(filterName) {
|
||||||
return ALLOW_FREE_CHOICE.has(filterName)
|
return !NO_CONTAINS_OPERATOR.has(filterName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// As of March 2023, Safari does not support negative lookbehind regexes. In case it throws an error, falls back to plain | matching. This means
|
// As of March 2023, Safari does not support negative lookbehind regexes. In case it throws an error, falls back to plain | matching. This means
|
||||||
@ -102,6 +100,11 @@ export function parseQueryFilter(query, filter) {
|
|||||||
return {type, clauses}
|
return {type, clauses}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isFilteringOnFixedValue(query, filter) {
|
||||||
|
const { type, clauses } = parseQueryFilter(query, filter)
|
||||||
|
return type == FILTER_OPERATIONS.is && clauses.length == 1
|
||||||
|
}
|
||||||
|
|
||||||
export function formatFilterGroup(filterGroup) {
|
export function formatFilterGroup(filterGroup) {
|
||||||
if (filterGroup === 'utm') {
|
if (filterGroup === 'utm') {
|
||||||
return 'UTM tags'
|
return 'UTM tags'
|
||||||
|
Loading…
Reference in New Issue
Block a user