Skip to content

Commit

Permalink
Merge pull request #42931 from code-dot-org/dtp_candidate_130daa5a
Browse files Browse the repository at this point in the history
DTP (Test > Production: 130daa5)
  • Loading branch information
sureshc committed Oct 11, 2021
2 parents d5b1ba2 + 8b124e5 commit 8b933d7
Show file tree
Hide file tree
Showing 130 changed files with 2,637 additions and 1,016 deletions.
1 change: 1 addition & 0 deletions apps/i18n/common/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -1486,6 +1486,7 @@
"projectTypeMinecraftHero": "Minecraft Hero",
"projectTypePlaylab": "Play Lab",
"projectTypePlaylabPreReader": "Play Lab (Pre-reader)",
"projectTypePoetry": "Poetry",
"projectTypeStarwars": "Star Wars",
"projectTypeStarwarsBlocks": "Star Wars (Blocks)",
"projectTypeSpecialTopic": "Featured Topics",
Expand Down
139 changes: 6 additions & 133 deletions apps/src/StudioApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,9 @@ import AbuseError from './code-studio/components/AbuseError';
import Alert from './templates/alert';
import AuthoredHints from './authoredHints';
import ChallengeDialog from './templates/ChallengeDialog';
import DialogButtons from './templates/DialogButtons';
import DialogInstructions from './templates/instructions/DialogInstructions';
import DropletTooltipManager from './blockTooltips/DropletTooltipManager';
import FeedbackUtils from './feedback';
import InstructionsDialog from '@cdo/apps/templates/instructions/InstructionsDialog';
import InstructionsDialogWrapperDEPRECATED from './templates/instructions/InstructionsDialogWrapperDEPRECATED';
import SmallFooter from './code-studio/components/SmallFooter';
import Sounds from './Sounds';
import VersionHistory from './templates/VersionHistory';
Expand All @@ -54,12 +51,10 @@ import {
configCircuitPlayground,
configMicrobit
} from './lib/kits/maker/dropletConfig';
import {closeDialog as closeInstructionsDialog} from './redux/instructionsDialog';
import {getStore} from './redux';
import {getValidatedResult, initializeContainedLevel} from './containedLevels';
import {lockContainedLevelAnswers} from './code-studio/levels/codeStudioLevels';
import {parseElement as parseXmlElement} from './xml';
import {resetAniGif} from '@cdo/apps/utils';
import {setIsRunning, setIsEditWhileRun, setStepSpeed} from './redux/runState';
import {isEditWhileRun} from './lib/tools/jsdebugger/redux';
import {setPageConstants} from './redux/pageConstants';
Expand Down Expand Up @@ -320,27 +315,14 @@ StudioApp.prototype.init = function(config) {
this.configureDom(config);

if (!config.level.iframeEmbedAppAndCode) {
// We are migrating usages of InstructionsDialogWrapperDEPRECATED to use
// InstructionsDialog instead. NetSim is the first consumer to be migrated.
const useNewDialog = config.app === 'netsim';
ReactDOM.render(
<Provider store={getStore()}>
{useNewDialog ? (
<InstructionsDialog
title={msg.puzzleTitle({
stage_total: config.level.lesson_total,
puzzle_number: config.level.puzzle_number
})}
/>
) : (
<div>
<InstructionsDialogWrapperDEPRECATED
showInstructionsDialog={autoClose => {
this.showInstructionsDialog_(config.level, autoClose);
}}
/>
</div>
)}
<InstructionsDialog
title={msg.puzzleTitle({
stage_total: config.level.lesson_total,
puzzle_number: config.level.puzzle_number
})}
/>
</Provider>,
document.body.appendChild(document.createElement('div'))
);
Expand Down Expand Up @@ -1311,115 +1293,6 @@ StudioApp.prototype.onReportComplete = function(response) {
}
};

/**
* Show our instructions dialog. This should never be called directly, and will
* instead be called when the state of our redux store changes.
* @param {object} level
* @param {boolean} autoClose - closes instructions after 32s if true
*/
StudioApp.prototype.showInstructionsDialog_ = function(level, autoClose) {
const reduxState = getStore().getState();
const isMarkdownMode =
!!reduxState.instructions.longInstructions &&
!reduxState.instructionsDialog.imgOnly;

var headerElement;
if (isMarkdownMode) {
headerElement = document.createElement('h1');
headerElement.className = 'markdown-level-header-text dialog-title';
headerElement.innerHTML = msg.puzzleTitle({
stage_total: level.lesson_total,
puzzle_number: level.puzzle_number
});
if (!this.icon) {
headerElement.className += ' no-modal-icon';
}
}

// Create a div to eventually hold this content, and add it to the
// overall container. We don't want to render directly into the
// container just yet, because our React component could contain some
// elements that don't want to be rendered until they are in the DOM
var instructionsReactContainer = document.createElement('div');
instructionsReactContainer.className = 'instructions-content';
var instructionsDiv = document.createElement('div');
instructionsDiv.className = isMarkdownMode
? 'markdown-instructions-container'
: 'instructions-container';
instructionsDiv.appendChild(instructionsReactContainer);

var buttons = document.createElement('div');
instructionsDiv.appendChild(buttons);
ReactDOM.render(<DialogButtons ok={true} />, buttons);

// If there is an instructions block on the screen, we want the instructions dialog to
// shrink down to that instructions block when it's dismissed.
// We then want to flash the instructions block.
var hideOptions = null;
var endTargetSelector = '#bubble';

if ($(endTargetSelector).length) {
hideOptions = {};
hideOptions.endTarget = endTargetSelector;
}

var hideFn = _.bind(function() {
// Set focus to ace editor when instructions close:
if (this.editCode && this.currentlyUsingBlocks()) {
this.editor.aceEditor.focus();
}

// update redux
getStore().dispatch(closeInstructionsDialog());
}, this);

this.instructionsDialog = this.createModalDialog({
markdownMode: isMarkdownMode,
contentDiv: instructionsDiv,
icon: this.icon,
defaultBtnSelector: '#ok-button',
onHidden: hideFn,
scrollContent: true,
scrollableSelector: '.instructions-content',
header: headerElement
});

// Now that our elements are guaranteed to be in the DOM, we can
// render in our react components
$(this.instructionsDialog.div).on('show.bs.modal', () => {
ReactDOM.render(
<Provider store={getStore()}>
<DialogInstructions />
</Provider>,
instructionsReactContainer
);
resetAniGif(this.instructionsDialog.div.find('img.aniGif').get(0));
});

if (autoClose) {
setTimeout(
_.bind(function() {
this.instructionsDialog.hide();
}, this),
32000
);
}

var okayButton = buttons.querySelector('#ok-button');
if (okayButton) {
dom.addClickTouchEvent(
okayButton,
_.bind(function() {
if (this.instructionsDialog) {
this.instructionsDialog.hide();
}
}, this)
);
}

this.instructionsDialog.show({hideOptions: hideOptions});
};

/**
* Resizes the blockly workspace.
*/
Expand Down
7 changes: 4 additions & 3 deletions apps/src/code-studio/assets/SpriteUpload.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,16 @@ export default class SpriteUpload extends React.Component {
};

generateMetadata = () => {
const {filename, aliases} = this.state;
const {filename, aliases, category} = this.state;
let image = this.refs.spritePreview;
let metadata = {
name: filename,
name: filename.split('.')[0],
aliases: aliases,
frameCount: 1,
frameSize: {x: image.clientWidth, y: image.clientHeight},
looping: true,
frameDelay: 2
frameDelay: 2,
categories: [category]
};
this.setState({metadata: JSON.stringify(metadata)});
};
Expand Down
6 changes: 6 additions & 0 deletions apps/src/code-studio/initApp/loadApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,12 @@ const sourceHandler = {
getSelectedSong() {
return getAppOptions().level.selectedSong;
},
setSelectedPoem(poem) {
getAppOptions().level.selectedPoem = poem;
},
getSelectedPoem() {
return getAppOptions().level.selectedPoem;
},
setInitialLevelHtml(levelHtml) {
getAppOptions().level.levelHtml = levelHtml;
},
Expand Down
20 changes: 18 additions & 2 deletions apps/src/code-studio/initApp/project.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ var currentSources = {
html: null,
makerAPIsEnabled: null,
animations: null,
selectedSong: null
selectedSong: null,
selectedPoem: null
};

/**
Expand All @@ -134,6 +135,7 @@ function unpackSources(data) {
makerAPIsEnabled: data.makerAPIsEnabled,
generatedProperties: data.generatedProperties,
selectedSong: data.selectedSong,
selectedPoem: data.selectedPoem,
libraries: data.libraries
};
}
Expand Down Expand Up @@ -677,6 +679,7 @@ var projects = (module.exports = {
* @param {function(boolean)} sourceHandler.setMakerAPIsEnabled
* @param {function(): boolean} sourceHandler.getMakerAPIsEnabled
* @param {function(): boolean} sourceHandler.setSelectedSong
* @param {function(): boolean} sourceHandler.setSelectedPoem
*/
init(sourceHandler) {
this.sourceHandler = sourceHandler;
Expand All @@ -699,6 +702,10 @@ var projects = (module.exports = {
sourceHandler.setSelectedSong(currentSources.selectedSong);
}

if (currentSources.selectedPoem) {
sourceHandler.setSelectedPoem(currentSources.selectedPoem);
}

if (currentSources.animations) {
sourceHandler.setInitialAnimationList(currentSources.animations);
}
Expand Down Expand Up @@ -906,6 +913,8 @@ var projects = (module.exports = {
return 'basketball';
}
return 'bounce';
case 'poetry':
return appOptions.level.standaloneAppName;
default:
return null;
}
Expand Down Expand Up @@ -962,7 +971,7 @@ var projects = (module.exports = {
},
/**
* Saves the project only if the sources {source, html, animations,
* makerAPIsEnabled, selectedSong} have changed.
* makerAPIsEnabled, selectedSong, selectedPoem} have changed.
* @returns {Promise} A promise containing the project data if the project
* was saved, otherwise returns a promise which resolves with no arguments.
*/
Expand Down Expand Up @@ -1180,6 +1189,11 @@ var projects = (module.exports = {
return this.save();
},

saveSelectedPoem(poem) {
this.sourceHandler.setSelectedPoem(poem);
return this.save();
},

/**
* Saves the project to the Channels API. Calls `callback` on success if a
* callback function was provided.
Expand Down Expand Up @@ -1254,6 +1268,7 @@ var projects = (module.exports = {
const html = this.sourceHandler.getLevelHtml();
const makerAPIsEnabled = this.sourceHandler.getMakerAPIsEnabled();
const selectedSong = this.sourceHandler.getSelectedSong();
const selectedPoem = this.sourceHandler.getSelectedPoem();
const generatedProperties = this.sourceHandler.getGeneratedProperties();
const libraries = this.sourceHandler.getLibrariesList();
callback({
Expand All @@ -1262,6 +1277,7 @@ var projects = (module.exports = {
animations,
makerAPIsEnabled,
selectedSong,
selectedPoem,
generatedProperties,
libraries
});
Expand Down
13 changes: 0 additions & 13 deletions apps/src/javalab/PlaygroundImage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,9 @@ export default class PlaygroundImage extends React.Component {
dynamicStyles.height = heightAdjusted;
dynamicStyles.marginTop = yAdjusted;
dynamicStyles.marginLeft = xAdjusted;
dynamicStyles.clipPath = `inset(0 ${this.getClipPath(
widthAdjusted,
xAdjusted
)} ${this.getClipPath(heightAdjusted, yAdjusted)} 0)`;
return dynamicStyles;
}

// If the image would go outside of the 800x800 box we put playground
// into, cut it off at the appropriate dimension. This will crop any images
// that go outside of the box, which is our expected behavior.
getClipPath(dimension, coordinate) {
return dimension + coordinate > 800
? `${dimension + coordinate - 800}px`
: 0;
}

render() {
const {fileUrl, id, onClick, isClickable} = this.props;
let dynamicStyles = this.getDynamicStyles();
Expand Down
5 changes: 3 additions & 2 deletions apps/src/javalab/PlaygroundText.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ export default class PlaygroundText extends React.Component {
left: x * 2,
top: y * 2,
zIndex: index,
height: height * 2,
color: `rgb(${parseInt(colorRed)}, ${parseInt(colorGreen)}, ${parseInt(
colorBlue
)})`,
Expand Down Expand Up @@ -85,6 +84,8 @@ const styles = {
position: 'absolute',
display: 'flex',
alignItems: 'center',
transformOrigin: 'top left'
transformOrigin: 'top left',
whiteSpace: 'nowrap',
lineHeight: 1
}
};
8 changes: 1 addition & 7 deletions apps/src/netsim/netsim.js
Original file line number Diff line number Diff line change
Expand Up @@ -1404,11 +1404,5 @@ NetSim.prototype.resetShard = function() {
* Show the instrutions modal dialog on top of the NetSim interface.
*/
NetSim.prototype.showInstructionsDialog = function() {
getStore().dispatch(
openInstructionsDialog({
autoClose: false,
imgOnly: false,
hintsOnly: false
})
);
getStore().dispatch(openInstructionsDialog({imgOnly: false}));
};
10 changes: 7 additions & 3 deletions apps/src/p5lab/P5LabVisualizationHeader.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ class P5LabVisualizationHeader extends React.Component {
allowAnimationMode: PropTypes.bool.isRequired,
onInterfaceModeChange: PropTypes.func.isRequired,
isBlockly: PropTypes.bool.isRequired,
numAllowedModes: PropTypes.number.isRequired
numAllowedModes: PropTypes.number.isRequired,
isShareView: PropTypes.bool.isRequired
};

changeInterfaceMode = mode => {
Expand Down Expand Up @@ -59,7 +60,9 @@ class P5LabVisualizationHeader extends React.Component {
const {interfaceMode, allowAnimationMode} = this.props;
return (
<div>
{this.props.labType === P5LabType.POETRY && <PoemSelector />}
{!this.props.isShareView && this.props.labType === P5LabType.POETRY && (
<PoemSelector />
)}
{this.props.numAllowedModes > 1 && (
<div style={styles.main} id="playSpaceHeader">
<ToggleGroup
Expand Down Expand Up @@ -110,7 +113,8 @@ export default connect(
interfaceMode: state.interfaceMode,
allowAnimationMode: allowAnimationMode(state),
isBlockly: state.pageConstants.isBlockly,
numAllowedModes: countAllowedModes(state)
numAllowedModes: countAllowedModes(state),
isShareView: state.pageConstants.isShareView
}),
dispatch => ({
onInterfaceModeChange: mode => dispatch(changeInterfaceMode(mode))
Expand Down

0 comments on commit 8b933d7

Please sign in to comment.