Added Loader to indicate loading of sketches (#880)
* Added Loader to indicate loading of sketches * Fixed styles * Changed styles * remove prefixes * Issues Fixed: * added Loader * Refactor * Issues Fixed * clean up loader functions
This commit is contained in:
parent
870d9ceded
commit
538a41c617
9 changed files with 110 additions and 10 deletions
|
@ -118,5 +118,8 @@ export const HIDE_RUNTIME_ERROR_WARNING = 'HIDE_RUNTIME_ERROR_WARNING';
|
|||
export const SHOW_RUNTIME_ERROR_WARNING = 'SHOW_RUNTIME_ERROR_WARNING';
|
||||
export const SET_ASSETS = 'SET_ASSETS';
|
||||
|
||||
export const START_LOADING = 'START_LOADING';
|
||||
export const STOP_LOADING = 'STOP_LOADING';
|
||||
|
||||
export const START_SAVING_PROJECT = 'START_SAVING_PROJECT';
|
||||
export const END_SAVING_PROJECT = 'END_SAVING_PROJECT';
|
||||
|
|
9
client/modules/App/components/loader.jsx
Normal file
9
client/modules/App/components/loader.jsx
Normal file
|
@ -0,0 +1,9 @@
|
|||
import React from 'react';
|
||||
|
||||
const Loader = () => (
|
||||
<div className="loader">
|
||||
<div className="loader__circle1" />
|
||||
<div className="loader__circle2" />
|
||||
</div>
|
||||
);
|
||||
export default Loader;
|
9
client/modules/IDE/actions/loader.js
Normal file
9
client/modules/IDE/actions/loader.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
import * as ActionTypes from '../../../constants';
|
||||
|
||||
export function startLoader() {
|
||||
return { type: ActionTypes.START_LOADING };
|
||||
}
|
||||
|
||||
export function stopLoader() {
|
||||
return { type: ActionTypes.STOP_LOADING };
|
||||
}
|
|
@ -2,12 +2,14 @@ import axios from 'axios';
|
|||
import * as ActionTypes from '../../../constants';
|
||||
import { showErrorModal, setPreviousPath } from './ide';
|
||||
import { resetProject } from './project';
|
||||
import { startLoader, stopLoader } from './loader';
|
||||
|
||||
const __process = (typeof global !== 'undefined' ? global : window).process;
|
||||
const ROOT_URL = __process.env.API_URL;
|
||||
|
||||
export function getProjects(username) {
|
||||
return (dispatch) => {
|
||||
dispatch(startLoader());
|
||||
let url;
|
||||
if (username) {
|
||||
url = `${ROOT_URL}/${username}/projects`;
|
||||
|
@ -20,11 +22,15 @@ export function getProjects(username) {
|
|||
type: ActionTypes.SET_PROJECTS,
|
||||
projects: response.data
|
||||
});
|
||||
dispatch(stopLoader());
|
||||
})
|
||||
.catch(response => dispatch({
|
||||
.catch((response) => {
|
||||
dispatch({
|
||||
type: ActionTypes.ERROR,
|
||||
error: response.data
|
||||
}));
|
||||
});
|
||||
dispatch(stopLoader());
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import { bindActionCreators } from 'redux';
|
|||
import * as ProjectActions from '../actions/project';
|
||||
import * as SketchActions from '../actions/projects';
|
||||
import * as ToastActions from '../actions/toast';
|
||||
import Loader from '../../App/components/loader';
|
||||
|
||||
const trashCan = require('../../../images/trash-can.svg');
|
||||
|
||||
|
@ -25,6 +26,20 @@ class SketchList extends React.Component {
|
|||
return `p5.js Web Editor | ${this.props.username}'s sketches`;
|
||||
}
|
||||
|
||||
hasSketches() {
|
||||
return !this.props.loading && this.props.sketches.length > 0;
|
||||
}
|
||||
|
||||
renderLoader() {
|
||||
if (this.props.loading) return <Loader />;
|
||||
return null;
|
||||
}
|
||||
|
||||
renderEmptyTable() {
|
||||
if (!this.props.loading && this.props.sketches.length === 0) return (<p className="sketches-table__empty">No sketches.</p>);
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
const username = this.props.username !== undefined ? this.props.username : this.props.user.username;
|
||||
return (
|
||||
|
@ -32,10 +47,9 @@ class SketchList extends React.Component {
|
|||
<Helmet>
|
||||
<title>{this.getSketchesTitle()}</title>
|
||||
</Helmet>
|
||||
{ this.props.sketches.length === 0 &&
|
||||
<p className="sketches-table__empty">No sketches.</p>
|
||||
}
|
||||
{ this.props.sketches.length > 0 &&
|
||||
{this.renderLoader()}
|
||||
{this.renderEmptyTable()}
|
||||
{this.hasSketches() &&
|
||||
<table className="sketches-table" summary="table containing all saved projects">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -95,6 +109,7 @@ SketchList.propTypes = {
|
|||
updatedAt: PropTypes.string.isRequired
|
||||
})).isRequired,
|
||||
username: PropTypes.string,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
deleteProject: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
|
@ -105,7 +120,8 @@ SketchList.defaultProps = {
|
|||
function mapStateToProps(state) {
|
||||
return {
|
||||
user: state.user,
|
||||
sketches: state.sketches
|
||||
sketches: state.sketches,
|
||||
loading: state.loading,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
14
client/modules/IDE/reducers/loading.js
Normal file
14
client/modules/IDE/reducers/loading.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import * as ActionTypes from '../../../constants';
|
||||
|
||||
const loading = (state = false, action) => {
|
||||
switch (action.type) {
|
||||
case ActionTypes.START_LOADING:
|
||||
return true;
|
||||
case ActionTypes.STOP_LOADING:
|
||||
return false;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default loading;
|
|
@ -10,6 +10,7 @@ import sketches from './modules/IDE/reducers/projects';
|
|||
import toast from './modules/IDE/reducers/toast';
|
||||
import console from './modules/IDE/reducers/console';
|
||||
import assets from './modules/IDE/reducers/assets';
|
||||
import loading from './modules/IDE/reducers/loading';
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
form,
|
||||
|
@ -22,7 +23,8 @@ const rootReducer = combineReducers({
|
|||
editorAccessibility,
|
||||
toast,
|
||||
console,
|
||||
assets
|
||||
assets,
|
||||
loading
|
||||
});
|
||||
|
||||
export default rootReducer;
|
||||
|
|
40
client/styles/components/_loader.scss
Normal file
40
client/styles/components/_loader.scss
Normal file
|
@ -0,0 +1,40 @@
|
|||
.loader {
|
||||
width: #{80 / $base-font-size }rem;
|
||||
height: #{80 / $base-font-size}rem;
|
||||
|
||||
position: relative;
|
||||
margin: #{100 / $base-font-size}rem auto;
|
||||
}
|
||||
|
||||
.loader__circle1,
|
||||
.loader__circle2 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 80%;
|
||||
|
||||
@include themify() {
|
||||
background-color: getThemifyVariable('logo-color');
|
||||
}
|
||||
|
||||
opacity: 0.6;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
animation: sk-bounce 2.0s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.loader__circle2 {
|
||||
animation-delay: -1.0s;
|
||||
}
|
||||
|
||||
@keyframes sk-bounce {
|
||||
|
||||
0%,
|
||||
100% {
|
||||
transform: scale(0.0);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(1.0);
|
||||
}
|
||||
}
|
|
@ -41,6 +41,7 @@
|
|||
@import 'components/keyboard-shortcuts';
|
||||
@import 'components/copyable-input';
|
||||
@import 'components/feedback';
|
||||
@import 'components/loader';
|
||||
@import 'components/uploader';
|
||||
|
||||
@import 'layout/ide';
|
||||
|
|
Loading…
Reference in a new issue