From 7e59b60deaf8e9d83553a0bb4d6f16aed717b1d5 Mon Sep 17 00:00:00 2001 From: kovtun Date: Thu, 8 Feb 2018 13:22:14 +0100 Subject: [PATCH 01/10] Improved the efficiency when loading InfoPanel and InfoPanelView. Added object comparison function to common.js. --- .gitignore | 1 + common.js | 38 ++++++++++++++++++- components/Deck/InfoPanel/InfoPanel.js | 11 +++++- .../Deck/InfoPanel/InfoPanelInfoView.js | 11 +++++- 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 6c9c708d9..32739709e 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ slidewiki migrate .idea/ package-lock.json +*.iml diff --git a/common.js b/common.js index a54adb2bc..4104fb511 100644 --- a/common.js +++ b/common.js @@ -132,5 +132,41 @@ export default { isEmailAddress: (email) => { var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return re.test(email); - } + }, + + equals: function(x, y) { + if (x === y) return true; + // if both x and y are null or undefined and exactly the same + + if (! (x instanceof Object) || ! (y instanceof Object)) return false; + // if they are not strictly equal, they both need to be Objects + + if (x.constructor !== y.constructor) return false; + // they must have the exact same prototype chain, the closest we can do is + // test there constructor. + + for (var p in x) { + if (! x.hasOwnProperty(p)) continue; + // other properties were tested using x.constructor === y.constructor + + if (! y.hasOwnProperty(p)) return false; + // allows to compare x[p] and y[p] when set to undefined + + if (x[p] === y[p]) continue; + // if they have the same strict value or identity then they are equal + + if (typeof(x[p]) !== "object") return false; + // Numbers, Strings, Functions, Booleans must be strictly equal + + if (! exports.default.equals(x[p], y[p])) return false; + // Objects and Arrays must be tested recursively + } + + for (p in y) { + if (y.hasOwnProperty(p) && !x.hasOwnProperty(p)) return false; + // allows x[p] to be set to undefined + } + + return true; + }, }; diff --git a/components/Deck/InfoPanel/InfoPanel.js b/components/Deck/InfoPanel/InfoPanel.js index e4028996f..a78c3c33a 100644 --- a/components/Deck/InfoPanel/InfoPanel.js +++ b/components/Deck/InfoPanel/InfoPanel.js @@ -4,9 +4,18 @@ import {connectToStores} from 'fluxible-addons-react'; import classNames from 'classnames'; import InfoPanelHeader from './InfoPanelHeader'; import InfoPanelInfoView from './InfoPanelInfoView'; - +import {equals} from '../../../common.js'; class InfoPanel extends React.Component { + shouldComponentUpdate(nextProps, nextState) { + let samePropsState = equals(this.props, nextProps); + // Content should be updated only when properties have changed. + return !samePropsState; + } + + componentDidUpdate() { + console.log('Updated InfoPanel.'); + } render() { const rootNodeStyles = { diff --git a/components/Deck/InfoPanel/InfoPanelInfoView.js b/components/Deck/InfoPanel/InfoPanelInfoView.js index 4f851b577..0b1b5103c 100644 --- a/components/Deck/InfoPanel/InfoPanelInfoView.js +++ b/components/Deck/InfoPanel/InfoPanelInfoView.js @@ -8,9 +8,18 @@ import ContributorsPanel from '../ContentModulesPanel/ContributorsPanel/Contribu import cheerio from 'cheerio'; import PresentationPanel from './PresentationsPanel'; import ActivityFeedStore from '../../../stores/ActivityFeedStore'; - +import {equals} from '../../../common.js'; class InfoPanelInfoView extends React.Component { + shouldComponentUpdate(nextProps, nextState) { + let samePropsState = equals(this.props, nextProps); + // Content should be updated only when properties have changed. + return !samePropsState; + } + + componentDidUpdate() { + console.log('Updated InfoPanelInfoView.'); + } getNameofNodes(tree, selector) { if(!selector.get('spath')){ From 24d0af96bf664f73944a3219b03f394c0a43765e Mon Sep 17 00:00:00 2001 From: kovtun Date: Fri, 9 Feb 2018 10:00:11 +0100 Subject: [PATCH 02/10] Removed temporary logging for debugging purposes. --- components/Deck/InfoPanel/InfoPanel.js | 4 ---- components/Deck/InfoPanel/InfoPanelInfoView.js | 4 ---- 2 files changed, 8 deletions(-) diff --git a/components/Deck/InfoPanel/InfoPanel.js b/components/Deck/InfoPanel/InfoPanel.js index a78c3c33a..e71367547 100644 --- a/components/Deck/InfoPanel/InfoPanel.js +++ b/components/Deck/InfoPanel/InfoPanel.js @@ -13,10 +13,6 @@ class InfoPanel extends React.Component { return !samePropsState; } - componentDidUpdate() { - console.log('Updated InfoPanel.'); - } - render() { const rootNodeStyles = { fontSize: '1.06em' diff --git a/components/Deck/InfoPanel/InfoPanelInfoView.js b/components/Deck/InfoPanel/InfoPanelInfoView.js index 0b1b5103c..98ffbf80b 100644 --- a/components/Deck/InfoPanel/InfoPanelInfoView.js +++ b/components/Deck/InfoPanel/InfoPanelInfoView.js @@ -17,10 +17,6 @@ class InfoPanelInfoView extends React.Component { return !samePropsState; } - componentDidUpdate() { - console.log('Updated InfoPanelInfoView.'); - } - getNameofNodes(tree, selector) { if(!selector.get('spath')){ return 0; From 011a371bfb42591ca7e24f81e5502a6fbf965ada Mon Sep 17 00:00:00 2001 From: kadevgraaf Date: Fri, 9 Feb 2018 11:53:43 +0100 Subject: [PATCH 03/10] fix linking errors --- common.js | 6 +++--- test/setup.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/common.js b/common.js index 4104fb511..683195f28 100644 --- a/common.js +++ b/common.js @@ -130,7 +130,7 @@ export default { }, isEmailAddress: (email) => { - var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + let re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; return re.test(email); }, @@ -145,7 +145,7 @@ export default { // they must have the exact same prototype chain, the closest we can do is // test there constructor. - for (var p in x) { + for (let p in x) { if (! x.hasOwnProperty(p)) continue; // other properties were tested using x.constructor === y.constructor @@ -155,7 +155,7 @@ export default { if (x[p] === y[p]) continue; // if they have the same strict value or identity then they are equal - if (typeof(x[p]) !== "object") return false; + if (typeof(x[p]) !== 'object') return false; // Numbers, Strings, Functions, Booleans must be strictly equal if (! exports.default.equals(x[p], y[p])) return false; diff --git a/test/setup.js b/test/setup.js index e72c3f084..134edd93c 100644 --- a/test/setup.js +++ b/test/setup.js @@ -1,6 +1,6 @@ require('babel-register')(); // setup file -var enzyme = require('enzyme'); -var Adapter = require('enzyme-adapter-react-15'); +let enzyme = require('enzyme'); +let Adapter = require('enzyme-adapter-react-15'); enzyme.configure({ adapter: new Adapter() }); From cd39196aef093e154e816c2831872a9aafe3c5b8 Mon Sep 17 00:00:00 2001 From: kovtun Date: Fri, 9 Feb 2018 11:56:15 +0100 Subject: [PATCH 04/10] Fixed the code style problem. --- common.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.js b/common.js index 4104fb511..6916a3f7a 100644 --- a/common.js +++ b/common.js @@ -155,7 +155,7 @@ export default { if (x[p] === y[p]) continue; // if they have the same strict value or identity then they are equal - if (typeof(x[p]) !== "object") return false; + if (typeof(x[p]) !== 'object') return false; // Numbers, Strings, Functions, Booleans must be strictly equal if (! exports.default.equals(x[p], y[p])) return false; From 91c8dba95996a28f42deca679e1c13310be482a7 Mon Sep 17 00:00:00 2001 From: Viktor Kovtun Date: Fri, 23 Feb 2018 13:32:35 +0200 Subject: [PATCH 05/10] Added loading indicator on the right side of the slide view. --- actions/loadContributors.js | 2 + common.js | 2 +- .../ActivityFeedPanel/ActivityFeedPanel.js | 3 +- .../Deck/ActivityFeedPanel/ActivityList.js | 2 + components/Deck/InfoPanel/InfoPanel.js | 34 +++++++++---- .../Deck/InfoPanel/InfoPanelInfoView.js | 50 ++++++++++++------- stores/ContributorsStore.js | 13 ++++- 7 files changed, 75 insertions(+), 31 deletions(-) diff --git a/actions/loadContributors.js b/actions/loadContributors.js index 8eac2e8e0..21a8a3eb0 100644 --- a/actions/loadContributors.js +++ b/actions/loadContributors.js @@ -17,6 +17,8 @@ export default function loadContributors(context, payload, done) { return; } + context.dispatch('LOAD_CONTRIBUTORS_LOAD', {loadingIndicator: true}); + context.service.read('contributors.list', payload, {timeout: 20 * 1000}, (err, res) => { if (err) { log.error(context, {filepath: __filename}); diff --git a/common.js b/common.js index 683195f28..d14c04c95 100644 --- a/common.js +++ b/common.js @@ -162,7 +162,7 @@ export default { // Objects and Arrays must be tested recursively } - for (p in y) { + for (let p in y) { if (y.hasOwnProperty(p) && !x.hasOwnProperty(p)) return false; // allows x[p] to be set to undefined } diff --git a/components/Deck/ActivityFeedPanel/ActivityFeedPanel.js b/components/Deck/ActivityFeedPanel/ActivityFeedPanel.js index dc31cc930..6ba5e6d5d 100644 --- a/components/Deck/ActivityFeedPanel/ActivityFeedPanel.js +++ b/components/Deck/ActivityFeedPanel/ActivityFeedPanel.js @@ -33,8 +33,7 @@ class ActivityFeedPanel extends React.Component { return (
-
Activity Feed -
+
Activity Feed
{activityDIV}
diff --git a/components/Deck/ActivityFeedPanel/ActivityList.js b/components/Deck/ActivityFeedPanel/ActivityList.js index 079e8b0bb..8788eef0b 100644 --- a/components/Deck/ActivityFeedPanel/ActivityList.js +++ b/components/Deck/ActivityFeedPanel/ActivityList.js @@ -34,6 +34,8 @@ class ActivityList extends React.Component { // TODO: same as in the ActivityFeedStore; check if there is more elegant way to tell the component that action loadMoreActivities (in the onScroll function) was executed if (!nextProps.ActivityFeedStore.wasFetch) return; this.loading = false; + let activitiesCount = this.props.ActivityFeedStore.activities.length; + console.log('ActivityList.componentWillReceiveProps() [' + 'activitiesCount=' + activitiesCount + ']'); } render() { return ( diff --git a/components/Deck/InfoPanel/InfoPanel.js b/components/Deck/InfoPanel/InfoPanel.js index e71367547..e8fd29aca 100644 --- a/components/Deck/InfoPanel/InfoPanel.js +++ b/components/Deck/InfoPanel/InfoPanel.js @@ -5,31 +5,47 @@ import classNames from 'classnames'; import InfoPanelHeader from './InfoPanelHeader'; import InfoPanelInfoView from './InfoPanelInfoView'; import {equals} from '../../../common.js'; +import ContributorsStore from '../../../stores/ContributorsStore'; class InfoPanel extends React.Component { + constructor(props) { + super(props); + this.isLoading = this.isContentUndefined(); + } + shouldComponentUpdate(nextProps, nextState) { let samePropsState = equals(this.props, nextProps); + this.isLoading = this.isContentUndefined(); // Content should be updated only when properties have changed. - return !samePropsState; + return !this.isLoading && !samePropsState; } - render() { - const rootNodeStyles = { - fontSize: '1.06em' - }; + componentWillReceiveProps(nextProps) { + this.isLoading = this.isContentUndefined(); + } + componentWillUnmount() { + this.props.ContributorsStore.contributors = []; + this.isLoading = true; + } - return ( - - ); + isContentUndefined() { + return this.props.ContributorsStore.contributors === undefined + || this.props.ContributorsStore.contributors === []; + } + + + render() { + return (); } } InfoPanel.contextTypes = { executeAction: React.PropTypes.func.isRequired }; -InfoPanel = connectToStores(InfoPanel, [], (context, props) => { +InfoPanel = connectToStores(InfoPanel, [ContributorsStore], (context, props) => { return { + ContributorsStore: context.getStore(ContributorsStore).getState() }; }); diff --git a/components/Deck/InfoPanel/InfoPanelInfoView.js b/components/Deck/InfoPanel/InfoPanelInfoView.js index 98ffbf80b..be5d36187 100644 --- a/components/Deck/InfoPanel/InfoPanelInfoView.js +++ b/components/Deck/InfoPanel/InfoPanelInfoView.js @@ -2,7 +2,6 @@ import React from 'react'; import {NavLink} from 'fluxible-router'; import {connectToStores} from 'fluxible-addons-react'; import DeckTreeStore from '../../../stores/DeckTreeStore'; -//import ActivityList from '../ActivityFeedPanel/ActivityList'; import ActivityFeedPanel from '../ActivityFeedPanel/ActivityFeedPanel'; import ContributorsPanel from '../ContentModulesPanel/ContributorsPanel/ContributorsPanel'; import cheerio from 'cheerio'; @@ -11,14 +10,25 @@ import ActivityFeedStore from '../../../stores/ActivityFeedStore'; import {equals} from '../../../common.js'; class InfoPanelInfoView extends React.Component { + constructor(props) { + super(props); + this.isLoading = true; + } + shouldComponentUpdate(nextProps, nextState) { let samePropsState = equals(this.props, nextProps); + + console.log('InfoPanelInfoView.shouldComponentUpdate() [nextProps.loadingIndicator=' + + nextProps.loadingIndicator + ', this.props.loadingIndicator=' + this.props.loadingIndicator + ']'); + this.isLoading = nextProps.loadingIndicator; + + // Content should be updated only when properties have changed. return !samePropsState; } getNameofNodes(tree, selector) { - if(!selector.get('spath')){ + if (!selector.get('spath')) { return 0; } let names = []; @@ -28,12 +38,13 @@ class InfoPanelInfoView extends React.Component { nodes.forEach ((node, index) => { position = node.split(':')[1]; names.push(currentChildren.get(position - 1).get('title')); - if(currentChildren.get(position - 1).get('children')){ + if (currentChildren.get(position - 1).get('children')) { currentChildren = currentChildren.get(position - 1).get('children'); } }); return names; } + render() { let deckTree = this.props.DeckTreeStore.deckTree; let selector = this.props.DeckTreeStore.selector; @@ -76,27 +87,32 @@ class InfoPanelInfoView extends React.Component { }); title = list; //use title of slide titlediv = -
-

- - {title} -

-
; - +
+

+ + {title} +

+
; } else { //title = rootNode.title; //title = ''; //use title of deck titlediv = ''; - } + return (
- {this.props.DeckTreeStore.revisionId !== this.props.DeckTreeStore.latestRevisionId && -
- Updated version available -
} - {titlediv} + {this.isLoading ?
Loading
: ''} + { + this.props.DeckTreeStore.revisionId !== this.props.DeckTreeStore.latestRevisionId && +
+ + + Updated version available + +
+ } + {titlediv}
@@ -130,7 +146,7 @@ InfoPanelInfoView.contextTypes = { InfoPanelInfoView= connectToStores(InfoPanelInfoView, [ActivityFeedStore, DeckTreeStore], (context, props) => { return { ActivityFeedStore: context.getStore(ActivityFeedStore).getState(), - DeckTreeStore: context.getStore(DeckTreeStore).getState() + DeckTreeStore: context.getStore(DeckTreeStore).getState(), }; }); export default InfoPanelInfoView; diff --git a/stores/ContributorsStore.js b/stores/ContributorsStore.js index 03fd9cf67..17e34d09e 100644 --- a/stores/ContributorsStore.js +++ b/stores/ContributorsStore.js @@ -9,6 +9,11 @@ class ContributorsStore extends BaseStore { this.translators = []; this.listName = ''; this.selector = {}; + this.loadingIndicator = false; + } + loading(payload){ + this.loadingIndicator = payload.loadingIndicator; + this.emitChange(); } updateContributors(payload) { this.contributors = this.getContributors(payload.contributors); @@ -16,6 +21,7 @@ class ContributorsStore extends BaseStore { this.translators = this.getTranslators(payload.contributors); this.listName = payload.listName; this.selector = payload.selector; + this.loadingIndicator = false; this.emitChange(); } @@ -24,7 +30,8 @@ class ContributorsStore extends BaseStore { contributors: this.contributors, creator: this.creator, translators: this.translators, - selector: this.selector + selector: this.selector, + loadingIndicator: this.loadingIndicator }; } dehydrate() { @@ -35,6 +42,7 @@ class ContributorsStore extends BaseStore { this.creator = state.creator; this.translators = state.translators; this.selector = state.selector; + this.loadingIndicator = state.loadingIndicator; } getBasedonRole(role, list) { @@ -60,7 +68,8 @@ class ContributorsStore extends BaseStore { ContributorsStore.storeName = 'ContributorsStore'; ContributorsStore.handlers = { - 'LOAD_CONTRIBUTORS_SUCCESS': 'updateContributors' + 'LOAD_CONTRIBUTORS_SUCCESS': 'updateContributors', + 'LOAD_CONTRIBUTORS_LOAD': 'loading' }; export default ContributorsStore; From dc110f2ca9ab675332c8bd70d0621834c45b45d2 Mon Sep 17 00:00:00 2001 From: Viktor Kovtun Date: Fri, 23 Feb 2018 13:44:40 +0200 Subject: [PATCH 06/10] Removed unnecessary logging. --- components/Deck/InfoPanel/InfoPanel.js | 1 - components/Deck/InfoPanel/InfoPanelInfoView.js | 5 ----- 2 files changed, 6 deletions(-) diff --git a/components/Deck/InfoPanel/InfoPanel.js b/components/Deck/InfoPanel/InfoPanel.js index e8fd29aca..170c49a31 100644 --- a/components/Deck/InfoPanel/InfoPanel.js +++ b/components/Deck/InfoPanel/InfoPanel.js @@ -34,7 +34,6 @@ class InfoPanel extends React.Component { || this.props.ContributorsStore.contributors === []; } - render() { return (); } diff --git a/components/Deck/InfoPanel/InfoPanelInfoView.js b/components/Deck/InfoPanel/InfoPanelInfoView.js index be5d36187..f9430e169 100644 --- a/components/Deck/InfoPanel/InfoPanelInfoView.js +++ b/components/Deck/InfoPanel/InfoPanelInfoView.js @@ -17,12 +17,7 @@ class InfoPanelInfoView extends React.Component { shouldComponentUpdate(nextProps, nextState) { let samePropsState = equals(this.props, nextProps); - - console.log('InfoPanelInfoView.shouldComponentUpdate() [nextProps.loadingIndicator=' + - nextProps.loadingIndicator + ', this.props.loadingIndicator=' + this.props.loadingIndicator + ']'); this.isLoading = nextProps.loadingIndicator; - - // Content should be updated only when properties have changed. return !samePropsState; } From ea22d0cc1cad6abe58d0575009037207bc51558f Mon Sep 17 00:00:00 2001 From: Viktor Kovtun Date: Fri, 23 Feb 2018 19:17:56 +0200 Subject: [PATCH 07/10] When removing the loading indicator taken into account if the activities has been loaded. --- actions/activityfeed/loadActivities.js | 2 ++ components/Deck/InfoPanel/InfoPanel.js | 11 ++++++++--- stores/ActivityFeedStore.js | 15 ++++++++++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/actions/activityfeed/loadActivities.js b/actions/activityfeed/loadActivities.js index c58bf0dc1..b02856d96 100644 --- a/actions/activityfeed/loadActivities.js +++ b/actions/activityfeed/loadActivities.js @@ -17,6 +17,8 @@ export default function loadActivities(context, payload, done) { return; } + context.dispatch('LOAD_ACTIVITIES_LOAD', {loadingIndicator: true}); + context.service.read('activities.list', payload, {timeout: 20 * 1000}, (err, res) => { if (err) { log.error(context, {filepath: __filename}); diff --git a/components/Deck/InfoPanel/InfoPanel.js b/components/Deck/InfoPanel/InfoPanel.js index 170c49a31..f59d85452 100644 --- a/components/Deck/InfoPanel/InfoPanel.js +++ b/components/Deck/InfoPanel/InfoPanel.js @@ -6,6 +6,7 @@ import InfoPanelHeader from './InfoPanelHeader'; import InfoPanelInfoView from './InfoPanelInfoView'; import {equals} from '../../../common.js'; import ContributorsStore from '../../../stores/ContributorsStore'; +import ActivityFeedStore from '../../../stores/ActivityFeedStore'; class InfoPanel extends React.Component { constructor(props) { @@ -26,12 +27,15 @@ class InfoPanel extends React.Component { componentWillUnmount() { this.props.ContributorsStore.contributors = []; + this.props.ActivityFeedStore.activities = []; this.isLoading = true; } isContentUndefined() { return this.props.ContributorsStore.contributors === undefined - || this.props.ContributorsStore.contributors === []; + || this.props.ContributorsStore.contributors === [] + || this.props.ActivityFeedStore.activities === undefined + || this.props.ActivityFeedStore.activities === []; } render() { @@ -42,9 +46,10 @@ class InfoPanel extends React.Component { InfoPanel.contextTypes = { executeAction: React.PropTypes.func.isRequired }; -InfoPanel = connectToStores(InfoPanel, [ContributorsStore], (context, props) => { +InfoPanel = connectToStores(InfoPanel, [ContributorsStore, ActivityFeedStore], (context, props) => { return { - ContributorsStore: context.getStore(ContributorsStore).getState() + ContributorsStore: context.getStore(ContributorsStore).getState(), + ActivityFeedStore: context.getStore(ActivityFeedStore).getState() }; }); diff --git a/stores/ActivityFeedStore.js b/stores/ActivityFeedStore.js index f2594a5b5..0728d9b26 100644 --- a/stores/ActivityFeedStore.js +++ b/stores/ActivityFeedStore.js @@ -9,12 +9,14 @@ class ActivityFeedStore extends BaseStore { this.selector = {}; this.hasMore = true; this.presentations = []; + this.loadingIndicator = false; } updateActivities(payload) { this.activities = payload.activities; this.activityType = payload.activityType; this.selector = payload.selector; this.hasMore = payload.hasMore; + this.loadingIndicator = false; this.emitChange(); } loadMoreActivities(payload) { @@ -27,6 +29,7 @@ class ActivityFeedStore extends BaseStore { } updateActivityType(payload) { this.activityType = payload.activityType; + this.loadingIndicator = false; this.emitChange(); } // incrementLikes(payload) { @@ -59,6 +62,7 @@ class ActivityFeedStore extends BaseStore { // } addActivity(payload) { const activity = payload.activity; + this.loadingIndicator = false; if (this.selector.stype === activity.content_kind && this.selector.sid === activity.content_id || activity.activity_type === 'move' && this.selector.stype === 'deck' && this.selector.sid === activity.move_info.source_id) { this.activities.unshift(activity);//add to the beginning @@ -70,6 +74,7 @@ class ActivityFeedStore extends BaseStore { } } addActivities(payload) { + this.loadingIndicator = false; payload.activities.forEach((activity) => { if (this.selector.stype === activity.content_kind && this.selector.sid === activity.content_id) { this.activities.unshift(activity);//add to the beginning @@ -82,6 +87,7 @@ class ActivityFeedStore extends BaseStore { this.emitChange(); } addLikeActivity(payload) { + this.loadingIndicator = false; if (payload.selector.stype === 'deck') { let activity = { activity_type: 'react', @@ -103,6 +109,7 @@ class ActivityFeedStore extends BaseStore { } } removeLikeActivity(payload) { + this.loadingIndicator = false; //find like activity and remove it if (payload.selector.stype === 'deck') { let i = 0; @@ -119,6 +126,7 @@ class ActivityFeedStore extends BaseStore { } } updatePresentations(payload) { + this.loadingIndicator = false; // console.log('ActivityFeedStore: updatePresentations', payload); this.presentations = payload; this.emitChange(); @@ -143,6 +151,10 @@ class ActivityFeedStore extends BaseStore { this.hasMore = state.hasMore; this.presentations = state.presentations; } + loading(payload){ + this.loadingIndicator = payload.loadingIndicator; + this.emitChange(); + } } ActivityFeedStore.storeName = 'ActivityFeedStore'; @@ -157,7 +169,8 @@ ActivityFeedStore.handlers = { 'ADD_ACTIVITIES_SUCCESS': 'addActivities', 'LIKE_ACTIVITY_SUCCESS': 'addLikeActivity', 'DISLIKE_ACTIVITY_SUCCESS': 'removeLikeActivity', - 'LOAD_PRESENTATIONS_SUCCESS': 'updatePresentations' + 'LOAD_PRESENTATIONS_SUCCESS': 'updatePresentations', + 'LOAD_ACTIVITIES_LOAD': 'loading' }; export default ActivityFeedStore; From 71898e18a01bd52061825fc019767276f2bdc8c3 Mon Sep 17 00:00:00 2001 From: Viktor Kovtun Date: Tue, 23 Oct 2018 11:58:40 +0200 Subject: [PATCH 08/10] Fixed merging error. --- components/Deck/InfoPanel/InfoPanelInfoView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/Deck/InfoPanel/InfoPanelInfoView.js b/components/Deck/InfoPanel/InfoPanelInfoView.js index 1bcb3c738..41e5366a1 100644 --- a/components/Deck/InfoPanel/InfoPanelInfoView.js +++ b/components/Deck/InfoPanel/InfoPanelInfoView.js @@ -302,7 +302,6 @@ class InfoPanelInfoView extends React.Component {
} -
{ translationMissing && canEdit ?
@@ -393,6 +392,7 @@ InfoPanelInfoView.contextTypes = { executeAction: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, }; + InfoPanelInfoView= connectToStores(InfoPanelInfoView, [ActivityFeedStore, DeckTreeStore, TranslationStore, PermissionsStore, ContentStore], (context, props) => { return { ActivityFeedStore: context.getStore(ActivityFeedStore).getState(), From 9a75ebe6a820843c0036ccd72d741ca8a15ad0a9 Mon Sep 17 00:00:00 2001 From: kadevgraaf Date: Mon, 29 Oct 2018 10:03:59 +0100 Subject: [PATCH 09/10] update reveal.js --- custom_modules/reveal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_modules/reveal.js b/custom_modules/reveal.js index 16089caa3..94cbb6cf3 160000 --- a/custom_modules/reveal.js +++ b/custom_modules/reveal.js @@ -1 +1 @@ -Subproject commit 16089caa3e0fd9a56f7ebf5d47b482f32922217f +Subproject commit 94cbb6cf334540ae2058dff4516f16498732b06b From 6aef2beaa18e072db34cfd380ea2ebab39b8757b Mon Sep 17 00:00:00 2001 From: Viktor Kovtun Date: Fri, 30 Nov 2018 16:45:12 +0100 Subject: [PATCH 10/10] Fixed not working loading indicator after someone deleted InfoPanel.js and I merged that deletion with no consideration of the code. --- components/Deck/Deck.js | 52 ++++++++++++++----- .../Deck/InfoPanel/InfoPanelInfoView.js | 21 +------- 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/components/Deck/Deck.js b/components/Deck/Deck.js index 80cabf23f..9e4de87e2 100644 --- a/components/Deck/Deck.js +++ b/components/Deck/Deck.js @@ -12,22 +12,49 @@ import SlideEditLeftPanel from './SlideEditLeftPanel/SlideEditLeftPanel'; import ContentPanel from './ContentPanel/ContentPanel'; import NavigationPanel from './NavigationPanel/NavigationPanel'; import ContentModulesPanel from './ContentModulesPanel/ContentModulesPanel'; -//import ActivityFeedPanel from './ActivityFeedPanel/ActivityFeedPanel'; -//import ServiceUnavailable from '../Error/ServiceUnavailable';//NOTE error code has been refactored - this component doesn't exist anymore, code was moved to Error.js in same directory import InfoPanelInfoView from './InfoPanel/InfoPanelInfoView'; import TranslationStore from '../../stores/TranslationStore'; -import { FormattedMessage, defineMessages } from 'react-intl'; +import ContributorsStore from '../../stores/ContributorsStore'; +import {equals} from '../../common'; class Deck extends React.Component { - handleExpandClick(){ - this.context.executeAction(hideLeftColumn, {}); - return false; + constructor(props) { + super(props); + this.isLoading = this.isContentUndefined(); } - handleCollapseClick(){ - this.context.executeAction(restoreDeckPageLayout, {}); - return false; + + // handleExpandClick(){ + // this.context.executeAction(hideLeftColumn, {}); + // return false; + // } + // + // handleCollapseClick(){ + // this.context.executeAction(restoreDeckPageLayout, {}); + // return false; + // } + + shouldComponentUpdate(nextProps, nextState) { + let samePropsState = equals(this.props, nextProps); + this.isLoading = this.isContentUndefined(); + // Content should be updated only when properties have changed. + return !this.isLoading && !samePropsState; } + + componentWillReceiveProps(nextProps) { + this.isLoading = this.isContentUndefined(); + } + + componentWillUnmount() { + this.props.ContributorsStore.contributors = []; + this.isLoading = true; + } + + isContentUndefined() { + return this.props.ContributorsStore.contributors === undefined + || this.props.ContributorsStore.contributors === []; + } + render() { const error = this.props.ServiceErrorStore.error; let status = this.props.DeckPageStore.componentsStatus; @@ -212,7 +239,7 @@ class Deck extends React.Component { rightPanel = (
- +
@@ -251,12 +278,13 @@ Deck.contextTypes = { executeAction: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, }; -Deck = connectToStores(Deck, [DeckPageStore, ServiceErrorStore, UserProfileStore, TranslationStore], (context, props) => { +Deck = connectToStores(Deck, [DeckPageStore, ServiceErrorStore, UserProfileStore, TranslationStore, ContributorsStore], (context, props) => { return { DeckPageStore: context.getStore(DeckPageStore).getState(), ServiceErrorStore: context.getStore(ServiceErrorStore).getState(), UserProfileStore: context.getStore(UserProfileStore).getState(), - TranslationStore: context.getStore(TranslationStore).getState() + TranslationStore: context.getStore(TranslationStore).getState(), + ContributorsStore: context.getStore(ContributorsStore).getState() }; }); export default Deck; diff --git a/components/Deck/InfoPanel/InfoPanelInfoView.js b/components/Deck/InfoPanel/InfoPanelInfoView.js index 624559a35..5f14bc6aa 100644 --- a/components/Deck/InfoPanel/InfoPanelInfoView.js +++ b/components/Deck/InfoPanel/InfoPanelInfoView.js @@ -29,7 +29,7 @@ class InfoPanelInfoView extends React.Component { } shouldComponentUpdate(nextProps, nextState) { - let samePropsState = equals(this.props, nextProps); + const samePropsState = equals(this.props, nextProps); this.isLoading = nextProps.loadingIndicator; // Content should be updated only when properties have changed. return !samePropsState; @@ -59,24 +59,6 @@ class InfoPanelInfoView extends React.Component { return (
{this.isLoading &&
Loading
} -
- {this.context.intl.formatMessage(this.messages.selectLanguage)}: {currentLanguageName ? ('(' + currentLanguageName + ')') : ''}} - icon={null} - aria-label="Select language" data-tooltip="Select language" - defaultValue={activeLanguage} options={languageOptions} onChange={this.changeCurrentLanguage.bind(this)} /> -
-
- { - this.props.DeckTreeStore.revisionId !== this.props.DeckTreeStore.latestRevisionId && -
- - - Updated version available - -
- } { showZoomControls &&
@@ -107,6 +89,7 @@ class InfoPanelInfoView extends React.Component {
} +