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:
siddhant 2019-05-02 02:02:39 +05:30 committed by Cassie Tarakajian
parent 870d9ceded
commit 538a41c617
9 changed files with 110 additions and 10 deletions

View file

@ -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';

View 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;

View 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 };
}

View file

@ -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({
type: ActionTypes.ERROR,
error: response.data
}));
.catch((response) => {
dispatch({
type: ActionTypes.ERROR,
error: response.data
});
dispatch(stopLoader());
});
};
}

View file

@ -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,
};
}

View 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;

View file

@ -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;

View 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);
}
}

View file

@ -41,6 +41,7 @@
@import 'components/keyboard-shortcuts';
@import 'components/copyable-input';
@import 'components/feedback';
@import 'components/loader';
@import 'components/uploader';
@import 'layout/ide';