From f6dc2726b559098dc25db28922d73001a57d5ade Mon Sep 17 00:00:00 2001 From: Christopher Willis-Ford Date: Fri, 28 Dec 2018 03:36:30 -0800 Subject: [PATCH] Implement projectDidSave telemetry event --- src/components/gui/gui.jsx | 2 ++ src/components/menu-bar/menu-bar.jsx | 25 +++++++++++++++--- src/lib/collect-metadata.js | 39 ++++++++++++++++++++++++++++ src/lib/project-saver-hoc.jsx | 31 ++-------------------- 4 files changed, 65 insertions(+), 32 deletions(-) create mode 100644 src/lib/collect-metadata.js diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx index a203310b1..829215b39 100644 --- a/src/components/gui/gui.jsx +++ b/src/components/gui/gui.jsx @@ -99,6 +99,7 @@ const GUIComponent = props => { onActivateTab, onClickLogo, onExtensionButtonClick, + onProjectTelemetryEvent, onRequestCloseBackdropLibrary, onRequestCloseCostumeLibrary, onRequestCloseTelemetryModal, @@ -225,6 +226,7 @@ const GUIComponent = props => { onCloseAccountNav={onCloseAccountNav} onLogOut={onLogOut} onOpenRegistration={onOpenRegistration} + onProjectTelemetryEvent={onProjectTelemetryEvent} onSeeCommunity={onSeeCommunity} onShare={onShare} onToggleLoginOpen={onToggleLoginOpen} diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx index 825f6096f..671f94b8e 100644 --- a/src/components/menu-bar/menu-bar.jsx +++ b/src/components/menu-bar/menu-bar.jsx @@ -5,6 +5,8 @@ import PropTypes from 'prop-types'; import bindAll from 'lodash.bindall'; 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'; @@ -54,6 +56,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'; @@ -153,6 +157,7 @@ class MenuBar extends React.Component { 'handleCloseFileMenuAndThen', 'handleLanguageMouseUp', 'handleRestoreOption', + 'handleSaveToComputer', 'restoreOptionMessage' ]); } @@ -219,6 +224,16 @@ class MenuBar extends React.Component { fn(); }; } + handleSaveToComputer (downloadProject) { + return () => { + this.props.onRequestCloseFile(); + downloadProject(); + 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); @@ -395,7 +410,7 @@ class MenuBar extends React.Component { {(className, downloadProject) => ( { 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 }; }; diff --git a/src/lib/collect-metadata.js b/src/lib/collect-metadata.js new file mode 100644 index 000000000..0623aa96d --- /dev/null +++ b/src/lib/collect-metadata.js @@ -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; diff --git a/src/lib/project-saver-hoc.jsx b/src/lib/project-saver-hoc.jsx index f57c1039b..addfd6eb0 100644 --- a/src/lib/project-saver-hoc.jsx +++ b/src/lib/project-saver-hoc.jsx @@ -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'; @@ -304,35 +305,7 @@ const ProjectSaverHOC = function (WrappedComponent) { //TODO make a telemetry HOC and move this stuff there reportTelemetryEvent (event) { if (this.props.onProjectTelemetryEvent) { - //TODO move most or all of this into a collectMetadata() method on the VM/Runtime - const metadata = { - projectName: this.props.reduxProjectTitle, - language: this.props.locale, - spriteCount: 0, - blocksCount: 0, - costumesCount: 0, - listsCount: 0, - scriptCount: 0, - soundsCount: 0, - variablesCount: 0 - }; - - for (const target of this.props.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; - } - } - } - + const metadata = collectMetadata(this.props.vm, this.props.reduxProjectTitle, this.props.locale); this.props.onProjectTelemetryEvent(event, metadata); } }