mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-23 15:47:53 -05:00
addtostudiomodal: incomplete progress on 1. container-presentation refactor, 2. redux handling of add and leave studio requests
This commit is contained in:
parent
9cac70ab18
commit
6a32edb2fe
5 changed files with 168 additions and 257 deletions
|
@ -42,6 +42,8 @@ const Select = require('../../forms/select.jsx');
|
|||
const Spinner = require('../../spinner/spinner.jsx');
|
||||
const TextArea = require('../../forms/textarea.jsx');
|
||||
const FlexRow = require('../../flex-row/flex-row.jsx');
|
||||
const AddToStudioModalPresentation = require('presentation.jsx');
|
||||
const RequestStatus = require('').intlShape;
|
||||
|
||||
require('../../forms/button.scss');
|
||||
require('./modal.scss');
|
||||
|
@ -61,61 +63,59 @@ class AddToStudioModal extends React.Component {
|
|||
// membership/stats/name. use that for rendering.
|
||||
this.state = {
|
||||
waitingToClose: false,
|
||||
joined: {},
|
||||
updateQueued: {}
|
||||
studioState: {},
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.updateJoined(this.props.projectStudios);
|
||||
this.updateStudioState(this.props.projectStudios, this.props.curatedStudios);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
this.updateJoined(nextProps.projectStudios);
|
||||
this.updateStudioState(nextProps.projectStudios, nextProps.curatedStudios);
|
||||
}
|
||||
|
||||
updateJoined(projectStudios) {
|
||||
// projectStudios could have dropped some studios since the last time
|
||||
// we traveresd it, so we should build the joined state object
|
||||
// from scratch.
|
||||
|
||||
updateStudioState(projectStudios, curatedStudios) {
|
||||
// can't just use the spread operator here, because we may have
|
||||
// project studios removed from the list.
|
||||
let joined = Object.assign({}, this.state.joined);
|
||||
projectStudios.forEach((studio) => {
|
||||
joined[studio.id] = true;
|
||||
});
|
||||
this.setState({joined: Object.assign({}, joined)});
|
||||
}
|
||||
// NOTE: This isn't handling the removal of a studio from the list well.
|
||||
|
||||
requestJoinStudio(studioId) {
|
||||
// submit here? or through presentation?
|
||||
}
|
||||
requestLeaveStudio(studioId) {
|
||||
// submit here? or through presentation?
|
||||
// can't build it from scratch, because needs transitional state
|
||||
let studioState = Object.assign({}, this.state.studioState);
|
||||
|
||||
// remove all states that are not in transition
|
||||
for (let id in studioState) {
|
||||
if (studioState[id] === AddToStudioModalPresentation.State.IN
|
||||
|| studioState[id] === AddToStudioModalPresentation.State.OUT) {
|
||||
delete studioState[id];
|
||||
}
|
||||
}
|
||||
// for all studios with no state, either because they weren't transitional
|
||||
// or they're new, start them with state OUT
|
||||
curatedStudios.forEach((curatedStudio) => {
|
||||
if (!(curatedStudio.id in studioState)) {
|
||||
studioState[curatedStudio.id] = AddToStudioModalPresentation.State.OUT
|
||||
}
|
||||
});
|
||||
// nests which all states to in for studios this project is in
|
||||
projectStudios.forEach((joinedStudio) => {
|
||||
studioState[joinedStudio.id] = AddToStudioModalPresentation.State.IN
|
||||
});
|
||||
// NOTE: do I really need this assign? I took it out
|
||||
this.setState({studioState: studioState});
|
||||
}
|
||||
|
||||
handleToggle(studioId) {
|
||||
const joined = this.state.joined;
|
||||
const updateQueued = this.state.updateQueued;
|
||||
console.log(updateQueued)
|
||||
if (!(studioId in updateQueued)) { // we haven't requested it yet...
|
||||
const updateType = (studioId in joined) ? 'leave' : 'join';
|
||||
console.log("queueing " + updateType + " request for studio: " + studioId);
|
||||
this.setState(prevState => ({
|
||||
updateQueued: {
|
||||
...prevState.updateQueued,
|
||||
[studioId]: {updateType: updateType}
|
||||
}
|
||||
}), () => { // callback
|
||||
// submit request to server
|
||||
|
||||
if (updateType === 'join') {
|
||||
this.requestJoinStudio(studioId);
|
||||
} else {
|
||||
this.requestLeaveStudio(studioId);
|
||||
}
|
||||
});
|
||||
if (studioId in this.state.studioState) {
|
||||
const studioState = this.state.studioState[studioId];
|
||||
// ignore clicks on studio buttons that are still waiting for response
|
||||
if (studioState === AddToStudioModalPresentation.State.IN) {
|
||||
this.props.onToggleStudio(studioId, false)
|
||||
} elseif (studioState === AddToStudioModalPresentation.State.OUT) {
|
||||
this.props.onToggleStudio(studioId, true)
|
||||
}
|
||||
} else {
|
||||
// NOTE: error
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,132 +151,26 @@ class AddToStudioModal extends React.Component {
|
|||
}
|
||||
render () {
|
||||
const {
|
||||
intl,
|
||||
projectStudios,
|
||||
curatedStudios,
|
||||
onAddToStudio, // eslint-disable-line no-unused-vars
|
||||
isOpen,
|
||||
onRequestClose
|
||||
} = this.props;
|
||||
const joined = this.state.joined;
|
||||
const updateQueued = this.state.updateQueued;
|
||||
const contentLabel = intl.formatMessage({id: "addToStudio.title"});
|
||||
const checkmark = <img alt="checkmark-icon"
|
||||
className="studio-status-icon-checkmark-img"
|
||||
src="/svgs/modal/confirm.svg"
|
||||
/>
|
||||
const plus = <img alt="plus-icon"
|
||||
className="studio-status-icon-plus-img"
|
||||
src="/svgs/modal/add.svg"
|
||||
/>
|
||||
const studioButtons = curatedStudios.map((studio, index) => {
|
||||
const isAdded = (studio.id in joined);
|
||||
const isWaiting = (studio.id in updateQueued);
|
||||
return (
|
||||
<div className={"studio-selector-button " +
|
||||
(isWaiting ? "studio-selector-button-waiting" :
|
||||
(isAdded ? "studio-selector-button-selected" : ""))}
|
||||
key={studio.id}
|
||||
onClick={() => this.handleToggle(studio.id)}
|
||||
>
|
||||
<div className={"studio-selector-button-text " +
|
||||
((isWaiting || isAdded) ? "studio-selector-button-text-selected" :
|
||||
".studio-selector-button-text-unselected")}>
|
||||
{truncate(studio.title, {'length': 20, 'separator': /[,:\.;]*\s+/})}
|
||||
</div>
|
||||
<div className={"studio-status-icon" +
|
||||
((isWaiting || isAdded) ? "" : " studio-status-icon-unselected")}
|
||||
>
|
||||
{isWaiting ? (<Spinner type="smooth" />) : (isAdded ? checkmark : plus)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className="mod-addToStudio"
|
||||
contentLabel={contentLabel}
|
||||
ref={component => { // bind to base modal, to pass handleRequestClose through
|
||||
this.baseModal = component;
|
||||
}}
|
||||
onRequestClose={onRequestClose}
|
||||
isOpen={isOpen}
|
||||
>
|
||||
<div>
|
||||
<div className="addToStudio-modal-header">
|
||||
<div className="addToStudio-content-label">
|
||||
{contentLabel}
|
||||
</div>
|
||||
</div>
|
||||
<div className="addToStudio-modal-content">
|
||||
<div className="studio-list-outer-scrollbox">
|
||||
<div className="studio-list-inner-scrollbox">
|
||||
<div className="studio-list-container">
|
||||
{studioButtons}
|
||||
</div>
|
||||
</div>
|
||||
<div className="studio-list-bottom-gradient">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<Form
|
||||
className="add-to-studio"
|
||||
onSubmit={this.handleSubmit}
|
||||
>
|
||||
<FlexRow className="action-buttons">
|
||||
<Button
|
||||
className="action-button close-button white"
|
||||
onClick={this.handleRequestClose}
|
||||
key="closeButton"
|
||||
name="closeButton"
|
||||
type="button"
|
||||
>
|
||||
<div className="action-button-text">
|
||||
<FormattedMessage id="general.close" />
|
||||
</div>
|
||||
</Button>
|
||||
{this.state.waitingToClose ? [
|
||||
<Button
|
||||
className="action-button submit-button submit-button-waiting"
|
||||
disabled="disabled"
|
||||
key="submitButton"
|
||||
type="submit"
|
||||
>
|
||||
<div className="action-button-text">
|
||||
<Spinner type="smooth" />
|
||||
<FormattedMessage id="addToStudio.finishing" />
|
||||
</div>
|
||||
</Button>
|
||||
] : [
|
||||
<Button
|
||||
className="action-button submit-button"
|
||||
key="submitButton"
|
||||
type="submit"
|
||||
>
|
||||
<div className="action-button-text">
|
||||
<FormattedMessage id="general.okay" />
|
||||
</div>
|
||||
</Button>
|
||||
]}
|
||||
</FlexRow>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</Modal>
|
||||
<AddToStudioModalPresentation
|
||||
studios={curatedStudios}
|
||||
studioState={this.state.studioState}
|
||||
isOpen={isOpen}
|
||||
onToggleStudio={handleToggle}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AddToStudioModal.propTypes = {
|
||||
intl: intlShape,
|
||||
projectStudios: PropTypes.arrayOf(PropTypes.object),
|
||||
curatedStudios: PropTypes.arrayOf(PropTypes.object),
|
||||
onAddToStudio: PropTypes.func,
|
||||
onRequestClose: PropTypes.func,
|
||||
type: PropTypes.string
|
||||
studioRequests: PropTypes.object,
|
||||
onToggleStudio: PropTypes.func,
|
||||
onRequestClose: PropTypes.func
|
||||
};
|
||||
|
||||
module.exports = injectIntl(AddToStudioModal);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
const keyMirror = require('keymirror');
|
||||
const bindAll = require('lodash.bindall');
|
||||
const truncate = require('lodash.truncate');
|
||||
const PropTypes = require('prop-types');
|
||||
|
@ -18,11 +19,17 @@ const FlexRow = require('../../flex-row/flex-row.jsx');
|
|||
require('../../forms/button.scss');
|
||||
require('./modal.scss');
|
||||
|
||||
module.exports.State = keyMirror({
|
||||
IN: null,
|
||||
OUT: null,
|
||||
JOINING: null,
|
||||
LEAVING: null
|
||||
});
|
||||
|
||||
class AddToStudioModalPresentation extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
bindAll(this, [ // NOTE: will need to add and bind callback fn to handle addind and removing studios
|
||||
'handleToggle',
|
||||
'handleRequestClose',
|
||||
'handleSubmit'
|
||||
]);
|
||||
|
@ -33,83 +40,25 @@ class AddToStudioModalPresentation extends React.Component {
|
|||
// membership/stats/name. use that for rendering.
|
||||
this.state = {
|
||||
waitingToClose: false,
|
||||
joined: {},
|
||||
updateQueued: {}
|
||||
studios: props.studios
|
||||
};
|
||||
}
|
||||
|
||||
requestJoinStudio(studioId) {
|
||||
// submit here? or through presentation?
|
||||
}
|
||||
requestLeaveStudio(studioId) {
|
||||
// submit here? or through presentation?
|
||||
}
|
||||
|
||||
handleToggle(studioId) {
|
||||
const joined = this.state.joined;
|
||||
const updateQueued = this.state.updateQueued;
|
||||
console.log(updateQueued)
|
||||
if (!(studioId in updateQueued)) { // we haven't requested it yet...
|
||||
const updateType = (studioId in joined) ? 'leave' : 'join';
|
||||
console.log("queueing " + updateType + " request for studio: " + studioId);
|
||||
this.setState(prevState => ({
|
||||
updateQueued: {
|
||||
...prevState.updateQueued,
|
||||
[studioId]: {updateType: updateType}
|
||||
}
|
||||
}), () => { // callback
|
||||
// submit request to server
|
||||
|
||||
if (updateType === 'join') {
|
||||
this.requestJoinStudio(studioId);
|
||||
} else {
|
||||
this.requestLeaveStudio(studioId);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// we need to separately handle
|
||||
// server responses to our update requests,
|
||||
// and after each one, check to see if there are no outstanding updates
|
||||
// queued.
|
||||
checkForOutstandingUpdates () {
|
||||
const updateQueued = this.state.updateQueued;
|
||||
if (Object.keys(updateQueued).length == 0) {
|
||||
setTimeout(function() {
|
||||
this.setState({waitingToClose: false}, () => {
|
||||
this.handleRequestClose();
|
||||
});
|
||||
}.bind(this), 3000);
|
||||
}
|
||||
}
|
||||
|
||||
handleRequestClose () {
|
||||
// NOTE that we do NOT clear joined, so we don't lose
|
||||
// user's work from a stray click outside the modal...
|
||||
// but maybe this should be different?
|
||||
this.baseModal.handleRequestClose();
|
||||
}
|
||||
handleSubmit (formData) {
|
||||
// NOTE:For this approach to work, we need to separately handle
|
||||
// server responses to our update requests,
|
||||
// and after each one, check to see if there are no outstanding updates
|
||||
// queued.
|
||||
this.setState({waitingToClose: true}, () => {
|
||||
this.checkForOutstandingUpdates();
|
||||
});
|
||||
this.props.handleSubmit(formData);
|
||||
}
|
||||
render () {
|
||||
// NOTE: how does intl get injected?
|
||||
const {
|
||||
intl,
|
||||
studios,
|
||||
onAddToStudio, // eslint-disable-line no-unused-vars
|
||||
isOpen,
|
||||
onRequestClose
|
||||
onToggleStudio,
|
||||
isOpen
|
||||
} = this.props;
|
||||
const joined = this.state.joined;
|
||||
const updateQueued = this.state.updateQueued;
|
||||
const contentLabel = intl.formatMessage({id: "addToStudio.title");
|
||||
const contentLabel = intl.formatMessage({id: "addToStudio.title"});
|
||||
const checkmark = <img alt="checkmark-icon"
|
||||
className="studio-status-icon-checkmark-img"
|
||||
src="/svgs/modal/confirm.svg"
|
||||
|
@ -118,25 +67,30 @@ class AddToStudioModalPresentation extends React.Component {
|
|||
className="studio-status-icon-plus-img"
|
||||
src="/svgs/modal/add.svg"
|
||||
/>
|
||||
const studioButtons = curatedStudios.map((studio, index) => {
|
||||
const isAdded = (studio.id in joined);
|
||||
const isWaiting = (studio.id in updateQueued);
|
||||
const studioButtons = studios.map((studio, index) => {
|
||||
const thisStudioState = studioState[studio.id];
|
||||
return (
|
||||
<div className={"studio-selector-button " +
|
||||
(isWaiting ? "studio-selector-button-waiting" :
|
||||
(isAdded ? "studio-selector-button-selected" : ""))}
|
||||
(thisStudioState === module.exports.State.JOINING ||
|
||||
thisStudioState === module.exports.State.LEAVING) ?
|
||||
"studio-selector-button-waiting" :
|
||||
(thisStudioState === module.exports.State.IN ? "studio-selector-button-selected" : ""))}
|
||||
key={studio.id}
|
||||
onClick={() => this.handleToggle(studio.id)}
|
||||
onClick={() => this.props.onToggleStudio(studio.id)}
|
||||
>
|
||||
<div className={"studio-selector-button-text " +
|
||||
((isWaiting || isAdded) ? "studio-selector-button-text-selected" :
|
||||
".studio-selector-button-text-unselected")}>
|
||||
(thisStudioState === module.exports.State.OUT ?
|
||||
"studio-selector-button-text-unselected" :
|
||||
".studio-selector-button-text-selected")}>
|
||||
{truncate(studio.title, {'length': 20, 'separator': /[,:\.;]*\s+/})}
|
||||
</div>
|
||||
<div className={"studio-status-icon" +
|
||||
((isWaiting || isAdded) ? "" : " studio-status-icon-unselected")}
|
||||
<div className={"studio-status-icon " +
|
||||
(thisStudioState === module.exports.State.OUT ? "studio-status-icon-unselected" : "")}
|
||||
>
|
||||
{isWaiting ? (<Spinner type="smooth" />) : (isAdded ? checkmark : plus)}
|
||||
{(thisStudioState === module.exports.State.JOINING ||
|
||||
thisStudioState === module.exports.State.LEAVING) ?
|
||||
(<Spinner type="smooth" />) :
|
||||
(thisStudioState === module.exports.State.IN ? checkmark : plus)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
@ -149,7 +103,7 @@ class AddToStudioModalPresentation extends React.Component {
|
|||
ref={component => { // bind to base modal, to pass handleRequestClose through
|
||||
this.baseModal = component;
|
||||
}}
|
||||
onRequestClose={onRequestClose}
|
||||
onRequestClose={this.props.onRequestClose}
|
||||
isOpen={isOpen}
|
||||
>
|
||||
<div>
|
||||
|
@ -188,13 +142,14 @@ class AddToStudioModalPresentation extends React.Component {
|
|||
</Button>
|
||||
{this.state.waitingToClose ? [
|
||||
<Button
|
||||
className="action-button submit-button"
|
||||
className="action-button submit-button submit-button-waiting"
|
||||
disabled="disabled"
|
||||
key="submitButton"
|
||||
type="submit"
|
||||
>
|
||||
<div className="action-button-text">
|
||||
<Spinner />
|
||||
<Spinner type="smooth" />
|
||||
<FormattedMessage id="addToStudio.finishing" />
|
||||
</div>
|
||||
</Button>
|
||||
] : [
|
||||
|
@ -225,4 +180,4 @@ AddToStudioModalPresentation.propTypes = {
|
|||
onRequestClose: PropTypes.func
|
||||
};
|
||||
|
||||
module.exports = injectIntl(AddToStudioModal);
|
||||
module.exports = injectIntl(AddToStudioModalPresentation);
|
||||
|
|
|
@ -20,7 +20,8 @@ module.exports.getInitialState = () => ({
|
|||
parent: module.exports.Status.NOT_FETCHED,
|
||||
remixes: module.exports.Status.NOT_FETCHED,
|
||||
projectStudios: module.exports.Status.NOT_FETCHED,
|
||||
curatedStudios: module.exports.Status.NOT_FETCHED
|
||||
curatedStudios: module.exports.Status.NOT_FETCHED,
|
||||
studioRequests: {}
|
||||
},
|
||||
projectInfo: {},
|
||||
remixes: [],
|
||||
|
@ -30,7 +31,7 @@ module.exports.getInitialState = () => ({
|
|||
original: {},
|
||||
parent: {},
|
||||
projectStudios: [],
|
||||
curatedStudios: []
|
||||
curatedStudios: [],
|
||||
});
|
||||
|
||||
module.exports.previewReducer = (state, action) => {
|
||||
|
@ -79,6 +80,10 @@ module.exports.previewReducer = (state, action) => {
|
|||
state = JSON.parse(JSON.stringify(state));
|
||||
state.status[action.infoType] = action.status;
|
||||
return state;
|
||||
case 'SET_STUDIO_FETCH_STATUS':
|
||||
state = JSON.parse(JSON.stringify(state));
|
||||
state.status.studioRequests[action.studioId] = action.status;
|
||||
return state;
|
||||
case 'ERROR':
|
||||
log.error(action.error);
|
||||
return state;
|
||||
|
@ -132,12 +137,20 @@ module.exports.setCuratedStudios = items => ({
|
|||
items: items
|
||||
});
|
||||
|
||||
// NOTE: unclear to me what kind of Delta to do to what data when add and leave commands come back
|
||||
|
||||
module.exports.setFetchStatus = (type, status) => ({
|
||||
type: 'SET_FETCH_STATUS',
|
||||
infoType: type,
|
||||
status: status
|
||||
});
|
||||
|
||||
module.exports.setStudioFetchStatus = (studioId, status) => ({
|
||||
type: 'SET_STUDIO_FETCH_STATUS',
|
||||
studioId: studioId,
|
||||
status: status
|
||||
});
|
||||
|
||||
module.exports.getProjectInfo = (id, token) => (dispatch => {
|
||||
const opts = {
|
||||
uri: `/projects/${id}`
|
||||
|
@ -391,6 +404,44 @@ module.exports.getCuratedStudios = (username, token) => (dispatch => {
|
|||
});
|
||||
});
|
||||
|
||||
module.exports.addToStudio = (studioId, projectId, token) => (dispatch => {
|
||||
api({
|
||||
uri: `/studios/${studioId}/project/${projectId}`,
|
||||
authentication: token,
|
||||
method: 'POST'
|
||||
}, (err, body) => {
|
||||
if (err) {
|
||||
dispatch(module.exports.setError(err));
|
||||
return;
|
||||
}
|
||||
if (typeof body === 'undefined') {
|
||||
dispatch(module.exports.setError('Add to studio returned no data'));
|
||||
return;
|
||||
}
|
||||
dispatch(module.exports.setStudioFetchStatus(studioId, module.exports.Status.FETCHED));
|
||||
// NOTE: is there a way here to update or refresh the project studio list?
|
||||
});
|
||||
});
|
||||
|
||||
module.exports.leaveStudio = (studioId, projectId, token) => (dispatch => {
|
||||
api({
|
||||
uri: `/studios/${studioId}/project/${projectId}`,
|
||||
authentication: token,
|
||||
method: 'DELETE'
|
||||
}, (err, body) => {
|
||||
if (err) {
|
||||
dispatch(module.exports.setError(err));
|
||||
return;
|
||||
}
|
||||
if (typeof body === 'undefined') {
|
||||
dispatch(module.exports.setError('Leave studio returned no data'));
|
||||
return;
|
||||
}
|
||||
dispatch(module.exports.setStudioFetchStatus(studioId, module.exports.Status.FETCHED));
|
||||
// NOTE: is there a way here to update or refresh the project studio list?
|
||||
});
|
||||
});
|
||||
|
||||
module.exports.updateProject = (id, jsonData, username, token) => (dispatch => {
|
||||
api({
|
||||
uri: `/projects/${id}`,
|
||||
|
|
|
@ -33,7 +33,6 @@ class PreviewPresentation extends React.Component {
|
|||
bindAll(this, [
|
||||
'handleAddToStudioClick',
|
||||
'handleAddToStudioClose',
|
||||
'handleAddToStudioSubmit',
|
||||
'handleReportClick',
|
||||
'handleReportClose',
|
||||
'handleReportSubmit'
|
||||
|
@ -184,24 +183,6 @@ class PreviewPresentation extends React.Component {
|
|||
handleAddToStudioClose () {
|
||||
this.setState({addToStudioOpen: false});
|
||||
}
|
||||
handleAddToStudioSubmit (studiosToAdd, studiosToLeave, callback) {
|
||||
console.log('studios to add: ');
|
||||
console.log(studiosToAdd);
|
||||
console.log('studios to leave: ');
|
||||
console.log(studiosToLeave);
|
||||
// const data = {
|
||||
// ...formData,
|
||||
// id: this.props.projectId,
|
||||
// username: this.props.user.username
|
||||
// };
|
||||
//console.log('submit addToStudio data', data); // eslint-disable-line no-console
|
||||
|
||||
// TODO: post to API; in that callback,
|
||||
// pass error to modal via its callback.
|
||||
this.setState({addToStudioOpen: false}, () => {
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
// Report Project modal
|
||||
handleReportClick (e) {
|
||||
|
@ -240,6 +221,8 @@ class PreviewPresentation extends React.Component {
|
|||
sessionStatus,
|
||||
projectStudios,
|
||||
curatedStudios,
|
||||
studioRequests,
|
||||
onToggleStudio,
|
||||
user,
|
||||
onFavoriteClicked,
|
||||
onLoveClicked,
|
||||
|
@ -493,7 +476,8 @@ class PreviewPresentation extends React.Component {
|
|||
key="add-to-studio-modal"
|
||||
projectStudios={projectStudios}
|
||||
curatedStudios={this.mockedMyStudios}
|
||||
onAddToStudio={this.handleAddToStudioSubmit}
|
||||
studioRequests={studioRequests}
|
||||
onToggleStudio={onToggleStudio}
|
||||
onRequestClose={this.handleAddToStudioClose}
|
||||
/>
|
||||
]
|
||||
|
@ -608,6 +592,8 @@ PreviewPresentation.propTypes = {
|
|||
sessionStatus: PropTypes.string.isRequired,
|
||||
projectStudios: PropTypes.arrayOf(PropTypes.object),
|
||||
curatedStudios: PropTypes.arrayOf(PropTypes.object),
|
||||
studioRequests: PropTypes.object,
|
||||
onToggleStudio: PropTypes.func,
|
||||
user: PropTypes.shape({
|
||||
id: PropTypes.number,
|
||||
banned: PropTypes.bool,
|
||||
|
|
|
@ -126,6 +126,21 @@ class Preview extends React.Component {
|
|||
);
|
||||
}
|
||||
}
|
||||
handleToggleStudio (studioId, isAdd) {
|
||||
if (isAdd === true) {
|
||||
this.props.addToStudio(
|
||||
studioId,
|
||||
this.props.projectInfo.id,
|
||||
this.props.user.token
|
||||
);
|
||||
} else {
|
||||
this.props.leaveStudio(
|
||||
studioId,
|
||||
this.props.projectInfo.id,
|
||||
this.props.user.token
|
||||
);
|
||||
}
|
||||
}
|
||||
handleFavoriteToggle () {
|
||||
this.props.setFavedStatus(
|
||||
!this.props.faved,
|
||||
|
@ -203,6 +218,8 @@ class Preview extends React.Component {
|
|||
sessionStatus={this.props.sessionStatus}
|
||||
projectStudios={this.props.projectStudios}
|
||||
curatedStudios={this.props.curatedStudios}
|
||||
studioRequests={this.props.studioRequests}
|
||||
onToggleStudio={this.handleToggleStudio}
|
||||
user={this.props.user}
|
||||
onFavoriteClicked={this.handleFavoriteToggle}
|
||||
onLoveClicked={this.handleLoveToggle}
|
||||
|
@ -245,6 +262,7 @@ Preview.propTypes = {
|
|||
setPlayer: PropTypes.func.isRequired,
|
||||
projectStudios: PropTypes.arrayOf(PropTypes.object),
|
||||
curatedStudios: PropTypes.arrayOf(PropTypes.object),
|
||||
studioRequests: PropTypes.object,
|
||||
updateProject: PropTypes.func.isRequired,
|
||||
user: PropTypes.shape({
|
||||
id: PropTypes.number,
|
||||
|
@ -274,6 +292,7 @@ const mapStateToProps = state => ({
|
|||
sessionStatus: state.session.status,
|
||||
projectStudios: state.preview.projectStudios,
|
||||
curatedStudios: state.preview.curatedStudios,
|
||||
studioRequests: state.preview.status.studioRequests,
|
||||
user: state.session.session.user,
|
||||
playerMode: state.scratchGui.mode.isPlayerOnly,
|
||||
fullScreen: state.scratchGui.mode.isFullScreen
|
||||
|
@ -299,6 +318,12 @@ const mapDispatchToProps = dispatch => ({
|
|||
getCuratedStudios: (username, token) => {
|
||||
dispatch(previewActions.getCuratedStudios(username, token));
|
||||
},
|
||||
addToStudio: (studioId, id, token) => {
|
||||
dispatch(previewActions.addToStudio(studioId, id, token));
|
||||
},
|
||||
leaveStudio: (studioId, id, token) => {
|
||||
dispatch(previewActions.leaveStudio(studioId, id, token));
|
||||
},
|
||||
getFavedStatus: (id, username, token) => {
|
||||
dispatch(previewActions.getFavedStatus(id, username, token));
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue