From d71994bfd1aa1e1296db0a4b2b705a9e30932a01 Mon Sep 17 00:00:00 2001 From: Patricia Ennenbach Date: Wed, 29 Sep 2021 11:12:12 +0200 Subject: [PATCH 01/53] =?UTF-8?q?=F0=9F=94=80=20merge=20-=20=F0=9F=92=AC?= =?UTF-8?q?=20Update=20tutorial=20description=20(#97)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/edu/game-00-hallo-welt/game.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/edu/game-00-hallo-welt/game.js b/src/lib/edu/game-00-hallo-welt/game.js index b53a47671..5a78d0914 100644 --- a/src/lib/edu/game-00-hallo-welt/game.js +++ b/src/lib/edu/game-00-hallo-welt/game.js @@ -7,7 +7,7 @@ import ab from './assets/b.mp4' export default { id: '00', name: 'Hallo Welt', - subtitle: '00 Video: Erste Schritte', + subtitle: '00 Erste Schritte', image: aL00, preVideo: 'https://wdradaptiv-vh.akamaihd.net/i/medp/ondemand/weltweit/fsk0/191/1910629/,1910629_22682393,1910629_22682388,1910629_22682390,1910629_22682389,1910629_22682392,1910629_22682391,.mp4.csmil/master.m3u8', From 47f74931a353d813f42d941d5d3955a1107ef45e Mon Sep 17 00:00:00 2001 From: Camila Espinoza <56554983+cami-espinozaq@users.noreply.github.com> Date: Wed, 31 May 2023 16:29:01 +0200 Subject: [PATCH 02/53] Piano Analytics Implementation (#102) * sending page.display events for main menu * added page display events for lernen tab * added missing pagedisplay events --------- Co-authored-by: Camila --- package.json | 3 +- src/components/menu/menu.jsx | 39 +++++++- .../video-button-modal/video-button-modal.jsx | 13 ++- src/containers/content.jsx | 8 ++ src/containers/gui.jsx | 52 ++++++++++- src/containers/menu.jsx | 3 + src/entrypoints/index.jsx | 3 + src/lib/piano-analytics/constants.js | 38 ++++++++ src/lib/piano-analytics/main.js | 92 +++++++++++++++++++ src/reducers/editor-tab.js | 7 ++ yarn.lock | 9 +- 11 files changed, 258 insertions(+), 9 deletions(-) create mode 100644 src/lib/piano-analytics/constants.js create mode 100644 src/lib/piano-analytics/main.js diff --git a/package.json b/package.json index 3bcfe15d8..b0098a109 100644 --- a/package.json +++ b/package.json @@ -129,9 +129,9 @@ "rimraf": "^2.6.1", "scratch-paint": "0.2.0-prerelease.20181120191526", "scratch-render": "0.1.0-prerelease.20210325231800", + "scratch-render-fonts": "1.0.0-prerelease.20210401210003", "scratch-storage": "1.2.2", "scratch-svg-renderer": "0.2.0-prerelease.20210511195415", - "scratch-render-fonts": "1.0.0-prerelease.20210401210003", "selenium-webdriver": "4.0.0-alpha.1", "serverless": "^1.30.3", "serverless-domain-manager": "^3.1.0", @@ -183,6 +183,7 @@ "jspdf": "^1.5.3", "lodash.keyby": "^4.6.0", "multer": "^1.4.1", + "piano-analytics-js": "^6.8.3", "qrcode.react": "^0.9.3", "scratch-audio": "0.1.0-prerelease.20200528195344", "scratch-blocks": "0.1.0-prerelease.20210529032338", diff --git a/src/components/menu/menu.jsx b/src/components/menu/menu.jsx index 6aaf13f27..7405c7e13 100644 --- a/src/components/menu/menu.jsx +++ b/src/components/menu/menu.jsx @@ -25,6 +25,16 @@ import buttonIconInfo from '!raw-loader!../../../assets/icons/menu_eltern-info.s import buttonIconMausseite from '!raw-loader!../../../assets/icons/menu_mausseite.svg' import buttonIconDatenschutz from '!raw-loader!../../../assets/icons/icon_hilfe.svg' import buttonIconImpressum from '!raw-loader!../../../assets/icons/menu_impressum.svg' +import { paEvent } from '../../lib/piano-analytics/main.js' +import { menuTabTitles } from '../../lib/piano-analytics/constants.js' + +// TODO: Use when updating react-intl (must use static values for now) +// const tabListData = { +// 0: { title: "Lernen", id: "gui.gui.eduGames", svg: tabIconEdugames }, +// 1: { title: "Meine Sachen", id: "gui.gui.games", svg: tabIconProjects }, +// 2: { title: "Beispiele", id: "gui.gui.examples", svg: tabIconExamples }, +// 3: { title: "Videos", id: "gui.gui.videos", svg: tabIconVideos }, +// } export const MenuComponent = (props) => { const tabClassNames = { @@ -39,6 +49,26 @@ export const MenuComponent = (props) => { tabSelected: classNames(tabStyles.reactTabsTabSelected, styles.isSelected), } + // TODO: Use when updating react-intl + // const menuTab = (index) => { + // const { title, id, svg } = tabListData[index] + + // return ( + // + //
+ // + // + //
+ //
+ // ) + // } + return (
@@ -72,7 +102,10 @@ export const MenuComponent = (props) => { selectedTabClassName={tabClassNames.tabSelected} selectedTabPanelClassName={tabClassNames.tabPanelSelected} selectedIndex={props.selectedTab} - onSelect={props.handleTabSelected} + onSelect={(index) => { + paEvent.pageDisplay({ pages: ["Menu", menuTabTitles[index]], pageType: "Hauptseite" }) + return props.handleTabSelected(index) + }} > @@ -152,6 +185,10 @@ export const MenuComponent = (props) => { iconSvg={buttonIconMausseite} external linkTo="https://www.wdrmaus.de/" + onClick={() => { + // TODO: add click event + console.log("zur Maus-Seite") + }} > Zur Maus-Seite diff --git a/src/components/video-button-modal/video-button-modal.jsx b/src/components/video-button-modal/video-button-modal.jsx index 043a1d257..af00d5cea 100644 --- a/src/components/video-button-modal/video-button-modal.jsx +++ b/src/components/video-button-modal/video-button-modal.jsx @@ -1,11 +1,13 @@ import PropTypes from 'prop-types' -import React, { useState } from 'react' +import React, { useEffect, useState } from 'react' import Modal from '../modal/modal.jsx' import VideoPlayer from '../video-player/video-player.jsx' import defaultImage from '../../../assets/img/meine_sachen.png' import styles from './video-button-modal.css' +import { paEvent } from '../../lib/piano-analytics/main.js' +import { menuTabTitles } from '../../lib/piano-analytics/constants.js' const VideoButtonModal = ({ title, image, note, video }) => { const [showModal, setShowModal] = useState(false) @@ -14,6 +16,15 @@ const VideoButtonModal = ({ title, image, note, video }) => { // Add the '(' back to the 2nd line for correct display secondline = secondline ? `(${secondline}` : '' + useEffect(() => { + if (!showModal) return + + paEvent.pageDisplay({ + pages: ["Menu", menuTabTitles[3], `Video ${note}`], + pageType: 'Video' + }) + }, [showModal]) + return ( <>
({ saveProjectVisible: state.scratchGui.modals.saveProject, eduLayerActive: state.scratchGui.eduLayer.enabled, eduId: state.scratchGui.eduLayer.gameId, + isNewProject: state.router.result && !!state.router.result.newProject }) +const logPageDisplay = (eduId, isNewProject, tab) => { + let pages = [] + if (isNewProject) { + pages = [menuTabTitles[1], 'New Project'] + } else if (eduId && eduId.match(/beispiel(0|0\d{1})?$/gm)) { + pages = [menuTabTitles[2], `Beispiel ${eduId}`] + } else if (eduId) { + pages = [menuTabTitles[0], `Lernspiel ${eduId}`] + } + + paEvent.pageDisplay({ + pages: tab ? [...pages, editorTabNames[tab]] : pages, + pageType: "Spiele" + }) +} + +const onTabActivating = (eduId, isNewProject, tab) => { + logPageDisplay(eduId, isNewProject, tab) + return activateTab(tab) +} + const mapDispatchToProps = (dispatch) => ({ closeSaveModal: () => dispatch(closeSaveProject()), onExtensionButtonClick: () => dispatch(openExtensionLibrary()), - onActivateTab: (tab) => dispatch(activateTab(tab)), - onActivateCostumesTab: () => dispatch(activateTab(COSTUMES_TAB_INDEX)), - onActivateSoundsTab: () => dispatch(activateTab(SOUNDS_TAB_INDEX)), + onActivateTab: (eduId, isNewProject, tab) => dispatch(onTabActivating(eduId, isNewProject, tab)), + onActivateCostumesTab: (eduId, isNewProject) => dispatch(onTabActivating(eduId, isNewProject, COSTUMES_TAB_INDEX)), + onActivateSoundsTab: (eduId, isNewProject) => dispatch(onTabActivating(eduId, isNewProject, SOUNDS_TAB_INDEX)), onLayoutModeClick: () => dispatch(toggleLayoutMode()), onSetUnchanged: () => dispatch(setProjectUnchanged()), }) -const ConnectedGUI = connect(mapStateToProps, mapDispatchToProps)(GUI) +const mergeProps = (stateProps, dispatchProps, ownProps) => { + return { + ...ownProps, + ...stateProps, + ...dispatchProps, + onActivateTab: (tab) => dispatchProps.onActivateTab(stateProps.eduId, stateProps.isNewProject, tab), + onActivateCostumesTab: () => dispatchProps.onActivateCostumesTab(stateProps.eduId, stateProps.isNewProject), + onActivateSoundsTab: () => dispatchProps.onActivateSoundsTab(stateProps.eduId, stateProps.isNewProject), + } +} + +const ConnectedGUI = connect(mapStateToProps, mapDispatchToProps, mergeProps)(GUI) // eslint-disable-next-line new-cap const WrappedGui = flow([ diff --git a/src/containers/menu.jsx b/src/containers/menu.jsx index defac7240..4d7fc7cd2 100644 --- a/src/containers/menu.jsx +++ b/src/containers/menu.jsx @@ -6,6 +6,7 @@ import { push } from 'redux-little-router' import { MenuComponent } from '../components/menu/menu.jsx' import { MenuTabs } from '../lib/routing' import { games, examples, videos } from '../lib/edu' +import { paEvent } from '../lib/piano-analytics/main.js' const tabIdToTab = { 0: MenuTabs.edugames, @@ -45,6 +46,8 @@ class Menu extends React.Component { projects: [], videos: videos.map(Menu.mapVideoData), } + + paEvent.pageDisplay({ pages: ['Menu'], pageType: 'Hauptseite' }) } componentDidMount() { diff --git a/src/entrypoints/index.jsx b/src/entrypoints/index.jsx index c23a93c81..8563c71e5 100644 --- a/src/entrypoints/index.jsx +++ b/src/entrypoints/index.jsx @@ -5,6 +5,9 @@ import ReactDOM from 'react-dom' import App from '../containers/app.jsx' import '../css/defaults.css' +import { paSetConfig } from '../lib/piano-analytics/main.js' + +paSetConfig() const appTarget = document.getElementById('__mausapp') diff --git a/src/lib/piano-analytics/constants.js b/src/lib/piano-analytics/constants.js new file mode 100644 index 000000000..96f81285e --- /dev/null +++ b/src/lib/piano-analytics/constants.js @@ -0,0 +1,38 @@ +export const EVENTS = { + pageDisplay: 'page.display', + clickNavigation: 'click.navigation', + clickExit: 'click.exit', + clickAction: 'click.action', +} + +export const PROPERTIES = { + siteLevel2: 'site_level2', + brand: 'brand', + redaction: 'editorial_department', + platform: 'platform', + siteTitle: 'page_title', + pageLevel1: 'page_chapter1', + pageLevel2: 'page_chapter2', + pageLevel3: 'page_chapter3', + siteType: 'page_type', + publicationTimeAt: 'publication_time', // date + reactionUpdatedAt: 'last_editorial_update', // date + daysSincePublication: 'days_since_publication', // integer + clickLabel: 'click', + clickTarget: 'click_target', + clickChapter1: 'click_chapter1', + clickChapter2: 'click_chapter2', +} + +export const DEFAULT_PROPERTY_VALUES = { + [PROPERTIES.siteLevel2]: 'Programmieren mit der Maus', + [PROPERTIES.brand]: 'Die Maus', + [PROPERTIES.redaction]: 'PG Kinder und Familie', +} + +export const menuTabTitles = { + 0: 'Lernen', + 1: 'Meine Sachen', + 2: 'Beispiele', + 3: 'Videos', +} diff --git a/src/lib/piano-analytics/main.js b/src/lib/piano-analytics/main.js new file mode 100644 index 000000000..bc01bdc32 --- /dev/null +++ b/src/lib/piano-analytics/main.js @@ -0,0 +1,92 @@ +import { pianoAnalytics } from 'piano-analytics-js' +import { EVENTS, PROPERTIES, DEFAULT_PROPERTY_VALUES } from './constants' + +pianoAnalytics.setConfigurations({ + site: 621455, + collectDomain: 'https://logs1414.xiti.com/', +}) + +export const paSetConfig = () => { + let configurations + + if (process.env.NODE_ENV === 'production') { + configurations = { + site: 632700, + collectDomain: 'https://ama.wdr.de/', + } + } else { + configurations = { + site: 621455, + collectDomain: 'https://logs1414.xiti.com/', + } + } + pianoAnalytics.setConfigurations(configurations) +} + +const pageLevelKeys = [ + PROPERTIES.pageLevel1, + PROPERTIES.pageLevel2, + PROPERTIES.pageLevel3, +] + +const sendEvent = (eventKey, data) => { + let properties = { ...DEFAULT_PROPERTY_VALUES } + + switch (typeof data) { + case 'string': + properties[PROPERTIES.pageLevel1] = data + break + + case 'object': + properties = { ...properties, ...data } + break + } + + return pianoAnalytics.sendEvent(eventKey, { + ...getCustomProperties(properties), + ...properties, + }) +} + +const getCustomProperties = (data) => { + const pageList = pageLevelKeys + .filter((key) => key in data) + .map((key) => data[key]) + const platform = window.navigator.userAgent.match(/^(.*?)\(/) + + return { + page: [data[PROPERTIES.siteLevel2], ...pageList].join('_'), + ...(pageList.length && { [PROPERTIES.siteTitle]: pageList.slice(-1)[0] }), + ...(platform.length && { [PROPERTIES.platform]: platform.slice(-1)[0] }), + } +} + +const clickEventEntries = () => { + const { pageDisplay, ...otherEvents } = EVENTS + + return Object.entries(otherEvents).map(([eventName, eventKey]) => [ + eventName, + (data) => sendEvent(eventKey, data), + ]) +} + +const clickEvents = Object.fromEntries(clickEventEntries()) + +export const paEvent = { + pageDisplay: ({ pages, pageType }) => { + let data = {} + + if (typeof pages === 'string') { + data[PROPERTIES.pageLevel1] = pages + } else { + const pagesList = [...pages].slice(0, 3) + pagesList.forEach((page, index) => { + data[PROPERTIES[`pageLevel${index + 1}`]] = page + }) + } + + if (pageType) data[PROPERTIES.siteType] = pageType + return sendEvent(EVENTS.pageDisplay, data) + }, + ...clickEvents, +} diff --git a/src/reducers/editor-tab.js b/src/reducers/editor-tab.js index 142ea11f1..b91e1878e 100644 --- a/src/reducers/editor-tab.js +++ b/src/reducers/editor-tab.js @@ -9,6 +9,12 @@ const initialState = { activeTabIndex: BLOCKS_TAB_INDEX, } +const editorTabNames = { + [BLOCKS_TAB_INDEX]: 'Code', + [COSTUMES_TAB_INDEX]: 'Kostüme', + [SOUNDS_TAB_INDEX]: 'Töne', +} + const reducer = function (state, action) { if (typeof state === 'undefined') { state = initialState @@ -37,4 +43,5 @@ export { BLOCKS_TAB_INDEX, COSTUMES_TAB_INDEX, SOUNDS_TAB_INDEX, + editorTabNames, } diff --git a/yarn.lock b/yarn.lock index dff317dea..f583b5212 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8645,7 +8645,7 @@ intl-format-cache@^2.0.5: intl-messageformat-parser@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/intl-messageformat-parser/-/intl-messageformat-parser-1.4.0.tgz#b43d45a97468cadbe44331d74bb1e8dea44fc075" - integrity sha1-tD1FqXRoytvkQzHXS7Ho3qRPwHU= + integrity sha512-/XkqFHKezO6UcF4Av2/Lzfrez18R0jyw7kRFhSeB/YRakdrgSc9QfFZUwNJI9swMwMoNPygK1ArC5wdFSjPw+A== intl-messageformat-parser@^1.2.0: version "1.8.1" @@ -8655,7 +8655,7 @@ intl-messageformat-parser@^1.2.0: intl-messageformat@^2.0.0, intl-messageformat@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-2.2.0.tgz#345bcd46de630b7683330c2e52177ff5eab484fc" - integrity sha1-NFvNRt5jC3aDMwwuUhd/9eq0hPw= + integrity sha512-I+tSvHnXqJYjDfNmY95tpFMj30yoakC6OXAo+wu/wTMy6tA/4Fd4mvV7Uzs4cqK/Ap29sHhwjcY+78a8eifcXw== dependencies: intl-messageformat-parser "1.4.0" @@ -12152,6 +12152,11 @@ pez@2.x.x: hoek "4.x.x" nigel "2.x.x" +piano-analytics-js@^6.8.3: + version "6.8.3" + resolved "https://registry.yarnpkg.com/piano-analytics-js/-/piano-analytics-js-6.8.3.tgz#f13bfaafdc0a58b7045cfb02be20a918cf3231a7" + integrity sha512-2NI77WkB1I31ZYdHe9brUhrCpEeDWqdlY/KmUKgvF6npbTiONzMGJOKui6eqKJkoo8f0Wuy1ucmpGM7wXYVdGw== + picomatch@^2.0.5: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" From 7e9fc6de9478e0e512877fa78249d05c59ffc953 Mon Sep 17 00:00:00 2001 From: Camila Date: Mon, 5 Jun 2023 19:45:46 +0200 Subject: [PATCH 03/53] added missing piano events --- src/components/edu-stage/edu-stage.jsx | 22 ++++++- src/components/menu/menu.jsx | 10 ++-- src/components/stage-header/stage-header.jsx | 19 +++++- src/containers/controls.jsx | 10 ++++ src/containers/gui.jsx | 9 +-- src/containers/stage-header.jsx | 1 + src/lib/piano-analytics/main.js | 62 ++++++++++++-------- 7 files changed, 93 insertions(+), 40 deletions(-) diff --git a/src/components/edu-stage/edu-stage.jsx b/src/components/edu-stage/edu-stage.jsx index f1e4b97df..15fb512f3 100644 --- a/src/components/edu-stage/edu-stage.jsx +++ b/src/components/edu-stage/edu-stage.jsx @@ -17,6 +17,7 @@ import { eduUrl } from '../../lib/routing' import { gamesKeyed } from '../../lib/edu/' import VideoPlayer from '../video-player/video-player.jsx' import styles from './edu-stage.css' +import { guiTypePages, paEvent } from '../../lib/piano-analytics/main' const EduStageComponent = (props) => { const [isPreVideoModalOpen, setPreVideoModalOpen] = useState(false) @@ -58,7 +59,10 @@ const EduStageComponent = (props) => {
{props.caption}
@@ -97,7 +104,10 @@ const EduStageComponent = (props) => { arrowRight style="primary" wiggle={props.slideIndex === 0 && !props.finished} - onClick={props.nextSlide} + onClick={() => { + sendPaEvent(props.gameId, 'Weiter Button') + return props.nextSlide() + }} disabled={props.finished} > {!props.linkNextGame ? 'Weiter' : 'Nächstes Lernspiel'} @@ -108,6 +118,12 @@ const EduStageComponent = (props) => { ) } +const sendPaEvent = (gameId, lastLevel) => { + const pages = guiTypePages(gameId) + pages.push(lastLevel) + paEvent.clickAction({ pages }) +} + EduStageComponent.propTypes = { caption: PropTypes.string, imageSrc: PropTypes.string, diff --git a/src/components/menu/menu.jsx b/src/components/menu/menu.jsx index 7405c7e13..64189c461 100644 --- a/src/components/menu/menu.jsx +++ b/src/components/menu/menu.jsx @@ -185,10 +185,12 @@ export const MenuComponent = (props) => { iconSvg={buttonIconMausseite} external linkTo="https://www.wdrmaus.de/" - onClick={() => { - // TODO: add click event - console.log("zur Maus-Seite") - }} + onClick={() => + paEvent.clickExit({ + pages: ['Menu', 'Zur Maus-Seite'], + pageType: 'Beitrag' + }) + } > Zur Maus-Seite diff --git a/src/components/stage-header/stage-header.jsx b/src/components/stage-header/stage-header.jsx index 7770a157a..edea3a077 100644 --- a/src/components/stage-header/stage-header.jsx +++ b/src/components/stage-header/stage-header.jsx @@ -7,6 +7,7 @@ import { Link } from 'redux-little-router' import Controls from '../../containers/controls.jsx' import Fullscreen from '../../containers/fullscreen.jsx' import MenuButton from '../menu-button/menu-button.jsx' +import { guiTypePages, paEvent } from '../../lib/piano-analytics/main.js' import styles from './stage-header.css' import saveIcon from '!raw-loader!../../../assets/icons/header_save.svg' @@ -14,7 +15,7 @@ import menuIcon from '!raw-loader!../../../assets/icons/header_menu.svg' import mailIcon from '!raw-loader!../../../assets/icons/menu_impressum.svg' const StageHeaderComponent = function (props) { - const { isFullScreen, onSaveProject, vm } = props + const { isFullScreen, onSaveProject, vm, gameId } = props return (
sendPaEvent('clickAction', gameId, 'Los')} + onStopAllClick={() => sendPaEvent('clickAction', gameId, 'Stopp')} /> {isFullScreen ? ( @@ -45,6 +48,7 @@ const StageHeaderComponent = function (props) { iconSvg={mailIcon} external linkTo="mailto:maus@wdr.de" + onClick={() => sendPaEvent('clickExit', gameId, 'Feedback')} > Feedback @@ -52,7 +56,10 @@ const StageHeaderComponent = function (props) { orientation="vertical" id="save" iconSvg={saveIcon} - onClick={onSaveProject} + onClick={() => { + sendPaEvent('clickAction', gameId, 'Speichern') + return onSaveProject() + }} > Speichern @@ -61,6 +68,7 @@ const StageHeaderComponent = function (props) { linkTo="/" className={styles.headerIcon} iconSvg={menuIcon} + onClick={() => sendPaEvent('clickAction', gameId, 'Übersicht')} > Übersicht @@ -72,9 +80,16 @@ const StageHeaderComponent = function (props) { ) } +const sendPaEvent = (eventType, gameId, lastLevel) => { + const pages = guiTypePages(gameId) + pages.push(lastLevel) + return paEvent[eventType]({ pages }) +} + StageHeaderComponent.propTypes = { intl: intlShape, isFullScreen: PropTypes.bool.isRequired, + gameId: PropTypes.string, onSaveProject: PropTypes.func.isRequired, vm: PropTypes.instanceOf(VM).isRequired, } diff --git a/src/containers/controls.jsx b/src/containers/controls.jsx index cfbdcd92c..3e1af2063 100644 --- a/src/containers/controls.jsx +++ b/src/containers/controls.jsx @@ -35,6 +35,10 @@ class Controls extends React.Component { } handleGreenFlagClick(e) { e.preventDefault() + + if (this.props.onGreenFlagClick) { + this.props.onGreenFlagClick() + } if (e.shiftKey) { this.setState({ turbo: !this.state.turbo }) this.props.vm.setTurboMode(!this.state.turbo) @@ -44,6 +48,10 @@ class Controls extends React.Component { } handleStopAllClick(e) { e.preventDefault() + + if (this.props.onStopAllClick) { + this.props.onStopAllClick() + } this.props.vm.stopAll() } render() { @@ -65,6 +73,8 @@ class Controls extends React.Component { Controls.propTypes = { vm: PropTypes.instanceOf(VM), + onGreenFlagClick: PropTypes.func, + onStopAllClick: PropTypes.func } export default Controls diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx index 5466d5eb1..b5d68df4b 100644 --- a/src/containers/gui.jsx +++ b/src/containers/gui.jsx @@ -23,8 +23,7 @@ import { StageSizeProviderHOC } from '../lib/stage-size-provider.jsx' import GUIComponent from '../components/gui/gui.jsx' import { toggleLayoutMode } from '../reducers/layout-mode' import { setProjectUnchanged } from '../reducers/project-changed' -import { paEvent } from '../lib/piano-analytics/main' -import { menuTabTitles } from '../lib/piano-analytics/constants' +import { guiTypePages, paEvent } from '../lib/piano-analytics/main' class GUI extends React.Component { constructor(props) { @@ -157,11 +156,9 @@ const mapStateToProps = (state) => ({ const logPageDisplay = (eduId, isNewProject, tab) => { let pages = [] if (isNewProject) { - pages = [menuTabTitles[1], 'New Project'] - } else if (eduId && eduId.match(/beispiel(0|0\d{1})?$/gm)) { - pages = [menuTabTitles[2], `Beispiel ${eduId}`] + pages = guiTypePages(null) } else if (eduId) { - pages = [menuTabTitles[0], `Lernspiel ${eduId}`] + pages = guiTypePages(eduId) } paEvent.pageDisplay({ diff --git a/src/containers/stage-header.jsx b/src/containers/stage-header.jsx index 34009300a..e7388baf8 100644 --- a/src/containers/stage-header.jsx +++ b/src/containers/stage-header.jsx @@ -39,6 +39,7 @@ StageHeader.propTypes = { const mapStateToProps = (state) => ({ isFullScreen: state.scratchGui.mode.isFullScreen, + gameId: state.scratchGui.eduLayer.gameId }) const mapDispatchToProps = (dispatch) => ({ diff --git a/src/lib/piano-analytics/main.js b/src/lib/piano-analytics/main.js index bc01bdc32..bbae26bc6 100644 --- a/src/lib/piano-analytics/main.js +++ b/src/lib/piano-analytics/main.js @@ -1,5 +1,10 @@ import { pianoAnalytics } from 'piano-analytics-js' -import { EVENTS, PROPERTIES, DEFAULT_PROPERTY_VALUES } from './constants' +import { + EVENTS, + PROPERTIES, + DEFAULT_PROPERTY_VALUES, + menuTabTitles, +} from './constants' pianoAnalytics.setConfigurations({ site: 621455, @@ -23,6 +28,18 @@ export const paSetConfig = () => { pianoAnalytics.setConfigurations(configurations) } +export const guiTypePages = (gameId) => { + if (!gameId) { + return [menuTabTitles[1], 'New Project'] + } + + if (gameId.match(/beispiel(0|0\d{1})?$/gm)) { + return [menuTabTitles[2], `Beispiel ${gameId}`] + } else { + return [menuTabTitles[0], `Lernspiel ${gameId}`] + } +} + const pageLevelKeys = [ PROPERTIES.pageLevel1, PROPERTIES.pageLevel2, @@ -61,32 +78,27 @@ const getCustomProperties = (data) => { } } -const clickEventEntries = () => { - const { pageDisplay, ...otherEvents } = EVENTS +const pageValuesToData = ({ pages, pageType }) => { + let data = {} + + if (typeof pages === 'string') { + data[PROPERTIES.pageLevel1] = pages + } else { + const pagesList = [...pages].slice(0, 3) + pagesList.forEach((page, index) => { + data[PROPERTIES[`pageLevel${index + 1}`]] = page + }) + } + + if (pageType) data[PROPERTIES.siteType] = pageType + return data +} - return Object.entries(otherEvents).map(([eventName, eventKey]) => [ +const clickEventEntries = () => { + return Object.entries(EVENTS).map(([eventName, eventKey]) => [ eventName, - (data) => sendEvent(eventKey, data), + (data) => sendEvent(eventKey, pageValuesToData(data)), ]) } -const clickEvents = Object.fromEntries(clickEventEntries()) - -export const paEvent = { - pageDisplay: ({ pages, pageType }) => { - let data = {} - - if (typeof pages === 'string') { - data[PROPERTIES.pageLevel1] = pages - } else { - const pagesList = [...pages].slice(0, 3) - pagesList.forEach((page, index) => { - data[PROPERTIES[`pageLevel${index + 1}`]] = page - }) - } - - if (pageType) data[PROPERTIES.siteType] = pageType - return sendEvent(EVENTS.pageDisplay, data) - }, - ...clickEvents, -} +export const paEvent = Object.fromEntries(clickEventEntries()) From bf90d49ff35706ea1e0753b12875ccdcb5296671 Mon Sep 17 00:00:00 2001 From: Camila Espinoza <56554983+cami-espinozaq@users.noreply.github.com> Date: Mon, 19 Jun 2023 01:36:55 +0200 Subject: [PATCH 04/53] Create develop.yml --- .github/workflows/develop.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/workflows/develop.yml diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml new file mode 100644 index 000000000..44c84dbed --- /dev/null +++ b/.github/workflows/develop.yml @@ -0,0 +1,10 @@ +name: staging deployment + +on: + push: + branches: + - develop + +jobs: + build: + runs-on: ubuntu-latest From d60b8fd521e985ed4e36009d8c031fd3657a11d6 Mon Sep 17 00:00:00 2001 From: Camila Espinoza <56554983+cami-espinozaq@users.noreply.github.com> Date: Mon, 19 Jun 2023 01:41:53 +0200 Subject: [PATCH 05/53] Update develop.yml --- .github/workflows/develop.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index 44c84dbed..362768463 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -8,3 +8,20 @@ on: jobs: build: runs-on: ubuntu-latest + strategy: + matrix: + node-version: [18.x] + steps: + - uses: actions/checkout@v3 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + - run: npm ci + - name: serverless deploy + uses: serverless/github-action@v3.2 + with: + args: deploy + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} From 033e1d07abf0d7074061f4bed6d79873e2afccba Mon Sep 17 00:00:00 2001 From: Camila Espinoza <56554983+cami-espinozaq@users.noreply.github.com> Date: Mon, 19 Jun 2023 01:48:26 +0200 Subject: [PATCH 06/53] Update develop.yml --- .github/workflows/develop.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index 362768463..e096d2d2f 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -17,7 +17,10 @@ jobs: uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} - - run: npm ci + - name: Install dependencies + run: yarn install + - name: Run Lint + run: yarn run lint - name: serverless deploy uses: serverless/github-action@v3.2 with: From f08769a7e05a95724813ba8cbf12f42d29c3d559 Mon Sep 17 00:00:00 2001 From: Camila Espinoza <56554983+cami-espinozaq@users.noreply.github.com> Date: Tue, 20 Jun 2023 10:39:06 +0200 Subject: [PATCH 07/53] Update develop.yml trying to deploy without lint for now --- .github/workflows/develop.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index e096d2d2f..efa1c2bf3 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -19,8 +19,6 @@ jobs: node-version: ${{ matrix.node-version }} - name: Install dependencies run: yarn install - - name: Run Lint - run: yarn run lint - name: serverless deploy uses: serverless/github-action@v3.2 with: From 721691bd573216b894c5afb835df49994e9b389d Mon Sep 17 00:00:00 2001 From: Camila Espinoza <56554983+cami-espinozaq@users.noreply.github.com> Date: Tue, 20 Jun 2023 10:46:44 +0200 Subject: [PATCH 08/53] Update develop.yml downgraded node --- .github/workflows/develop.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index efa1c2bf3..7f2361275 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [18.x] + node-version: [14.x] steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} From 7965986fcc15cae70250540421156495a01a835c Mon Sep 17 00:00:00 2001 From: Camila Espinoza <56554983+cami-espinozaq@users.noreply.github.com> Date: Tue, 20 Jun 2023 10:58:41 +0200 Subject: [PATCH 09/53] Update develop.yml --- .github/workflows/develop.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index 7f2361275..caef4c251 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [14.x] + node-version: [12.x] steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} From 91bb3d2fdf614f0ac920ae353a78b04b16a65abd Mon Sep 17 00:00:00 2001 From: Camila Espinoza <56554983+cami-espinozaq@users.noreply.github.com> Date: Tue, 20 Jun 2023 11:32:36 +0200 Subject: [PATCH 10/53] Update develop.yml --- .github/workflows/develop.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index caef4c251..a98099167 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -20,9 +20,7 @@ jobs: - name: Install dependencies run: yarn install - name: serverless deploy - uses: serverless/github-action@v3.2 - with: - args: deploy + run: yarn deploy env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} From 5d1a38cfb8bd65c260338c8387cc21a398fed940 Mon Sep 17 00:00:00 2001 From: Camila Espinoza <56554983+cami-espinozaq@users.noreply.github.com> Date: Tue, 20 Jun 2023 13:08:34 +0200 Subject: [PATCH 11/53] Update develop.yml --- .github/workflows/develop.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index a98099167..083e73a3a 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -20,7 +20,7 @@ jobs: - name: Install dependencies run: yarn install - name: serverless deploy - run: yarn deploy + run: SLS_STAGE=staging yarn deploy env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} From 6a9c0ecf2b2e2118bd1a8e36a587925980a8b88d Mon Sep 17 00:00:00 2001 From: Camila Espinoza <56554983+cami-espinozaq@users.noreply.github.com> Date: Tue, 20 Jun 2023 14:49:51 +0200 Subject: [PATCH 12/53] Update develop.yml --- .github/workflows/develop.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index 083e73a3a..2378bc149 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -20,7 +20,7 @@ jobs: - name: Install dependencies run: yarn install - name: serverless deploy - run: SLS_STAGE=staging yarn deploy + run: SLS_STAGE=staging TRAVIS_BRANCH=develop BRANCH=develop yarn deploy env: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} From 384fcf55fa381b7796690c9e2653fb312f4ea891 Mon Sep 17 00:00:00 2001 From: Camila Espinoza <56554983+cami-espinozaq@users.noreply.github.com> Date: Tue, 20 Jun 2023 18:02:22 +0200 Subject: [PATCH 13/53] Update develop.yml --- .github/workflows/develop.yml | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index 2378bc149..a726ba9cc 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -11,16 +11,32 @@ jobs: strategy: matrix: node-version: [12.x] + python-version: [3.0] + env: + S3_BUCKET_PREFIX: hackingstudio-code4maus-projects + AWS_REGION: eu-central-1 + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} steps: - - uses: actions/checkout@v3 + - name: Checkout app + uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v3 with: node-version: ${{ matrix.node-version }} + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: before install dep + run: | + sudo apt-get install -y python3-pip python3-setuptools libcups2-dev + pip3 install --user awscli + export PATH=$PATH:$HOME/.local/bin - name: Install dependencies run: yarn install - name: serverless deploy - run: SLS_STAGE=staging TRAVIS_BRANCH=develop BRANCH=develop yarn deploy - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + run: SLS_STAGE=staging BRANCH=develop yarn deploy + + + From 76568025e621f7f4b265a976eaf7c30b7ef4d74c Mon Sep 17 00:00:00 2001 From: Camila Date: Thu, 13 Jul 2023 12:37:47 +0200 Subject: [PATCH 14/53] added requirement for awscli --- requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..338dd939d --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +aws-cli==2.11.16 From 7be1a8ae32ca8b189292844418a97f19c7c80530 Mon Sep 17 00:00:00 2001 From: Camila Date: Thu, 13 Jul 2023 12:40:07 +0200 Subject: [PATCH 15/53] awscli without version --- netlify.toml | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/netlify.toml b/netlify.toml index 26683849d..7b4b89815 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,4 +1,4 @@ [build] - Command = "NODE_ENV=production yarn build:netlify" + Command = "NODE_ENV=staging yarn build:netlify" Functions = "lambda" Publish = "build" diff --git a/requirements.txt b/requirements.txt index 338dd939d..4eb712b49 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -aws-cli==2.11.16 +aws-cli From 53d7a39030915a10c9ac526c1b79c41e1b55843a Mon Sep 17 00:00:00 2001 From: Camila Date: Thu, 13 Jul 2023 12:42:16 +0200 Subject: [PATCH 16/53] fixed requirement name --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 4eb712b49..88294b13f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -aws-cli +awscli From 318046577caf7e19d538c26e1f2bf1589cda623a Mon Sep 17 00:00:00 2001 From: Camila Date: Thu, 13 Jul 2023 13:41:09 +0200 Subject: [PATCH 17/53] add cors policy for piano --- netlify.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/netlify.toml b/netlify.toml index 7b4b89815..0317fd9e6 100644 --- a/netlify.toml +++ b/netlify.toml @@ -2,3 +2,7 @@ Command = "NODE_ENV=staging yarn build:netlify" Functions = "lambda" Publish = "build" +[[headers]] + for = "/*" + [headers.values] + Access-Control-Allow-Origin = "https://logs1414.xiti.com" From 76747d1f6d35057dd5f989473456457a4b41d96a Mon Sep 17 00:00:00 2001 From: Camila Date: Thu, 10 Aug 2023 18:35:49 +0200 Subject: [PATCH 18/53] paEvents improvements --- src/containers/gui.jsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx index 5466d5eb1..c9ff96dc3 100644 --- a/src/containers/gui.jsx +++ b/src/containers/gui.jsx @@ -48,7 +48,7 @@ class GUI extends React.Component { } } componentDidUpdate(prevProps) { - if (this.props.isNewProject) { + if (this.props.isNewProject && prevProps.fetchingProject) { logPageDisplay(null, this.props.isNewProject) } @@ -165,7 +165,7 @@ const logPageDisplay = (eduId, isNewProject, tab) => { } paEvent.pageDisplay({ - pages: tab ? [...pages, editorTabNames[tab]] : pages, + pages: tab || tab === 0 ? [...pages, editorTabNames[tab]] : pages, pageType: "Spiele" }) } @@ -179,8 +179,8 @@ const mapDispatchToProps = (dispatch) => ({ closeSaveModal: () => dispatch(closeSaveProject()), onExtensionButtonClick: () => dispatch(openExtensionLibrary()), onActivateTab: (eduId, isNewProject, tab) => dispatch(onTabActivating(eduId, isNewProject, tab)), - onActivateCostumesTab: (eduId, isNewProject) => dispatch(onTabActivating(eduId, isNewProject, COSTUMES_TAB_INDEX)), - onActivateSoundsTab: (eduId, isNewProject) => dispatch(onTabActivating(eduId, isNewProject, SOUNDS_TAB_INDEX)), + onActivateCostumesTab: () => dispatch(activateTab(COSTUMES_TAB_INDEX)), + onActivateSoundsTab: () => dispatch(activateTab(SOUNDS_TAB_INDEX)), onLayoutModeClick: () => dispatch(toggleLayoutMode()), onSetUnchanged: () => dispatch(setProjectUnchanged()), }) @@ -191,8 +191,8 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => { ...stateProps, ...dispatchProps, onActivateTab: (tab) => dispatchProps.onActivateTab(stateProps.eduId, stateProps.isNewProject, tab), - onActivateCostumesTab: () => dispatchProps.onActivateCostumesTab(stateProps.eduId, stateProps.isNewProject), - onActivateSoundsTab: () => dispatchProps.onActivateSoundsTab(stateProps.eduId, stateProps.isNewProject), + onActivateCostumesTab: () => dispatchProps.onActivateCostumesTab(), + onActivateSoundsTab: () => dispatchProps.onActivateSoundsTab(), } } From eb4e0681efcd0c22bbb134576724f7c794133ef8 Mon Sep 17 00:00:00 2001 From: Camila Date: Mon, 28 Aug 2023 16:59:45 +0200 Subject: [PATCH 19/53] ok --- src/components/menu/menu.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/menu/menu.jsx b/src/components/menu/menu.jsx index 7405c7e13..b7b0c9d04 100644 --- a/src/components/menu/menu.jsx +++ b/src/components/menu/menu.jsx @@ -187,7 +187,7 @@ export const MenuComponent = (props) => { linkTo="https://www.wdrmaus.de/" onClick={() => { // TODO: add click event - console.log("zur Maus-Seite") + console.log("click: zur Maus-Seite") }} > Zur Maus-Seite From ab3a3e5cc8c9c1081a63304a899887e1c3590bad Mon Sep 17 00:00:00 2001 From: Camila Espinoza <56554983+cami-espinozaq@users.noreply.github.com> Date: Mon, 28 Aug 2023 17:02:44 +0200 Subject: [PATCH 20/53] Update develop.yml --- .github/workflows/develop.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index a726ba9cc..52b8a80ad 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -1,4 +1,4 @@ -name: staging deployment +name: staging deployment v1 on: push: From bf8f2280760d1d05ce32a5e01b2b8af30e20fbfb Mon Sep 17 00:00:00 2001 From: Camila Date: Tue, 19 Sep 2023 13:46:44 +0200 Subject: [PATCH 21/53] added click action and exit events --- src/components/gui/gui.jsx | 21 +++- src/components/menu/menu.jsx | 9 +- src/components/stage-header/stage-header.jsx | 3 +- .../welcome-screen/welcome-screen.jsx | 97 +++++++++++-------- src/containers/controls.jsx | 18 ++++ src/containers/gui.jsx | 16 +-- src/lib/piano-analytics/constants.js | 2 +- src/lib/piano-analytics/main.js | 58 ++++++++--- 8 files changed, 147 insertions(+), 77 deletions(-) diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx index e8ac7ae6d..2b99ae6e1 100644 --- a/src/components/gui/gui.jsx +++ b/src/components/gui/gui.jsx @@ -34,6 +34,7 @@ import costumesIcon from './icon--costumes.svg' import expandIcon from './expand_right@2x.svg' import styles from './gui.css' +import { buildGuiPage, paEvent } from '../../lib/piano-analytics/main.js' // Cache this value to only retreive it once the first time. // Assume that it doesn't change for a session. @@ -67,6 +68,7 @@ const GUIComponent = (props) => { closeSaveModal, saveProjectError, isSaving, + isNewProject, projectName, eduLayerActive, eduId, @@ -102,6 +104,17 @@ const GUIComponent = (props) => { isRendererSupported = Renderer.isSupported() } + const logClickEvent = (eventFn, eventName) => { + paEvent.clickAction({ + pages: buildGuiPage(props.eduId, props.isNewProject, props.activeTabIndex), + pageType: 'Spiele', + chapter1: 'Speichern', + chapter2: eventName, + target: eventName + }) + eventFn() + } + return (
{loading ? : null} @@ -125,7 +138,7 @@ const GUIComponent = (props) => {

{saveProjectError}

@@ -162,7 +175,7 @@ const GUIComponent = (props) => {
- +
diff --git a/src/components/menu/menu.jsx b/src/components/menu/menu.jsx index b7b0c9d04..8f19e1991 100644 --- a/src/components/menu/menu.jsx +++ b/src/components/menu/menu.jsx @@ -186,8 +186,13 @@ export const MenuComponent = (props) => { external linkTo="https://www.wdrmaus.de/" onClick={() => { - // TODO: add click event - console.log("click: zur Maus-Seite") + paEvent.clickExit({ + pages: ['Menu', menuTabTitles[props.selectedTab]], + pageType: 'Hauptseite', + chapter1: 'Exit', + chapter2: 'Zur Maus-Seite', + target: "https://www.wdrmaus.de/" + }) }} > Zur Maus-Seite diff --git a/src/components/stage-header/stage-header.jsx b/src/components/stage-header/stage-header.jsx index 7770a157a..d2c34e541 100644 --- a/src/components/stage-header/stage-header.jsx +++ b/src/components/stage-header/stage-header.jsx @@ -14,7 +14,7 @@ import menuIcon from '!raw-loader!../../../assets/icons/header_menu.svg' import mailIcon from '!raw-loader!../../../assets/icons/menu_impressum.svg' const StageHeaderComponent = function (props) { - const { isFullScreen, onSaveProject, vm } = props + const { isFullScreen, onSaveProject, vm, logPageInfo } = props return (
{isFullScreen ? ( diff --git a/src/components/welcome-screen/welcome-screen.jsx b/src/components/welcome-screen/welcome-screen.jsx index 17d6830e2..b28850a16 100644 --- a/src/components/welcome-screen/welcome-screen.jsx +++ b/src/components/welcome-screen/welcome-screen.jsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect } from 'react' import { Link } from 'redux-little-router' import Button from '../button/button.jsx' @@ -8,58 +8,69 @@ import { eduUrl } from '../../lib/routing' import helloWorldImage from '../../lib/edu/shared_assets/L00.jpg' import mausImage from '../../../assets/img/maus1.png' import styles from './welcome-screen.css' +import { paEvent } from '../../lib/piano-analytics/main.js' -const WelcomeScreenComponent = () => ( -
- WDR +const WelcomeScreenComponent = () => { -
-
- + useEffect(() => { + paEvent.pageDisplay({ + pages: ['Willkommensseite'], + pageType: 'Onboarding' + }) + }, []) -

- Willkommen zu Programmieren mit der Maus! -

-

- Hier lernst du Schritt für Schritt Bildergeschichten und Spiele mit - der Maus zu programmieren. Viel Spaß! -

+ return ( +
+ WDR - -
- Spielst du zum ersten Mal? -
- Fang am besten mit unserem ersten Lernspiel an. +
+
+ + +

+ Willkommen zu Programmieren mit der Maus! +

+

+ Hier lernst du Schritt für Schritt Bildergeschichten und Spiele mit + der Maus zu programmieren. Viel Spaß! +

+ + +
+ Spielst du zum ersten Mal? +
+ Fang am besten mit unserem ersten Lernspiel an. +
+
- -
- - + + - -
- Kennst du dich schon aus? -
- Gehe direkt zur Übersicht und klicke dein nächstes Lernspiel an. - Gespeicherte Spiele findest du unter „Meine Sachen“. + +
+ Kennst du dich schon aus? +
+ Gehe direkt zur Übersicht und klicke dein nächstes Lernspiel an. + Gespeicherte Spiele findest du unter „Meine Sachen“. +
+
- -
- - + + +
-
-) + ) +} export default WelcomeScreenComponent diff --git a/src/containers/controls.jsx b/src/containers/controls.jsx index cfbdcd92c..6f265b2f4 100644 --- a/src/containers/controls.jsx +++ b/src/containers/controls.jsx @@ -4,6 +4,7 @@ import React from 'react' import VM from 'scratch-vm' import ControlsComponent from '../components/controls/controls.jsx' +import { paEvent } from '../lib/piano-analytics/main.js' class Controls extends React.Component { constructor(props) { @@ -41,14 +42,31 @@ class Controls extends React.Component { } else { this.props.vm.greenFlag() } + + paEvent.clickAction({ + pages: this.props.logPageInfo, + pageType: 'Spiele', + chapter1: 'Code', + chapter2: 'Los', + target: 'Code ausführen' + }) } handleStopAllClick(e) { e.preventDefault() this.props.vm.stopAll() + + paEvent.clickAction({ + pages: this.props.logPageInfo, + pageType: 'Spiele', + chapter1: 'Code', + chapter2: 'Stopp', + target: 'Code stoppen' + }) } render() { const { vm, // eslint-disable-line no-unused-vars + logPageInfo, ...props } = this.props return ( diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx index c9ff96dc3..e7cb730da 100644 --- a/src/containers/gui.jsx +++ b/src/containers/gui.jsx @@ -23,7 +23,7 @@ import { StageSizeProviderHOC } from '../lib/stage-size-provider.jsx' import GUIComponent from '../components/gui/gui.jsx' import { toggleLayoutMode } from '../reducers/layout-mode' import { setProjectUnchanged } from '../reducers/project-changed' -import { paEvent } from '../lib/piano-analytics/main' +import { buildGuiPage, paEvent } from '../lib/piano-analytics/main' import { menuTabTitles } from '../lib/piano-analytics/constants' class GUI extends React.Component { @@ -155,19 +155,9 @@ const mapStateToProps = (state) => ({ }) const logPageDisplay = (eduId, isNewProject, tab) => { - let pages = [] - if (isNewProject) { - pages = [menuTabTitles[1], 'New Project'] - } else if (eduId && eduId.match(/beispiel(0|0\d{1})?$/gm)) { - pages = [menuTabTitles[2], `Beispiel ${eduId}`] - } else if (eduId) { - pages = [menuTabTitles[0], `Lernspiel ${eduId}`] - } + const pages = buildGuiPage(eduId, isNewProject, tab) - paEvent.pageDisplay({ - pages: tab || tab === 0 ? [...pages, editorTabNames[tab]] : pages, - pageType: "Spiele" - }) + paEvent.pageDisplay({ pages: pages, pageType: "Spiele" }) } const onTabActivating = (eduId, isNewProject, tab) => { diff --git a/src/lib/piano-analytics/constants.js b/src/lib/piano-analytics/constants.js index 96f81285e..03dd1e459 100644 --- a/src/lib/piano-analytics/constants.js +++ b/src/lib/piano-analytics/constants.js @@ -14,7 +14,7 @@ export const PROPERTIES = { pageLevel1: 'page_chapter1', pageLevel2: 'page_chapter2', pageLevel3: 'page_chapter3', - siteType: 'page_type', + siteType: 'content_type', publicationTimeAt: 'publication_time', // date reactionUpdatedAt: 'last_editorial_update', // date daysSincePublication: 'days_since_publication', // integer diff --git a/src/lib/piano-analytics/main.js b/src/lib/piano-analytics/main.js index bc01bdc32..9705da785 100644 --- a/src/lib/piano-analytics/main.js +++ b/src/lib/piano-analytics/main.js @@ -1,5 +1,11 @@ import { pianoAnalytics } from 'piano-analytics-js' -import { EVENTS, PROPERTIES, DEFAULT_PROPERTY_VALUES } from './constants' +import { + EVENTS, + PROPERTIES, + DEFAULT_PROPERTY_VALUES, + menuTabTitles, +} from './constants' +import { editorTabNames } from '../../reducers/editor-tab' pianoAnalytics.setConfigurations({ site: 621455, @@ -61,17 +67,6 @@ const getCustomProperties = (data) => { } } -const clickEventEntries = () => { - const { pageDisplay, ...otherEvents } = EVENTS - - return Object.entries(otherEvents).map(([eventName, eventKey]) => [ - eventName, - (data) => sendEvent(eventKey, data), - ]) -} - -const clickEvents = Object.fromEntries(clickEventEntries()) - export const paEvent = { pageDisplay: ({ pages, pageType }) => { let data = {} @@ -88,5 +83,42 @@ export const paEvent = { if (pageType) data[PROPERTIES.siteType] = pageType return sendEvent(EVENTS.pageDisplay, data) }, - ...clickEvents, + clickAction: (params) => clickEvent(EVENTS.clickAction, params), + clickExit: (params) => clickEvent(EVENTS.clickExit, params), +} + +export const buildGuiPage = (eduId, isNewProject, activeTab) => { + let pages = [] + if (isNewProject) { + pages = [menuTabTitles[1], 'New Project'] + } else if (eduId && eduId.match(/beispiel(0|0\d{1})?$/gm)) { + pages = [menuTabTitles[2], `Beispiel ${eduId}`] + } else if (eduId) { + pages = [menuTabTitles[0], `Lernspiel ${eduId}`] + } + return [...pages, editorTabNames[activeTab || 0]] +} + +const clickEvent = ( + eventName, + { pages, pageType, chapter1, chapter2, target } +) => { + let data = {} + + const pagesList = [...pages].slice(0, 3) + pagesList.forEach((page, index) => { + data[PROPERTIES[`pageLevel${index + 1}`]] = page + }) + data[PROPERTIES.siteType] = pageType + + const clickProperties = { + [PROPERTIES.clickChapter1]: chapter1, + [PROPERTIES.clickChapter2]: chapter2, + [PROPERTIES.clickTarget]: target, + } + + return sendEvent(eventName, { + ...data, + ...clickProperties, + }) } From 1fac7e8b1ffb2090c128ce556e309b6563154fcf Mon Sep 17 00:00:00 2001 From: Camila Date: Fri, 6 Oct 2023 17:56:05 +0200 Subject: [PATCH 22/53] changes from feedback --- src/components/edu-stage/edu-stage.jsx | 22 +++++++++++++++------- src/lib/piano-analytics/constants.js | 1 + src/lib/piano-analytics/main.js | 3 +-- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/components/edu-stage/edu-stage.jsx b/src/components/edu-stage/edu-stage.jsx index 15fb512f3..533b36c33 100644 --- a/src/components/edu-stage/edu-stage.jsx +++ b/src/components/edu-stage/edu-stage.jsx @@ -60,7 +60,7 @@ const EduStageComponent = (props) => {