diff --git a/actions/loadDeck.js b/actions/loadDeck.js
index 746a839f7..4106b4c61 100644
--- a/actions/loadDeck.js
+++ b/actions/loadDeck.js
@@ -37,6 +37,11 @@ import log from './log/clog';
export default function loadDeck(context, payload, done) {
log.info(context); // do not remove such log messages. If you don't want to see them, change log level in config
context.dispatch('UPDATE_MODE', {mode: 'loading'});
+
+ // resets the deck view store
+ // TODO (what other store to reset ???)
+ context.dispatch('LOAD_DECK_PAGE_START');
+
if (!(AllowedPattern.DECK_ID.test(payload.params.id))) {
context.executeAction(deckIdTypeError, payload, done);
return;
@@ -102,16 +107,6 @@ export default function loadDeck(context, payload, done) {
payload.params.jwt = context.getStore(UserProfileStore).getState().jwt;
- let permissionsPromise;
- //if user is not logged in, only allow view mode and reset permissions, else load this user's permissions on the selected root deck
- if (!payload.params.jwt){
- if (!payload.query.interestedUser) //NOTE should not be changed in the special case: Link from email for deck owner to add new editor
- payloadCustom.params.mode = 'view';
- permissionsPromise = context.executeAction(resetPermissions, payloadCustom);
- } else {
- permissionsPromise = context.executeAction(loadPermissions, payloadCustom);
- }
-
context.dispatch('UPDATE_DECK_PAGE_CONTENT', payloadCustom);
pageTitle = pageTitle + ' | ' + payloadCustom.params.stype + ' | ' + payloadCustom.params.sid + ' | ' + payloadCustom.params.mode;
if((currentState.selector.id === payloadCustom.params.id) && (currentState.selector.spath === payloadCustom.params.spath)){
@@ -131,6 +126,12 @@ export default function loadDeck(context, payload, done) {
// load translation stuff
context.executeAction(loadNodeTranslations, payload.params, (err, results) => {
+ if (err) {
+ // log the error and return!!!
+ log.error(context, {filepath: __filename, message: err.message});
+ return done(err);
+ }
+
//load all required actions in parallel
async.parallel([
(callback) => {
@@ -141,6 +142,16 @@ export default function loadDeck(context, payload, done) {
}, callback);
},
(callback) => {
+ let permissionsPromise;
+ //if user is not logged in, only allow view mode and reset permissions, else load this user's permissions on the selected root deck
+ if (!payload.params.jwt){
+ if (!payload.query.interestedUser) //NOTE should not be changed in the special case: Link from email for deck owner to add new editor
+ payloadCustom.params.mode = 'view';
+ permissionsPromise = context.executeAction(resetPermissions, payloadCustom);
+ } else {
+ permissionsPromise = context.executeAction(loadPermissions, payloadCustom);
+ }
+
permissionsPromise.then(() => {
let permissions = context.getStore(PermissionsStore).getState().permissions;
//special handling for special case: Link from email for deck owner to add new editor
diff --git a/actions/loadDeckView.js b/actions/loadDeckView.js
index 156963249..3237cf11a 100644
--- a/actions/loadDeckView.js
+++ b/actions/loadDeckView.js
@@ -16,8 +16,7 @@ export default function loadDeckView(context, payload, done) {
context.service.read('deck.content', payload, {timeout: 20 * 1000}, (err, res) => {
if (err) {
- console.log(err);
- log.error(context, {filepath: __filename});
+ log.error(context, {filepath: __filename, message: err.message });
context.executeAction(serviceUnavailable, payload, done);
return;
} else {
diff --git a/actions/loadLegacy.js b/actions/loadLegacy.js
index 08e2f6def..3c5481d0d 100644
--- a/actions/loadLegacy.js
+++ b/actions/loadLegacy.js
@@ -10,7 +10,7 @@ export default function loadLegacy(context, payload, done) {
context.executeAction(serviceUnavailable, payload, done);
//context.dispatch('LOAD_FEATURED_FAILURE', err);
} else {
- done({'statusCode':'301','redirectURL': '/deck/' + res.new_id});
+ done({'statusCode': 301,'redirectURL': '/deck/' + res.new_id});
}
});
}
diff --git a/actions/translation/loadNodeTranslations.js b/actions/translation/loadNodeTranslations.js
index 5f8151971..6358a835b 100644
--- a/actions/translation/loadNodeTranslations.js
+++ b/actions/translation/loadNodeTranslations.js
@@ -6,8 +6,8 @@ export default function loadNodeTranslations(context, payload, done) {
context.service.read('decktree.nodetranslation', payload, {timeout: 20 * 1000}, (err, res) => {
if (err) {
- log.error(context, {filepath: __filename});
- context.executeAction(serviceUnavailable, payload, done);
+ log.error(context, {filepath: __filename, message: err.message});
+ done(err);
} else {
context.dispatch('LOAD_TRANSLATIONS_SUCCESS', res);
done();
diff --git a/components/Deck/ContentPanel/SlideModes/SlideViewPanel/SlideViewPanel.js b/components/Deck/ContentPanel/SlideModes/SlideViewPanel/SlideViewPanel.js
index 31e24723a..f2f8b359c 100644
--- a/components/Deck/ContentPanel/SlideModes/SlideViewPanel/SlideViewPanel.js
+++ b/components/Deck/ContentPanel/SlideModes/SlideViewPanel/SlideViewPanel.js
@@ -50,7 +50,7 @@ class SlideViewPanel extends React.Component {
deckTheme = this.props.DeckTreeStore.theme;
}
}
- if (this.currentID === selector.sid){
+ if (this.currentID === selector.sid && this.props.SlideViewStore.slideId) {
let hideSpeakerNotes = true;
if (this.props.SlideViewStore.speakernotes !== '' && this.props.SlideViewStore.speakernotes !== ' '){hideSpeakerNotes = false;}
@@ -73,8 +73,7 @@ class SlideViewPanel extends React.Component {
};
return (
- {(this.currentID !== selector.sid) ?
: ''}
- {this.slideContentView}
+ {this.slideContentView ||
}
);
}
diff --git a/components/Deck/DeckLandingPage.js b/components/Deck/DeckLandingPage.js
index c8e7491c2..61a9c05a2 100644
--- a/components/Deck/DeckLandingPage.js
+++ b/components/Deck/DeckLandingPage.js
@@ -4,6 +4,7 @@ import { NavLink } from 'fluxible-router';
import { Grid, Divider, Button, Header, Image, Icon, Item, Label, Menu, Segment, Container } from 'semantic-ui-react';
import { connectToStores } from 'fluxible-addons-react';
+import ContentStore from '../../stores/ContentStore';
import DeckPageStore from '../../stores/DeckPageStore';
import DeckViewStore from '../../stores/DeckViewStore';
import ContentLikeStore from '../../stores/ContentLikeStore';
@@ -55,8 +56,170 @@ class DeckLandingPage extends React.Component {
return presLocation;
}
+ getPlaceholder() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This work is licensed under Creative Commons Attribution-ShareAlike 4.0 International License
+
+
+
+
+
+
+
+
+
+
+
+ );
+ }
+
render() {
let deckData = this.props.DeckViewStore.deckData;
+ if (lodash.isEmpty(deckData)) return this.getPlaceholder();
let firstSlide = (this.props.DeckViewStore.slidesData && this.props.DeckViewStore.slidesData.children && this.props.DeckViewStore.slidesData.children[0]);
const totalSlides = lodash.get(this.props.DeckViewStore.slidesData, 'children.length', undefined);
@@ -296,8 +459,17 @@ class DeckLandingPage extends React.Component {
}
}
-DeckLandingPage = connectToStores(DeckLandingPage, [ContentLikeStore, DeckPageStore, DeckViewStore, TranslationStore, ContentModulesStore, SimilarContentStore], (context, props) => {
+DeckLandingPage = connectToStores(DeckLandingPage, [
+ ContentStore,
+ ContentLikeStore,
+ DeckPageStore,
+ DeckViewStore,
+ TranslationStore,
+ ContentModulesStore,
+ SimilarContentStore,
+], (context, props) => {
return {
+ ContentStore: context.getStore(ContentStore).getState(),
ContentLikeStore: context.getStore(ContentLikeStore).getState(),
DeckPageStore: context.getStore(DeckPageStore).getState(),
DeckViewStore: context.getStore(DeckViewStore).getState(),
diff --git a/configs/routes.js b/configs/routes.js
index 0ab12d7a9..f790fc42b 100644
--- a/configs/routes.js
+++ b/configs/routes.js
@@ -23,6 +23,7 @@ import loadImportFile from '../actions/loadImportFile';
import loadPresentation from '../actions/loadPresentation';
import loadAddDeck from '../actions/loadAddDeck';
import notFoundError from '../actions/error/notFoundError';
+import serviceUnavailable from '../actions/error/serviceUnavailable';
import loadResetPassword from '../actions/loadResetPassword';
import async from 'async';
import { chooseAction } from '../actions/user/userprofile/chooseAction';
@@ -381,7 +382,16 @@ export default {
handler: require('../components/Deck/DeckLandingPage'),
page: 'decklandingpage',
action: (context, payload, done) => {
- context.executeAction(loadDeck, payload, done);
+ context.executeAction(loadDeck, payload, (err) => {
+ if (err) {
+ if (err.statusCode === 404) {
+ return context.executeAction(notFoundError, payload, done);
+ } else {
+ return context.executeAction(serviceUnavailable, payload, done);
+ }
+ }
+ done();
+ });
}
},
@@ -397,13 +407,18 @@ export default {
},
(callback) => {
context.executeAction(loadDeckStats, {deckId: payload.params.id}, callback);
- },
+ }],
(err, result) => {
- if(err) console.log(err);
+ if (err) {
+ if (err.statusCode === 404) {
+ return context.executeAction(notFoundError, payload, done);
+ } else {
+ return context.executeAction(serviceUnavailable, payload, done);
+ }
+ }
done();
}
- ]);
-
+ );
}
},
@@ -429,7 +444,17 @@ export default {
}
}
- context.executeAction(loadDeck, payload, done);
+ context.executeAction(loadDeck, payload, (err) => {
+ if (err) {
+ // check for either 404 or 422. 422 is returned from deck service when the deck/slide combo do not match
+ if (err.statusCode === 404 || err.statusCode === 422) {
+ return context.executeAction(notFoundError, payload, done);
+ } else {
+ return context.executeAction(serviceUnavailable, payload, done);
+ }
+ }
+ done();
+ });
}
},
@@ -448,7 +473,7 @@ export default {
];
urlParts = urlParts.filter((u) => !!u);
- done({statusCode: '301', redirectURL: urlParts.join('/')});
+ done({statusCode: 301, redirectURL: urlParts.join('/')});
},
},
legacydeck: {
@@ -656,12 +681,18 @@ export default {
payload.params.sid = payload.params.slideID;//needs to be reset for loadPresentation
payload.params.language = payload.query.language;
context.executeAction(loadPresentation, payload, callback);
- },
+ }],
(err, result) => {
- if(err) console.log(err);
+ if (err) {
+ if (err.statusCode === 404) {
+ return context.executeAction(notFoundError, payload, done);
+ } else {
+ return context.executeAction(serviceUnavailable, payload, done);
+ }
+ }
done();
}
- ]);
+ );
}
},
presentationIE: {
@@ -683,12 +714,18 @@ export default {
// adding language to the params
payload.params.language = payload.query.language;
context.executeAction(loadPresentation, payload, callback);
- },
+ }],
(err, result) => {
- if(err) console.log(err);
+ if (err) {
+ if (err.statusCode === 404) {
+ return context.executeAction(notFoundError, payload, done);
+ } else {
+ return context.executeAction(serviceUnavailable, payload, done);
+ }
+ }
done();
}
- ]);
+ );
}
},
print: {
@@ -714,12 +751,18 @@ export default {
// adding language to the params
payload.params.language = payload.query.language;
context.executeAction(loadPresentation, payload, callback);
- },
+ }],
(err, result) => {
- if(err) console.log(err);
+ if (err) {
+ if (err.statusCode === 404) {
+ return context.executeAction(notFoundError, payload, done);
+ } else {
+ return context.executeAction(serviceUnavailable, payload, done);
+ }
+ }
done();
}
- ]);
+ );
}
},
oldSlugPresentation: {
@@ -735,7 +778,7 @@ export default {
];
urlParts = urlParts.filter((u) => !!u);
- done({statusCode: '301', redirectURL: urlParts.join('/')});
+ done({statusCode: 301, redirectURL: urlParts.join('/')});
},
},
neo4jguide: {
@@ -760,7 +803,7 @@ export default {
];
urlParts = urlParts.filter((u) => !!u);
- done({statusCode: '301', redirectURL: urlParts.join('/')});
+ done({statusCode: 301, redirectURL: urlParts.join('/')});
},
},
importfile: {
diff --git a/server/handleServerRendering.js b/server/handleServerRendering.js
index ee32707cd..286f49298 100644
--- a/server/handleServerRendering.js
+++ b/server/handleServerRendering.js
@@ -120,26 +120,25 @@ export default function handleServerRendering(req, res, next){
reqId: req.reqId
}, (err) => {
if (err) {
- if (err.statusCode && err.statusCode === '301') {
- //console.log('REDIRECTING to '+ JSON.stringify(err));
+ if (err.statusCode === 301) {
res.redirect(301, err.redirectURL);
- }else
- if (err.statusCode && err.statusCode === '404') {
+ } else if (err.statusCode) {
+ // render page and also set status to the error code
let html = renderApp(req, res, context);
debug('Sending markup');
res.type('html');
res.status(err.statusCode);
log.error({Id: res.reqId, URL: req.url, StatusCode: res.statusCode, StatusMessage: res.statusMessage, Message: 'Sending response'});
+ res.write('' + html);
res.end();
- return;
- }else{
+ } else {
+ // TODO render page even though there was an error ????
let html = renderApp(req, res, context);
debug('Sending markup');
res.type('html');
res.write('' + html);
log.error({Id: res.reqId, URL: req.url, StatusCode: res.statusCode, StatusMessage: res.statusMessage, Message: 'Sending response'});
res.end();
- return;
}
} else {
diff --git a/services/deck.js b/services/deck.js
index dacf2cbda..d21a51ad1 100644
--- a/services/deck.js
+++ b/services/deck.js
@@ -225,6 +225,8 @@ export default {
return userPromisesMap[user] = userPromisesMap[user] || rp.get({
uri: Microservices.user.uri + '/user/' + user.toString(),
json: true,
+ }).catch((err) => {
+ // ignore this for now, return nothing
});
});
return Promise.all(userPromises);
@@ -252,8 +254,8 @@ export default {
callback(null, {
deckData,
slidesData,
- creatorData: usersData[0],
- ownerData: usersData[1],
+ creatorData: usersData[0] || {},
+ ownerData: usersData[1] || {},
originCreatorData: usersData[2] || {},
});
}).catch((err) => {
diff --git a/services/decktree.js b/services/decktree.js
index 22d1e279e..cffbe70e4 100644
--- a/services/decktree.js
+++ b/services/decktree.js
@@ -30,8 +30,7 @@ export default {
}).then((res) => {
callback(null, {translations: res, selector: selector, language: args.language});
}).catch((err) => {
- console.log(err);
- callback(null, {translations: [], selector: selector, language: args.language});
+ callback(err);
});
}
diff --git a/stores/DeckViewStore.js b/stores/DeckViewStore.js
index 4d4aa0d7d..c0fd69e08 100644
--- a/stores/DeckViewStore.js
+++ b/stores/DeckViewStore.js
@@ -34,6 +34,16 @@ class DeckViewStore extends BaseStore {
this.emitChange();
}
+ resetContent() {
+ this.deckData = {};
+ this.slidesData = {};
+ this.creatorData = {};
+ this.ownerData = {};
+ this.originCreatorData = {};
+ this.deckViewPanelHeight = 450;
+ this.emitChange();
+ }
+
getState() {
return {
deckData: this.deckData,
@@ -59,6 +69,7 @@ class DeckViewStore extends BaseStore {
DeckViewStore.storeName = 'DeckViewStore';
DeckViewStore.handlers = {
+ 'LOAD_DECK_PAGE_START': 'resetContent',
'LOAD_DECK_CONTENT_SUCCESS': 'updateContent',
'UPDATE_DECK_VIEW_PANEL_HEIGHT': 'updateDeckViewPanelHeight',
'INCREMENT_DECK_VIEW_COUNTER': 'incrementDeckViewCounter'
diff --git a/stores/SlideViewStore.js b/stores/SlideViewStore.js
index f5d548fed..4a8f80f81 100644
--- a/stores/SlideViewStore.js
+++ b/stores/SlideViewStore.js
@@ -14,6 +14,16 @@ class SlideViewStore extends BaseStore {
this.annotations = [];
}
+ resetContent() {
+ this.id = '';
+ this.slideId = '';
+ this.title = '';
+ this.content = '';
+ this.speakernotes = '';
+ this.tags = [];
+ this.emitChange();
+ }
+
updateContent(payload) {
//this.id = payload.slide.id;
this.slideId = payload.selector.sid;
@@ -78,6 +88,7 @@ class SlideViewStore extends BaseStore {
SlideViewStore.storeName = 'SlideViewStore';
SlideViewStore.handlers = {
+ 'LOAD_DECK_PAGE_START': 'resetContent',
'LOAD_SLIDE_CONTENT_SUCCESS': 'updateContent',
'ZOOM': 'zoomContent'
};