From 1b2d48ff22a0e3e7f198ee237c8c4421c6599741 Mon Sep 17 00:00:00 2001 From: Benoit Schweblin Date: Sat, 22 Jun 2019 22:19:01 +0100 Subject: [PATCH] Removed monetizejs sponsorship support. Reduced time counter increment interval. Added badge service. Refactored user service. Replaced Google+ with People API. --- server/pandoc.js | 11 +- server/pdf.js | 11 +- server/user.js | 18 - src/components/App.vue | 2 - src/components/ExplorerNode.vue | 12 +- src/components/Layout.vue | 3 - src/components/Modal.vue | 2 + src/components/NavigationBar.vue | 10 +- src/components/Notification.vue | 1 + src/components/SideBar.vue | 7 +- src/components/UserImage.vue | 9 +- src/components/UserName.vue | 9 +- src/components/common/vueGlobals.js | 4 +- src/components/gutters/Comment.vue | 2 + src/components/gutters/CommentList.vue | 30 +- src/components/gutters/CurrentDiscussion.vue | 3 +- src/components/gutters/NewComment.vue | 6 +- src/components/gutters/StickyComment.vue | 1 - src/components/menus/HistoryMenu.vue | 9 +- src/components/menus/ImportExportMenu.vue | 32 +- src/components/menus/MainMenu.vue | 44 +- src/components/menus/PublishMenu.vue | 22 +- src/components/menus/SyncMenu.vue | 50 +- src/components/modals/AboutModal.vue | 11 +- .../modals/AccountManagementModal.vue | 2 + .../modals/BadgeManagementModal.vue | 109 ++++ src/components/modals/FilePropertiesModal.vue | 22 +- src/components/modals/HtmlExportModal.vue | 6 +- src/components/modals/PandocExportModal.vue | 13 +- src/components/modals/PdfExportModal.vue | 7 +- .../modals/PublishManagementModal.vue | 2 + src/components/modals/SettingsModal.vue | 22 +- src/components/modals/SyncManagementModal.vue | 2 + src/components/modals/TemplatesModal.vue | 18 +- .../modals/WorkspaceManagementModal.vue | 5 +- src/components/modals/common/modalTemplate.js | 3 +- src/data/constants.js | 1 + src/data/features.js | 466 ++++++++++++++++++ src/icons/Seal.vue | 5 + src/icons/index.js | 2 + src/services/badgeSvc.js | 37 ++ src/services/explorerSvc.js | 2 + .../providers/couchdbWorkspaceProvider.js | 2 + src/services/providers/gistProvider.js | 2 +- src/services/providers/githubProvider.js | 2 +- .../providers/githubWorkspaceProvider.js | 4 +- src/services/providers/gitlabProvider.js | 2 +- .../providers/gitlabWorkspaceProvider.js | 4 +- .../providers/googleDriveWorkspaceProvider.js | 2 + .../providers/helpers/dropboxHelper.js | 9 +- .../providers/helpers/githubHelper.js | 9 +- .../providers/helpers/gitlabHelper.js | 9 +- .../providers/helpers/googleHelper.js | 59 ++- .../providers/helpers/wordpressHelper.js | 7 +- .../providers/helpers/zendeskHelper.js | 7 +- src/services/publishSvc.js | 9 +- src/services/sponsorSvc.js | 55 --- src/services/syncSvc.js | 16 +- src/services/userSvc.js | 108 ++-- src/services/workspaceSvc.js | 11 + src/store/content.js | 2 + src/store/data.js | 16 +- src/store/discussion.js | 3 +- src/store/index.js | 21 +- src/store/layout.js | 2 +- src/store/notification.js | 14 +- src/store/userInfo.js | 16 +- src/styles/app.scss | 8 +- 68 files changed, 1082 insertions(+), 350 deletions(-) create mode 100644 src/components/modals/BadgeManagementModal.vue create mode 100644 src/data/features.js create mode 100644 src/icons/Seal.vue create mode 100644 src/services/badgeSvc.js delete mode 100644 src/services/sponsorSvc.js diff --git a/server/pandoc.js b/server/pandoc.js index c5af214b..79b1505f 100644 --- a/server/pandoc.js +++ b/server/pandoc.js @@ -41,12 +41,9 @@ exports.generate = (req, res) => { const outputFormat = Object.prototype.hasOwnProperty.call(outputFormats, req.query.format) ? req.query.format : 'pdf'; - Promise.all([ - user.checkSponsor(req.query.idToken), - user.checkMonetize(req.query.token), - ]) - .then(([isSponsor, isMonetize]) => { - if (!isSponsor && !isMonetize) { + user.checkSponsor(req.query.idToken) + .then((isSponsor) => { + if (!isSponsor) { throw new Error('unauthorized'); } @@ -79,7 +76,7 @@ exports.generate = (req, res) => { if (!Number.isNaN(options.tocDepth)) { params.push('--toc-depth', options.tocDepth); } - options.highlightStyle = highlightStyles.indexOf(options.highlightStyle) !== -1 ? options.highlightStyle : 'kate'; + options.highlightStyle = highlightStyles.includes(options.highlightStyle) ? options.highlightStyle : 'kate'; params.push('--highlight-style', options.highlightStyle); Object.keys(metadata).forEach((key) => { params.push('-M', `${key}=${metadata[key]}`); diff --git a/server/pdf.js b/server/pdf.js index dba38b39..7b849732 100644 --- a/server/pdf.js +++ b/server/pdf.js @@ -50,12 +50,9 @@ const readJson = (str) => { exports.generate = (req, res) => { let wkhtmltopdfError = ''; - Promise.all([ - user.checkSponsor(req.query.idToken), - user.checkMonetize(req.query.token), - ]) - .then(([isSponsor, isMonetize]) => { - if (!isSponsor && !isMonetize) { + user.checkSponsor(req.query.idToken) + .then((isSponsor) => { + if (!isSponsor) { throw new Error('unauthorized'); } return new Promise((resolve, reject) => { @@ -127,7 +124,7 @@ exports.generate = (req, res) => { } // Page size - params.push('--page-size', authorizedPageSizes.indexOf(options.pageSize) === -1 ? 'A4' : options.pageSize); + params.push('--page-size', !authorizedPageSizes.includes(options.pageSize) ? 'A4' : options.pageSize); // Use a temp file as wkhtmltopdf can't access /dev/stdout on Amazon EC2 for some reason const binPath = process.env.WKHTMLTOPDF_PATH || 'wkhtmltopdf'; diff --git a/server/user.js b/server/user.js index c633e8b2..9ff126d7 100644 --- a/server/user.js +++ b/server/user.js @@ -116,21 +116,3 @@ exports.checkSponsor = (idToken) => { return exports.getUserFromToken(idToken) .then(userInfo => userInfo && userInfo.sponsorUntil > Date.now(), () => false); }; - -exports.checkMonetize = (token) => { - if (!token) { - return Promise.resolve(false); - } - return new Promise(resolve => request({ - uri: 'https://monetizejs.com/api/payments', - qs: { - access_token: token, - }, - json: true, - }, (err, paymentsRes, payments) => { - const authorized = payments && payments.app === 'ESTHdCYOi18iLhhO' && ( - (payments.chargeOption && payments.chargeOption.alias === 'once') || - (payments.subscriptionOption && payments.subscriptionOption.alias === 'yearly')); - resolve(!err && paymentsRes.statusCode === 200 && authorized); - })); -}; diff --git a/src/components/App.vue b/src/components/App.vue index 37b5227f..8238df6b 100644 --- a/src/components/App.vue +++ b/src/components/App.vue @@ -19,7 +19,6 @@ import ContextMenu from './ContextMenu'; import SplashScreen from './SplashScreen'; import syncSvc from '../services/syncSvc'; import networkSvc from '../services/networkSvc'; -import sponsorSvc from '../services/sponsorSvc'; import tempFileSvc from '../services/tempFileSvc'; import store from '../store'; import './common/vueGlobals'; @@ -55,7 +54,6 @@ export default { try { await syncSvc.init(); await networkSvc.init(); - await sponsorSvc.init(); this.ready = true; tempFileSvc.setReady(); } catch (err) { diff --git a/src/components/ExplorerNode.vue b/src/components/ExplorerNode.vue index ee5c8311..b01b1a25 100644 --- a/src/components/ExplorerNode.vue +++ b/src/components/ExplorerNode.vue @@ -22,6 +22,7 @@ import { mapMutations, mapActions } from 'vuex'; import workspaceSvc from '../services/workspaceSvc'; import explorerSvc from '../services/explorerSvc'; import store from '../store'; +import badgeSvc from '../services/badgeSvc'; export default { name: 'explorer-node', // Required for recursivity @@ -81,7 +82,7 @@ export default { ]), select(id = this.node.item.id, doOpen = true) { const node = store.getters['explorer/nodeMap'][id]; - if (!node) { + if (!node || node.item.id === store.state.explorer.selectedId) { return false; } store.commit('explorer/setSelectedId', id); @@ -92,6 +93,7 @@ export default { store.commit('explorer/toggleOpenNode', id); } else { store.commit('file/setCurrentId', id); + badgeSvc.addBadge('switchFile'); } }, 10); } @@ -104,9 +106,11 @@ export default { if (newChildNode.isFolder) { const item = await workspaceSvc.storeItem(newChildNode.item); this.select(item.id); + badgeSvc.addBadge('createFolder'); } else { const item = await workspaceSvc.createFile(newChildNode.item); this.select(item.id); + badgeSvc.addBadge('createFile'); } } catch (e) { // Cancel @@ -115,15 +119,16 @@ export default { store.commit('explorer/setNewItem', null); }, async submitEdit(cancel) { - const { item } = store.getters['explorer/editingNode']; + const { item, isFolder } = store.getters['explorer/editingNode']; const value = this.editingValue; this.setEditingId(null); - if (!cancel && item.id && value) { + if (!cancel && item.id && value && item.name !== value) { try { await workspaceSvc.storeItem({ ...item, name: value, }); + badgeSvc.addBadge(isFolder ? 'renameFolder' : 'renameFile'); } catch (e) { // Cancel } @@ -151,6 +156,7 @@ export default { ...sourceNode.item, parentId: targetNode.item.id, }); + badgeSvc.addBadge('moveFiles'); } }, async onContextMenu(evt) { diff --git a/src/components/Layout.vue b/src/components/Layout.vue index fa3b9709..924d2ee4 100644 --- a/src/components/Layout.vue +++ b/src/components/Layout.vue @@ -177,11 +177,9 @@ export default { .sticky-comment, .current-discussion { background-color: mix(#000, $editor-background-light, 6.7%); - border-color: $editor-background-light; .app--dark & { background-color: mix(#fff, $editor-background-dark, 6.7%); - border-color: $editor-background-dark; } } } @@ -204,7 +202,6 @@ $preview-background-dark: #252525; .sticky-comment, .current-discussion { background-color: mix(#000, $preview-background-light, 6.7%); - border-color: $preview-background-light; } } diff --git a/src/components/Modal.vue b/src/components/Modal.vue index 8208baf1..79ce9b4a 100644 --- a/src/components/Modal.vue +++ b/src/components/Modal.vue @@ -37,6 +37,7 @@ import SyncManagementModal from './modals/SyncManagementModal'; import PublishManagementModal from './modals/PublishManagementModal'; import WorkspaceManagementModal from './modals/WorkspaceManagementModal'; import AccountManagementModal from './modals/AccountManagementModal'; +import BadgeManagementModal from './modals/BadgeManagementModal'; import SponsorModal from './modals/SponsorModal'; // Providers @@ -88,6 +89,7 @@ export default { PublishManagementModal, WorkspaceManagementModal, AccountManagementModal, + BadgeManagementModal, SponsorModal, // Providers GooglePhotoModal, diff --git a/src/components/NavigationBar.vue b/src/components/NavigationBar.vue index 43a009ee..44549fce 100644 --- a/src/components/NavigationBar.vue +++ b/src/components/NavigationBar.vue @@ -57,6 +57,7 @@ import utils from '../services/utils'; import pagedownButtons from '../data/pagedownButtons'; import store from '../store'; import workspaceSvc from '../services/workspaceSvc'; +import badgeSvc from '../services/badgeSvc'; // According to mousetrap const mod = /Mac|iPod|iPhone|iPad/.test(navigator.platform) ? 'Meta' : 'Ctrl'; @@ -178,7 +179,7 @@ export default { }, requestSync() { if (this.isSyncPossible && !this.isSyncRequested) { - syncSvc.requestSync(); + syncSvc.requestSync(true); } }, requestPublish() { @@ -188,7 +189,11 @@ export default { }, pagedownClick(name) { if (store.getters['content/isCurrentEditable']) { + const text = editorSvc.clEditor.getContent(); editorSvc.pagedownEditor.uiManager.doClick(name); + if (text !== editorSvc.clEditor.getContent()) { + badgeSvc.addBadge('formatButtons'); + } } }, async editTitle(toggle) { @@ -198,12 +203,13 @@ export default { } else { const title = this.title.trim(); this.title = store.getters['file/current'].name; - if (title) { + if (title && this.title !== title) { try { await workspaceSvc.storeItem({ ...store.getters['file/current'], name: title, }); + badgeSvc.addBadge('editCurrentFileName'); } catch (e) { // Cancel } diff --git a/src/components/Notification.vue b/src/components/Notification.vue index f1c0ee9c..2ed2ac4c 100644 --- a/src/components/Notification.vue +++ b/src/components/Notification.vue @@ -3,6 +3,7 @@
+
diff --git a/src/components/SideBar.vue b/src/components/SideBar.vue index c7d1f9d5..99819cb2 100644 --- a/src/components/SideBar.vue +++ b/src/components/SideBar.vue @@ -19,7 +19,7 @@ - + @@ -54,7 +54,7 @@ const panelNames = { publish: 'Publish', history: 'File history', importExport: 'Import/export', - workspaceBackup: 'Workspace backup', + workspaceBackups: 'Workspace backups', }; export default { @@ -174,8 +174,9 @@ export default { font-size: 0.95em; p { - margin: 10px; + margin: 10px 15px; line-height: 1.5; + font-style: italic; } } diff --git a/src/components/UserImage.vue b/src/components/UserImage.vue index 7d3935d2..a46340d0 100644 --- a/src/components/UserImage.vue +++ b/src/components/UserImage.vue @@ -10,14 +10,17 @@ import store from '../store'; export default { props: ['userId'], computed: { + sanitizedUserId() { + return userSvc.sanitizeUserId(this.userId); + }, url() { - const userInfo = store.state.userInfo.itemsById[this.userId]; + const userInfo = store.state.userInfo.itemsById[this.sanitizedUserId]; return userInfo && userInfo.imageUrl && `url('${userInfo.imageUrl}')`; }, }, watch: { - userId: { - handler: userId => userSvc.getInfo(userId), + sanitizedUserId: { + handler: sanitizedUserId => userSvc.addUserId(sanitizedUserId), immediate: true, }, }, diff --git a/src/components/UserName.vue b/src/components/UserName.vue index c87bdafe..d30b505e 100644 --- a/src/components/UserName.vue +++ b/src/components/UserName.vue @@ -9,14 +9,17 @@ import store from '../store'; export default { props: ['userId'], computed: { + sanitizedUserId() { + return userSvc.sanitizeUserId(this.userId); + }, name() { - const userInfo = store.state.userInfo.itemsById[this.userId]; + const userInfo = store.state.userInfo.itemsById[this.sanitizedUserId]; return userInfo ? userInfo.name : 'Someone'; }, }, watch: { - userId: { - handler: userId => userSvc.getInfo(userId), + sanitizedUserId: { + handler: sanitizedUserId => userSvc.addUserId(sanitizedUserId), immediate: true, }, }, diff --git a/src/components/common/vueGlobals.js b/src/components/common/vueGlobals.js index 961bc91d..d63c1eab 100644 --- a/src/components/common/vueGlobals.js +++ b/src/components/common/vueGlobals.js @@ -75,6 +75,6 @@ Vue.directive('clipboard', { // Global filters Vue.filter('formatTime', time => - // Access the minute counter for reactive refresh - timeSvc.format(time, store.state.minuteCounter)); + // Access the time counter for reactive refresh + timeSvc.format(time, store.state.timeCounter)); diff --git a/src/components/gutters/Comment.vue b/src/components/gutters/Comment.vue index ce91cf4e..25632f6a 100644 --- a/src/components/gutters/Comment.vue +++ b/src/components/gutters/Comment.vue @@ -28,6 +28,7 @@ import UserName from '../UserName'; import editorSvc from '../../services/editorSvc'; import htmlSanitizer from '../../libs/htmlSanitizer'; import store from '../../store'; +import badgeSvc from '../../services/badgeSvc'; export default { components: { @@ -52,6 +53,7 @@ export default { try { await store.dispatch('modal/open', 'commentDeletion'); store.dispatch('discussion/cleanCurrentFile', { filterComment: this.comment }); + badgeSvc.addBadge('removeComment'); } catch (e) { // Cancel } diff --git a/src/components/gutters/CommentList.vue b/src/components/gutters/CommentList.vue index 15708a63..5e33c9c4 100644 --- a/src/components/gutters/CommentList.vue +++ b/src/components/gutters/CommentList.vue @@ -133,11 +133,6 @@ export default { : editorSvc.previewElt.parentNode; this.updateSticky = () => { - const commitIfDifferent = (value) => { - if (store.state.discussion.stickyComment !== value) { - store.commit('discussion/setStickyComment', value); - } - }; let height = 0; let offsetTop = this.tops.current; const lastCommentElt = this.$el.querySelector(`.comment--${this.currentDiscussionLastCommentId}`); @@ -152,13 +147,15 @@ export default { const currentDiscussionElt = document.querySelector('.current-discussion__inner'); const minOffsetTop = this.scrollerElt.scrollTop + 10; const maxOffsetTop = (this.scrollerElt.scrollTop + this.scrollerElt.clientHeight) - height - - currentDiscussionElt.clientHeight - 10; + - currentDiscussionElt.clientHeight; + let stickyComment = null; if (offsetTop > maxOffsetTop || maxOffsetTop < minOffsetTop) { - commitIfDifferent('bottom'); + stickyComment = 'bottom'; } else if (offsetTop < minOffsetTop) { - commitIfDifferent('top'); - } else { - commitIfDifferent(null); + stickyComment = 'top'; + } + if (store.state.discussion.stickyComment !== stickyComment) { + store.commit('discussion/setStickyComment', stickyComment); } }; @@ -199,19 +196,6 @@ export default { padding-top: 10px; } -.comment-list__current-discussion { - border-top: 2px solid; - border-bottom: 2px solid; - - .comment-list--top & { - border-bottom-color: transparent; - } - - .comment-list--bottom & { - border-top-color: transparent; - } -} - /* use div selector to avoid collision with Prism */ div.comment { padding: 5px 10px 10px; diff --git a/src/components/gutters/CurrentDiscussion.vue b/src/components/gutters/CurrentDiscussion.vue index aaed6937..fa0ccc3f 100644 --- a/src/components/gutters/CurrentDiscussion.vue +++ b/src/components/gutters/CurrentDiscussion.vue @@ -34,6 +34,7 @@ import animationSvc from '../../services/animationSvc'; import markdownConversionSvc from '../../services/markdownConversionSvc'; import StickyComment from './StickyComment'; import store from '../../store'; +import badgeSvc from '../../services/badgeSvc'; export default { components: { @@ -103,6 +104,7 @@ export default { store.dispatch('discussion/cleanCurrentFile', { filterDiscussion: this.currentDiscussion, }); + badgeSvc.addBadge('removeDiscussion'); } catch (e) { // Cancel } @@ -118,7 +120,6 @@ export default { position: absolute; right: 0; bottom: 0; - border-top: 2px solid; .sticky-comment { position: relative; diff --git a/src/components/gutters/NewComment.vue b/src/components/gutters/NewComment.vue index a06f707f..635ef5e3 100644 --- a/src/components/gutters/NewComment.vue +++ b/src/components/gutters/NewComment.vue @@ -30,6 +30,7 @@ import markdownConversionSvc from '../../services/markdownConversionSvc'; import utils from '../../services/utils'; import userSvc from '../../services/userSvc'; import store from '../../store'; +import badgeSvc from '../../services/badgeSvc'; export default { components: { @@ -70,12 +71,15 @@ export default { [utils.uid()]: comment, }, }; - // Create discussion if (discussionId === store.state.discussion.newDiscussionId) { + // Create discussion patch.discussions = { ...store.getters['content/current'].discussions, [discussionId]: store.getters['discussion/newDiscussion'], }; + badgeSvc.addBadge('createDiscussion'); + } else { + badgeSvc.addBadge('addComment'); } store.dispatch('content/patchCurrent', patch); store.commit('discussion/setNewCommentText'); diff --git a/src/components/gutters/StickyComment.vue b/src/components/gutters/StickyComment.vue index 12232fb1..7988305a 100644 --- a/src/components/gutters/StickyComment.vue +++ b/src/components/gutters/StickyComment.vue @@ -40,7 +40,6 @@ export default { right: 0; font-size: 15px; padding-top: 10px; - border-bottom: 2px solid; .current-discussion & { width: auto !important; diff --git a/src/components/menus/HistoryMenu.vue b/src/components/menus/HistoryMenu.vue index 37d239af..b3f93e20 100644 --- a/src/components/menus/HistoryMenu.vue +++ b/src/components/menus/HistoryMenu.vue @@ -56,6 +56,7 @@ import utils from '../../services/utils'; import googleHelper from '../../services/providers/helpers/googleHelper'; import syncSvc from '../../services/syncSvc'; import store from '../../store'; +import badgeSvc from '../../services/badgeSvc'; let editorClassAppliers = []; let previewClassAppliers = []; @@ -237,10 +238,12 @@ export default { syncLocation: { immediate: true, handler(value) { - if (!value) { - const firstSyncLocation = this.syncLocations[0]; - if (firstSyncLocation) { + const firstSyncLocation = this.syncLocations[0]; + if (firstSyncLocation) { + if (!value) { this.syncLocationId = firstSyncLocation.id; + } else if (value.id !== firstSyncLocation.id) { + badgeSvc.addBadge('chooseHistory'); } } }, diff --git a/src/components/menus/ImportExportMenu.vue b/src/components/menus/ImportExportMenu.vue index 334e087c..e26cbd06 100644 --- a/src/components/menus/ImportExportMenu.vue +++ b/src/components/menus/ImportExportMenu.vue @@ -53,6 +53,7 @@ import Provider from '../../services/providers/common/Provider'; import store from '../../store'; import workspaceSvc from '../../services/workspaceSvc'; import exportSvc from '../../services/exportSvc'; +import badgeSvc from '../../services/badgeSvc'; const turndownService = new TurndownService(store.getters['data/computedSettings'].turndown); @@ -85,6 +86,7 @@ export default { name: file.name, }); store.commit('file/setCurrentId', item.id); + badgeSvc.addBadge('importMarkdown'); }, async onImportHtml(evt) { const file = evt.target.files[0]; @@ -96,23 +98,29 @@ export default { name: file.name, }); store.commit('file/setCurrentId', item.id); + badgeSvc.addBadge('importHtml'); }, - exportMarkdown() { + async exportMarkdown() { const currentFile = store.getters['file/current']; - return exportSvc.exportToDisk(currentFile.id, 'md') - .catch(() => { /* Cancel */ }); + try { + await exportSvc.exportToDisk(currentFile.id, 'md'); + badgeSvc.addBadge('exportMarkdown'); + } catch (e) { /* Cancel */ } }, - exportHtml() { - return store.dispatch('modal/open', 'htmlExport') - .catch(() => { /* Cancel */ }); + async exportHtml() { + try { + await store.dispatch('modal/open', 'htmlExport'); + } catch (e) { /* Cancel */ } }, - exportPdf() { - return store.dispatch('modal/open', 'pdfExport') - .catch(() => { /* Cancel */ }); + async exportPdf() { + try { + await store.dispatch('modal/open', 'pdfExport'); + } catch (e) { /* Cancel */ } }, - exportPandoc() { - return store.dispatch('modal/open', 'pandocExport') - .catch(() => { /* Cancel */ }); + async exportPandoc() { + try { + await store.dispatch('modal/open', 'pandocExport'); + } catch (e) { /* Cancel */ } }, }, }; diff --git a/src/components/menus/MainMenu.vue b/src/components/menus/MainMenu.vue index dcfb0950..a5a8ef84 100644 --- a/src/components/menus/MainMenu.vue +++ b/src/components/menus/MainMenu.vue @@ -99,15 +99,20 @@
User accounts
Manage access to your external accounts. + + +
Badges
+ List application features and earned badges. +

- + - Workspace backup + Workspace backups
Reset application
- Sign out and clean all workspaces. + Sign out and clean all workspace data.

@@ -161,6 +166,12 @@ export default { return Object.values(store.getters['data/tokensByType']) .reduce((count, tokensBySub) => count + Object.values(tokensBySub).length, 0); }, + badgeCount() { + return store.getters['data/allBadges'].filter(badge => badge.isEarned).length; + }, + featureCount() { + return store.getters['data/allBadges'].length; + }, }, methods: { ...mapActions('data', { @@ -186,35 +197,30 @@ export default { }, async settings() { try { - const settings = await store.dispatch('modal/open', 'settings'); - store.dispatch('data/setSettings', settings); - } catch (e) { - // Cancel - } + await store.dispatch('modal/open', 'settings'); + } catch (e) { /* Cancel */ } }, async templates() { try { - const { templates } = await store.dispatch('modal/open', 'templates'); - store.dispatch('data/setTemplatesById', templates); - } catch (e) { - // Cancel - } + await store.dispatch('modal/open', 'templates'); + } catch (e) { /* Cancel */ } }, async accounts() { try { await store.dispatch('modal/open', 'accountManagement'); - } catch (e) { - // Cancel - } + } catch (e) { /* Cancel */ } + }, + async badges() { + try { + await store.dispatch('modal/open', 'badgeManagement'); + } catch (e) { /* Cancel */ } }, async reset() { try { await store.dispatch('modal/open', 'reset'); window.location.href = '#reset=true'; window.location.reload(); - } catch (e) { - // Cancel - } + } catch (e) { /* Cancel */ } }, about() { store.dispatch('modal/open', 'about'); diff --git a/src/components/menus/PublishMenu.vue b/src/components/menus/PublishMenu.vue index 71738393..4c959045 100644 --- a/src/components/menus/PublishMenu.vue +++ b/src/components/menus/PublishMenu.vue @@ -129,13 +129,13 @@ const tokensToArray = (tokens, filter = () => true) => Object.values(tokens) .filter(token => filter(token)) .sort((token1, token2) => token1.name.localeCompare(token2.name)); -const publishModalOpener = type => async (token) => { +const publishModalOpener = (type, featureId) => async (token) => { try { const publishLocation = await store.dispatch('modal/open', { type, token, }); - publishSvc.createPublishLocation(publishLocation); + publishSvc.createPublishLocation(publishLocation, featureId); } catch (e) { /* cancel */ } }; @@ -236,15 +236,15 @@ export default { await zendeskHelper.addAccount(subdomain, clientId); } catch (e) { /* cancel */ } }, - publishBlogger: publishModalOpener('bloggerPublish'), - publishBloggerPage: publishModalOpener('bloggerPagePublish'), - publishDropbox: publishModalOpener('dropboxPublish'), - publishGithub: publishModalOpener('githubPublish'), - publishGist: publishModalOpener('gistPublish'), - publishGitlab: publishModalOpener('gitlabPublish'), - publishGoogleDrive: publishModalOpener('googleDrivePublish'), - publishWordpress: publishModalOpener('wordpressPublish'), - publishZendesk: publishModalOpener('zendeskPublish'), + publishBlogger: publishModalOpener('bloggerPublish', 'publishToBlogger'), + publishBloggerPage: publishModalOpener('bloggerPagePublish', 'publishToBloggerPage'), + publishDropbox: publishModalOpener('dropboxPublish', 'publishToDropbox'), + publishGithub: publishModalOpener('githubPublish', 'publishToGithub'), + publishGist: publishModalOpener('gistPublish', 'publishToGist'), + publishGitlab: publishModalOpener('gitlabPublish', 'publishToGitlab'), + publishGoogleDrive: publishModalOpener('googleDrivePublish', 'publishToGoogleDrive'), + publishWordpress: publishModalOpener('wordpressPublish', 'publishToWordPress'), + publishZendesk: publishModalOpener('zendeskPublish', 'publishToZendesk'), }, }; diff --git a/src/components/menus/SyncMenu.vue b/src/components/menus/SyncMenu.vue index 3340079c..6c5451e4 100644 --- a/src/components/menus/SyncMenu.vue +++ b/src/components/menus/SyncMenu.vue @@ -108,6 +108,7 @@ import githubProvider from '../../services/providers/githubProvider'; import gitlabProvider from '../../services/providers/gitlabProvider'; import syncSvc from '../../services/syncSvc'; import store from '../../store'; +import badgeSvc from '../../services/badgeSvc'; const tokensToArray = (tokens, filter = () => true) => Object.values(tokens) .filter(token => filter(token)) @@ -162,7 +163,7 @@ export default { methods: { requestSync() { if (!this.isSyncRequested) { - syncSvc.requestSync(); + syncSvc.requestSync(true); } }, async manageSync() { @@ -194,28 +195,36 @@ export default { await googleHelper.addDriveAccount(!store.getters['data/localSettings'].googleDriveRestrictedAccess); } catch (e) { /* cancel */ } }, - async openGoogleDrive(token) { - const files = await googleHelper.openPicker(token, 'doc'); - store.dispatch( - 'queue/enqueue', - () => googleDriveProvider.openFiles(token, files), - ); - }, async openDropbox(token) { const paths = await dropboxHelper.openChooser(token); store.dispatch( 'queue/enqueue', - () => dropboxProvider.openFiles(token, paths), + async () => { + await dropboxProvider.openFiles(token, paths); + badgeSvc.addBadge('openFromDropbox'); + }, + ); + }, + async saveDropbox(token) { + try { + await openSyncModal(token, 'dropboxSave'); + badgeSvc.addBadge('saveOnDropbox'); + } catch (e) { /* cancel */ } + }, + async openGoogleDrive(token) { + const files = await googleHelper.openPicker(token, 'doc'); + store.dispatch( + 'queue/enqueue', + async () => { + await googleDriveProvider.openFiles(token, files); + badgeSvc.addBadge('openFromGoogleDrive'); + }, ); }, async saveGoogleDrive(token) { try { await openSyncModal(token, 'googleDriveSave'); - } catch (e) { /* cancel */ } - }, - async saveDropbox(token) { - try { - await openSyncModal(token, 'dropboxSave'); + badgeSvc.addBadge('saveOnGoogleDrive'); } catch (e) { /* cancel */ } }, async openGithub(token) { @@ -226,18 +235,23 @@ export default { }); store.dispatch( 'queue/enqueue', - () => githubProvider.openFile(token, syncLocation), + async () => { + await githubProvider.openFile(token, syncLocation); + badgeSvc.addBadge('openFromGithub'); + }, ); } catch (e) { /* cancel */ } }, async saveGithub(token) { try { await openSyncModal(token, 'githubSave'); + badgeSvc.addBadge('saveOnGithub'); } catch (e) { /* cancel */ } }, async saveGist(token) { try { await openSyncModal(token, 'gistSync'); + badgeSvc.addBadge('saveOnGist'); } catch (e) { /* cancel */ } }, async openGitlab(token) { @@ -248,13 +262,17 @@ export default { }); store.dispatch( 'queue/enqueue', - () => gitlabProvider.openFile(token, syncLocation), + async () => { + await gitlabProvider.openFile(token, syncLocation); + badgeSvc.addBadge('openFromGitlab'); + }, ); } catch (e) { /* cancel */ } }, async saveGitlab(token) { try { await openSyncModal(token, 'gitlabSave'); + badgeSvc.addBadge('saveOnGitlab'); } catch (e) { /* cancel */ } }, }, diff --git a/src/components/modals/AboutModal.vue b/src/components/modals/AboutModal.vue index acbb16e1..39be3c26 100644 --- a/src/components/modals/AboutModal.vue +++ b/src/components/modals/AboutModal.vue @@ -2,8 +2,6 @@