Fix merge conflict for cherry-picking 0b8e78df3a0c49d5dcf706b1c26346da3dcc0bc4
This commit is contained in:
parent
36d20281db
commit
b8fb51d283
8 changed files with 138 additions and 35 deletions
|
@ -80,6 +80,8 @@ export const SHOW_NEW_FOLDER_MODAL = 'SHOW_NEW_FOLDER_MODAL';
|
||||||
export const CLOSE_NEW_FOLDER_MODAL = 'CLOSE_NEW_FOLDER_MODAL';
|
export const CLOSE_NEW_FOLDER_MODAL = 'CLOSE_NEW_FOLDER_MODAL';
|
||||||
export const SHOW_FOLDER_CHILDREN = 'SHOW_FOLDER_CHILDREN';
|
export const SHOW_FOLDER_CHILDREN = 'SHOW_FOLDER_CHILDREN';
|
||||||
export const HIDE_FOLDER_CHILDREN = 'HIDE_FOLDER_CHILDREN';
|
export const HIDE_FOLDER_CHILDREN = 'HIDE_FOLDER_CHILDREN';
|
||||||
|
export const OPEN_UPLOAD_FILE_MODAL = 'OPEN_UPLOAD_FILE_MODAL';
|
||||||
|
export const CLOSE_UPLOAD_FILE_MODAL = 'CLOSE_UPLOAD_FILE_MODAL';
|
||||||
|
|
||||||
export const SHOW_SHARE_MODAL = 'SHOW_SHARE_MODAL';
|
export const SHOW_SHARE_MODAL = 'SHOW_SHARE_MODAL';
|
||||||
export const CLOSE_SHARE_MODAL = 'CLOSE_SHARE_MODAL';
|
export const CLOSE_SHARE_MODAL = 'CLOSE_SHARE_MODAL';
|
||||||
|
|
|
@ -75,6 +75,18 @@ export function closeNewFileModal() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function openUploadFileModal() {
|
||||||
|
return {
|
||||||
|
type: ActionTypes.OPEN_UPLOAD_FILE_MODAL
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function closeUploadFileModal() {
|
||||||
|
return {
|
||||||
|
type: ActionTypes.CLOSE_UPLOAD_FILE_MODAL
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function expandSidebar() {
|
export function expandSidebar() {
|
||||||
return {
|
return {
|
||||||
type: ActionTypes.EXPAND_SIDEBAR
|
type: ActionTypes.EXPAND_SIDEBAR
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { bindActionCreators, compose } from 'redux';
|
||||||
import { reduxForm } from 'redux-form';
|
import { reduxForm } from 'redux-form';
|
||||||
import classNames from 'classnames';
|
|
||||||
import InlineSVG from 'react-inlinesvg';
|
import InlineSVG from 'react-inlinesvg';
|
||||||
import NewFileForm from './NewFileForm';
|
import NewFileForm from './NewFileForm';
|
||||||
import FileUploader from './FileUploader';
|
import { getCanUploadMedia, getreachedTotalSizeLimit } from '../selectors/users';
|
||||||
|
import { closeNewFileModal } from '../actions/ide';
|
||||||
|
import { createFile } from '../actions/files';
|
||||||
import { CREATE_FILE_REGEX } from '../../../../server/utils/fileUtils';
|
import { CREATE_FILE_REGEX } from '../../../../server/utils/fileUtils';
|
||||||
|
|
||||||
const exitUrl = require('../../../images/exit.svg');
|
const exitUrl = require('../../../images/exit.svg');
|
||||||
|
@ -28,16 +31,12 @@ class NewFileModal extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const modalClass = classNames({
|
|
||||||
'modal': true,
|
|
||||||
'modal--reduced': !this.props.canUploadMedia
|
|
||||||
});
|
|
||||||
return (
|
return (
|
||||||
<section className={modalClass} ref={(element) => { this.modal = element; }}>
|
<section className="modal" ref={(element) => { this.modal = element; }}>
|
||||||
<div className="modal-content">
|
<div className="modal-content">
|
||||||
<div className="modal__header">
|
<div className="modal__header">
|
||||||
<h2 className="modal__title">Add File</h2>
|
<h2 className="modal__title">Create File</h2>
|
||||||
<button className="modal__exit-button" onClick={this.props.closeModal}>
|
<button className="modal__exit-button" onClick={this.props.closeNewFileModal}>
|
||||||
<InlineSVG src={exitUrl} alt="Close New File Modal" />
|
<InlineSVG src={exitUrl} alt="Close New File Modal" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -45,17 +44,6 @@ class NewFileModal extends React.Component {
|
||||||
focusOnModal={this.focusOnModal}
|
focusOnModal={this.focusOnModal}
|
||||||
{...this.props}
|
{...this.props}
|
||||||
/>
|
/>
|
||||||
{(() => {
|
|
||||||
if (this.props.canUploadMedia) {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<p className="modal__divider">OR</p>
|
|
||||||
<FileUploader />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
})()}
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
@ -63,8 +51,8 @@ class NewFileModal extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
NewFileModal.propTypes = {
|
NewFileModal.propTypes = {
|
||||||
closeModal: PropTypes.func.isRequired,
|
createFile: PropTypes.func.isRequired,
|
||||||
canUploadMedia: PropTypes.bool.isRequired
|
closeNewFileModal: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
function validate(formProps) {
|
function validate(formProps) {
|
||||||
|
@ -79,9 +67,22 @@ function validate(formProps) {
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return {
|
||||||
|
canUploadMedia: getCanUploadMedia(state),
|
||||||
|
reachedTotalSizeLimit: getreachedTotalSizeLimit(state)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export default reduxForm({
|
function mapDispatchToProps(dispatch) {
|
||||||
|
return bindActionCreators({ createFile, closeNewFileModal }, dispatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default compose(
|
||||||
|
connect(mapStateToProps, mapDispatchToProps),
|
||||||
|
reduxForm({
|
||||||
form: 'new-file',
|
form: 'new-file',
|
||||||
fields: ['name'],
|
fields: ['name'],
|
||||||
validate
|
validate
|
||||||
})(NewFileModal);
|
})
|
||||||
|
)(NewFileModal);
|
||||||
|
|
|
@ -113,6 +113,19 @@ class Sidebar extends React.Component {
|
||||||
Add file
|
Add file
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
aria-label="upload file"
|
||||||
|
onClick={() => {
|
||||||
|
this.props.openUploadFileModal();
|
||||||
|
setTimeout(this.props.closeProjectOptions, 0);
|
||||||
|
}}
|
||||||
|
onBlur={this.onBlurComponent}
|
||||||
|
onFocus={this.onFocusComponent}
|
||||||
|
>
|
||||||
|
Add file
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -137,6 +150,7 @@ Sidebar.propTypes = {
|
||||||
openProjectOptions: PropTypes.func.isRequired,
|
openProjectOptions: PropTypes.func.isRequired,
|
||||||
closeProjectOptions: PropTypes.func.isRequired,
|
closeProjectOptions: PropTypes.func.isRequired,
|
||||||
newFolder: PropTypes.func.isRequired,
|
newFolder: PropTypes.func.isRequired,
|
||||||
|
openUploadFileModal: PropTypes.func.isRequired,
|
||||||
owner: PropTypes.shape({
|
owner: PropTypes.shape({
|
||||||
id: PropTypes.string
|
id: PropTypes.string
|
||||||
}),
|
}),
|
||||||
|
|
43
client/modules/IDE/components/UploadFileModal.jsx
Normal file
43
client/modules/IDE/components/UploadFileModal.jsx
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { Link } from 'react-router';
|
||||||
|
import FileUploader from './FileUploader';
|
||||||
|
import { getreachedTotalSizeLimit } from '../selectors/users';
|
||||||
|
|
||||||
|
class UploadFileModal extends React.Component {
|
||||||
|
propTypes = {
|
||||||
|
reachedTotalSizeLimit: PropTypes.bool.isRequired
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<section className="modal" ref={(element) => { this.modal = element; }}>
|
||||||
|
{ this.props.reachedTotalSizeLimit &&
|
||||||
|
<p>
|
||||||
|
{
|
||||||
|
`You have reached the size limit for the number of files you can upload to your account.
|
||||||
|
If you would like to upload more, please remove the ones you aren't using anymore by
|
||||||
|
looking through your `
|
||||||
|
}
|
||||||
|
<Link to="/assets">assets</Link>
|
||||||
|
{'.'}
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
{ !this.props.reachedTotalSizeLimit &&
|
||||||
|
<div>
|
||||||
|
<FileUploader />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return {
|
||||||
|
reachedTotalSizeLimit: getreachedTotalSizeLimit(state)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(UploadFileModal);
|
|
@ -12,6 +12,7 @@ import Toolbar from '../components/Toolbar';
|
||||||
import Preferences from '../components/Preferences';
|
import Preferences from '../components/Preferences';
|
||||||
import NewFileModal from '../components/NewFileModal';
|
import NewFileModal from '../components/NewFileModal';
|
||||||
import NewFolderModal from '../components/NewFolderModal';
|
import NewFolderModal from '../components/NewFolderModal';
|
||||||
|
import UploadFileModal from '../components/UploadFileModal';
|
||||||
import ShareModal from '../components/ShareModal';
|
import ShareModal from '../components/ShareModal';
|
||||||
import KeyboardShortcutModal from '../components/KeyboardShortcutModal';
|
import KeyboardShortcutModal from '../components/KeyboardShortcutModal';
|
||||||
import ErrorModal from '../components/ErrorModal';
|
import ErrorModal from '../components/ErrorModal';
|
||||||
|
@ -349,12 +350,8 @@ class IDEView extends React.Component {
|
||||||
</SplitPane>
|
</SplitPane>
|
||||||
</SplitPane>
|
</SplitPane>
|
||||||
</div>
|
</div>
|
||||||
{this.props.ide.modalIsVisible &&
|
{ this.props.ide.modalIsVisible &&
|
||||||
<NewFileModal
|
<NewFileModal />
|
||||||
canUploadMedia={this.props.user.authenticated}
|
|
||||||
closeModal={this.props.closeNewFileModal}
|
|
||||||
createFile={this.props.createFile}
|
|
||||||
/>
|
|
||||||
}
|
}
|
||||||
{this.props.ide.newFolderModalVisible &&
|
{this.props.ide.newFolderModalVisible &&
|
||||||
<NewFolderModal
|
<NewFolderModal
|
||||||
|
@ -362,6 +359,11 @@ class IDEView extends React.Component {
|
||||||
createFolder={this.props.createFolder}
|
createFolder={this.props.createFolder}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
{this.props.ide.uploadFileModalVisible &&
|
||||||
|
<UploadFileModal
|
||||||
|
closeModal={this.props.closeUploadFileModal}
|
||||||
|
/>
|
||||||
|
}
|
||||||
{ this.props.location.pathname === '/about' &&
|
{ this.props.location.pathname === '/about' &&
|
||||||
<Overlay
|
<Overlay
|
||||||
title="About"
|
title="About"
|
||||||
|
@ -475,6 +477,7 @@ IDEView.propTypes = {
|
||||||
justOpenedProject: PropTypes.bool.isRequired,
|
justOpenedProject: PropTypes.bool.isRequired,
|
||||||
errorType: PropTypes.string,
|
errorType: PropTypes.string,
|
||||||
runtimeErrorWarningVisible: PropTypes.bool.isRequired,
|
runtimeErrorWarningVisible: PropTypes.bool.isRequired,
|
||||||
|
uploadFileModalVisible: PropTypes.bool.isRequired
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
stopSketch: PropTypes.func.isRequired,
|
stopSketch: PropTypes.func.isRequired,
|
||||||
project: PropTypes.shape({
|
project: PropTypes.shape({
|
||||||
|
@ -532,7 +535,6 @@ IDEView.propTypes = {
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
dispatchConsoleEvent: PropTypes.func.isRequired,
|
dispatchConsoleEvent: PropTypes.func.isRequired,
|
||||||
newFile: PropTypes.func.isRequired,
|
newFile: PropTypes.func.isRequired,
|
||||||
closeNewFileModal: PropTypes.func.isRequired,
|
|
||||||
expandSidebar: PropTypes.func.isRequired,
|
expandSidebar: PropTypes.func.isRequired,
|
||||||
collapseSidebar: PropTypes.func.isRequired,
|
collapseSidebar: PropTypes.func.isRequired,
|
||||||
cloneProject: PropTypes.func.isRequired,
|
cloneProject: PropTypes.func.isRequired,
|
||||||
|
@ -545,7 +547,6 @@ IDEView.propTypes = {
|
||||||
newFolder: PropTypes.func.isRequired,
|
newFolder: PropTypes.func.isRequired,
|
||||||
closeNewFolderModal: PropTypes.func.isRequired,
|
closeNewFolderModal: PropTypes.func.isRequired,
|
||||||
createFolder: PropTypes.func.isRequired,
|
createFolder: PropTypes.func.isRequired,
|
||||||
createFile: PropTypes.func.isRequired,
|
|
||||||
closeShareModal: PropTypes.func.isRequired,
|
closeShareModal: PropTypes.func.isRequired,
|
||||||
showEditorOptions: PropTypes.func.isRequired,
|
showEditorOptions: PropTypes.func.isRequired,
|
||||||
closeEditorOptions: PropTypes.func.isRequired,
|
closeEditorOptions: PropTypes.func.isRequired,
|
||||||
|
@ -577,6 +578,7 @@ IDEView.propTypes = {
|
||||||
showRuntimeErrorWarning: PropTypes.func.isRequired,
|
showRuntimeErrorWarning: PropTypes.func.isRequired,
|
||||||
hideRuntimeErrorWarning: PropTypes.func.isRequired,
|
hideRuntimeErrorWarning: PropTypes.func.isRequired,
|
||||||
startSketch: PropTypes.func.isRequired,
|
startSketch: PropTypes.func.isRequired,
|
||||||
|
closeUploadFileModal: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ const initialState = {
|
||||||
preferencesIsVisible: false,
|
preferencesIsVisible: false,
|
||||||
projectOptionsVisible: false,
|
projectOptionsVisible: false,
|
||||||
newFolderModalVisible: false,
|
newFolderModalVisible: false,
|
||||||
|
uploadFileModalVisible: false,
|
||||||
shareModalVisible: false,
|
shareModalVisible: false,
|
||||||
shareModalProjectId: 'abcd',
|
shareModalProjectId: 'abcd',
|
||||||
shareModalProjectName: 'My Cute Sketch',
|
shareModalProjectName: 'My Cute Sketch',
|
||||||
|
@ -105,6 +106,10 @@ const ide = (state = initialState, action) => {
|
||||||
return Object.assign({}, state, { runtimeErrorWarningVisible: false });
|
return Object.assign({}, state, { runtimeErrorWarningVisible: false });
|
||||||
case ActionTypes.SHOW_RUNTIME_ERROR_WARNING:
|
case ActionTypes.SHOW_RUNTIME_ERROR_WARNING:
|
||||||
return Object.assign({}, state, { runtimeErrorWarningVisible: true });
|
return Object.assign({}, state, { runtimeErrorWarningVisible: true });
|
||||||
|
case ActionTypes.OPEN_UPLOAD_FILE_MODAL:
|
||||||
|
return Object.assign({}, state, { uploadFileModalVisible: true });
|
||||||
|
case ActionTypes.CLOSE_UPLOAD_FILE_MODAL:
|
||||||
|
return Object.assign({}, state, { uploadFileModalVisible: false });
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
24
client/modules/IDE/selectors/users.js
Normal file
24
client/modules/IDE/selectors/users.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
|
const getAuthenticated = state => state.user.authenticated;
|
||||||
|
const getTotalSize = state => state.user.totalSize;
|
||||||
|
|
||||||
|
export const getCanUploadMedia = createSelector(
|
||||||
|
getAuthenticated,
|
||||||
|
getTotalSize,
|
||||||
|
(authenticated, totalSize) => {
|
||||||
|
if (!authenticated) return false;
|
||||||
|
// eventually do the same thing for verified when
|
||||||
|
// email verification actually works
|
||||||
|
if (totalSize > 250000000) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const getreachedTotalSizeLimit = createSelector(
|
||||||
|
getTotalSize,
|
||||||
|
(totalSize) => {
|
||||||
|
if (totalSize > 250000000) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
);
|
Loading…
Reference in a new issue