From 737f2c65e5867bfcd5035ea701ea0dba0b0d8b41 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2024 00:03:38 -0700 Subject: [PATCH 1/5] Bump debug from 4.1.1 to 4.3.4 in /functions (#1765) Bumps [debug](https://github.com/debug-js/debug) from 4.1.1 to 4.3.4. - [Release notes](https://github.com/debug-js/debug/releases) - [Commits](https://github.com/debug-js/debug/compare/4.1.1...4.3.4) --- updated-dependencies: - dependency-name: debug dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: ikuleshov --- functions/package-lock.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/functions/package-lock.json b/functions/package-lock.json index 0d3172f85..ce84422af 100644 --- a/functions/package-lock.json +++ b/functions/package-lock.json @@ -1801,11 +1801,11 @@ "optional": true }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "decompress-response": { @@ -5124,7 +5124,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" } } }, From 91b8e8669dacc93fd4421ab1fcd623e0dc57c37c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2024 00:10:24 -0700 Subject: [PATCH 2/5] Bump basic-auth-connect from 1.0.0 to 1.1.0 in /functions (#2037) Bumps [basic-auth-connect](https://github.com/expressjs/basic-auth-connect) from 1.0.0 to 1.1.0. - [Release notes](https://github.com/expressjs/basic-auth-connect/releases) - [Commits](https://github.com/expressjs/basic-auth-connect/compare/1.0.0...1.1.0) --- updated-dependencies: - dependency-name: basic-auth-connect dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- functions/package-lock.json | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/functions/package-lock.json b/functions/package-lock.json index ce84422af..0e4a9a45a 100644 --- a/functions/package-lock.json +++ b/functions/package-lock.json @@ -982,9 +982,12 @@ } }, "basic-auth-connect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz", - "integrity": "sha1-/bC0OWLKe0BFanwrtI/hc9otISI=" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/basic-auth-connect/-/basic-auth-connect-1.1.0.tgz", + "integrity": "sha512-rKcWjfiRZ3p5WS9e5q6msXa07s6DaFAMXoyowV+mb2xQG+oYdw2QEUyKi0Xp95JvXzShlM+oGy5QuqSK6TfC1Q==", + "requires": { + "tsscmp": "^1.0.6" + } }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -5724,6 +5727,11 @@ } } }, + "tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==" + }, "tsutils": { "version": "2.29.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", From b1e0859464cfab116544d8cc21dc36b190b19c1a Mon Sep 17 00:00:00 2001 From: Marina Kennedy Date: Thu, 3 Oct 2024 03:23:55 -0400 Subject: [PATCH 3/5] remove support for UA section (#1968) Co-authored-by: ikuleshov --- src/components/Home/index.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/components/Home/index.tsx b/src/components/Home/index.tsx index ff37fc290..13dccd7ed 100644 --- a/src/components/Home/index.tsx +++ b/src/components/Home/index.tsx @@ -60,12 +60,6 @@ const IndexPage: React.FC = () => { . We encourage you to take a look if you'd like to see how anything is done. - Support for UA & GA4 - - There is support for both Universal Analytics (UA) and Google Analytics - 4 (GA4). Click the toggle in the nav bar to switch between the UA and - GA4 versions of the site. - Demos Live demos to help you learn about Google Analytics features. From 4d44d60cc3fff0ac883bfe27f18615644b744551 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 3 Oct 2024 00:28:51 -0700 Subject: [PATCH 4/5] Bump basic-auth-connect from 1.0.0 to 1.1.0 in /lib (#2040) Bumps [basic-auth-connect](https://github.com/expressjs/basic-auth-connect) from 1.0.0 to 1.1.0. - [Release notes](https://github.com/expressjs/basic-auth-connect/releases) - [Commits](https://github.com/expressjs/basic-auth-connect/compare/1.0.0...1.1.0) --- updated-dependencies: - dependency-name: basic-auth-connect dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: ikuleshov --- lib/yarn.lock | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/yarn.lock b/lib/yarn.lock index 217ccbe5a..2897a1952 100644 --- a/lib/yarn.lock +++ b/lib/yarn.lock @@ -583,9 +583,11 @@ base64-js@^1.3.0, base64-js@^1.3.1: integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== basic-auth-connect@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/basic-auth-connect/-/basic-auth-connect-1.0.0.tgz#fdb0b43962ca7b40456a7c2bb48fe173da2d2122" - integrity sha512-kiV+/DTgVro4aZifY/hwRwALBISViL5NP4aReaR2EVJEObpbUBHIkdJh/YpcoEiYt7nBodZ6U2ajZeZvSxUCCg== + version "1.1.0" + resolved "https://registry.yarnpkg.com/basic-auth-connect/-/basic-auth-connect-1.1.0.tgz#b44af37d5b3bd7561b56491e58cf26ae1578f0c7" + integrity sha512-rKcWjfiRZ3p5WS9e5q6msXa07s6DaFAMXoyowV+mb2xQG+oYdw2QEUyKi0Xp95JvXzShlM+oGy5QuqSK6TfC1Q== + dependencies: + tsscmp "^1.0.6" basic-auth@~2.0.1: version "2.0.1" @@ -4042,6 +4044,11 @@ tslib@^2.0.1, tslib@^2.1.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w== +tsscmp@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" + integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA== + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" From 9a7455fb1e753d1822fd98147e7cf3de55bab36e Mon Sep 17 00:00:00 2001 From: ikuleshov Date: Thu, 3 Oct 2024 09:30:37 -0700 Subject: [PATCH 5/5] Dimensions and Metrics Explorer UX update (#2027) * Add screen_view, ad_impression, campaign_details events to EventBuilder * remove UA toggle * update the react-spinner version * remove unimplemented LineItem component * Force Typography to use span tag instead of div to avoid compilation warnings. Remove duplicate code and fix tests by renaming labels... * remove UA code and tests * fix tests * Dimensions and Metrics Explorer UX update Use the autocomplete component to search metrics/dimensions. The main list of all dimensions/metrics remains unchanged when selecting fields for compatibility check. The list of options available in Autocomplete components is updated based on fields' compatibility. Display field categories in accordion with Expand all / Collapse all options. Add option to display compatible only/incompatible only/all fields. Render field description using Markdown. --- package.json | 4 +- .../DimensionsMetricsExplorer/Compatible.tsx | 196 +++++++---- .../ga4/DimensionsMetricsExplorer/Field.tsx | 149 +++------ .../ga4/DimensionsMetricsExplorer/index.tsx | 304 ++++++++++-------- .../useCompatibility.tsx | 9 +- .../useDimensionsAndMetrics.ts | 2 + .../DimensionsMetricsExplorer/useInputs.ts | 12 - src/constants.ts | 1 - 8 files changed, 344 insertions(+), 333 deletions(-) delete mode 100644 src/components/ga4/DimensionsMetricsExplorer/useInputs.ts diff --git a/package.json b/package.json index 199d34240..a638de547 100644 --- a/package.json +++ b/package.json @@ -44,21 +44,23 @@ "react-helmet": "^6.1.0", "react-icons": "^4.8.0", "react-json-view": "^1.21.3", + "react-markdown": "^9.0.1", "react-loader-spinner": "^6.1.6", "react-redux": "^8.0.5", "react-syntax-highlighter": "^15.5.0", "redux": "^4.2.1", + "remark-gfm": "^4.0.0", "tsconfig-paths-webpack-plugin": "^4.0.1", "use-debounce": "^9.0.4", "use-query-params": "^0.4.3" }, "devDependencies": { + "@reach/router": "^1.3.4", "@testing-library/jest-dom": "^6.1.2", "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^13.1.8", "@types/gapi": "^0.0.39", "@types/gapi.auth2": "^0.0.54", - "@reach/router": "^1.3.4", "@types/gapi.client.analytics": "^3.0.7", "@types/gapi.client.analyticsadmin": "^1.0.0", "@types/gapi.client.analyticsdata": "^1.0.2", diff --git a/src/components/ga4/DimensionsMetricsExplorer/Compatible.tsx b/src/components/ga4/DimensionsMetricsExplorer/Compatible.tsx index 8116b345f..d3a641012 100644 --- a/src/components/ga4/DimensionsMetricsExplorer/Compatible.tsx +++ b/src/components/ga4/DimensionsMetricsExplorer/Compatible.tsx @@ -11,6 +11,9 @@ import { navigate } from "gatsby" import * as React from "react" import QueryExplorerLink from "../QueryExplorer/BasicReport/QueryExplorerLink" import { CompatibleHook } from "./useCompatibility" +import Autocomplete from '@mui/material/Autocomplete'; +import {Dimension, Metric} from '@/components/ga4/DimensionsMetricsExplorer/useDimensionsAndMetrics'; +import TextField from '@mui/material/TextField'; const PREFIX = 'Compatible'; @@ -23,9 +26,9 @@ const classes = { }; const StyledPaper = styled(Paper)(( - { - theme - } + { + theme + } ) => ({ [`&.${classes.compatible}`]: { padding: theme.spacing(2), @@ -56,16 +59,23 @@ const StyledPaper = styled(Paper)(( } })); -const WithProperty: React.FC< - CompatibleHook & { property: PropertySummary | undefined } -> = ({ - dimensions, - metrics, - removeMetric, - removeDimension, - property, - hasFieldSelected, -}) => { +type CompatibleProps = + CompatibleHook + & { + property: PropertySummary | undefined, + allMetrics: Metric[], + allDimensions: Dimension[] +} +const WithProperty: React.FC = ({ + dimensions, + metrics, + removeMetric, + removeDimension, setDimensions, setMetrics, + property, + hasFieldSelected, incompatibleDimensions, incompatibleMetrics, + allDimensions, + allMetrics, + }) => { if (property === undefined) { @@ -73,72 +83,124 @@ const WithProperty: React.FC< } return ( - <> - - As you choose dimensions & metrics (by clicking the checkbox next to - their name), they will be added here. Incompatible dimensions & metrics - will be grayed out. - -
- Dimensions: -
- {dimensions !== undefined && dimensions.length > 0 - ? dimensions.map(d => ( - navigate(`#${d.apiName}`)} - onDelete={() => removeDimension(d)} - /> - )) - : "No dimensions selected."} -
- Metrics: -
- {metrics !== undefined && metrics.length > 0 - ? metrics?.map(m => ( - removeMetric(m)} - /> - )) - : "No metrics selected."} -
-
- {hasFieldSelected && ( + <> - Use these fields in the{" "} - + As you choose dimensions & metrics, they will be added here. + Incompatible dimensions & metrics will be grayed out. - )} - +
+ Dimensions: +
+ + fullWidth + autoComplete + multiple + isOptionEqualToValue={(a, b) => a.apiName === b.apiName} + onChange={(event, value) => setDimensions(value)} + value={dimensions || []} + options={allDimensions} + getOptionDisabled={(option) => + incompatibleDimensions?.find(d => d.apiName === option.apiName) !== undefined + } + getOptionLabel={dimension => `${dimension.apiName}: ${dimension.uiName}` || ""} + renderInput={params => ( + + Select dimensions. + + } + /> + )} + renderTags={(tagValue, getTagProps) => + tagValue.map((option, index) => { + return ( + navigate(`#${option.apiName}`)} + onDelete={() => removeDimension(option)} + /> + ); + }) + } + /> +
+ Metrics: +
+ + fullWidth + autoComplete + multiple + isOptionEqualToValue={(a, b) => a.apiName === b.apiName} + onChange={(event, value) => setMetrics(value)} + value={metrics || []} + options={allMetrics} + getOptionDisabled={(option) => + incompatibleMetrics?.find(d => d.apiName === option.apiName) !== undefined + } + getOptionLabel={metric => `${metric.apiName}: ${metric.uiName}` || ""} + renderInput={params => ( + + Select metrics. + + } + /> + )} + renderTags={(tagValue, getTagProps) => + tagValue.map((option, index) => { + return ( + navigate(`#${option.apiName}`)} + onDelete={() => removeMetric(option)} + /> + ); + }) + } + /> +
+
+ {hasFieldSelected && ( + + Use these fields in the{" "} + + + )} + ) } const Compatible: React.FC< - CompatibleHook & { property: PropertySummary | undefined } + CompatibleHook & { allDimensions: Dimension[], allMetrics: Metric[], property: PropertySummary | undefined } > = props => { const { reset, property, hasFieldSelected } = props return ( - - - Compatible Fields - - - - - - {property === undefined && ( - - Pick a property above to enable this functionality. + + + Compatible Fields + + + - )} - + + {property === undefined && ( + + Pick a property above to enable this functionality. + + )} + ); } diff --git a/src/components/ga4/DimensionsMetricsExplorer/Field.tsx b/src/components/ga4/DimensionsMetricsExplorer/Field.tsx index 513144bcb..182fccd97 100644 --- a/src/components/ga4/DimensionsMetricsExplorer/Field.tsx +++ b/src/components/ga4/DimensionsMetricsExplorer/Field.tsx @@ -1,18 +1,20 @@ import * as React from "react" -import { styled } from '@mui/material/styles'; +import {styled} from '@mui/material/styles'; import IconLink from "@mui/icons-material/Link" import Typography from "@mui/material/Typography" import InlineCode from "@/components/InlineCode" -import { CopyIconButton } from "@/components/CopyButton" +import {CopyIconButton} from "@/components/CopyButton" import ExternalLink from "@/components/ExternalLink" -import { Dimension, Metric } from "./useDimensionsAndMetrics" -import { QueryParam } from "." -import { AccountSummary, PropertySummary } from "@/types/ga4/StreamPicker" +import {Dimension, Metric} from "./useDimensionsAndMetrics" +import {QueryParam} from "." +import {AccountSummary, PropertySummary} from "@/types/ga4/StreamPicker" import LabeledCheckbox from "@/components/LabeledCheckbox" -import { CompatibleHook } from "./useCompatibility" +import {CompatibleHook} from "./useCompatibility" +import Markdown from 'react-markdown' +import remarkGfm from 'remark-gfm' const PREFIX = 'Field'; @@ -56,68 +58,6 @@ const Root = styled('div')(( } })); -const knownLinks: [string, JSX.Element][] = [ - [ - "", - - Set up and manage conversion events - , - ], - [ - "", - - Keywords: Definition - , - ], - [ - "", - - User-ID for cross-platform analysis - , - ], - [ - "", - - Data filters - , - ], -] - -const linkifyText = ( - remainingString: string, - elements: (JSX.Element | string)[] -): [string, (JSX.Element | string)[]] => { - const firstMatch = knownLinks.reduce( - (acc, [inText], idx) => { - const { matchIndex } = acc - const currentMatchIndex = remainingString.indexOf(inText) - if (currentMatchIndex !== -1) { - if (currentMatchIndex < matchIndex || matchIndex === -1) { - return { - matchIndex: currentMatchIndex, - knownLinksIndex: idx, - } - } - } - return acc - }, - { knownLinksIndex: -1, matchIndex: -1 } - ) - if (firstMatch.matchIndex === -1) { - elements.push(remainingString) - return ["", elements] - } else { - const [inText, link] = knownLinks[firstMatch.knownLinksIndex] - const before = remainingString.substring(0, firstMatch.matchIndex) - const after = remainingString.substring( - firstMatch.matchIndex + inText.length - ) - elements.push(before) - elements.push(link) - return [after, elements] - } -} - interface FieldProps extends CompatibleHook { field: | { type: "dimension"; value: Dimension } @@ -128,7 +68,6 @@ interface FieldProps extends CompatibleHook { const Field: React.FC = props => { - const { field, account, @@ -158,27 +97,6 @@ const Field: React.FC = props => { return `${baseURL}${search}#${apiName}` }, [field, apiName, account, property]) - const withLinks = React.useMemo(() => { - let remainingText = description - let elements: (JSX.Element | string)[] = [] - let mightHaveLinks = true - while (mightHaveLinks) { - const result = linkifyText(remainingText, elements) - remainingText = result[0] - elements = result[1] - if (remainingText === "") { - mightHaveLinks = false - } - } - return ( - <> - {elements.map((e, idx) => ( - {e} - ))} - - ) - }, [description]) - const isCompatible = React.useMemo(() => { return ( incompatibleDimensions?.find(d => d.apiName === field.value.apiName) === @@ -208,29 +126,34 @@ const Field: React.FC = props => { }, [checked, addDimension, addMetric, removeDimension, removeMetric, field]) return ( - - - {property === undefined ? ( - uiName - ) : ( - - {uiName} - - )} - {apiName} - } - toCopy={link} - tooltipText={`Copy link to ${apiName}`} - /> - - {withLinks} - + <> + { + + + {property === undefined ? ( + uiName + ) : ( + + {uiName} + + )} + {apiName} + } + toCopy={link} + tooltipText={`Copy link to ${apiName}`} + /> + + {description} + + } + ); } diff --git a/src/components/ga4/DimensionsMetricsExplorer/index.tsx b/src/components/ga4/DimensionsMetricsExplorer/index.tsx index 1cbeef95f..10ae8a8e2 100644 --- a/src/components/ga4/DimensionsMetricsExplorer/index.tsx +++ b/src/components/ga4/DimensionsMetricsExplorer/index.tsx @@ -1,33 +1,29 @@ import * as React from "react" -import { styled } from '@mui/material/styles'; -import { useMemo } from "react" -import ExternalLink from "@/components/ExternalLink" +import {Link} from "gatsby" + +import {styled} from '@mui/material/styles'; import Typography from "@mui/material/Typography" -import TextField from "@mui/material/TextField" -import IconButton from "@mui/material/IconButton" -import Clear from "@mui/icons-material/Clear" +import MenuItem from '@mui/material/MenuItem'; +import FormControl from '@mui/material/FormControl'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import Accordion from '@mui/material/Accordion'; +import AccordionDetails from '@mui/material/AccordionDetails'; +import AccordionSummary from '@mui/material/AccordionSummary'; +import {Button, InputLabel, Select, SelectChangeEvent} from '@mui/material'; -import { Url, StorageKey } from "@/constants" -import { useScrollTo } from "@/hooks" +import ExternalLink from "@/components/ExternalLink" +import {StorageKey, Url} from "@/constants" +import {useScrollTo} from "@/hooks" import Loadable from "@/components/Loadable" -import Info from "@/components/Info" +import ScrollToTop from "@/components/ScrollToTop" + import Field from "./Field" -import useInputs from "./useInputs" -import { - useDimensionsAndMetrics, - Successful, - Dimension, - Metric, -} from "./useDimensionsAndMetrics" +import {Dimension, Metric, Successful, useDimensionsAndMetrics,} from "./useDimensionsAndMetrics" import StreamPicker from "../StreamPicker" -import useAccountProperty, { - AccountProperty, -} from "../StreamPicker/useAccountProperty" -import { Link } from "gatsby" +import useAccountProperty, {AccountProperty} from "../StreamPicker/useAccountProperty" import useCompatibility from "./useCompatibility" import Compatible from "./Compatible" -import ScrollToTop from "@/components/ScrollToTop" const PREFIX = 'DimensionsMetricsExplorer'; @@ -64,132 +60,166 @@ const dataAPI = ( ) const RenderSuccessful: React.FC = ({ - categories, - aps, -}) => { - - const { search, setSearch } = useInputs() - const searchRegex = useMemo( - () => - search - ? new RegExp( - // Escape all "special" regex characters. We're only creating a regex - // here to make the testing code more simple. - search.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), - "gi" - ) - : undefined, - [search] - ) + categories, + metrics, + dimensions, + aps, + }) => { - const compability = useCompatibility(aps) + type ViewMode = 'all' | 'compatible' | 'incompatible' + const [viewMode, setViewMode] = React.useState('all') - const searchFilter = React.useCallback( - (c: Dimension | Metric) => { - if (searchRegex === undefined) { - return true - } - return searchRegex.test(c.uiName!) || searchRegex.test(c.apiName!) - }, - [searchRegex] + const compatibility = useCompatibility(aps) + + useScrollTo() + const handleViewModeChange = (event: SelectChangeEvent) => { + setViewMode(event.target.value as ViewMode); + }; + + const fieldDisplayFilter = React.useCallback( + (c: Dimension | Metric) => { + const isCompatible = compatibility.incompatibleDimensions?.find(d => + d.apiName === c.apiName) === undefined && + compatibility.incompatibleMetrics?.find(d => + d.apiName === c.apiName) === undefined + return viewMode === 'all' || (viewMode === 'compatible' && + isCompatible) || (viewMode === 'incompatible' && !isCompatible); + }, + [viewMode, + compatibility.incompatibleDimensions, + compatibility.incompatibleMetrics] ) const filteredCategories = React.useMemo( - () => - categories.map(c => ({ - ...c, - dimensions: c.dimensions.filter(searchFilter), - metrics: c.metrics.filter(searchFilter), - })), - [searchFilter, categories] + () => + categories.map(c => ({ + ...c, + dimensions: c.dimensions.filter(fieldDisplayFilter), + metrics: c.metrics.filter(fieldDisplayFilter), + })), + [categories, fieldDisplayFilter] ) - const notAllFields = useMemo(() => { - if (searchRegex !== undefined) { - return ( - - You are only viewing a subset of the available metrics and dimensions. - - ) - } - }, [searchRegex]) + const resetAllCategoryAccordions = (expanded: boolean) => + { + const initialCategoryAccordionState = {} as any + categories.forEach( (x) => initialCategoryAccordionState[x.category]=expanded ) + return initialCategoryAccordionState + } - useScrollTo() + const [categoryAccordionState, + setCategoryAccordionState] = React.useState(resetAllCategoryAccordions(true)); - return ( - ( - - setSearch(e.target.value)} - InputProps={{ - endAdornment: ( - setSearch("")}> - - - ), - }} - /> - {notAllFields} - {filteredCategories.map(({ category, dimensions, metrics }) => { - if (dimensions.length === 0 && metrics.length === 0) { - return null + const handleCategoryAccordionStateChange = + (category: string) => (event: React.SyntheticEvent, isExpanded: boolean) => { + const newState = { + ...categoryAccordionState } - const baseAnchor = encodeURIComponent(category) - return ( - - - {category} - - {dimensions.length > 0 && ( - <> - - Dimensions - - {dimensions.map(dimension => ( - - ))} - - )} - {metrics.length > 0 && ( - <> - - Metrics - - {metrics.map(metric => ( - - ))} - - )} - - ) + newState[category] = isExpanded + setCategoryAccordionState(newState); + }; + + return ( + ( + + + + View mode + + + + + Dimensions & Metrics + + + + + + {filteredCategories.map(({category, dimensions, metrics}) => { + if (dimensions.length === 0 && metrics.length === 0) { + return null + } + const baseAnchor = encodeURIComponent(category) + return ( + + + } + > + + {category} + + + + {dimensions.length > 0 && ( + <> + + Dimensions + + {dimensions.map(dimension => ( + + ))} + + )} + {metrics.length > 0 && ( + <> + + Metrics + + {metrics.map(metric => ( + + ))} + + )} + + + + ) })} ) ); diff --git a/src/components/ga4/DimensionsMetricsExplorer/useCompatibility.tsx b/src/components/ga4/DimensionsMetricsExplorer/useCompatibility.tsx index ffe3a45e7..ab184bf83 100644 --- a/src/components/ga4/DimensionsMetricsExplorer/useCompatibility.tsx +++ b/src/components/ga4/DimensionsMetricsExplorer/useCompatibility.tsx @@ -6,10 +6,13 @@ import { Dimension, Metric } from "./useDimensionsAndMetrics" type CheckCompatibilityResponse = gapi.client.analyticsdata.CheckCompatibilityResponse export interface CompatibleHook { - dimensions: Dimension[] | undefined - incompatibleDimensions: Dimension[] | undefined + dimensions?: Dimension[] metrics: Metric[] | undefined + incompatibleDimensions: Dimension[] | undefined incompatibleMetrics: Metric[] | undefined + setDimensions: (value: (((prevState: (Dimension[] | undefined)) => (Dimension[] | undefined)) | Dimension[] | undefined)) => void + setMetrics: (value: (((prevState: (Metric[] | undefined)) => (Metric[] | undefined)) | Metric[] | undefined)) => void + addDimension: (d: Dimension) => void removeDimension: (d: Dimension) => void addMetric: (m: Metric) => void @@ -95,6 +98,8 @@ const useCompatibility = (ap: AccountProperty): CompatibleHook => { return { dimensions, metrics, + setDimensions, + setMetrics, addDimension, removeDimension, addMetric, diff --git a/src/components/ga4/DimensionsMetricsExplorer/useDimensionsAndMetrics.ts b/src/components/ga4/DimensionsMetricsExplorer/useDimensionsAndMetrics.ts index f4679b798..b68663adc 100644 --- a/src/components/ga4/DimensionsMetricsExplorer/useDimensionsAndMetrics.ts +++ b/src/components/ga4/DimensionsMetricsExplorer/useDimensionsAndMetrics.ts @@ -10,6 +10,8 @@ import { AccountProperty } from "../StreamPicker/useAccountProperty" export type Dimension = gapi.client.analyticsdata.DimensionMetadata export type Metric = gapi.client.analyticsdata.MetricMetadata +export type DimensionOrMetric = Dimension | Metric + export type Successful = { dimensions: Dimension[] metrics: Metric[] diff --git a/src/components/ga4/DimensionsMetricsExplorer/useInputs.ts b/src/components/ga4/DimensionsMetricsExplorer/useInputs.ts deleted file mode 100644 index 5be7b0c3d..000000000 --- a/src/components/ga4/DimensionsMetricsExplorer/useInputs.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { usePersistentString } from "@/hooks" -import { StorageKey } from "@/constants" - -const useInputs = () => { - const [search, setSearch] = usePersistentString( - StorageKey.ga4DimensionsMetricsSearch - ) - - return { search, setSearch } -} - -export default useInputs diff --git a/src/constants.ts b/src/constants.ts index 31d98d214..f93f31f3b 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -94,7 +94,6 @@ export enum StorageKey { // GA4 Dimensions and metrics explorer ga4DimensionsMetrics = "/ga4/dimensions-metrics/", ga4DimensionsMetricsExplorerAPS = "/ga4/dimensions-metrics-explorer/aps", - ga4DimensionsMetricsSearch = "/ga4/dimensions-metrics-explorer/search", ga4DimensionsMetricsFields = "/ga4/dimensions-metrics-explorer/fields", ga4DimensionsMetricsAccountSummaries = "/ga4/dimensions-metrics-explorer/account-summaries", ga4DimensionsMetricsSelectedAccount = "/ga4/dimensions-metrics-explorer/selected-account",