Skip to content
Snippets Groups Projects
Commit c973bf0e authored by Paul Kaplan's avatar Paul Kaplan
Browse files

Make the blocks workspace a drop area for BACKPACK_CODE drag types

parent c5e765ae
No related branches found
No related tags found
No related merge requests found
......@@ -10,10 +10,10 @@ import styles from './backpack.css';
// TODO make sprite selector item not require onClick
const noop = () => {};
const dragTypeMap = {
const dragTypeMap = { // Keys correspond with the backpack-server item types
costume: DragConstants.BACKPACK_COSTUME,
sound: DragConstants.BACKPACK_SOUND,
code: DragConstants.BACKPACK_CODE,
script: DragConstants.BACKPACK_CODE,
sprite: DragConstants.BACKPACK_SPRITE
};
......
@import "../../css/units.css";
@import "../../css/colors.css";
.blocks {
height: 100%;
}
.drag-over:after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.75;
background-color: #8cbcff;
transition: all 0.25s ease;
}
.blocks :global(.injectionDiv){
position: absolute;
top: 0;
......
import PropTypes from 'prop-types';
import classNames from 'classnames';
import React from 'react';
import Box from '../box/box.jsx';
import styles from './blocks.css';
const BlocksComponent = props => {
const {
componentRef,
containerRef,
dragOver,
...componentProps
} = props;
return (
<Box
className={styles.blocks}
componentRef={componentRef}
className={classNames(styles.blocks, {
[styles.dragOver]: dragOver
})}
{...componentProps}
componentRef={containerRef}
/>
);
};
BlocksComponent.propTypes = {
componentRef: PropTypes.func
containerRef: PropTypes.func,
dragOver: PropTypes.bool
};
export default BlocksComponent;
......@@ -16,6 +16,8 @@ import extensionData from '../lib/libraries/extensions/index.jsx';
import CustomProcedures from './custom-procedures.jsx';
import errorBoundaryHOC from '../lib/error-boundary-hoc.jsx';
import {STAGE_DISPLAY_SIZES} from '../lib/layout-constants';
import DropAreaHOC from '../lib/drop-area-hoc.jsx';
import DragConstants from '../lib/drag-constants';
import {connect} from 'react-redux';
import {updateToolbox} from '../reducers/toolbox';
......@@ -38,6 +40,10 @@ const addFunctionListener = (object, property, callback) => {
};
};
const DroppableBlocks = DropAreaHOC([
DragConstants.BACKPACK_CODE
])(BlocksComponent);
class Blocks extends React.Component {
constructor (props) {
super(props);
......@@ -47,6 +53,7 @@ class Blocks extends React.Component {
'detachVM',
'handleCategorySelected',
'handleConnectionModalStart',
'handleDrop',
'handleStatusButtonUpdate',
'handleOpenSoundRecorder',
'handlePromptStart',
......@@ -404,6 +411,14 @@ class Blocks extends React.Component {
ws.refreshToolboxSelection_();
ws.toolbox_.scrollToCategoryById('myBlocks');
}
handleDrop (dragInfo) {
fetch(dragInfo.payload.bodyUrl)
.then(response => response.json())
.then(blocks => {
this.props.vm.shareBlocksToTarget(blocks, this.props.vm.editingTarget.id);
this.props.vm.refreshWorkspace();
});
}
render () {
/* eslint-disable no-unused-vars */
const {
......@@ -427,9 +442,10 @@ class Blocks extends React.Component {
} = this.props;
/* eslint-enable no-unused-vars */
return (
<div>
<BlocksComponent
<React.Fragment>
<DroppableBlocks
componentRef={this.setBlocks}
onDrop={this.handleDrop}
{...props}
/>
{this.state.prompt ? (
......@@ -458,7 +474,7 @@ class Blocks extends React.Component {
onRequestClose={this.handleCustomProceduresClose}
/>
) : null}
</div>
</React.Fragment>
);
}
}
......
......@@ -2,6 +2,7 @@ export default {
SOUND: 'SOUND',
COSTUME: 'COSTUME',
SPRITE: 'SPRITE',
CODE: 'CODE',
BACKPACK_SOUND: 'BACKPACK_SOUND',
BACKPACK_COSTUME: 'BACKPACK_COSTUME',
......
......@@ -4,7 +4,34 @@ import React from 'react';
import omit from 'lodash.omit';
import {connect} from 'react-redux';
/**
* Higher Order Component to give components the ability to react to drag overs
* and drops of objects stored in the assetDrag redux state.
*
* Example: You want to enable MyComponent to receive drops from a drag type
* Wrapped = DropAreaHOC([...dragTypes])(
* <MyComponent />
* )
*
* MyComponent now receives 2 new props
* containerRef: a ref that must be set on the container element
* dragOver: boolean if an asset is being dragged above the component
*
* Use the wrapped component:
* <Wrapped onDrop={yourDropHandler} />
*
* NB: This HOC _only_ works with objects that drag using the assetDrag reducer.
* This _does not_ handle drags for blocks coming from the workspace.
*
* @param {Array.<string>} dragTypes Types to respond to, from DragConstants
* @returns {function} The HOC, specialized for those drag types
*/
const DropAreaHOC = function (dragTypes) {
/**
* Return the HOC, specialized for the dragTypes
* @param {React.Component} WrappedComponent component to receive drop behaviors
* @returns {React.Component} component with drag over/drop behavior
*/
return function (WrappedComponent) {
class DropAreaWrapper extends React.Component {
constructor (props) {
......@@ -46,6 +73,9 @@ const DropAreaHOC = function (dragTypes) {
}
setRef (el) {
this.ref = el;
if (this.props.componentRef) {
this.props.componentRef(this.ref);
}
}
render () {
const componentProps = omit(this.props, ['onDrop', 'dragInfo']);
......@@ -60,6 +90,7 @@ const DropAreaHOC = function (dragTypes) {
}
DropAreaWrapper.propTypes = {
componentRef: PropTypes.func,
dragInfo: PropTypes.shape({
currentOffset: PropTypes.shape({
x: PropTypes.number,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment