+
+
+ {file.hasConflictingName && (
+
+ {i18n.backpackFileNameConflictWarning()}
+
+ )}
+
+
onToggleFile(file.name)}
+ style={styles.checkbox}
+ />
+
+ );
+}
+
+CommitDialogFile.propTypes = {
+ file: fileShape.isRequired,
+ onToggleFile: PropTypes.func.isRequired
+};
+
const PADDING = 8;
const styles = {
bold: {
@@ -281,10 +355,19 @@ const styles = {
paddingBottom: PADDING / 2,
borderBottom: `1px solid ${color.lightest_gray}`
},
+ fileLabelContainer: {
+ display: 'flex',
+ flexDirection: 'column'
+ },
fileLabel: {
flexGrow: 2,
color: color.default_text
},
+ fileNameConflictWarning: {
+ color: color.default_text,
+ fontStyle: 'italic',
+ fontSize: 12
+ },
checkbox: {
width: 18,
height: 18
diff --git a/apps/src/javalab/JavabuilderConnection.js b/apps/src/javalab/JavabuilderConnection.js
index 33bc17b6fe71e..7feb9f627fecc 100644
--- a/apps/src/javalab/JavabuilderConnection.js
+++ b/apps/src/javalab/JavabuilderConnection.js
@@ -31,6 +31,16 @@ export default class JavabuilderConnection {
// Get the access token to connect to javabuilder and then open the websocket connection.
// The token prevents access to our javabuilder AWS execution environment by un-verified users.
connectJavabuilder() {
+ // Don't attempt to connect to Javabuilder if we do not have a project identifier.
+ // This typically occurs if a teacher is trying to view a student's project
+ // that has not been modified from the starter code.
+ // This case does not apply to students, who are able to execute unmodified starter code.
+ // See this comment for more detail: https://github.com/code-dot-org/code-dot-org/pull/42313#discussion_r701417221
+ if (project.getCurrentId() === undefined) {
+ this.onOutputMessage(javalabMsg.errorProjectNotEditedYet());
+ return;
+ }
+
$.ajax({
url: '/javabuilder/access_token',
type: 'get',
@@ -44,10 +54,14 @@ export default class JavabuilderConnection {
})
.done(result => this.establishWebsocketConnection(result.token))
.fail(error => {
- this.onOutputMessage(
- 'We hit an error connecting to our server. Try again.'
- );
- console.error(error.responseText);
+ if (error.status === 403) {
+ this.onOutputMessage(
+ javalabMsg.errorJavabuilderConnectionNotAuthorized()
+ );
+ } else {
+ this.onOutputMessage(javalabMsg.errorJavabuilderConnectionGeneral());
+ console.error(error.responseText);
+ }
});
}
diff --git a/apps/src/javalab/Theater.js b/apps/src/javalab/Theater.js
index 9a258149b1f54..9c042f51c3b10 100644
--- a/apps/src/javalab/Theater.js
+++ b/apps/src/javalab/Theater.js
@@ -7,16 +7,22 @@ export default class Theater {
this.context = null;
this.onOutputMessage = onOutputMessage;
this.onNewlineMessage = onNewlineMessage;
+ this.loadEventsFinished = 0;
}
handleSignal(data) {
switch (data.value) {
case TheaterSignalType.AUDIO_URL: {
- this.getAudioElement().src = data.detail.url;
+ // Wait for the audio to load before starting playback
+ this.getAudioElement().src =
+ data.detail.url + this.getCacheBustSuffix();
+ this.getAudioElement().oncanplaythrough = () => this.startPlayback();
break;
}
case TheaterSignalType.VISUAL_URL: {
- this.getImgElement().src = data.detail.url;
+ // Preload the image. Once it's ready, start the playback
+ this.getImgElement().src = data.detail.url + this.getCacheBustSuffix();
+ this.getImgElement().onload = () => this.startPlayback();
break;
}
default:
@@ -24,8 +30,19 @@ export default class Theater {
}
}
+ startPlayback() {
+ this.loadEventsFinished++;
+ // We expect exactly 2 responses from Javabuilder. One for audio and one for video.
+ // Wait for both to respond and load before starting playback.
+ if (this.loadEventsFinished > 1) {
+ this.getImgElement().style.visibility = 'visible';
+ this.getAudioElement().play();
+ }
+ }
+
reset() {
- this.getImgElement().src = '';
+ this.loadEventsFinished = 0;
+ this.getImgElement().style.visibility = 'hidden';
this.getAudioElement().src = '';
}
@@ -44,4 +61,8 @@ export default class Theater {
);
this.onNewlineMessage();
}
+
+ getCacheBustSuffix() {
+ return '?=' + new Date().getTime();
+ }
}
diff --git a/apps/src/javalab/TheaterVisualizationColumn.jsx b/apps/src/javalab/TheaterVisualizationColumn.jsx
index f322d4753512d..8b5038e0002ba 100644
--- a/apps/src/javalab/TheaterVisualizationColumn.jsx
+++ b/apps/src/javalab/TheaterVisualizationColumn.jsx
@@ -41,7 +41,7 @@ class TheaterVisualizationColumn extends React.Component {