diff --git a/frontend/app/components/Funnels/FunnelDetails/FunnelDetails.js b/frontend/app/components/Funnels/FunnelDetails/FunnelDetails.js index a00ea34e5..48142ef13 100644 --- a/frontend/app/components/Funnels/FunnelDetails/FunnelDetails.js +++ b/frontend/app/components/Funnels/FunnelDetails/FunnelDetails.js @@ -78,7 +78,7 @@ const FunnelDetails = (props) => { const showEmptyMessage = hasNoStages && activeTab === TAB_ISSUES && !loading; return ( -
+
{ } else {} } - const onDateChange = (e) => { + const onDateChange = (e) => { props.applyFilter(e, funnel.funnelId) } const options = funnels.map(({ funnelId, name }) => ({ text: name, value: funnelId })).toJS(); - const selectedFunnel = funnels.filter(i => i.funnelId === parseInt(funnelId)).first() || {}; + const selectedFunnel = funnels.filter(i => i.funnelId === parseInt(funnelId)).first() || {}; return (
@@ -117,5 +117,5 @@ const FunnelHeader = (props) => { } export default connect(state => ({ - funnelFilters: state.getIn([ 'funnels', 'instance', 'filter' ]), + funnelFilters: state.getIn([ 'funnels', 'instance' ]), }), { applyFilter, deleteFunnel, fetch, fetchInsights, fetchIssuesFiltered, fetchSessionsFiltered })(FunnelHeader) diff --git a/frontend/app/components/Onboarding/components/OnboardingTabs/ProjectCodeSnippet/ProjectCodeSnippet.js b/frontend/app/components/Onboarding/components/OnboardingTabs/ProjectCodeSnippet/ProjectCodeSnippet.js index bf0e83791..7002ed604 100644 --- a/frontend/app/components/Onboarding/components/OnboardingTabs/ProjectCodeSnippet/ProjectCodeSnippet.js +++ b/frontend/app/components/Onboarding/components/OnboardingTabs/ProjectCodeSnippet/ProjectCodeSnippet.js @@ -15,32 +15,40 @@ const inputModeOptions = [ { text: 'Obscure all inputs', value: 'hidden' }, ]; -const codeSnippet = ` -`; - +const inputModeOptionsMap = {} +inputModeOptions.forEach((o, i) => inputModeOptionsMap[o.value] = i) const ProjectCodeSnippet = props => { const { site, gdpr } = props; const [changed, setChanged] = useState(false) const [copied, setCopied] = useState(false) + const codeSnippet = ` +`; + const saveGDPR = (value) => { setChanged(true) props.saveGDPR(site.id, GDPR({...value})); diff --git a/frontend/app/components/shared/TrackingCodeModal/ProjectCodeSnippet/ProjectCodeSnippet.js b/frontend/app/components/shared/TrackingCodeModal/ProjectCodeSnippet/ProjectCodeSnippet.js index e269c2cc7..50ca97823 100644 --- a/frontend/app/components/shared/TrackingCodeModal/ProjectCodeSnippet/ProjectCodeSnippet.js +++ b/frontend/app/components/shared/TrackingCodeModal/ProjectCodeSnippet/ProjectCodeSnippet.js @@ -14,25 +14,8 @@ const inputModeOptions = [ { text: 'Obscure all inputs', value: 'hidden' }, ]; -const codeSnippet = ` -`; +const inputModeOptionsMap = {} +inputModeOptions.forEach((o, i) => inputModeOptionsMap[o.value] = i) const ProjectCodeSnippet = props => { @@ -40,6 +23,32 @@ const ProjectCodeSnippet = props => { const [changed, setChanged] = useState(false) const [copied, setCopied] = useState(false) + const codeSnippet = ` +`; + const saveGDPR = (value) => { setChanged(true) props.saveGDPR(site.id, GDPR({...value})); @@ -47,11 +56,11 @@ const ProjectCodeSnippet = props => { const onChangeSelect = (event, { name, value }) => { const { gdpr } = site; - const _gdpr = { ...gdpr.toData() }; + // const _gdpr = { ...gdpr.toData() }; + // props.editGDPR({ [ name ]: value }); + // _gdpr[name] = value; props.editGDPR({ [ name ]: value }); - _gdpr[name] = value; - props.editGDPR({ [ name ]: value }); - saveGDPR(_gdpr) + saveGDPR({ ...gdpr, [ name ]: value }); }; const onChangeOption = (event, { name, checked }) => { @@ -74,8 +83,8 @@ const ProjectCodeSnippet = props => { snippet = snippet.replace('PROJECT_KEY', site.projectKey); } return snippet - .replace('XXX', getOptionValues()) - .replace('HOST', site && site.host); + //.replace('XXX', getOptionValues()) + //.replace('HOST', site && site.host); } const copyHandler = (code) => { diff --git a/frontend/app/duck/funnelFilters.js b/frontend/app/duck/funnelFilters.js index 294ba2039..468887afb 100644 --- a/frontend/app/duck/funnelFilters.js +++ b/frontend/app/duck/funnelFilters.js @@ -114,7 +114,7 @@ const reducer = (state = initialState, action = {}) => { Filter(action.filter) .set('events', state.getIn([ 'appliedFilter', 'events' ])) ) - : state.mergeIn([ 'appliedFilter' ], action.filter); + : state.mergeIn(['instance'], action.filter); case ADD_CUSTOM_FILTER: return state.update('customFilters', vars => vars.set(action.filter, action.value)); case REMOVE_CUSTOM_FILTER: diff --git a/frontend/app/duck/search.js b/frontend/app/duck/search.js index 3d15ae950..cf742e556 100644 --- a/frontend/app/duck/search.js +++ b/frontend/app/duck/search.js @@ -60,6 +60,7 @@ function reducer(state = initialState, action = {}) { case EDIT: return state.mergeIn(['instance'], action.instance); case APPLY: + console.log('APPLY', action.filter); return action.fromUrl ? state.set('instance', Filter(action.filter)) : state.mergeIn(['instance'], action.filter); diff --git a/frontend/app/duck/site.js b/frontend/app/duck/site.js index e5783b147..7e911c477 100644 --- a/frontend/app/duck/site.js +++ b/frontend/app/duck/site.js @@ -43,10 +43,11 @@ const reducer = (state = initialState, action = {}) => { return state.mergeIn([ 'instance', 'gdpr' ], action.data); case SAVE_GDPR_SUCCESS: const gdpr = GDPR(action.data); - return state.update('list', itemInListUpdater({ - [ idKey ] : state.getIn([ 'instance', idKey ]), - gdpr, - })).setIn([ 'instance', 'gdpr' ], gdpr); + return state.setIn([ 'instance', 'gdpr' ], gdpr); + // return state.update('list', itemInListUpdater({ + // [ idKey ] : state.getIn([ 'instance', idKey ]), + // gdpr, + // })).setIn([ 'instance', 'gdpr' ], gdpr); } return state; }; diff --git a/frontend/app/types/filter/filterType.ts b/frontend/app/types/filter/filterType.ts index ccb5156cd..2958f10e2 100644 --- a/frontend/app/types/filter/filterType.ts +++ b/frontend/app/types/filter/filterType.ts @@ -63,6 +63,7 @@ export enum FilterKey { AVG_CPU_LOAD = "AVG_CPU_LOAD", AVG_MEMORY_USAGE = "AVG_MEMORY_USAGE", FETCH_FAILED = "FETCH_FAILED", + FETCH = "FETCH", FETCH_URL = "FETCH_URL", FETCH_STATUS_CODE = "FETCH_STATUS_CODE", @@ -70,4 +71,9 @@ export enum FilterKey { FETCH_DURATION = "FETCH_DURATION", FETCH_REQUEST_BODY = "FETCH_REQUEST_BODY", FETCH_RESPONSE_BODY = "FETCH_RESPONSE_BODY", + + GRAPHQL_NAME = "GRAPHQL_NAME", + GRAPHQL_METHOD = "GRAPHQL_METHOD", + GRAPHQL_REQUEST_BODY = "GRAPHQL_REQUEST_BODY", + GRAPHQL_RESPONSE_BODY = "GRAPHQL_RESPONSE_BODY", } \ No newline at end of file diff --git a/frontend/app/types/filter/newFilter.js b/frontend/app/types/filter/newFilter.js index dedc4a7c5..29cb324b1 100644 --- a/frontend/app/types/filter/newFilter.js +++ b/frontend/app/types/filter/newFilter.js @@ -12,8 +12,21 @@ export const filtersMap = { [FilterKey.INPUT]: { key: FilterKey.INPUT, type: FilterType.MULTIPLE, category: FilterCategory.INTERACTIONS, label: 'Input', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/input', isEvent: true }, [FilterKey.LOCATION]: { key: FilterKey.LOCATION, type: FilterType.MULTIPLE, category: FilterCategory.INTERACTIONS, label: 'Page', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/location', isEvent: true }, [FilterKey.CUSTOM]: { key: FilterKey.CUSTOM, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Custom Events', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/custom', isEvent: true }, - [FilterKey.REQUEST]: { key: FilterKey.REQUEST, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Fetch', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch', isEvent: true }, - [FilterKey.GRAPHQL]: { key: FilterKey.GRAPHQL, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'GraphQL', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/graphql', isEvent: true }, + // [FilterKey.REQUEST]: { key: FilterKey.REQUEST, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Fetch', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch', isEvent: true }, + [FilterKey.FETCH]: { key: FilterKey.FETCH, type: FilterType.SUB_FILTERS, category: FilterCategory.JAVASCRIPT, operator: 'is', label: 'Network Request', filters: [ + { key: FilterKey.FETCH_URL, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'with URL', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, + { key: FilterKey.FETCH_STATUS_CODE, type: FilterType.NUMBER_MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'with status code', operator: '=', operatorOptions: filterOptions.customOperators, icon: 'filters/fetch' }, + { key: FilterKey.FETCH_METHOD, type: FilterType.MULTIPLE_DROPDOWN, category: FilterCategory.PERFORMANCE, label: 'with method', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch', options: filterOptions.methodOptions }, + { key: FilterKey.FETCH_DURATION, type: FilterType.NUMBER, category: FilterCategory.PERFORMANCE, label: 'with duration', operator: '=', operatorOptions: filterOptions.customOperators, icon: 'filters/fetch' }, + { key: FilterKey.FETCH_REQUEST_BODY, type: FilterType.STRING, category: FilterCategory.PERFORMANCE, label: 'with request body', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, + { key: FilterKey.FETCH_RESPONSE_BODY, type: FilterType.STRING, category: FilterCategory.PERFORMANCE, label: 'with response body', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, + ], icon: 'filters/fetch', isEvent: true }, + [FilterKey.GRAPHQL]: { key: FilterKey.GRAPHQL, type: FilterType.SUB_FILTERS, category: FilterCategory.JAVASCRIPT, label: 'GraphQL', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/graphql', isEvent: true, filters: [ + { key: FilterKey.GRAPHQL_NAME, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'with name', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, + { key: FilterKey.GRAPHQL_METHOD, type: FilterType.MULTIPLE_DROPDOWN, category: FilterCategory.PERFORMANCE, label: 'with method', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch', options: filterOptions.methodOptions }, + { key: FilterKey.GRAPHQL_REQUEST_BODY, type: FilterType.STRING, category: FilterCategory.PERFORMANCE, label: 'with request body', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, + { key: FilterKey.GRAPHQL_RESPONSE_BODY, type: FilterType.STRING, category: FilterCategory.PERFORMANCE, label: 'with response body', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, + ]}, [FilterKey.STATEACTION]: { key: FilterKey.STATEACTION, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'StateAction', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/state-action', isEvent: true }, [FilterKey.ERROR]: { key: FilterKey.ERROR, type: FilterType.MULTIPLE, category: FilterCategory.JAVASCRIPT, label: 'Error', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/error', isEvent: true }, // [FilterKey.METADATA]: { key: FilterKey.METADATA, type: FilterType.MULTIPLE, category: FilterCategory.METADATA, label: 'Metadata', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/metadata', isEvent: true }, @@ -33,14 +46,6 @@ export const filtersMap = { [FilterKey.USERANONYMOUSID]: { key: FilterKey.USERANONYMOUSID, type: FilterType.MULTIPLE, category: FilterCategory.USER, label: 'User AnonymousId', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/userid' }, // PERFORMANCE - [FilterKey.FETCH]: { key: FilterKey.FETCH, type: FilterType.SUB_FILTERS, category: FilterCategory.PERFORMANCE, operator: 'is', label: 'Network Request', filters: [ - { key: FilterKey.FETCH_URL, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'with URL', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, - { key: FilterKey.FETCH_STATUS_CODE, type: FilterType.NUMBER_MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'with status code', operator: '=', operatorOptions: filterOptions.customOperators, icon: 'filters/fetch' }, - { key: FilterKey.FETCH_METHOD, type: FilterType.MULTIPLE_DROPDOWN, category: FilterCategory.PERFORMANCE, label: 'with method', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch', options: filterOptions.methodOptions }, - { key: FilterKey.FETCH_DURATION, type: FilterType.NUMBER, category: FilterCategory.PERFORMANCE, label: 'with duration', operator: '=', operatorOptions: filterOptions.customOperators, icon: 'filters/fetch' }, - { key: FilterKey.FETCH_REQUEST_BODY, type: FilterType.STRING, category: FilterCategory.PERFORMANCE, label: 'with request body', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, - { key: FilterKey.FETCH_RESPONSE_BODY, type: FilterType.STRING, category: FilterCategory.PERFORMANCE, label: 'with response body', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/fetch' }, - ], icon: 'filters/perfromance-network-request', isEvent: true }, [FilterKey.DOM_COMPLETE]: { key: FilterKey.DOM_COMPLETE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'DOM Complete', operator: 'isAny', operatorOptions: filterOptions.stringOperators, source: [], icon: 'filters/dom-complete', isEvent: true, hasSource: true, sourceOperator: '=', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, [FilterKey.LARGEST_CONTENTFUL_PAINT_TIME]: { key: FilterKey.LARGEST_CONTENTFUL_PAINT_TIME, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Largest Contentful Paint', operator: 'isAny', operatorOptions: filterOptions.stringOperators, source: [], icon: 'filters/lcpt', isEvent: true, hasSource: true, sourceOperator: '=', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, [FilterKey.TTFB]: { key: FilterKey.TTFB, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Time to First Byte', operator: 'isAny', operatorOptions: filterOptions.stringOperators, source: [], icon: 'filters/ttfb', isEvent: true, hasSource: true, sourceOperator: '=', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators },