Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement/3168 matching ga4 properties #3311

Merged
merged 7 commits into from
May 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion assets/js/components/DetailsPermaLinks.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { Fragment } from '@wordpress/element';
import Data from 'googlesitekit-data';
import { CORE_SITE } from '../googlesitekit/datastore/site/constants';
import Link from './Link';
import getFullURL from '../util/getFullURL';
import { getFullURL } from '../util';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a big deal, but why this change?

I think in the past we separated the utils files to prevent chances of circular imports… but aside from that I don't have much of a preference 🙂

const { useSelect } = Data;

export default function DetailsPermaLinks( { title, path, serviceURL } ) {
Expand Down
4 changes: 1 addition & 3 deletions assets/js/components/data-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ import {
*/
import SourceLink from './SourceLink';
import Link from './Link';
import getFullURL from '../util/getFullURL';
import { getSiteKitAdminURL } from '../util';
import { getFullURL, getSiteKitAdminURL } from '../util';

// Construct a table component from a data object.
export const getDataTableFromData = ( data, headers, options ) => {
Expand Down Expand Up @@ -157,4 +156,3 @@ export const getDataTableFromData = ( data, headers, options ) => {
</div>
);
};

6 changes: 1 addition & 5 deletions assets/js/googlesitekit/datastore/site/info.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { addQueryArgs, getQueryArg } from '@wordpress/url';
*/
import Data from 'googlesitekit-data';
import { STORE_NAME, AMP_MODE_PRIMARY, AMP_MODE_SECONDARY } from './constants';
import { getLocale } from '../../../util/i18n';
import { getLocale, normalizeURL } from '../../../util';

const { createRegistrySelector } = Data;

Expand Down Expand Up @@ -519,10 +519,6 @@ export const selectors = {
*/
isSiteURLMatch: createRegistrySelector( ( select ) => ( state, url ) => {
const referenceURL = select( STORE_NAME ).getReferenceSiteURL();
const normalizeURL = ( incomingURL ) => incomingURL
.replace( /^https?:\/\/(www\.)?/i, '' ) // Remove protocol and optional "www." prefix from the URL.
.replace( /\/$/, '' ); // Remove trailing slash.

return normalizeURL( referenceURL ) === normalizeURL( url );
} ),
};
Expand Down
2 changes: 2 additions & 0 deletions assets/js/modules/analytics-4/datastore/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ export const STORE_NAME = 'modules/analytics-4';
export { STORE_NAME as MODULES_ANALYTICS_4 };

export const PROPERTY_CREATE = 'property_create';

export const MAX_WEBDATASTREAMS_PER_BATCH = 10;
74 changes: 73 additions & 1 deletion assets/js/modules/analytics-4/datastore/properties.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ import invariant from 'invariant';
*/
import API from 'googlesitekit-api';
import Data from 'googlesitekit-data';
import { STORE_NAME, PROPERTY_CREATE } from './constants';
import { STORE_NAME, PROPERTY_CREATE, MAX_WEBDATASTREAMS_PER_BATCH } from './constants';
import { normalizeURL } from '../../../util';
import { createFetchStore } from '../../../googlesitekit/data/create-fetch-store';
import { isValidPropertySelection } from '../utils/validation';
import { actions as webDataStreamActions } from './webdatastreams';
const { commonActions } = Data;

const fetchGetPropertyStore = createFetchStore( {
baseName: 'getProperty',
Expand Down Expand Up @@ -162,6 +164,76 @@ const baseActions = {
}
}() );
},

/**
* Matches a property by URL.
*
* @since n.e.x.t
*
* @param {Array.<number>} properties Array of property IDs.
* @param {Array.<string>|string} url A list of URLs or a signle URL to match properties.
* @return {Object} A property object if found.
*/
*matchPropertyByURL( properties, url ) {
const registry = yield commonActions.getRegistry();
const urls = ( Array.isArray( url ) ? url : [ url ] ).map( normalizeURL );

for ( let i = 0; i < properties.length; i += MAX_WEBDATASTREAMS_PER_BATCH ) {
const chunk = properties.slice( i, i + MAX_WEBDATASTREAMS_PER_BATCH );
const webdatastreams = yield commonActions.await(
registry.__experimentalResolveSelect( STORE_NAME ).getWebDataStreamsBatch( chunk ),
);

for ( const propertyID in webdatastreams ) {
for ( const webdatastream of webdatastreams[ propertyID ] ) {
for ( const singleURL of urls ) {
if ( singleURL === normalizeURL( webdatastream.defaultUri ) ) {
return yield commonActions.await(
registry.__experimentalResolveSelect( STORE_NAME ).getProperty( propertyID ),
);
}
}
}
}
}

return null;
},

/**
* Matches a property by measurement ID.
*
* @since n.e.x.t
*
* @param {Array.<number>} properties Array of property IDs.
* @param {Array.<string>|string} measurementID A list of measurement IDs or a signle measurement ID to match properties.
* @return {Object} A property object if found.
*/
*matchPropertyByMeasurementID( properties, measurementID ) {
const registry = yield commonActions.getRegistry();
const measurementIDs = Array.isArray( measurementID ) ? measurementID : [ measurementID ];

for ( let i = 0; i < properties.length; i += MAX_WEBDATASTREAMS_PER_BATCH ) {
const chunk = properties.slice( i, i + MAX_WEBDATASTREAMS_PER_BATCH );
const webdatastreams = yield commonActions.await(
registry.__experimentalResolveSelect( STORE_NAME ).getWebDataStreamsBatch( chunk ),
);

for ( const propertyID in webdatastreams ) {
for ( const webdatastream of webdatastreams[ propertyID ] ) {
for ( const singleMeasurementID of measurementIDs ) {
if ( singleMeasurementID === webdatastream.measurementId ) { // eslint-disable-line sitekit/acronym-case
return yield commonActions.await(
registry.__experimentalResolveSelect( STORE_NAME ).getProperty( propertyID ),
);
}
}
}
}
}

return null;
},
};

const baseControls = {
Expand Down
46 changes: 46 additions & 0 deletions assets/js/modules/analytics-4/datastore/properties.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,52 @@ describe( 'modules/analytics-4 properties', () => {
expect( registry.select( STORE_NAME ).getMeasurementID() ).toBe( fixtures.webDataStreams[ 1 ].measurementId ); // eslint-disable-line sitekit/acronym-case
} );
} );

describe( 'matchPropertyByURL', () => {
const property = fixtures.properties[ 0 ];
const propertyID = property._id;
const propertyIDs = [ propertyID ];

beforeEach( () => {
registry.dispatch( STORE_NAME ).receiveGetProperty( property, { propertyID } );
registry.dispatch( STORE_NAME ).receiveGetWebDataStreamsBatch( fixtures.webDataStreamsBatch, { propertyIDs } );
} );

it( 'should return a property object when a property is found', async () => {
const url = 'https://www.example.org/';
const matchedProperty = await registry.dispatch( STORE_NAME ).matchPropertyByURL( propertyIDs, url );
expect( matchedProperty ).toEqual( property );
} );

it( 'should return NULL when a property is not found', async () => {
const url = 'https://www.example.io/';
const matchedProperty = await registry.dispatch( STORE_NAME ).matchPropertyByURL( propertyIDs, url );
expect( matchedProperty ).toBeNull();
} );
} );

describe( 'matchPropertyByMeasurementID', () => {
const property = fixtures.properties[ 0 ];
const propertyID = property._id;
const propertyIDs = [ propertyID ];

beforeEach( () => {
registry.dispatch( STORE_NAME ).receiveGetProperty( property, { propertyID } );
registry.dispatch( STORE_NAME ).receiveGetWebDataStreamsBatch( fixtures.webDataStreamsBatch, { propertyIDs } );
} );

it( 'should return a property object when a property is found', async () => {
const measurementID = '1A2BCD346E';
const matchedProperty = await registry.dispatch( STORE_NAME ).matchPropertyByMeasurementID( propertyIDs, measurementID );
expect( matchedProperty ).toEqual( property );
} );

it( 'should return NULL when a property is not found', async () => {
const measurementID = '0000000000';
const matchedProperty = await registry.dispatch( STORE_NAME ).matchPropertyByMeasurementID( propertyIDs, measurementID );
expect( matchedProperty ).toBeNull();
} );
} );
} );

describe( 'selectors', () => {
Expand Down
4 changes: 1 addition & 3 deletions assets/js/modules/analytics-4/datastore/webdatastreams.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,12 @@ import difference from 'lodash/difference';
import API from 'googlesitekit-api';
import Data from 'googlesitekit-data';
import { createValidatedAction } from '../../../googlesitekit/data/utils';
import { STORE_NAME } from './constants';
import { STORE_NAME, MAX_WEBDATASTREAMS_PER_BATCH } from './constants';
import { CORE_SITE } from '../../../googlesitekit/datastore/site/constants';
import { createFetchStore } from '../../../googlesitekit/data/create-fetch-store';
import { isValidPropertyID } from '../utils/validation';
const { createRegistryControl, createRegistrySelector } = Data;

const MAX_WEBDATASTREAMS_PER_BATCH = 10;

const fetchGetWebDataStreamsStore = createFetchStore( {
baseName: 'getWebDataStreams',
controlCallback( { propertyID } ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ import { CORE_SITE } from '../../../../../googlesitekit/datastore/site/constants
import { CORE_USER } from '../../../../../googlesitekit/datastore/user/constants';
import { CORE_UI } from '../../../../../googlesitekit/datastore/ui/constants';
import { Grid, Row, Cell } from '../../../../../material-components/layout';
import { getURLPath } from '../../../../../util/getURLPath';
import { getURLPath } from '../../../../../util';
import whenActive from '../../../../../util/when-active';
import SourceLink from '../../../../../components/SourceLink';
import TotalUserCount from './TotalUserCount';
import UserCountGraph from './UserCountGraph';
import DimensionTabs from './DimensionTabs';
import UserDimensionsPieChart from './UserDimensionsPieChart';
import { isZeroReport } from '../../../util';
import { generateDateRangeArgs } from '../../../../analytics/util/report-date-range-args';
import { generateDateRangeArgs } from '../../../util/report-date-range-args';

const { useSelect, useDispatch } = Data;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ import whenActive from '../../../../util/when-active';
import PreviewBlock from '../../../../components/PreviewBlock';
import DataBlock from '../../../../components/DataBlock';
import Sparkline from '../../../../components/Sparkline';
import { calculateChange } from '../../../../util';
import { getURLPath } from '../../../../util/getURLPath';
import { calculateChange, getURLPath } from '../../../../util';
import parseDimensionStringToDate from '../../util/parseDimensionStringToDate';
import { isZeroReport } from '../../util';
import { generateDateRangeArgs } from '../../util/report-date-range-args';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ import whenActive from '../../../../util/when-active';
import PreviewBlock from '../../../../components/PreviewBlock';
import DataBlock from '../../../../components/DataBlock';
import Sparkline from '../../../../components/Sparkline';
import { calculateChange } from '../../../../util';
import { getURLPath } from '../../../../util/getURLPath';
import { calculateChange, getURLPath } from '../../../../util';
import parseDimensionStringToDate from '../../util/parseDimensionStringToDate';
import { isZeroReport } from '../../util';
import { generateDateRangeArgs } from '../../util/report-date-range-args';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import { Fragment, useState, useEffect } from '@wordpress/element';
import {
getTimeInSeconds,
calculateChange,
getURLPath,
} from '../../../../util';
import extractForSparkline from '../../../../util/extract-for-sparkline';
import {
Expand All @@ -45,7 +46,6 @@ import {
userReportDataDefaults,
parseTotalUsersData,
} from '../../util';
import { getURLPath } from '../../../../util/getURLPath';
import Data from 'googlesitekit-data';
import DataBlock from '../../../../components/DataBlock';
import withData from '../../../../components/higherorder/withData';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { __, _x, sprintf } from '@wordpress/i18n';
import Data from 'googlesitekit-data';
import { STORE_NAME } from '../../datastore/constants';
import { CORE_SITE } from '../../../../googlesitekit/datastore/site/constants';
import { getTimeInSeconds } from '../../../../util';
import { getTimeInSeconds, getURLPath } from '../../../../util';
import GoogleChart from '../../../../components/GoogleChart';
import withData from '../../../../components/higherorder/withData';
import { TYPE_MODULES } from '../../../../components/data';
Expand All @@ -45,7 +45,6 @@ import {
trafficSourcesReportDataDefaults,
isDataZeroForReporting,
} from '../../util';
import { getURLPath } from '../../../../util/getURLPath';

const { useSelect } = Data;

Expand Down
32 changes: 0 additions & 32 deletions assets/js/util/getFullURL.js

This file was deleted.

77 changes: 0 additions & 77 deletions assets/js/util/getFullURL.test.js

This file was deleted.

Loading