From 538a41c617ef0c76cce52c598b2bbe0ea12b0cf3 Mon Sep 17 00:00:00 2001 From: siddhant <30566406+siddhant1@users.noreply.github.com> Date: Thu, 2 May 2019 02:02:39 +0530 Subject: [PATCH] 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 --- client/constants.js | 3 ++ client/modules/App/components/loader.jsx | 9 +++++ client/modules/IDE/actions/loader.js | 9 +++++ client/modules/IDE/actions/projects.js | 14 +++++-- client/modules/IDE/components/SketchList.jsx | 26 ++++++++++--- client/modules/IDE/reducers/loading.js | 14 +++++++ client/reducers.js | 4 +- client/styles/components/_loader.scss | 40 ++++++++++++++++++++ client/styles/main.scss | 1 + 9 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 client/modules/App/components/loader.jsx create mode 100644 client/modules/IDE/actions/loader.js create mode 100644 client/modules/IDE/reducers/loading.js create mode 100644 client/styles/components/_loader.scss diff --git a/client/constants.js b/client/constants.js index 38fc467b..9cb3daa4 100644 --- a/client/constants.js +++ b/client/constants.js @@ -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'; diff --git a/client/modules/App/components/loader.jsx b/client/modules/App/components/loader.jsx new file mode 100644 index 00000000..1561387e --- /dev/null +++ b/client/modules/App/components/loader.jsx @@ -0,0 +1,9 @@ +import React from 'react'; + +const Loader = () => ( +
+
+
+
+); +export default Loader; diff --git a/client/modules/IDE/actions/loader.js b/client/modules/IDE/actions/loader.js new file mode 100644 index 00000000..f331094c --- /dev/null +++ b/client/modules/IDE/actions/loader.js @@ -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 }; +} diff --git a/client/modules/IDE/actions/projects.js b/client/modules/IDE/actions/projects.js index 5419f0fb..77dfbe52 100644 --- a/client/modules/IDE/actions/projects.js +++ b/client/modules/IDE/actions/projects.js @@ -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()); + }); }; } diff --git a/client/modules/IDE/components/SketchList.jsx b/client/modules/IDE/components/SketchList.jsx index 75a9b474..c0086ab5 100644 --- a/client/modules/IDE/components/SketchList.jsx +++ b/client/modules/IDE/components/SketchList.jsx @@ -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 ; + return null; + } + + renderEmptyTable() { + if (!this.props.loading && this.props.sketches.length === 0) return (

No sketches.

); + 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 { {this.getSketchesTitle()} - { this.props.sketches.length === 0 && -

No sketches.

- } - { this.props.sketches.length > 0 && + {this.renderLoader()} + {this.renderEmptyTable()} + {this.hasSketches() && @@ -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, }; } diff --git a/client/modules/IDE/reducers/loading.js b/client/modules/IDE/reducers/loading.js new file mode 100644 index 00000000..529c5747 --- /dev/null +++ b/client/modules/IDE/reducers/loading.js @@ -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; diff --git a/client/reducers.js b/client/reducers.js index c508c8ea..ef4d39c3 100644 --- a/client/reducers.js +++ b/client/reducers.js @@ -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; diff --git a/client/styles/components/_loader.scss b/client/styles/components/_loader.scss new file mode 100644 index 00000000..ec52410a --- /dev/null +++ b/client/styles/components/_loader.scss @@ -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); + } +} \ No newline at end of file diff --git a/client/styles/main.scss b/client/styles/main.scss index 12df45d3..3d9bf977 100644 --- a/client/styles/main.scss +++ b/client/styles/main.scss @@ -41,6 +41,7 @@ @import 'components/keyboard-shortcuts'; @import 'components/copyable-input'; @import 'components/feedback'; +@import 'components/loader'; @import 'components/uploader'; @import 'layout/ide';