Merge pull request #4645 from cwillisf/add-telemetry-hooks
Add telemetry hooks
This commit is contained in:
5 files changed
+93
-11
No files matched your search
@@ -97,6 +97,7 @@ const GUIComponent = props => {
|
||||
onActivateTab,
|
||||
onClickLogo,
|
||||
onExtensionButtonClick,
|
||||
onProjectTelemetryEvent,
|
||||
onRequestCloseBackdropLibrary,
|
||||
onRequestCloseCostumeLibrary,
|
||||
onRequestCloseTelemetryModal,
|
||||
@@ -217,6 +218,7 @@ const GUIComponent = props => {
|
||||
onCloseAccountNav={onCloseAccountNav}
|
||||
onLogOut={onLogOut}
|
||||
onOpenRegistration={onOpenRegistration}
|
||||
onProjectTelemetryEvent={onProjectTelemetryEvent}
|
||||
onSeeCommunity={onSeeCommunity}
|
||||
onShare={onShare}
|
||||
onToggleLoginOpen={onToggleLoginOpen}
|
||||
|
||||
@@ -6,6 +6,8 @@ import bindAll from 'lodash.bindall';
|
||||
import bowser from 'bowser';
|
||||
import React from 'react';
|
||||
|
||||
import VM from 'scratch-vm';
|
||||
|
||||
import Box from '../box/box.jsx';
|
||||
import Button from '../button/button.jsx';
|
||||
import CommunityButton from './community-button.jsx';
|
||||
@@ -55,6 +57,8 @@ import {
|
||||
loginMenuOpen
|
||||
} from '../../reducers/menus';
|
||||
|
||||
import collectMetadata from '../../lib/collect-metadata';
|
||||
|
||||
import styles from './menu-bar.css';
|
||||
|
||||
import helpIcon from '../../lib/assets/icon--tutorials.svg';
|
||||
@@ -146,10 +150,10 @@ class MenuBar extends React.Component {
|
||||
'handleClickSaveAsCopy',
|
||||
'handleClickSeeCommunity',
|
||||
'handleClickShare',
|
||||
'handleCloseFileMenuAndThen',
|
||||
'handleKeyPress',
|
||||
'handleLanguageMouseUp',
|
||||
'handleRestoreOption',
|
||||
'handleSaveToComputer',
|
||||
'restoreOptionMessage'
|
||||
]);
|
||||
}
|
||||
@@ -216,12 +220,6 @@ class MenuBar extends React.Component {
|
||||
this.props.onRequestCloseEdit();
|
||||
};
|
||||
}
|
||||
handleCloseFileMenuAndThen (fn) {
|
||||
return () => {
|
||||
this.props.onRequestCloseFile();
|
||||
fn();
|
||||
};
|
||||
}
|
||||
handleKeyPress (event) {
|
||||
const modifier = bowser.mac ? event.metaKey : event.ctrlKey;
|
||||
if (modifier && event.key === 's') {
|
||||
@@ -229,6 +227,16 @@ class MenuBar extends React.Component {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
handleSaveToComputer (downloadProjectCallback) {
|
||||
return () => {
|
||||
this.props.onRequestCloseFile();
|
||||
downloadProjectCallback();
|
||||
if (this.props.onProjectTelemetryEvent) {
|
||||
const metadata = collectMetadata(this.props.vm, this.props.projectTitle, this.props.locale);
|
||||
this.props.onProjectTelemetryEvent('projectDidSave', metadata);
|
||||
}
|
||||
};
|
||||
}
|
||||
handleLanguageMouseUp (e) {
|
||||
if (!this.props.languageMenuOpen) {
|
||||
this.props.onClickLanguage(e);
|
||||
@@ -402,10 +410,10 @@ class MenuBar extends React.Component {
|
||||
</MenuItem>
|
||||
)}
|
||||
</SBFileUploader>
|
||||
<SB3Downloader>{(className, downloadProject) => (
|
||||
<SB3Downloader>{(className, downloadProjectCallback) => (
|
||||
<MenuItem
|
||||
className={className}
|
||||
onClick={this.handleCloseFileMenuAndThen(downloadProject)}
|
||||
onClick={this.handleSaveToComputer(downloadProjectCallback)}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Save to your computer"
|
||||
@@ -743,6 +751,7 @@ MenuBar.propTypes = {
|
||||
onLogOut: PropTypes.func,
|
||||
onOpenRegistration: PropTypes.func,
|
||||
onOpenTipLibrary: PropTypes.func,
|
||||
onProjectTelemetryEvent: PropTypes.func,
|
||||
onRequestCloseAccount: PropTypes.func,
|
||||
onRequestCloseEdit: PropTypes.func,
|
||||
onRequestCloseFile: PropTypes.func,
|
||||
@@ -757,7 +766,8 @@ MenuBar.propTypes = {
|
||||
renderLogin: PropTypes.func,
|
||||
sessionExists: PropTypes.bool,
|
||||
showComingSoon: PropTypes.bool,
|
||||
username: PropTypes.string
|
||||
username: PropTypes.string,
|
||||
vm: PropTypes.instanceOf(VM).isRequired
|
||||
};
|
||||
|
||||
MenuBar.defaultProps = {
|
||||
@@ -775,11 +785,13 @@ const mapStateToProps = state => {
|
||||
isUpdating: getIsUpdating(loadingState),
|
||||
isShowingProject: getIsShowingProject(loadingState),
|
||||
languageMenuOpen: languageMenuOpen(state),
|
||||
locale: state.locales.locale,
|
||||
loginMenuOpen: loginMenuOpen(state),
|
||||
projectChanged: state.scratchGui.projectChanged,
|
||||
projectTitle: state.scratchGui.projectTitle,
|
||||
sessionExists: state.session && typeof state.session.session !== 'undefined',
|
||||
username: user ? user.username : null
|
||||
username: user ? user.username : null,
|
||||
vm: state.scratchGui.vm
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Report a telemetry event.
|
||||
* @param {string} event - one of `projectWasCreated`, `projectDidLoad`, `projectDidSave`, `projectWasUploaded`
|
||||
*/
|
||||
// TODO make a telemetry HOC and move this stuff there
|
||||
const collectMetadata = function (vm, projectName = '', locale = '') {
|
||||
// TODO move most or all of this into a collectMetadata() method on the VM/Runtime
|
||||
const metadata = {
|
||||
projectName: projectName,
|
||||
language: locale,
|
||||
spriteCount: 0,
|
||||
blocksCount: 0,
|
||||
costumesCount: 0,
|
||||
listsCount: 0,
|
||||
scriptCount: 0,
|
||||
soundsCount: 0,
|
||||
variablesCount: 0
|
||||
};
|
||||
|
||||
for (const target of vm.runtime.targets) {
|
||||
++metadata.spriteCount;
|
||||
metadata.blocksCount += Object.keys(target.sprite.blocks._blocks).length;
|
||||
metadata.costumesCount += target.sprite.costumes_.length;
|
||||
metadata.scriptCount += target.sprite.blocks._scripts.length;
|
||||
metadata.soundsCount += target.sprite.sounds.length;
|
||||
for (const variableName in target.variables) {
|
||||
const variable = target.variables[variableName];
|
||||
if (variable.type === 'list') {
|
||||
++metadata.listsCount;
|
||||
} else {
|
||||
++metadata.variablesCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return metadata;
|
||||
};
|
||||
|
||||
export default collectMetadata;
|
||||
@@ -6,6 +6,7 @@ import {connect} from 'react-redux';
|
||||
import VM from 'scratch-vm';
|
||||
import xhr from 'xhr';
|
||||
|
||||
import collectMetadata from '../lib/collect-metadata';
|
||||
import log from '../lib/log';
|
||||
import storage from '../lib/storage';
|
||||
import dataURItoBlob from '../lib/data-uri-to-blob';
|
||||
@@ -25,6 +26,7 @@ import {
|
||||
getIsAnyCreatingNewState,
|
||||
getIsCreatingCopy,
|
||||
getIsCreatingNew,
|
||||
getIsLoading,
|
||||
getIsManualUpdating,
|
||||
getIsRemixing,
|
||||
getIsShowingWithId,
|
||||
@@ -61,6 +63,13 @@ const ProjectSaverHOC = function (WrappedComponent) {
|
||||
this.props.onSetProjectThumbnailer(this.getProjectThumbnail);
|
||||
}
|
||||
componentDidUpdate (prevProps) {
|
||||
if (!this.props.isAnyCreatingNewState && prevProps.isAnyCreatingNewState) {
|
||||
this.reportTelemetryEvent('projectWasCreated');
|
||||
}
|
||||
if (!this.props.isLoading && prevProps.isLoading) {
|
||||
this.reportTelemetryEvent('projectDidLoad');
|
||||
}
|
||||
|
||||
if (this.props.projectChanged && !prevProps.projectChanged) {
|
||||
this.scheduleAutoSave();
|
||||
}
|
||||
@@ -305,6 +314,18 @@ const ProjectSaverHOC = function (WrappedComponent) {
|
||||
this.props.vm.renderer.draw();
|
||||
}
|
||||
|
||||
/**
|
||||
* Report a telemetry event.
|
||||
* @param {string} event - one of `projectWasCreated`, `projectDidLoad`, `projectDidSave`, `projectWasUploaded`
|
||||
*/
|
||||
// TODO make a telemetry HOC and move this stuff there
|
||||
reportTelemetryEvent (event) {
|
||||
if (this.props.onProjectTelemetryEvent) {
|
||||
const metadata = collectMetadata(this.props.vm, this.props.reduxProjectTitle, this.props.locale);
|
||||
this.props.onProjectTelemetryEvent(event, metadata);
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
const {
|
||||
/* eslint-disable no-unused-vars */
|
||||
@@ -314,6 +335,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
|
||||
isCreatingNew,
|
||||
projectChanged,
|
||||
isAnyCreatingNewState,
|
||||
isLoading,
|
||||
isManualUpdating,
|
||||
isRemixing,
|
||||
isShowingSaveable,
|
||||
@@ -359,6 +381,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
|
||||
isAnyCreatingNewState: PropTypes.bool,
|
||||
isCreatingCopy: PropTypes.bool,
|
||||
isCreatingNew: PropTypes.bool,
|
||||
isLoading: PropTypes.bool,
|
||||
isManualUpdating: PropTypes.bool,
|
||||
isRemixing: PropTypes.bool,
|
||||
isShared: PropTypes.bool,
|
||||
@@ -371,6 +394,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
|
||||
onCreateProject: PropTypes.func,
|
||||
onCreatedProject: PropTypes.func,
|
||||
onProjectError: PropTypes.func,
|
||||
onProjectTelemetryEvent: PropTypes.func,
|
||||
onRemixing: PropTypes.func,
|
||||
onShowAlert: PropTypes.func,
|
||||
onShowCopySuccessAlert: PropTypes.func,
|
||||
@@ -397,6 +421,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
|
||||
return {
|
||||
autoSaveTimeoutId: state.scratchGui.timeout.autoSaveTimeoutId,
|
||||
isAnyCreatingNewState: getIsAnyCreatingNewState(loadingState),
|
||||
isLoading: getIsLoading(loadingState),
|
||||
isCreatingCopy: getIsCreatingCopy(loadingState),
|
||||
isCreatingNew: getIsCreatingNew(loadingState),
|
||||
isRemixing: getIsRemixing(loadingState),
|
||||
@@ -406,6 +431,7 @@ const ProjectSaverHOC = function (WrappedComponent) {
|
||||
isUpdating: getIsUpdating(loadingState),
|
||||
isManualUpdating: getIsManualUpdating(loadingState),
|
||||
loadingState: loadingState,
|
||||
locale: state.locales.locale,
|
||||
projectChanged: state.scratchGui.projectChanged,
|
||||
reduxProjectId: state.scratchGui.projectState.projectId,
|
||||
reduxProjectTitle: state.scratchGui.projectTitle,
|
||||
|
||||
Reference in new issue
Block a user