diff --git a/frontend/app/components/Session/Player/ReplayPlayer/PlayerBlockHeader.tsx b/frontend/app/components/Session/Player/ReplayPlayer/PlayerBlockHeader.tsx index d9cf2c7db..b063fc72b 100644 --- a/frontend/app/components/Session/Player/ReplayPlayer/PlayerBlockHeader.tsx +++ b/frontend/app/components/Session/Player/ReplayPlayer/PlayerBlockHeader.tsx @@ -1,4 +1,5 @@ +import { useStore } from "App/mstore"; import React from 'react'; import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; @@ -25,7 +26,7 @@ const SESSIONS_ROUTE = sessionsRoute(); function PlayerBlockHeader(props: any) { const [hideBack, setHideBack] = React.useState(false); const { player, store } = React.useContext(PlayerContext); - + const { uxtestingStore } = useStore() const playerState = store?.get?.() || { width: 0, height: 0, showEvents: false } const { width = 0, height = 0, showEvents = false } = playerState @@ -92,7 +93,7 @@ function PlayerBlockHeader(props: any) {
- {live && !hideBack && ( + {live && !hideBack && !uxtestingStore.isUxt() && ( <>
diff --git a/tracker/tracker/package.json b/tracker/tracker/package.json index e5e5d698e..9e29003dd 100644 --- a/tracker/tracker/package.json +++ b/tracker/tracker/package.json @@ -1,7 +1,7 @@ { "name": "@openreplay/tracker", "description": "The OpenReplay tracker main package", - "version": "11.0.1-11", + "version": "11.0.1-19", "keywords": [ "logging", "replay" diff --git a/tracker/tracker/src/main/app/index.ts b/tracker/tracker/src/main/app/index.ts index c8d5e3fb0..7d495efaf 100644 --- a/tracker/tracker/src/main/app/index.ts +++ b/tracker/tracker/src/main/app/index.ts @@ -721,7 +721,9 @@ export default class App { uxtId = qId ? parseInt(qId, 10) : undefined } } - if (uxtId) this.uxtManager.getTest(uxtId, token, Boolean(savedUxtTag)) + if (uxtId && !this.uxtManager.isActive) { + this.uxtManager.getTest(uxtId, token, Boolean(savedUxtTag)) + } return SuccessfulStart(onStartInfo) }) diff --git a/tracker/tracker/src/main/modules/userTesting/index.ts b/tracker/tracker/src/main/modules/userTesting/index.ts index 6ab6ddc0f..c72580ae4 100644 --- a/tracker/tracker/src/main/modules/userTesting/index.ts +++ b/tracker/tracker/src/main/modules/userTesting/index.ts @@ -53,6 +53,7 @@ export default class UserTestManager { private widgetGuidelinesVisible = true private widgetTasksVisible = false private widgetVisible = true + public isActive = false private descriptionSection: HTMLElement | null = null private taskSection: HTMLElement | null = null private endSection: HTMLElement | null = null @@ -159,6 +160,7 @@ export default class UserTestManager { }) .then((res) => res.json()) .then(({ test }: { test: Test }) => { + this.isActive = true this.test = test this.createGreeting(test.title, test.reqMic, test.reqCamera) if (inProgress) { @@ -552,7 +554,7 @@ export default class UserTestManager { fontSize: '1.25rem', fontWeight: '500', }, - this.test?.reqMic || this.test?.reqCamera ? 'Uploading test recording...' : 'Thank you! 👍', + 'Thank you! 👍', ) const description = createElement( 'div', @@ -569,13 +571,27 @@ export default class UserTestManager { styles.buttonWidgetStyle, 'Submitting Feedback', ) + const spinner = createSpinner() + button.appendChild(spinner) if (this.test?.reqMic || this.test?.reqCamera) { - void this.userRecorder.sendToAPI().then(() => { - title.textContent = 'Thank you! 👍' - button.textContent = 'End Session' - isLoading = false - }) + void this.userRecorder + .sendToAPI() + .then(() => { + button.removeChild(spinner) + button.textContent = 'End Session' + isLoading = false + }) + .catch((err) => { + console.error(err) + button.removeChild(spinner) + button.textContent = 'End Session' + isLoading = false + }) + } else { + button.removeChild(spinner) + button.textContent = 'End Session' + isLoading = false } if (this.taskSection) { @@ -646,3 +662,32 @@ function generateChevron() { }) return container } + +const spinnerStyles = { + border: '4px solid rgba(255, 255, 255, 0.4)', + width: '16px', + height: '16px', + borderRadius: '50%', + borderLeftColor: '#fff', + animation: 'spin 0.5s linear infinite', +} + +function addKeyframes() { + const styleSheet = document.createElement('style') + styleSheet.type = 'text/css' + styleSheet.innerText = `@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } + }` + document.head.appendChild(styleSheet) +} + +function createSpinner() { + addKeyframes() + const spinner = document.createElement('div') + spinner.classList.add('spinner') + + Object.assign(spinner.style, spinnerStyles) + + return spinner +}