diff --git a/.github/workflows/develop.yml b/.github/workflows/develop.yml index 52b8a80ad..2c1fcb8d4 100644 --- a/.github/workflows/develop.yml +++ b/.github/workflows/develop.yml @@ -4,7 +4,7 @@ on: push: branches: - develop - + jobs: build: runs-on: ubuntu-latest @@ -18,25 +18,22 @@ jobs: AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} steps: - - 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 BRANCH=develop yarn deploy - - - + - 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 BRANCH=develop yarn deploy diff --git a/netlify.toml b/netlify.toml index 26683849d..0317fd9e6 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,4 +1,8 @@ [build] - Command = "NODE_ENV=production yarn build:netlify" + Command = "NODE_ENV=staging yarn build:netlify" Functions = "lambda" Publish = "build" +[[headers]] + for = "/*" + [headers.values] + Access-Control-Allow-Origin = "https://logs1414.xiti.com" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..88294b13f --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +awscli diff --git a/serverless.yml b/serverless.yml index 506a8e28c..19ffceaee 100644 --- a/serverless.yml +++ b/serverless.yml @@ -2,7 +2,7 @@ service: hackingstudio-code4maus provider: name: aws - runtime: nodejs12.x + runtime: nodejs18.x region: eu-central-1 role: 'arn:aws:iam::#{AWS::AccountId}:role/hackingstudio/code4maus/hackingstudio-code4maus-functions' stage: ${file(scripts/env.js):stage} diff --git a/src/components/edu-stage/edu-stage.jsx b/src/components/edu-stage/edu-stage.jsx index 15fb512f3..40a599705 100644 --- a/src/components/edu-stage/edu-stage.jsx +++ b/src/components/edu-stage/edu-stage.jsx @@ -60,7 +60,7 @@ const EduStageComponent = (props) => { @@ -162,7 +175,7 @@ const GUIComponent = (props) => { - - - - + + - -
- 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 3e1af2063..9b23bcb13 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) { @@ -45,6 +46,14 @@ 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() @@ -53,10 +62,19 @@ class Controls extends React.Component { this.props.onStopAllClick() } 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 b5d68df4b..e7cb730da 100644 --- a/src/containers/gui.jsx +++ b/src/containers/gui.jsx @@ -23,7 +23,8 @@ 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 { guiTypePages, 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 { constructor(props) { @@ -47,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) } @@ -154,17 +155,9 @@ const mapStateToProps = (state) => ({ }) const logPageDisplay = (eduId, isNewProject, tab) => { - let pages = [] - if (isNewProject) { - pages = guiTypePages(null) - } else if (eduId) { - pages = guiTypePages(eduId) - } + const pages = buildGuiPage(eduId, isNewProject, tab) - paEvent.pageDisplay({ - pages: tab ? [...pages, editorTabNames[tab]] : pages, - pageType: "Spiele" - }) + paEvent.pageDisplay({ pages: pages, pageType: "Spiele" }) } const onTabActivating = (eduId, isNewProject, tab) => { @@ -176,8 +169,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()), }) @@ -188,8 +181,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(), } } diff --git a/src/lib/piano-analytics/constants.js b/src/lib/piano-analytics/constants.js index 96f81285e..ec5290836 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 @@ -28,6 +28,7 @@ export const DEFAULT_PROPERTY_VALUES = { [PROPERTIES.siteLevel2]: 'Programmieren mit der Maus', [PROPERTIES.brand]: 'Die Maus', [PROPERTIES.redaction]: 'PG Kinder und Familie', + [PROPERTIES.platform]: 'Web', } export const menuTabTitles = { diff --git a/src/lib/piano-analytics/main.js b/src/lib/piano-analytics/main.js index bbae26bc6..cbdb51de2 100644 --- a/src/lib/piano-analytics/main.js +++ b/src/lib/piano-analytics/main.js @@ -5,6 +5,7 @@ import { DEFAULT_PROPERTY_VALUES, menuTabTitles, } from './constants' +import { editorTabNames } from '../../reducers/editor-tab' pianoAnalytics.setConfigurations({ site: 621455, @@ -69,36 +70,66 @@ 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 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 - }) - } +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 data + if (pageType) data[PROPERTIES.siteType] = pageType + return sendEvent(EVENTS.pageDisplay, data) + }, + clickAction: (params) => clickEvent(EVENTS.clickAction, params), + clickExit: (params) => clickEvent(EVENTS.clickExit, params), } -const clickEventEntries = () => { - return Object.entries(EVENTS).map(([eventName, eventKey]) => [ - eventName, - (data) => sendEvent(eventKey, pageValuesToData(data)), - ]) +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]] } -export const paEvent = Object.fromEntries(clickEventEntries()) +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, + [PROPERTIES.clickLabel]: chapter2, + } + + return sendEvent(eventName, { + ...data, + ...clickProperties, + }) +}