diff --git a/actions/import/storeTags.js b/actions/import/storeTags.js new file mode 100644 index 000000000..909e9f2c2 --- /dev/null +++ b/actions/import/storeTags.js @@ -0,0 +1,8 @@ +import { shortTitle } from '../../configs/general'; +const log = require('../log/clog'); + +export default function storeTags(context, payload, done) { + log.info(context); + context.dispatch('STORE_TAGS', payload); + done(); +} 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 5ad1bddac..3237cf11a 100644 --- a/actions/loadDeckView.js +++ b/actions/loadDeckView.js @@ -16,19 +16,14 @@ 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 { // console.log('loadDeckView params', payload.params, '\n', payload); res.isRootDeck = payload.params.spath === ''; context.dispatch('LOAD_DECK_CONTENT_SUCCESS', res); - context.dispatch('LOAD_DECK_METADATA_SUCCESS', { - thumbnailID: res.slidesData.children[0].id, - thumbnailTheme: res.slidesData.theme, - description: res.deckData.description - }); + context.dispatch('LOAD_DECK_METADATA_SUCCESS', {thumbnailID: res.slidesData.children[0].id}); } let pageTitle = shortTitle + ' | ' + res.slidesData.title; let cleanTitle = pageTitle.replace(/<\/?[^>]+(>|$)/g, '').replace(/'/g, '\'').replace(/"/g, '\"'); 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/slide/changeSlideTransition.js b/actions/slide/changeSlideTransition.js index e42207c44..6fc2cd398 100644 --- a/actions/slide/changeSlideTransition.js +++ b/actions/slide/changeSlideTransition.js @@ -2,9 +2,10 @@ import {shortTitle} from '../../configs/general'; import serviceUnavailable from '../error/serviceUnavailable'; const log = require('../log/clog'); -export default function changeSlideSize(context, payload, done) { +export default function changeSlideTransition(context, payload, done) { //catched by slideEditStore context.dispatch('CHANGE_SLIDE_TRANSITION', { - slideTransition: payload.slideTransition + slideTransition: payload.slideTransition //, + // transitionType: payload.transitionType // }); } diff --git a/actions/slide/loadSlideView.js b/actions/slide/loadSlideView.js index 5675e9b46..a57c8a284 100644 --- a/actions/slide/loadSlideView.js +++ b/actions/slide/loadSlideView.js @@ -24,10 +24,6 @@ export default function loadSlideView(context, payload, done) { } else { context.dispatch('LOAD_SLIDE_CONTENT_SUCCESS', res); context.dispatch('LOAD_SLIDE_EDIT_SUCCESS', res); - context.dispatch('LOAD_DECK_METADATA_SUCCESS', { - thumbnailID: res.selector.sid, - thumbnailTheme: context.getStore(DeckTreeStore).theme - }); } let deckTitle = context.getStore(DeckTreeStore).getState().deckTree.get('title'); let pageTitle = shortTitle + ' | ' + deckTitle + ' | ' + res.slide.title; diff --git a/actions/slide/saveSlideWithDeckTransition.js b/actions/slide/saveSlideWithDeckTransition.js new file mode 100644 index 000000000..1aac39ca8 --- /dev/null +++ b/actions/slide/saveSlideWithDeckTransition.js @@ -0,0 +1,26 @@ +const log = require('../log/clog'); +import saveSlide from './saveSlide'; + +export default function saveSlideWithDeckTransition(context, payload, done) { + let args = { + id: payload.currentSlidePayload.deckID + }; + context.service.read('deck.slides', args, {timeout: 20 * 1000}, (err, res) => { + res.slides.map((slide) => { + if(slide.id === payload.currentSlidePayload.id) { + context.executeAction(saveSlide, payload.currentSlidePayload); + } else { + let otherPayload = { + id: slide.id, + + transition: payload.currentSlidePayload.transition + }; + // Extract necessary information from each slide, add transition and update it in deck-service. + + } + }); + }); + + + +} 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/AddDeck/AddDeck.js b/components/AddDeck/AddDeck.js index 1acceec94..4c7665802 100644 --- a/components/AddDeck/AddDeck.js +++ b/components/AddDeck/AddDeck.js @@ -14,6 +14,7 @@ import checkNoOfSlides from '../../actions/addDeck/checkNoOfSlides'; import importCanceled from '../../actions/import/importCanceled'; import importFinished from '../../actions/import/importFinished'; import uploadFile from '../../actions/import/uploadFile'; +import storeTags from '../../actions/import/storeTags'; import addActivity from '../../actions/activityfeed/addActivity'; import publishDeck from '../../actions/addDeck/publishDeck'; import ImportModal from '../Import/ImportModal'; @@ -33,6 +34,7 @@ class AddDeck extends React.Component { constructor(props) { super(props); this.percentage = 0; + this.defaultTagNames = [];// used for saving defaultName properties for tags } componentDidMount() { // let that = this; @@ -75,7 +77,8 @@ class AddDeck extends React.Component { } handleAddDeck(x) { //console.log('handleAddDeck'); - + this.saveTags(); + this.context.executeAction(addDeckDeleteError, null); //validate input @@ -86,7 +89,14 @@ class AddDeck extends React.Component { const { value: educationLevel } = this.refs.dropdown_level.getSelectedItem(); // const license = this.refs.select_licenses.value; const license = 'CC BY-SA';//default license - const tags = [...this.tagInput.getSelected(), ...this.topicInput.getSelected()]; + let tags = [...this.tagInput.getSelected(), ...this.topicInput.getSelected()]; + tags.forEach((tag) => { + // check whether we have earlier assigned defaultName to tagName (in saveTags function) for this tag and restore the original state + if (this.defaultTagNames.includes(tag.tagName)) { + tag.defaultName = tag.tagName; + delete tag.tagName; + } + }); const acceptedConditions = this.refs.checkbox_conditions.checked; const acceptedImagesLicense = this.refs.checkbox_imageslicense.checked; //console.log(title, language, description, theme, license, tags, acceptedConditions); @@ -413,6 +423,25 @@ class AddDeck extends React.Component { console.error('Submission not possible - no file or not pptx/odp/zip'); } } + + saveTags() { + let tags = this.tagInput.getSelected(); + tags.forEach((tag) => { + if (!tag.tagName && tag.defaultName) { + tag.tagName = tag.defaultName;//assign defaultName to tagName to avoid errors during the initialization of the TagInput component + this.defaultTagNames.push((tag.defaultName));//save defaultName in the array so that in the end we can restore the tag state in handleAddDeck + } + }); + let topics = this.topicInput.getSelected(); + topics.forEach((topic) => { + if (!topic.tagName && topic.defaultName) { + topic.tagName = topic.defaultName; + this.defaultTagNames.push((topic.defaultName)); + } + }); + //save tags in the store so that they can be restored during the initialization of TagInput component + this.context.executeAction(storeTags, {tags:tags, topics: topics}); + } render() { //redirect to new deck if created @@ -611,13 +640,13 @@ class AddDeck extends React.Component {
- (this.topicInput = i)} tagFilter={{ tagType: 'topic' }} aria-labelledby="topics_label" aria-describedby="describe_topic" /> + (this.topicInput = i)} tagFilter={{ tagType: 'topic' }} aria-labelledby="topics_label" aria-describedby="describe_topic" />
- (this.tagInput = i)} allowAdditions={true} aria-labelledby="tags_label" aria-describedby="describe_tags" /> + (this.tagInput = i)} allowAdditions={true} aria-labelledby="tags_label" aria-describedby="describe_tags" />
@@ -637,7 +666,7 @@ class AddDeck extends React.Component { defaultMessage='Select file' />
*/} - + {/* */} diff --git a/components/Deck/ContentPanel/SlideModes/SlideEditPanel/SlideContentEditor.js b/components/Deck/ContentPanel/SlideModes/SlideEditPanel/SlideContentEditor.js index f1a71c0c2..645ffe667 100644 --- a/components/Deck/ContentPanel/SlideModes/SlideEditPanel/SlideContentEditor.js +++ b/components/Deck/ContentPanel/SlideModes/SlideEditPanel/SlideContentEditor.js @@ -8,6 +8,7 @@ import SlideViewStore from '../../../../../stores/SlideViewStore'; import MediaStore from '../../../../../stores/MediaStore'; import PaintModalStore from '../../../../../stores/PaintModalStore'; import saveSlide from '../../../../../actions/slide/saveSlide'; +import saveSlideWithDeckTransition from '../../../../../actions/slide/saveSlideWithDeckTransition'; import editImageWithSrc from '../../../../../actions/paint/editImageWithSrc'; import editSVGwithSVG from '../../../../../actions/paint/editSVGwithSVG'; import handleDroppedFile from '../../../../../actions/media/handleDroppedFile'; @@ -45,41 +46,83 @@ class SlideContentEditor extends React.Component { //this.redoContent = ''; this.scaleRatio = null; - CKEDITOR.on('instanceReady', (ev) => { - ev.editor.on('fileUploadRequest', (ev2) => { - ev2.cancel(); - }); + if (typeof CKEDITOR === 'undefined') { + setTimeout(() => { + CKEDITOR.on('instanceReady', (ev) => { - ev.editor.document.on('drop', (ev2) => { - if (ev2.data.$.dataTransfer.files) { - console.log('droppped'); - if (ev2.data.$.dataTransfer.files.length !== 0) { - let file = ev2.data.$.dataTransfer.files[0]; - let params = {}; - let url = URL.createObjectURL(file); - file.preview = url; - params.file = file; - - this.context.executeAction(handleDroppedFile, file); - } - } - }); + ev.editor.on('fileUploadRequest', (ev2) => { + ev2.cancel(); + }); + + ev.editor.document.on('drop', (ev2) => { + if (ev2.data.$.dataTransfer.files) { + console.log('droppped'); + if (ev2.data.$.dataTransfer.files.length !== 0) { + let file = ev2.data.$.dataTransfer.files[0]; + let params = {}; + let url = URL.createObjectURL(file); + file.preview = url; + params.file = file; + + this.context.executeAction(handleDroppedFile, file); + } + } + }); - ev.editor.document.on('paste', (ev2) => { - if (ev2.data.$.clipboardData.files) { - console.log('pasted'); - if (ev2.data.$.clipboardData.files.length !== 0){ - let file = ev2.data.$.clipboardData.files[0]; - let params = {}; - file.preview = URL.createObjectURL(file); - params.file = file; + ev.editor.document.on('paste', (ev2) => { + if (ev2.data.$.clipboardData.files) { + console.log('pasted'); + if (ev2.data.$.clipboardData.files.length !== 0){ + let file = ev2.data.$.clipboardData.files[0]; + let params = {}; + let url = URL.createObjectURL(file); + file.preview = url; + params.file = file; + + this.context.executeAction(handleDroppedFile, file); + } + } + }); + }); + }, 500); + } else { + CKEDITOR.on('instanceReady', (ev) => { - this.context.executeAction(handleDroppedFile, file); + ev.editor.on('fileUploadRequest', (ev2) => { + ev2.cancel(); + }); + + ev.editor.document.on('drop', (ev2) => { + if (ev2.data.$.dataTransfer.files) { + console.log('droppped'); + if (ev2.data.$.dataTransfer.files.length !== 0) { + let file = ev2.data.$.dataTransfer.files[0]; + let params = {}; + let url = URL.createObjectURL(file); + file.preview = url; + params.file = file; + + this.context.executeAction(handleDroppedFile, file); + } } - } - }); - }); + }); + ev.editor.document.on('paste', (ev2) => { + if (ev2.data.$.clipboardData.files) { + console.log('pasted'); + if (ev2.data.$.clipboardData.files.length !== 0){ + let file = ev2.data.$.clipboardData.files[0]; + let params = {}; + let url = URL.createObjectURL(file); + file.preview = url; + params.file = file; + + this.context.executeAction(handleDroppedFile, file); + } + } + }); + }); + } } hasChanges = () => { @@ -894,6 +937,7 @@ class SlideContentEditor extends React.Component { let dataSources = (this.props.DataSourceStore.dataSources !== undefined) ? this.props.DataSourceStore.dataSources : []; let tags = this.props.SlideViewStore.tags? this.props.SlideViewStore: []; let transition = this.props.SlideEditStore.slideTransition ? this.props.SlideEditStore.slideTransition : 'none'; + let transitionType = this.props.SlideEditStore.transitionType ? this.props.SlideEditStore.transitionType : 'slide'; let ltiWidth = this.props.SlideEditStore.ltiWidth; @@ -912,6 +956,7 @@ class SlideContentEditor extends React.Component { */ //setTimeout(function() { + //if (transitionType === 'slide') { this.context.executeAction(saveSlide, { id: currentSelector.sid, deckID: deckID, @@ -931,6 +976,22 @@ class SlideContentEditor extends React.Component { ltiResponseHTML: ltiResponseHTML, }); //},500); + /*} else { + let currentSlidePayload = { + id: currentSelector.sid, + deckID: deckID, + title: title, + content: content, + speakernotes: speakernotes, + dataSources: dataSources, + selector: currentSelector, + tags: tags, + transition: transition + }; + this.context.executeAction(saveSlideWithDeckTransition, { + currentSlidePayload: currentSlidePayload + }); + }*/ this.resize(); //this.forceUpdate(); diff --git a/components/Deck/ContentPanel/SlideModes/SlideEditPanel/SlideEditPanel.js b/components/Deck/ContentPanel/SlideModes/SlideEditPanel/SlideEditPanel.js index 8c0d281f3..12ec36d17 100644 --- a/components/Deck/ContentPanel/SlideModes/SlideEditPanel/SlideEditPanel.js +++ b/components/Deck/ContentPanel/SlideModes/SlideEditPanel/SlideEditPanel.js @@ -22,6 +22,12 @@ class SlideEditPanel extends React.Component { this.currentID = this.props.selector.sid; } */ + if (this.currentID !== this.props.selector.sid) + { + //console.log('slide id changed - destroy/unmount SlideContentEditor component'); + this.editorcontent = ''; //destroy/unmount SlideContentEditor component + this.currentID = this.props.selector.sid; + } } componentDidMount(){ 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) ?
Loading
: ''} - {this.slideContentView} + {this.slideContentView ||
Loading
}
); } 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 ( + + + ); + } + 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/components/Deck/SlideEditLeftPanel/SlideEditLeftPanel.js b/components/Deck/SlideEditLeftPanel/SlideEditLeftPanel.js index 4e958dd62..6dd22433a 100644 --- a/components/Deck/SlideEditLeftPanel/SlideEditLeftPanel.js +++ b/components/Deck/SlideEditLeftPanel/SlideEditLeftPanel.js @@ -26,6 +26,7 @@ import changeSlideSize from '../../../actions/slide/changeSlideSize'; import changeSlideTransition from '../../../actions/slide/changeSlideTransition'; import {FormattedMessage, defineMessages} from 'react-intl'; import PaintModal from '../../Paint/PaintModal'; +import TransitionModal from './TransitionModal'; class SlideEditLeftPanel extends React.Component { @@ -898,33 +899,39 @@ class SlideEditLeftPanel extends React.Component { // default, fast or slow // TODO: make gif animations of transitions let transitionContent = ( -
+
this.handleKeyPress(evt, 'handleBack')}> - this.handleKeyPress(evt, 'handleSlideTransitionchange', 'none')}> - - - this.handleKeyPress(evt, 'handleSlideTransitionchange', 'convex')}> - - - - this.handleKeyPress(evt, 'handleSlideTransitionchange', 'fade')}> - - - - this.handleKeyPress(evt, 'handleSlideTransitionchange', 'slide')}> - - - - this.handleKeyPress(evt, 'handleSlideTransitionchange', 'zoom')}> - - - - this.handleKeyPress(evt, 'handleSlideTransitionchange', 'concave')}> - - - + this.handleKeyPress(evt, 'handleSlideTransitionchange', 'none')}> + + + this.handleKeyPress(evt, 'handleSlideTransitionchange', 'convex')}> + + + + this.handleKeyPress(evt, 'handleSlideTransitionchange', 'fade')}> + + + + this.handleKeyPress(evt, 'handleSlideTransitionchange', 'slide')}> + + + + this.handleKeyPress(evt, 'handleSlideTransitionchange', 'zoom')}> + + + + this.handleKeyPress(evt, 'handleSlideTransitionchange', 'concave')}> + + + + {/* + + + + + */}
); let normalContent = ( diff --git a/components/Deck/SlideEditLeftPanel/TransitionModal.js b/components/Deck/SlideEditLeftPanel/TransitionModal.js new file mode 100644 index 000000000..2a7c0878a --- /dev/null +++ b/components/Deck/SlideEditLeftPanel/TransitionModal.js @@ -0,0 +1,227 @@ +import { Button, Divider, Dropdown, Icon, Input, Modal, Popup, Segment } from 'semantic-ui-react'; +import {connectToStores} from 'fluxible-addons-react'; +import FocusTrap from 'focus-trap-react'; +import {FormattedMessage, defineMessages} from 'react-intl'; +import PropTypes from 'prop-types'; +import React from 'react'; +import SlideEditStore from '../../../stores/SlideEditStore'; +import changeSlideTransition from '../../../actions/slide/changeSlideTransition'; + + + +class TransitionModal extends React.Component { + constructor(props) { + super(props); + + this.state = { + modalOpen: false, + activeTrap: false, + transition: null + }; + + this.unmountTrap = this.unmountTrap.bind(this); + this.handleOpen = this.handleOpen.bind(this); + this.handleClose = this.handleClose.bind(this); + + this.messages = defineMessages({ + noTransitionMessage: { + id: 'transitionModal.noneMessage', + defaultMessage: 'No slide transition' + }, + convexTransitionMessage: { + id: 'transitionModal.convexMessage', + defaultMessage: 'Convex' + }, + fadeTransitionMessage: { + id: 'transitionModal.fadeMessage', + defaultMessage: 'Fade' + }, + slideTransitionMessage: { + id: 'transitionModal.slideMessage', + defaultMessage: 'Slide' + }, + zoomTransitionMessage: { + id: 'transitionModal.zoomMessage', + defaultMessage: 'Zoom' + }, + concaveTransitionMessage: { + id: 'transitionModal.concaveMessage', + defaultMessage: 'Concave' + }, + ///////////// + question: { + id: 'transitionModal.question', + defaultMessage: 'You are able to add this transition to the full presentation or only to this slide. What do you prefer?' + }, + cancel: { + id: 'transitionModal.cancel', + defaultMessage: 'Cancel' + }, + applyFull: { + id: 'transitionModal.applyFull', + defaultMessage: 'Apply to the full presentation' + }, + onlySlide: { + id: 'transitionModal.onlySlide', + defaultMessage: 'Apply only to this slide' + } + + }); + } + + unmountTrap() { + if(this.state.activeTrap){ + this.setState({ activeTrap: false }); + $('#app').attr('aria-hidden','false'); + } + } + + handleOpen(){ + $('#app').attr('aria-hidden', 'true'); + this.setState({ + modalOpen:true, + activeTrap:true, + transition: this.props.transition + }); + } + + handleClose() { + $('#app').attr('aria-hidden', 'false'); + this.setState({ + modalOpen: false, + activeTrap: false + }); + } + + handleTransitionType(type) { + this.context.executeAction(changeSlideTransition, { + slideTransition: this.props.transition, + transitionType: type + }); + this.handleClose(); + } + + render() { + const headerStyle = { + 'textAlign': 'center' + }; + let transitionName = ''; + let modalTrigger = ''; + let noTransition = false; + let imgSrc = ''; + let alt = ''; + switch (this.props.transition) { + case 'none': + transitionName = this.context.intl.formatMessage(this.messages.noTransitionMessage); + noTransition = true; + break; + case 'convex': + transitionName = this.context.intl.formatMessage(this.messages.convexTransitionMessage); + imgSrc = '/assets/images/slidetransitions/convex.gif'; + alt = 'Convex slide transition'; + break; + case 'fade': + transitionName = this.context.intl.formatMessage(this.messages.fadeTransitionMessage); + imgSrc = '/assets/images/slidetransitions/fade.gif'; + alt = 'Fade slide transition'; + break; + case 'slide': + transitionName = this.context.intl.formatMessage(this.messages.slideTransitionMessage); + imgSrc = '/assets/images/slidetransitions/slide.gif'; + alt = 'Slide slide transition'; + break; + case 'zoom': + transitionName = this.context.intl.formatMessage(this.messages.zoomTransitionMessage); + imgSrc = '/assets/images/slidetransitions/zoom.gif'; + alt = 'Zoom slide transition'; + break; + case 'concave': + transitionName = this.context.intl.formatMessage(this.messages.concaveTransitionMessage); + imgSrc = '/assets/images/slidetransitions/concave.gif'; + alt = 'concave slide transition'; + break; + } + + if (noTransition) { + modalTrigger = + this.handleKeyPress(evt, 'handleSlideTransitionchange', this.props.transition)}> + {transitionName} + ; + } else { + modalTrigger = + this.handleKeyPress(evt, 'handleSlideTransitionchange', this.props.transition)}> + {transitionName} + + ; + } + + + let focusTrapOptions = { + onDeactivate:this.unmountTrap, + clickOutsideDeactivates:true, + initialFocus: '#transitionModal' + this.props.transition + 'Description' + }; + return ( + + + +

Select the way you want to add the transition

+
+ + +
+ {this.context.intl.formatMessage(this.messages.question)} +
+ +
+ + +