add toast component, start to add functionality
This commit is contained in:
parent
f1ead9f124
commit
3352fe9d0d
10 changed files with 126 additions and 4 deletions
|
@ -78,6 +78,9 @@ export const SHOW_EDITOR_OPTIONS = 'SHOW_EDITOR_OPTIONS';
|
||||||
export const CLOSE_EDITOR_OPTIONS = 'CLOSE_EDITOR_OPTIONS';
|
export const CLOSE_EDITOR_OPTIONS = 'CLOSE_EDITOR_OPTIONS';
|
||||||
export const SHOW_KEYBOARD_SHORTCUT_MODAL = 'SHOW_KEYBOARD_SHORTCUT_MODAL';
|
export const SHOW_KEYBOARD_SHORTCUT_MODAL = 'SHOW_KEYBOARD_SHORTCUT_MODAL';
|
||||||
export const CLOSE_KEYBOARD_SHORTCUT_MODAL = 'CLOSE_KEYBOARD_SHORTCUT_MODAL';
|
export const CLOSE_KEYBOARD_SHORTCUT_MODAL = 'CLOSE_KEYBOARD_SHORTCUT_MODAL';
|
||||||
|
export const SHOW_TOAST = 'SHOW_TOAST';
|
||||||
|
export const HIDE_TOAST = 'HIDE_TOAST';
|
||||||
|
export const SET_TOAST_TEXT = 'SET_TOAST_TEXT';
|
||||||
|
|
||||||
// eventually, handle errors more specifically and better
|
// eventually, handle errors more specifically and better
|
||||||
export const ERROR = 'ERROR';
|
export const ERROR = 'ERROR';
|
||||||
|
|
|
@ -5,6 +5,7 @@ import JSZip from 'jszip';
|
||||||
import JSZipUtils from 'jszip-utils';
|
import JSZipUtils from 'jszip-utils';
|
||||||
import { saveAs } from 'file-saver';
|
import { saveAs } from 'file-saver';
|
||||||
import { getBlobUrl } from './files';
|
import { getBlobUrl } from './files';
|
||||||
|
import { showToast, setToastText } from './toast';
|
||||||
|
|
||||||
const ROOT_URL = location.href.indexOf('localhost') > 0 ? 'http://localhost:8000/api' : '/api';
|
const ROOT_URL = location.href.indexOf('localhost') > 0 ? 'http://localhost:8000/api' : '/api';
|
||||||
|
|
||||||
|
@ -60,6 +61,8 @@ export function saveProject() {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: ActionTypes.PROJECT_SAVE_SUCCESS
|
type: ActionTypes.PROJECT_SAVE_SUCCESS
|
||||||
});
|
});
|
||||||
|
dispatch(showToast());
|
||||||
|
dispatch(setToastText('Project saved.'));
|
||||||
})
|
})
|
||||||
.catch((response) => dispatch({
|
.catch((response) => dispatch({
|
||||||
type: ActionTypes.PROJECT_SAVE_FAIL,
|
type: ActionTypes.PROJECT_SAVE_FAIL,
|
||||||
|
@ -76,6 +79,8 @@ export function saveProject() {
|
||||||
owner: response.data.user,
|
owner: response.data.user,
|
||||||
files: response.data.files
|
files: response.data.files
|
||||||
});
|
});
|
||||||
|
dispatch(showToast());
|
||||||
|
dispatch(setToastText('Project saved.'));
|
||||||
})
|
})
|
||||||
.catch(response => dispatch({
|
.catch(response => dispatch({
|
||||||
type: ActionTypes.PROJECT_SAVE_FAIL,
|
type: ActionTypes.PROJECT_SAVE_FAIL,
|
||||||
|
|
23
client/modules/IDE/actions/toast.js
Normal file
23
client/modules/IDE/actions/toast.js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import * as ActionTypes from '../../../constants';
|
||||||
|
|
||||||
|
export function hideToast() {
|
||||||
|
return {
|
||||||
|
type: ActionTypes.HIDE_TOAST
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function showToast() {
|
||||||
|
return (dispatch) => {
|
||||||
|
dispatch({
|
||||||
|
type: ActionTypes.SHOW_TOAST
|
||||||
|
});
|
||||||
|
setTimeout(() => dispatch(hideToast()), 1500);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setToastText(text) {
|
||||||
|
return {
|
||||||
|
type: ActionTypes.SET_TOAST_TEXT,
|
||||||
|
text
|
||||||
|
};
|
||||||
|
}
|
34
client/modules/IDE/components/Toast.js
Normal file
34
client/modules/IDE/components/Toast.js
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import React, { PropTypes } from 'react';
|
||||||
|
import { bindActionCreators } from 'redux';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import InlineSVG from 'react-inlinesvg';
|
||||||
|
const exitUrl = require('../../../images/exit.svg');
|
||||||
|
import * as ToastActions from '../actions/toast';
|
||||||
|
|
||||||
|
function Toast(props) {
|
||||||
|
return (
|
||||||
|
<section className="toast">
|
||||||
|
<p>
|
||||||
|
{props.text}
|
||||||
|
</p>
|
||||||
|
<button className="toast__close" onClick={props.hideToast}>
|
||||||
|
<InlineSVG src={exitUrl} alt="Close Keyboard Shortcuts Overlay" />
|
||||||
|
</button>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.propTypes = {
|
||||||
|
text: PropTypes.string.isRequired,
|
||||||
|
hideToast: PropTypes.func.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
function mapStateToProps(state) {
|
||||||
|
return state.toast;
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapDispatchToProps(dispatch) {
|
||||||
|
return bindActionCreators(ToastActions, dispatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(Toast);
|
|
@ -11,6 +11,7 @@ import ShareModal from '../components/ShareModal';
|
||||||
import KeyboardShortcutModal from '../components/KeyboardShortcutModal';
|
import KeyboardShortcutModal from '../components/KeyboardShortcutModal';
|
||||||
import Nav from '../../../components/Nav';
|
import Nav from '../../../components/Nav';
|
||||||
import Console from '../components/Console';
|
import Console from '../components/Console';
|
||||||
|
import Toast from '../components/Toast';
|
||||||
import { bindActionCreators } from 'redux';
|
import { bindActionCreators } from 'redux';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import * as FileActions from '../actions/files';
|
import * as FileActions from '../actions/files';
|
||||||
|
@ -19,6 +20,7 @@ import * as ProjectActions from '../actions/project';
|
||||||
import * as EditorAccessibilityActions from '../actions/editorAccessibility';
|
import * as EditorAccessibilityActions from '../actions/editorAccessibility';
|
||||||
import * as PreferencesActions from '../actions/preferences';
|
import * as PreferencesActions from '../actions/preferences';
|
||||||
import * as UserActions from '../../User/actions';
|
import * as UserActions from '../../User/actions';
|
||||||
|
import * as ToastActions from '../actions/toast';
|
||||||
import { getHTMLFile, getJSFiles, getCSSFiles } from '../reducers/files';
|
import { getHTMLFile, getJSFiles, getCSSFiles } from '../reducers/files';
|
||||||
import SplitPane from 'react-split-pane';
|
import SplitPane from 'react-split-pane';
|
||||||
import Overlay from '../../App/components/Overlay';
|
import Overlay from '../../App/components/Overlay';
|
||||||
|
@ -114,6 +116,7 @@ class IDEView extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="ide">
|
<div className="ide">
|
||||||
|
{this.props.toast.isVisible && <Toast />}
|
||||||
<Nav
|
<Nav
|
||||||
user={this.props.user}
|
user={this.props.user}
|
||||||
newProject={this.props.newProject}
|
newProject={this.props.newProject}
|
||||||
|
@ -124,6 +127,8 @@ class IDEView extends React.Component {
|
||||||
logoutUser={this.props.logoutUser}
|
logoutUser={this.props.logoutUser}
|
||||||
stopSketch={this.props.stopSketch}
|
stopSketch={this.props.stopSketch}
|
||||||
showShareModal={this.props.showShareModal}
|
showShareModal={this.props.showShareModal}
|
||||||
|
showToast={this.props.showToast}
|
||||||
|
setToastText={this.props.setToastText}
|
||||||
/>
|
/>
|
||||||
<Toolbar
|
<Toolbar
|
||||||
className="Toolbar"
|
className="Toolbar"
|
||||||
|
@ -434,7 +439,12 @@ IDEView.propTypes = {
|
||||||
showEditorOptions: PropTypes.func.isRequired,
|
showEditorOptions: PropTypes.func.isRequired,
|
||||||
closeEditorOptions: PropTypes.func.isRequired,
|
closeEditorOptions: PropTypes.func.isRequired,
|
||||||
showKeyboardShortcutModal: PropTypes.func.isRequired,
|
showKeyboardShortcutModal: PropTypes.func.isRequired,
|
||||||
closeKeyboardShortcutModal: PropTypes.func.isRequired
|
closeKeyboardShortcutModal: PropTypes.func.isRequired,
|
||||||
|
toast: PropTypes.shape({
|
||||||
|
isVisible: PropTypes.bool.isRequired
|
||||||
|
}).isRequired,
|
||||||
|
showToast: PropTypes.func.isRequired,
|
||||||
|
setToastText: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
function mapStateToProps(state) {
|
function mapStateToProps(state) {
|
||||||
|
@ -448,7 +458,8 @@ function mapStateToProps(state) {
|
||||||
preferences: state.preferences,
|
preferences: state.preferences,
|
||||||
editorAccessibility: state.editorAccessibility,
|
editorAccessibility: state.editorAccessibility,
|
||||||
user: state.user,
|
user: state.user,
|
||||||
project: state.project
|
project: state.project,
|
||||||
|
toast: state.toast
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,7 +470,8 @@ function mapDispatchToProps(dispatch) {
|
||||||
ProjectActions,
|
ProjectActions,
|
||||||
IDEActions,
|
IDEActions,
|
||||||
PreferencesActions,
|
PreferencesActions,
|
||||||
UserActions),
|
UserActions,
|
||||||
|
ToastActions),
|
||||||
dispatch);
|
dispatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
21
client/modules/IDE/reducers/toast.js
Normal file
21
client/modules/IDE/reducers/toast.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import * as ActionTypes from '../../../constants';
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
isVisible: false,
|
||||||
|
text: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
const toast = (state = initialState, action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case ActionTypes.SHOW_TOAST:
|
||||||
|
return Object.assign({}, state, { isVisible: true });
|
||||||
|
case ActionTypes.HIDE_TOAST:
|
||||||
|
return Object.assign({}, state, { isVisible: false });
|
||||||
|
case ActionTypes.SET_TOAST_TEXT:
|
||||||
|
return Object.assign({}, state, { text: action.text });
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default toast;
|
|
@ -6,6 +6,7 @@ import project from './modules/IDE/reducers/project';
|
||||||
import editorAccessibility from './modules/IDE/reducers/editorAccessibility';
|
import editorAccessibility from './modules/IDE/reducers/editorAccessibility';
|
||||||
import user from './modules/User/reducers';
|
import user from './modules/User/reducers';
|
||||||
import sketches from './modules/Sketch/reducers';
|
import sketches from './modules/Sketch/reducers';
|
||||||
|
import toast from './modules/IDE/reducers/toast';
|
||||||
import { reducer as form } from 'redux-form';
|
import { reducer as form } from 'redux-form';
|
||||||
|
|
||||||
const rootReducer = combineReducers({
|
const rootReducer = combineReducers({
|
||||||
|
@ -16,7 +17,8 @@ const rootReducer = combineReducers({
|
||||||
user,
|
user,
|
||||||
project,
|
project,
|
||||||
sketches,
|
sketches,
|
||||||
editorAccessibility
|
editorAccessibility,
|
||||||
|
toast
|
||||||
});
|
});
|
||||||
|
|
||||||
export default rootReducer;
|
export default rootReducer;
|
||||||
|
|
|
@ -25,6 +25,9 @@ $light-icon-color: #8b8b8b;
|
||||||
$light-icon-hover-color: $light-primary-text-color;
|
$light-icon-hover-color: $light-primary-text-color;
|
||||||
$light-shadow-color: rgba(0, 0, 0, 0.16);
|
$light-shadow-color: rgba(0, 0, 0, 0.16);
|
||||||
|
|
||||||
|
$toast-background-color: #979797;
|
||||||
|
$toast-text-color: $white;
|
||||||
|
|
||||||
$dark-primary-text-color: $white;
|
$dark-primary-text-color: $white;
|
||||||
$dark-secondary-text-color: #c2c2c2;
|
$dark-secondary-text-color: #c2c2c2;
|
||||||
$dark-inactive-color: #7d7d7d;
|
$dark-inactive-color: #7d7d7d;
|
||||||
|
|
18
client/styles/components/_toast.scss
Normal file
18
client/styles/components/_toast.scss
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
.toast {
|
||||||
|
background-color: $toast-background-color;
|
||||||
|
color: $toast-text-color;
|
||||||
|
padding: #{20 / $base-font-size}rem;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 40%;
|
||||||
|
display: flex;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast__close {
|
||||||
|
@extend %icon;
|
||||||
|
& g {
|
||||||
|
fill: $toast-text-color;
|
||||||
|
}
|
||||||
|
margin-left: #{10 / $base-font-size}rem;
|
||||||
|
}
|
|
@ -25,6 +25,7 @@
|
||||||
@import 'components/about';
|
@import 'components/about';
|
||||||
@import 'components/github-button';
|
@import 'components/github-button';
|
||||||
@import 'components/forms';
|
@import 'components/forms';
|
||||||
|
@import 'components/toast';
|
||||||
|
|
||||||
@import 'layout/ide';
|
@import 'layout/ide';
|
||||||
@import 'layout/sketch-list';
|
@import 'layout/sketch-list';
|
||||||
|
|
Loading…
Reference in a new issue