diff --git a/backend/README.md b/backend/README.md index e704d5b..bbbff42 100644 --- a/backend/README.md +++ b/backend/README.md @@ -57,4 +57,4 @@ firebase deploy --only functions:generateThumbnail ### create-page-collaboration > This function is triggered every time a record is added to the pageCollaborations collection. -* firebase deploy --only functions:onCreatePageCollaboration +* firebase deploy --only functions:onCreatePage diff --git a/backend/functions/create-page.js b/backend/functions/create-page.js index 7eed4d2..8e62b05 100644 --- a/backend/functions/create-page.js +++ b/backend/functions/create-page.js @@ -6,6 +6,7 @@ const common = require('./common') exports.handler = async (newPagesDoc, context, database) => { console.log(`In onCreatePages:[${newPagesDoc.id}]`) + // if this page is part of a collaboration then we also publish preview if (newPagesDoc.data().parentPagesRef) { console.log(`Page document is child record`) @@ -44,7 +45,28 @@ exports.handler = async (newPagesDoc, context, database) => { } console.log('story data:', storiesDoc.data()) - console.log('newPagesDoc1:', newPagesDoc.id) + console.log('newPagesDoc id:', newPagesDoc.id) + + let background = '#000000' + if (newPagesDoc.data().quote && newPagesDoc.data().quote.background) { + background = newPagesDoc.data().quote.background + } else if ( + newPagesDoc.data().background && + newPagesDoc.data().background.color + ) { + background = newPagesDoc.data().background.color + } + + let fontColor = '#ffffff' + if (newPagesDoc.data().quote && newPagesDoc.data().quote.color) { + fontColor = newPagesDoc.data().quote.color + } else if ( + newPagesDoc.data().background && + newPagesDoc.data().background.font && + newPagesDoc.data().background.font.color + ) { + fontColor = newPagesDoc.data().background.font.color + } // save record in the previews collection const preview = { @@ -60,6 +82,9 @@ exports.handler = async (newPagesDoc, context, database) => { uid: user.uid, usersRef: usersRef, userDisplayName: user.displayName || '', + quote: newPagesDoc.data().quote ? newPagesDoc.data().quote.src : '', + fontColor: fontColor, + backgroundColor: background, previewImageUrl: imagePreviewUrl, imageFilenameOid: imageOid, created: Date.now(), diff --git a/backend/functions/delete-page.js b/backend/functions/delete-page.js index e121f3c..3cc43ee 100644 --- a/backend/functions/delete-page.js +++ b/backend/functions/delete-page.js @@ -19,25 +19,47 @@ exports.handler = async (snap, context, database, storage, bucketName) => { const bookFilename = common.getBookFilename(deletedValue.book) console.log(`bookFilename:${bookFilename}`) if (bookFilename) { - await removeFile(bucket, 'books', bookFilename) + try { + await removeFile(bucket, 'books', bookFilename) + } catch (e) { + console.log( + `Error removing file:[books/${bookFilename}] for rich text`, + e + ) + } } const richTextsFilename = common.getRichTextFilename(deletedValue.richText) console.log(`richTextsFilename:${richTextsFilename}`) if (richTextsFilename) { - await removeFile(bucket, 'richTexts', richTextsFilename) + try { + await removeFile(bucket, 'richTexts', richTextsFilename) + } catch (e) { + console.log( + `Error removing file:[richTexts/${richTextsFilename}] for rich text`, + e + ) + } } const imageFilename = common.getImageFilename(deletedValue.image) console.log(`imageFilename:${imageFilename}`) if (imageFilename) { - await common.deleteImageFromDB(database, imageFilename) + try { + await common.deleteImageFromDB(database, imageFilename) + } catch (e) { + console.log(`Error deleting image:[${imageFilename}] from DB`, e) + } } if (common.pageIsCoverToStory(database, pageOid, imageFilename)) { console.log('Page image is cover story') if (deletedValue.storyOid) { - await common.updateStoryCoverImage(database, deletedValue.storyOid) + try { + await common.updateStoryCoverImage(database, deletedValue.storyOid) + } catch (e) { + console.log(`Error updating story cover image`, e) + } } } diff --git a/ui/api/service/page.js b/ui/api/service/page.js index 9ab5e6f..311dee5 100644 --- a/ui/api/service/page.js +++ b/ui/api/service/page.js @@ -18,12 +18,14 @@ function findPages(pagesRef) { image: { ...m.data().image }, book: { ...m.data().book }, richText: { ...m.data().richText }, + quote: { ...m.data().quote }, parentPagesOid: m.data().parentPagesOid, // parentPagesRef: m.data().parentPagesRef, parentPagesRef: `pages/${m.data().parentPagesOid}`, summary: m.data().summary, comments: m.data().comments, likes: m.data().likes, + background: { ...m.data().background }, wallpaperUrl: m.data().wallpaperUrl } log('page:', page) diff --git a/ui/api/service/preview.js b/ui/api/service/preview.js index 7d43a0f..24d579b 100644 --- a/ui/api/service/preview.js +++ b/ui/api/service/preview.js @@ -12,6 +12,9 @@ function findPreviews(previewsRef) { imageFilenameOid: m.data().imageFilenameOid, pageOid: m.data().pageOid, pagesRef: m.data().pagesRef, + quote: m.data().quote, + fontColor: m.data().fontColor, + backgroundColor: m.data().backgroundColor, previewImageUrl: m.data().previewImageUrl, wallpaperUrl: m.data().wallpaperUrl, storyOid: m.data().storyOid, @@ -68,3 +71,7 @@ export function addPreview(preview) { log(`Adding preview:[${preview}]`) return DB.collection('previews').add(preview) } + + +export const BACKGROUND_COLOURS = ['#26c6da', '#3f51b5', '#ffffff', '#000000', '#C2185B', '#ff8f00'] + diff --git a/ui/components/BaseMediumViewer.vue b/ui/components/BaseMediumViewer.vue index 3363898..81f6676 100644 --- a/ui/components/BaseMediumViewer.vue +++ b/ui/components/BaseMediumViewer.vue @@ -44,7 +44,7 @@ > @@ -61,6 +61,19 @@ class="transparent" mandatory > + + + Quote + Words @@ -123,12 +138,12 @@ fill-height class="dialog-content" > - + - + @@ -161,6 +176,10 @@ export default { type: Boolean, default: false }, + isQuoteEnabled: { + type: Boolean, + default: false + }, isBookEnabled: { type: Boolean, default: false @@ -215,6 +234,13 @@ export default { if (this.isImageEnabled) count++ return count }, + showQuoteToolbarBtn: function() { + return ( + this.enabledMediumTypeCount > 1 && + this.isQuoteEnabled && + !this.canDelete + ) + }, showRichTextToolbarBtn: function() { return ( this.enabledMediumTypeCount > 1 && diff --git a/ui/components/BasePagePublish.vue b/ui/components/BasePagePublish.vue new file mode 100644 index 0000000..d845dff --- /dev/null +++ b/ui/components/BasePagePublish.vue @@ -0,0 +1,444 @@ + + + diff --git a/ui/components/MediumViewerImage.vue b/ui/components/MediumViewerImage.vue index 27d0e56..b17b940 100644 --- a/ui/components/MediumViewerImage.vue +++ b/ui/components/MediumViewerImage.vue @@ -84,6 +84,7 @@ export default { reader.onloadend = () => { this.mutableSrc = reader.result + this.$emit('image-updated', this.mutableSrc) } reader.readAsDataURL(file) diff --git a/ui/components/MediumViewerQuote.vue b/ui/components/MediumViewerQuote.vue new file mode 100644 index 0000000..c0470e2 --- /dev/null +++ b/ui/components/MediumViewerQuote.vue @@ -0,0 +1,66 @@ + + + + diff --git a/ui/components/PageComments.vue b/ui/components/PageComments.vue index 71f137f..3ca9717 100644 --- a/ui/components/PageComments.vue +++ b/ui/components/PageComments.vue @@ -104,8 +104,7 @@ export default { return { comment: undefined, commentDialog: false, - mutableComments: [], - form: false + mutableComments: [] } }, created: function() { diff --git a/ui/components/PageContributionCard.vue b/ui/components/PageContributionCard.vue index 82c5471..740de37 100644 --- a/ui/components/PageContributionCard.vue +++ b/ui/components/PageContributionCard.vue @@ -25,6 +25,20 @@ + +
+ {{ childPage.quote && childPage.quote.src ? childPage.quote.src : childPage.summary }} +
+
@@ -33,7 +47,7 @@ - {{ childPage.summary }} + {{ childPage.summary }} + + + + Quote + + @@ -151,6 +168,7 @@ /> @@ -191,6 +209,15 @@ :user="user" :show-thumbnail="false" /> + + + + + + + + + @@ -206,10 +233,11 @@ import { findUserByOid } from '~/api/service/user' import PageContributionCard from '~/components/PageContributionCard' import PageContributionMediumViewer from '~/components/PageContributionMediumViewer' import PageComments from '~/components/PageComments' - import PageDetailRichText from './PageDetailRichText' +import PageDetailRichText from './PageDetailRichText' import PageDetailBookEpub from './PageDetailBookEpub' import PageDetailBookPdf from './PageDetailBookPdf' import PageDetailImage from './PageDetailImage' +// import PageDetailQuote from './PageDetailQuote' const log = debug('app:components/PageContributionList') @@ -223,6 +251,7 @@ export default { PageDetailBookEpub, PageDetailBookPdf, PageDetailImage, + // PageDetailQuote, }, mixins: [MediumViewerMixin, PageMixin], props: { @@ -256,6 +285,7 @@ export default { filename: null }, richText: {}, + quote: {}, summary: null, userDisplayName: null, comments: null @@ -266,11 +296,13 @@ export default { pageDetailBookEpubDialog: false, pageDetailBookPdfDialog: false, pageDetailImageDialog: false, + pageDetailQuoteDialog: false, readOnly: true, dialogKey: 0, viewerKey: 0, pageDetailDialogKey: 0, - commentsDialog: false + commentsDialog: false, + // pageQuoteDialog: false } }, computed: { @@ -347,6 +379,15 @@ export default { // force rerender this.dialogKey += 1 }, + // openPageQuoteDialog() { + // this.pageQuoteDialog = true + // }, + onQuoteSaved(quote) { + // log('in quote saved', quote) + // EventBus.$emit('story-page-quote-save', quote) + // this.pageDetailKey += 1 + // this.pageQuoteDialog = false + }, openMediumViewerNewPage(mediumType, selectedMedium) { this.selectedMedium = selectedMedium this.activeMedium = mediumType @@ -367,6 +408,7 @@ export default { ref: null }, richText: {}, + quote: {}, parentPagesOid: this.page.id, // parentPagesRef: null, // todo? summary: null, @@ -385,6 +427,7 @@ export default { this.pageDetailBookEpubDialog = false this.pageDetailBookPdfDialog = false this.pageDetailImageDialog = false + this.pageDetailQuoteDialog = false this.readOnly = true this.selectedChildPage = page @@ -400,30 +443,26 @@ export default { this.pageMediumDialog = true } else { if (this.getPageRichTextSrc(page)) { - log('a') this.selectedChildPageSrc = this.getPageRichTextSrc(page) this.pageDetailRichTextDialog = true // EventBus.$emit('open-page-detail-rich-text-dialog') } else if (this.getPageBookSrc(page)) { - log('b') this.selectedChildPageSrc = this.getPageBookSrc(page) if (this.getIsEpub(this.getBookType(page))) { - log('c') this.pageDetailBookEpubDialog = true // EventBus.$emit('open-page-detail-book-epub-dialog') } else if (this.getIsPdf(this.getBookType(page))) { - log('d') this.pageDetailBookPdfDialog = true // EventBus.$emit('open-page-detail-book-pdf-dialog') } } else if (this.getPageImageSrc(page)) { - log('e') this.pageDetailImageDialog = true this.selectedChildPageSrc = this.getPageImageSrc(page) - log('e', this.selectedChildPageSrc) // EventBus.$emit('open-page-detail-image-dialog') - } else { - log('end') + } else if (this.getPageQuoteSrc(page)) { + this.pageDetailQuoteDialog = true + this.selectedChildPageSrc = this.getPageQuoteSrc(page) + // EventBus.$emit('open-page-detail-image-dialog') } } }, diff --git a/ui/components/PageContributionMediumViewer.vue b/ui/components/PageContributionMediumViewer.vue index 7395132..d87c100 100644 --- a/ui/components/PageContributionMediumViewer.vue +++ b/ui/components/PageContributionMediumViewer.vue @@ -6,6 +6,7 @@ :theme="'secondary'" :user="user" :initial-medium="allSelectedMedium ? selectedMedium : activeMedium" + :is-quote-enabled="isQuoteEnabled" :is-book-enabled="isBookEnabled" :is-image-enabled="isImageEnabled" :is-rich-text-enabled="isRichTextEnabled" @@ -44,10 +45,18 @@ - @@ -92,16 +109,16 @@ import MediumViewerMixin from '../mixins/MediumViewerMixin' import BaseMediumViewer from '~/components/BaseMediumViewer' import MediumViewerBook from '~/components/MediumViewerBook' import MediumViewerImage from '~/components/MediumViewerImage' +import MediumViewerQuote from '~/components/MediumViewerQuote' import MediumViewerRichText from '~/components/MediumViewerRichText' +import PageContributionPublish from '~/components/PageContributionPublish' import PageContributionDeleteDialog from '~/components/PageContributionDeleteDialog' -import PageContributionSaveDialog from '~/components/PageContributionSaveDialog' import { uploadImage } from '~/api/service/image' import { uploadBook } from '~/api/service/book' import { uploadJson } from '~/api/service/rich-text' import { addPage, - deletePage, - getRandomPreviewWallpaper + deletePage } from '~/api/service/page' const log = debug('app:components/PageContributionMediumViewer') @@ -112,9 +129,10 @@ export default { BaseMediumViewer, MediumViewerBook, MediumViewerImage, + MediumViewerQuote, MediumViewerRichText, - PageContributionDeleteDialog, - PageContributionSaveDialog + PageContributionPublish, + PageContributionDeleteDialog }, mixins: [MediumViewerMixin], props: { @@ -162,9 +180,15 @@ export default { isRichTextPreview: false, hasBookChanged: false, isReadOnly: true, - pageContributionSaveDialog: false, + publishDialog: false, pageContributionDeleteDialog: false, - savedPart: null + savedPart: null, + publishKey: 0, + quote: { + src: '', + background: '', + color: '' + } } }, computed: { @@ -172,20 +196,43 @@ export default { allSelectedMedium: function() { return this.selectedMedium === undefined }, + isQuoteEnabled: function() { + return ( + this.allSelectedMedium || this.isMediaQuoteType(this.selectedMedium) + ) + }, isBookEnabled: function() { return this.allSelectedMedium || this.isMediaBookType(this.selectedMedium) }, isImageEnabled: function() { - return this.allSelectedMedium || this.isMediaImageType(this.selectedMedium) + return ( + this.allSelectedMedium || this.isMediaImageType(this.selectedMedium) + ) }, isRichTextEnabled: function() { return this.allSelectedMedium || this.isMediaRichType(this.selectedMedium) }, - imageSrc: function() { - if (this.contribution.image && this.contribution.image.ref) { - return this.contribution.image.ref + // quoteSrc: function() { + // if (this.contribution.quote && this.contribution.quote.src) { + // return this.contribution.quote.src + // } + // return '' + // }, + imageSrc: { + get() { + log('in imageSrc.get', this.contribution.image) + if (this.contribution.image && this.contribution.image.ref) { + return this.contribution.image.ref + } + return '' + }, + set(val) { + log('in previewImageSrc set', val) + + if (val) { + this.contribution.image.ref = val + } } - return '' }, bookSrc() { if (this.contribution.book && this.contribution.book.ref) { @@ -228,56 +275,92 @@ export default { saveMediaDialog(activeMedium) { log('saveMediaDialog:', activeMedium) this.mediaToSave = activeMedium - this.pageContributionSaveDialog = true + this.publishDialog = true }, - saveMedia(summary) { - log('in save media', this.mediaToSave, summary) + onPublishComplete(basePagePublishModel) { + log('in onPublishComplete', basePagePublishModel) + this.saveMedia(basePagePublishModel) + }, + saveMedia(basePagePublishModel) { + log('in save media', this.mediaToSave, basePagePublishModel) - let keywords = [] - let authorTags = [] - keywords = stringUtils.findKeywords(summary) - authorTags = stringUtils.findAuthorTags(summary) + if (basePagePublishModel && basePagePublishModel.summary) { + // only need to save page, Create-page function will create the preview record in the background + let keywords = [] + let authorTags = [] + keywords = stringUtils.findKeywords(basePagePublishModel.summary) + authorTags = stringUtils.findAuthorTags(basePagePublishModel.summary) - const pageCollaborationPart = { - invite: false, - public: true, - chapterOid: this.contribution.chapterOid, - storyOid: this.contribution.storyOid, - richText: {}, - parentPagesOid: this.contribution.parentPagesOid, - // parentPagesRef: this.contribution.parentPagesRef, - summary: summary, - keywords: keywords.map(keyword => keyword.toLowerCase()), - authorTags: authorTags, - uid: this.user.uid, - wallpaperUrl: getRandomPreviewWallpaper() - } + const pageCollaborationPart = { + invite: false, + public: true, + chapterOid: this.contribution.chapterOid, + storyOid: this.contribution.storyOid, + richText: {}, + parentPagesOid: this.contribution.parentPagesOid, + // parentPagesRef: this.contribution.parentPagesRef, + summary: basePagePublishModel.summary, + keywords: keywords.map(keyword => keyword.toLowerCase()), + authorTags: authorTags, + uid: this.user.uid, + quote: this.quote.src ? this.quote : null, + background: { + color: + basePagePublishModel.background.type === 'color' + ? basePagePublishModel.background.val + : '#000000', + font: { + color: + basePagePublishModel.background.type === 'color' + ? basePagePublishModel.background.fontColor + : '#FFFFFF' + }, + }, + wallpaperUrl: basePagePublishModel.background.val + } - if (this.isMediaBookType(this.mediaToSave)) { - this.saveBookFile(pageCollaborationPart) - .then(page => { - log('Page created:', page) - this.addPageToList(this.enhancePage(page)) - this.$toast.success('Book updated') - }) - .catch(error => { - log('Error saving book', error) - this.$toast.error('Error saving book') - }) - } else if (this.isMediaImageType(this.mediaToSave)) { - this.saveImageFile(pageCollaborationPart) - .then(page => { - log('Page created:', page) - this.addPageToList(this.enhancePage(page)) - this.$toast.success('Image updated') - }) - .catch(error => { - log('Error saving image', error) - this.$toast.error('Error saving image') - }) - } else if (this.isMediaRichType(this.mediaToSave)) { - this.savedPart = pageCollaborationPart - EventBus.$emit('rich-text-save') + if (this.isMediaBookType(this.mediaToSave)) { + this.saveBookFile(pageCollaborationPart) + .then(page => { + log('Page created:', page) + this.addPageToList(this.enhancePage(page)) + this.$toast.success('Book submitted') + }) + .catch(error => { + log('Error saving book', error) + this.$toast.error('Error saving book') + }) + } else if (this.isMediaImageType(this.mediaToSave)) { + this.saveImageFile(pageCollaborationPart) + .then(page => { + log('Page created:', page) + this.addPageToList(this.enhancePage(page)) + this.$toast.success('Image submitted') + }) + .catch(error => { + log('Error saving image', error) + this.$toast.error('Error saving image') + }) + } else if (this.isMediaRichType(this.mediaToSave)) { + this.savedPart = pageCollaborationPart + EventBus.$emit('rich-text-save') + } else if (this.isMediaQuoteType(this.mediaToSave)) { + log('adding quote:', this.quote) + this.saveQuote(pageCollaborationPart) + .then(page => { + log('Page created:', page) + this.addPageToList(this.enhancePage(page)) + this.$toast.success('Quote submitted') + }) + .catch(error => { + log('Error saving image', error) + this.$toast.error('Error saving image') + }) + } + } else { + this.$toast.error( + 'Please enter a short summary of your page you are going to publish' + ) } }, saveBookFile(part) { @@ -304,6 +387,20 @@ export default { return Promise.reject(new Error('File is not initialised')) } }, + saveQuote(part) { + if (this.quote) { + const pageQuoteData = { + quote: this.quote + } + + return addPage({ + ...part, + ...pageQuoteData + }) + } else { + return Promise.reject(new Error('Quote is not initialised')) + } + }, saveImageFile(part) { if (this.file) { return uploadImage(this.file).then(result => { @@ -379,7 +476,7 @@ export default { } }, addPageToList(page) { - this.pageContributionSaveDialog = false + this.publishDialog = false this.$emit('add', page) }, deleteMedia() { @@ -396,13 +493,22 @@ export default { }) }, deletePageFromList(pageOid) { - this.pageContributionSaveDialog = false + this.publishDialog = false this.$emit('delete', pageOid) }, enhancePage(page) { page.userDisplayName = this.user.data.displayName return page }, + imageUpdated(src) { + log('Image upload updated:', src) + this.imageSrc = src + this.rePublishDialog() + }, + rePublishDialog() { + // force rerender + this.publishKey += 1 + }, close() { this.$emit('close') } diff --git a/ui/components/PageContributionPublish.vue b/ui/components/PageContributionPublish.vue new file mode 100644 index 0000000..3f451d2 --- /dev/null +++ b/ui/components/PageContributionPublish.vue @@ -0,0 +1,112 @@ + + diff --git a/ui/components/PageContributionSaveDialog.vue b/ui/components/PageContributionSaveDialog.vue index be4272c..8fe91fa 100644 --- a/ui/components/PageContributionSaveDialog.vue +++ b/ui/components/PageContributionSaveDialog.vue @@ -5,7 +5,7 @@ width="600px" > - Save and Publish Page Collaboration diff --git a/ui/components/PageDetail.vue b/ui/components/PageDetail.vue index 927d0a7..2da73c2 100644 --- a/ui/components/PageDetail.vue +++ b/ui/components/PageDetail.vue @@ -12,6 +12,23 @@ + + + + Quote + + @@ -75,16 +92,23 @@ + class="page-detail-title subtitle-2 mb-2" + > {{ activeChapterName }} - - Page {{ activeChapter.index }} - {{ activePageNumber }} + + Page {{ activeChapter.index }}.{{ activePageNumber }} + + + + + {{ src }} + + + + + + mdi-close + + + + + {{ src }} + + + + + + + + diff --git a/ui/components/PageDetailQuoteCapture.vue b/ui/components/PageDetailQuoteCapture.vue new file mode 100644 index 0000000..44c8bcf --- /dev/null +++ b/ui/components/PageDetailQuoteCapture.vue @@ -0,0 +1,134 @@ + + + diff --git a/ui/components/PageDetailQuoteDialog.vue.del b/ui/components/PageDetailQuoteDialog.vue.del new file mode 100644 index 0000000..8e30d43 --- /dev/null +++ b/ui/components/PageDetailQuoteDialog.vue.del @@ -0,0 +1,119 @@ + + + diff --git a/ui/components/PageMediumViewer.vue b/ui/components/PageMediumViewer.vue index a88d2ca..e015fb1 100644 --- a/ui/components/PageMediumViewer.vue +++ b/ui/components/PageMediumViewer.vue @@ -45,6 +45,10 @@ diff --git a/ui/components/StoriesPreviewCard.vue b/ui/components/StoriesPreviewCard.vue index d6c14ff..abfa7f9 100644 --- a/ui/components/StoriesPreviewCard.vue +++ b/ui/components/StoriesPreviewCard.vue @@ -26,12 +26,6 @@ v-if="preview.previewImageUrl" :src="preview.previewImageUrl" /> - - - - - - - {{ preview.summary }} + {{ preview.summary }} + +
+ {{ preview.quote ? preview.quote : preview.summary }} +
+
{{ preview.title }} - {{ preview.summary }} + {{ preview.summary }} @@ -165,4 +173,14 @@ export default { overflow-wrap: break-word; word-break: break-word; } + +.quote-block { + line-height: 300px; + overflow: hidden; +} + +.quote-txt { + display: inline-block; + vertical-align: middle; +} diff --git a/ui/mixins/MediumViewerMixin.js b/ui/mixins/MediumViewerMixin.js index 46b95f3..351c2fb 100644 --- a/ui/mixins/MediumViewerMixin.js +++ b/ui/mixins/MediumViewerMixin.js @@ -13,6 +13,9 @@ export default { }, mediaImageType: function() { return 3 + }, + mediaQuoteType: function() { + return 4 } }, created: function() { @@ -30,6 +33,9 @@ export default { }) }, methods: { + isMediaQuoteType(activeMedium) { + return activeMedium === this.mediaQuoteType + }, isMediaBookType(activeMedium) { return activeMedium === this.mediaBookType }, diff --git a/ui/mixins/PageMixin.js b/ui/mixins/PageMixin.js index 3bc67f3..172565c 100644 --- a/ui/mixins/PageMixin.js +++ b/ui/mixins/PageMixin.js @@ -19,6 +19,13 @@ export default { }, getPageImageSrc(page) { return FileUtils.pageImageSrc(page) + }, + getPageQuoteSrc(page) { + if (page.quote && page.quote.src) { + return page.quote.src + } else { + return '' + } } } } diff --git a/ui/pages/story/_id/index.vue b/ui/pages/story/_id/index.vue index 5afd7a7..f1b5477 100644 --- a/ui/pages/story/_id/index.vue +++ b/ui/pages/story/_id/index.vue @@ -78,6 +78,9 @@ export default { filename: null, ref: null }, + quote: { + src: null + }, previewOid: null }, mutablePages: [], @@ -141,6 +144,15 @@ export default { } }) + EventBus.$on('story-page-quote-save', quote => { + log(`story-page-quote-save event received:`, quote) + this.page.quote = { + src: quote.src, + color: quote.color, + background: quote.background + } + }) + EventBus.$on('save-pages', pages => { log(`savePages event received:`, pages) this.mutablePages = this.pages.slice() @@ -151,6 +163,7 @@ export default { EventBus.$off('story-image-file-key') EventBus.$off('story-book-file-key') EventBus.$off('story-rich-text-file-key') + EventBus.$off('story-page-quote-save') EventBus.$off('save-pages') }, methods: { @@ -201,6 +214,7 @@ export default { invite: pageData.invite, public: pageData.public, richText: pageData.richText, + quote: pageData.quote, storyOid: pageData.storyOid, uid: pageData.uid, previewOid: pageData.previewRef ? pageData.previewRef.id : undefined,