From d7ed456a7b6f73e046ba3a2ef38eb21f82f06ca4 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Tue, 30 Jul 2019 11:41:54 +0200 Subject: Make todo layer resizable --- src/features/todos/store.js | 86 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/features/todos/store.js (limited to 'src/features/todos/store.js') diff --git a/src/features/todos/store.js b/src/features/todos/store.js new file mode 100644 index 000000000..e7e13b37f --- /dev/null +++ b/src/features/todos/store.js @@ -0,0 +1,86 @@ +import { + computed, + action, + observable, +} from 'mobx'; +import localStorage from 'mobx-localstorage'; + +import { todoActions } from './actions'; +import { FeatureStore } from '../utils/FeatureStore'; +import { createReactions } from '../../stores/lib/Reaction'; +import { createActionBindings } from '../utils/ActionBinding'; +import { DEFAULT_TODOS_WIDTH, TODOS_MIN_WIDTH } from '.'; + +const debug = require('debug')('Franz:feature:todos:store'); + +export default class TodoStore extends FeatureStore { + @observable isFeatureEnabled = false; + + @observable isFeatureActive = false; + + @computed get width() { + const width = this.settings.width || DEFAULT_TODOS_WIDTH; + + return width < TODOS_MIN_WIDTH ? TODOS_MIN_WIDTH : width; + } + + @computed get settings() { + return localStorage.getItem('todos') || {}; + } + + // ========== PUBLIC API ========= // + + @action start(stores, actions) { + debug('TodoStore::start'); + this.stores = stores; + this.actions = actions; + + // ACTIONS + + this._registerActions(createActionBindings([ + [todoActions.resize, this._resize], + ])); + + // REACTIONS + + this._allReactions = createReactions([ + this._setFeatureEnabledReaction, + ]); + + this._registerReactions(this._allReactions); + + this.isFeatureActive = true; + } + + @action stop() { + super.stop(); + debug('TodoStore::stop'); + this.reset(); + this.isFeatureActive = false; + } + + // ========== PRIVATE METHODS ========= // + + _updateSettings = (changes) => { + localStorage.setItem('todos', { + ...this.settings, + ...changes, + }); + }; + + // Actions + + @action _resize = ({ width }) => { + this._updateSettings({ + width, + }); + }; + + // Reactions + + _setFeatureEnabledReaction = () => { + const { isTodosEnabled } = this.stores.features.features; + + this.isFeatureEnabled = isTodosEnabled; + }; +} -- cgit v1.2.3-54-g00ecf From bd49d59008d64db13e3f37277ec873a3a464ef9e Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Wed, 31 Jul 2019 17:08:29 +0200 Subject: MVP for service <-> todos integration --- src/features/todos/actions.js | 11 ++ src/features/todos/components/TodosWebview.js | 20 +++- src/features/todos/containers/TodosScreen.js | 3 + src/features/todos/preload.js | 21 ++++ src/features/todos/store.js | 29 +++++ src/i18n/messages/src/lib/Menu.json | 157 ++++++++++++++------------ src/index.html | 11 +- src/lib/Menu.js | 16 +++ src/stores/ServicesStore.js | 3 + src/webview/contextMenu.js | 17 +++ 10 files changed, 210 insertions(+), 78 deletions(-) create mode 100644 src/features/todos/preload.js (limited to 'src/features/todos/store.js') diff --git a/src/features/todos/actions.js b/src/features/todos/actions.js index 673ce8531..696568f7f 100644 --- a/src/features/todos/actions.js +++ b/src/features/todos/actions.js @@ -5,6 +5,17 @@ export const todoActions = createActionsFromDefinitions({ resize: { width: PropTypes.number.isRequired, }, + setTodosWebview: { + webview: PropTypes.element.isRequired, + }, + handleHostMessage: { + action: PropTypes.string.isRequired, + data: PropTypes.object, + }, + handleClientMessage: { + action: PropTypes.string.isRequired, + data: PropTypes.object, + }, }, PropTypes.checkPropTypes); export default todoActions; diff --git a/src/features/todos/components/TodosWebview.js b/src/features/todos/components/TodosWebview.js index 1d99b9388..1f4730094 100644 --- a/src/features/todos/components/TodosWebview.js +++ b/src/features/todos/components/TodosWebview.js @@ -35,6 +35,8 @@ class TodosWebview extends Component { static propTypes = { classes: PropTypes.object.isRequired, authToken: PropTypes.string.isRequired, + handleClientMessage: PropTypes.func.isRequired, + setTodosWebview: PropTypes.func.isRequired, resize: PropTypes.func.isRequired, width: PropTypes.number.isRequired, minWidth: PropTypes.number.isRequired, @@ -43,7 +45,7 @@ class TodosWebview extends Component { state = { isDragging: false, width: 300, - } + }; componentWillMount() { const { width } = this.props; @@ -65,7 +67,7 @@ class TodosWebview extends Component { initialPos: event.clientX, delta: 0, }); - } + }; resizePanel(e) { const { minWidth } = this.props; @@ -113,10 +115,15 @@ class TodosWebview extends Component { } } + startListeningToIpcMessages() { + const { handleClientMessage } = this.props; + if (!this.webview) return; + this.webview.addEventListener('ipc-message', e => handleClientMessage(e.args[0])); + } + render() { const { authToken, classes } = this.props; const { width, delta, isDragging } = this.state; - return ( <>
{ + this.props.setTodosWebview(this.webview); + this.startListeningToIpcMessages(); + }} + partition="persist:todos" + preload="./features/todos/preload.js" + ref={(webview) => { this.webview = webview ? webview.view : null; }} src={`${environment.TODOS_FRONTEND}?authToken=${authToken}`} />
diff --git a/src/features/todos/containers/TodosScreen.js b/src/features/todos/containers/TodosScreen.js index 0759c22db..5b7c4531b 100644 --- a/src/features/todos/containers/TodosScreen.js +++ b/src/features/todos/containers/TodosScreen.js @@ -18,6 +18,7 @@ class TodosScreen extends Component { actions: PropTypes.shape({ todos: PropTypes.shape({ resize: PropTypes.func.isRequired, + handleIPCMessage: PropTypes.func.isRequired, }), }).isRequired, }; @@ -33,6 +34,8 @@ class TodosScreen extends Component { actions.todos.setTodosWebview({ webview })} width={stores.todos.width} minWidth={TODOS_MIN_WIDTH} resize={width => actions.todos.resize({ width })} diff --git a/src/features/todos/preload.js b/src/features/todos/preload.js new file mode 100644 index 000000000..533c9aea3 --- /dev/null +++ b/src/features/todos/preload.js @@ -0,0 +1,21 @@ +import { ipcRenderer } from 'electron'; + +const debug = require('debug')('Franz:feature:todos:preload'); + +debug('Preloading Todos Webview'); + +let hostMessageListener = () => {}; + +window.franz = { + onInitialize(ipcHostMessageListener) { + hostMessageListener = ipcHostMessageListener; + }, + sendToHost(message) { + ipcRenderer.sendToHost('clientMessage', message); + }, +}; + +ipcRenderer.on('hostMessage', (event, message) => { + debug('Received host message', event, message); + hostMessageListener(message); +}); diff --git a/src/features/todos/store.js b/src/features/todos/store.js index e7e13b37f..737902946 100644 --- a/src/features/todos/store.js +++ b/src/features/todos/store.js @@ -18,6 +18,8 @@ export default class TodoStore extends FeatureStore { @observable isFeatureActive = false; + webview = null; + @computed get width() { const width = this.settings.width || DEFAULT_TODOS_WIDTH; @@ -39,6 +41,9 @@ export default class TodoStore extends FeatureStore { this._registerActions(createActionBindings([ [todoActions.resize, this._resize], + [todoActions.setTodosWebview, this._setTodosWebview], + [todoActions.handleHostMessage, this._handleHostMessage], + [todoActions.handleClientMessage, this._handleClientMessage], ])); // REACTIONS @@ -76,6 +81,30 @@ export default class TodoStore extends FeatureStore { }); }; + @action _setTodosWebview = ({ webview }) => { + debug('_setTodosWebview', webview); + this.webview = webview; + }; + + @action _handleHostMessage = (message) => { + debug('_handleHostMessage', message); + if (message.action === 'create:todo') { + console.log(this.webview); + this.webview.send('hostMessage', message); + } + }; + + @action _handleClientMessage = (message) => { + debug('_handleClientMessage', message); + if (message.action === 'goToService') { + const { url, serviceId } = message.data; + if (url) { + this.stores.services.one(serviceId).webview.loadURL(url); + } + this.actions.service.setActive({ serviceId }); + } + }; + // Reactions _setFeatureEnabledReaction = () => { diff --git a/src/i18n/messages/src/lib/Menu.json b/src/i18n/messages/src/lib/Menu.json index 6f878cbd1..fa9509cbf 100644 --- a/src/i18n/messages/src/lib/Menu.json +++ b/src/i18n/messages/src/lib/Menu.json @@ -272,16 +272,29 @@ "column": 3 } }, + { + "id": "menu.view.toggleTodosDevTools", + "defaultMessage": "!!!Toggle Todos Developer Tools", + "file": "src/lib/Menu.js", + "start": { + "line": 99, + "column": 23 + }, + "end": { + "line": 102, + "column": 3 + } + }, { "id": "menu.view.toggleServiceDevTools", "defaultMessage": "!!!Toggle Service Developer Tools", "file": "src/lib/Menu.js", "start": { - "line": 99, + "line": 103, "column": 25 }, "end": { - "line": 102, + "line": 106, "column": 3 } }, @@ -290,11 +303,11 @@ "defaultMessage": "!!!Reload Service", "file": "src/lib/Menu.js", "start": { - "line": 103, + "line": 107, "column": 17 }, "end": { - "line": 106, + "line": 110, "column": 3 } }, @@ -303,11 +316,11 @@ "defaultMessage": "!!!Reload Franz", "file": "src/lib/Menu.js", "start": { - "line": 107, + "line": 111, "column": 15 }, "end": { - "line": 110, + "line": 114, "column": 3 } }, @@ -316,11 +329,11 @@ "defaultMessage": "!!!Minimize", "file": "src/lib/Menu.js", "start": { - "line": 111, + "line": 115, "column": 12 }, "end": { - "line": 114, + "line": 118, "column": 3 } }, @@ -329,11 +342,11 @@ "defaultMessage": "!!!Close", "file": "src/lib/Menu.js", "start": { - "line": 115, + "line": 119, "column": 9 }, "end": { - "line": 118, + "line": 122, "column": 3 } }, @@ -342,11 +355,11 @@ "defaultMessage": "!!!Learn More", "file": "src/lib/Menu.js", "start": { - "line": 119, + "line": 123, "column": 13 }, "end": { - "line": 122, + "line": 126, "column": 3 } }, @@ -355,11 +368,11 @@ "defaultMessage": "!!!Changelog", "file": "src/lib/Menu.js", "start": { - "line": 123, + "line": 127, "column": 13 }, "end": { - "line": 126, + "line": 130, "column": 3 } }, @@ -368,11 +381,11 @@ "defaultMessage": "!!!Support", "file": "src/lib/Menu.js", "start": { - "line": 127, + "line": 131, "column": 11 }, "end": { - "line": 130, + "line": 134, "column": 3 } }, @@ -381,11 +394,11 @@ "defaultMessage": "!!!Copy Debug Information", "file": "src/lib/Menu.js", "start": { - "line": 131, + "line": 135, "column": 13 }, "end": { - "line": 134, + "line": 138, "column": 3 } }, @@ -394,11 +407,11 @@ "defaultMessage": "!!!Franz Debug Information", "file": "src/lib/Menu.js", "start": { - "line": 135, + "line": 139, "column": 27 }, "end": { - "line": 138, + "line": 142, "column": 3 } }, @@ -407,11 +420,11 @@ "defaultMessage": "!!!Your Debug Information has been copied to your clipboard.", "file": "src/lib/Menu.js", "start": { - "line": 139, + "line": 143, "column": 23 }, "end": { - "line": 142, + "line": 146, "column": 3 } }, @@ -420,11 +433,11 @@ "defaultMessage": "!!!Terms of Service", "file": "src/lib/Menu.js", "start": { - "line": 143, + "line": 147, "column": 7 }, "end": { - "line": 146, + "line": 150, "column": 3 } }, @@ -433,11 +446,11 @@ "defaultMessage": "!!!Privacy Statement", "file": "src/lib/Menu.js", "start": { - "line": 147, + "line": 151, "column": 11 }, "end": { - "line": 150, + "line": 154, "column": 3 } }, @@ -446,11 +459,11 @@ "defaultMessage": "!!!File", "file": "src/lib/Menu.js", "start": { - "line": 151, + "line": 155, "column": 8 }, "end": { - "line": 154, + "line": 158, "column": 3 } }, @@ -459,11 +472,11 @@ "defaultMessage": "!!!View", "file": "src/lib/Menu.js", "start": { - "line": 155, + "line": 159, "column": 8 }, "end": { - "line": 158, + "line": 162, "column": 3 } }, @@ -472,11 +485,11 @@ "defaultMessage": "!!!Services", "file": "src/lib/Menu.js", "start": { - "line": 159, + "line": 163, "column": 12 }, "end": { - "line": 162, + "line": 166, "column": 3 } }, @@ -485,11 +498,11 @@ "defaultMessage": "!!!Window", "file": "src/lib/Menu.js", "start": { - "line": 163, + "line": 167, "column": 10 }, "end": { - "line": 166, + "line": 170, "column": 3 } }, @@ -498,11 +511,11 @@ "defaultMessage": "!!!Help", "file": "src/lib/Menu.js", "start": { - "line": 167, + "line": 171, "column": 8 }, "end": { - "line": 170, + "line": 174, "column": 3 } }, @@ -511,11 +524,11 @@ "defaultMessage": "!!!About Franz", "file": "src/lib/Menu.js", "start": { - "line": 171, + "line": 175, "column": 9 }, "end": { - "line": 174, + "line": 178, "column": 3 } }, @@ -524,11 +537,11 @@ "defaultMessage": "!!!What's new?", "file": "src/lib/Menu.js", "start": { - "line": 175, + "line": 179, "column": 16 }, "end": { - "line": 178, + "line": 182, "column": 3 } }, @@ -537,11 +550,11 @@ "defaultMessage": "!!!Settings", "file": "src/lib/Menu.js", "start": { - "line": 179, + "line": 183, "column": 12 }, "end": { - "line": 182, + "line": 186, "column": 3 } }, @@ -550,11 +563,11 @@ "defaultMessage": "!!!Check for updates", "file": "src/lib/Menu.js", "start": { - "line": 183, + "line": 187, "column": 19 }, "end": { - "line": 186, + "line": 190, "column": 3 } }, @@ -563,11 +576,11 @@ "defaultMessage": "!!!Hide", "file": "src/lib/Menu.js", "start": { - "line": 187, + "line": 191, "column": 8 }, "end": { - "line": 190, + "line": 194, "column": 3 } }, @@ -576,11 +589,11 @@ "defaultMessage": "!!!Hide Others", "file": "src/lib/Menu.js", "start": { - "line": 191, + "line": 195, "column": 14 }, "end": { - "line": 194, + "line": 198, "column": 3 } }, @@ -589,11 +602,11 @@ "defaultMessage": "!!!Unhide", "file": "src/lib/Menu.js", "start": { - "line": 195, + "line": 199, "column": 10 }, "end": { - "line": 198, + "line": 202, "column": 3 } }, @@ -602,11 +615,11 @@ "defaultMessage": "!!!Quit", "file": "src/lib/Menu.js", "start": { - "line": 199, + "line": 203, "column": 8 }, "end": { - "line": 202, + "line": 206, "column": 3 } }, @@ -615,11 +628,11 @@ "defaultMessage": "!!!Add New Service...", "file": "src/lib/Menu.js", "start": { - "line": 203, + "line": 207, "column": 17 }, "end": { - "line": 206, + "line": 210, "column": 3 } }, @@ -628,11 +641,11 @@ "defaultMessage": "!!!Add New Workspace...", "file": "src/lib/Menu.js", "start": { - "line": 207, + "line": 211, "column": 19 }, "end": { - "line": 210, + "line": 214, "column": 3 } }, @@ -641,11 +654,11 @@ "defaultMessage": "!!!Open workspace drawer", "file": "src/lib/Menu.js", "start": { - "line": 211, + "line": 215, "column": 23 }, "end": { - "line": 214, + "line": 218, "column": 3 } }, @@ -654,11 +667,11 @@ "defaultMessage": "!!!Close workspace drawer", "file": "src/lib/Menu.js", "start": { - "line": 215, + "line": 219, "column": 24 }, "end": { - "line": 218, + "line": 222, "column": 3 } }, @@ -667,11 +680,11 @@ "defaultMessage": "!!!Activate next service...", "file": "src/lib/Menu.js", "start": { - "line": 219, + "line": 223, "column": 23 }, "end": { - "line": 222, + "line": 226, "column": 3 } }, @@ -680,11 +693,11 @@ "defaultMessage": "!!!Activate previous service...", "file": "src/lib/Menu.js", "start": { - "line": 223, + "line": 227, "column": 27 }, "end": { - "line": 226, + "line": 230, "column": 3 } }, @@ -693,11 +706,11 @@ "defaultMessage": "!!!Disable notifications & audio", "file": "src/lib/Menu.js", "start": { - "line": 227, + "line": 231, "column": 11 }, "end": { - "line": 230, + "line": 234, "column": 3 } }, @@ -706,11 +719,11 @@ "defaultMessage": "!!!Enable notifications & audio", "file": "src/lib/Menu.js", "start": { - "line": 231, + "line": 235, "column": 13 }, "end": { - "line": 234, + "line": 238, "column": 3 } }, @@ -719,11 +732,11 @@ "defaultMessage": "!!!Workspaces", "file": "src/lib/Menu.js", "start": { - "line": 235, + "line": 239, "column": 14 }, "end": { - "line": 238, + "line": 242, "column": 3 } }, @@ -732,11 +745,11 @@ "defaultMessage": "!!!Default", "file": "src/lib/Menu.js", "start": { - "line": 239, + "line": 243, "column": 20 }, "end": { - "line": 242, + "line": 246, "column": 3 } } diff --git a/src/index.html b/src/index.html index f29aa2686..198c1ab7b 100644 --- a/src/index.html +++ b/src/index.html @@ -35,11 +35,16 @@ const originalReloadBehaviour = window._onLiveReloadFileChanged; window._onLiveReloadFileChanged = (file) => { - if (!file.path.includes('/build/webview/') && !file.path.includes('/build/index.js') && !file.path.includes('/build/electron/')) { + const isTodoPreloadPath = file.path.includes('/build/features/todos/preload.js'); + if (!file.path.includes('/build/webview/') && !file.path.includes('/build/index.js') && !file.path.includes('/build/electron/') && !isTodoPreloadPath) { originalReloadBehaviour(file); } else { - if (file.path.includes('/build/webview/')) { - debug('Livereload: Reloading all webvies'); + if (isTodoPreloadPath) { + debug('Livereload: Reloading all webviews'); + const webview = document.querySelector('webview[partition="persist:todos"]'); + if (webview) webview.reload(); + } else if (file.path.includes('/build/webview/')) { + debug('Livereload: Reloading all webviews'); const webviews = document.querySelectorAll('webview').forEach(webview => webview.reload()); } else { debug('Livereload: skip reload as only main process files have changed'); diff --git a/src/lib/Menu.js b/src/lib/Menu.js index 22d788918..9e491e151 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js @@ -96,6 +96,10 @@ const menuItems = defineMessages({ id: 'menu.view.toggleDevTools', defaultMessage: '!!!Toggle Developer Tools', }, + toggleTodosDevTools: { + id: 'menu.view.toggleTodosDevTools', + defaultMessage: '!!!Toggle Todos Developer Tools', + }, toggleServiceDevTools: { id: 'menu.view.toggleServiceDevTools', defaultMessage: '!!!Toggle Service Developer Tools', @@ -240,6 +244,7 @@ const menuItems = defineMessages({ id: 'menu.workspaces.defaultWorkspace', defaultMessage: '!!!Default', }, + }); function getActiveWebview() { @@ -620,6 +625,17 @@ export default class FranzMenu { enabled: this.stores.user.isLoggedIn && this.stores.services.enabled.length > 0, }); + if (this.stores.features.features.isTodosEnabled) { + tpl[1].submenu.push({ + label: intl.formatMessage(menuItems.toggleTodosDevTools), + accelerator: `${cmdKey}+Shift+Alt+O`, + click: () => { + const webview = document.querySelector('webview[partition="persist:todos"]'); + if (webview) webview.openDevTools(); + }, + }); + } + tpl[1].submenu.unshift({ label: intl.formatMessage(menuItems.reloadService), id: 'reloadService', // TODO: needed? diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 109ac5cd7..b13425249 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js @@ -440,6 +440,9 @@ export default class ServicesStore extends Store { redirect: false, }); } + } else if (channel === 'feature:todos') { + Object.assign(args[0].data, { serviceId }); + this.actions.todos.handleHostMessage(args[0]); } } diff --git a/src/webview/contextMenu.js b/src/webview/contextMenu.js index a4a6ab899..663b1ebca 100644 --- a/src/webview/contextMenu.js +++ b/src/webview/contextMenu.js @@ -36,6 +36,23 @@ const buildMenuTpl = (props, suggestions, isSpellcheckEnabled, defaultSpellcheck // @adlk: we can't use roles here due to a bug with electron where electron.remote.webContents.getFocusedWebContents() returns the first webview in DOM instead of the focused one // Github issue creation is pending let menuTpl = [ + { + type: 'separator', + }, { + id: 'createTodo', + label: `Create todo: "${textSelection.length > 15 ? `${textSelection.slice(0, 15)}...` : textSelection}"`, + visible: hasText, + click() { + debug('Create todo from selected text', textSelection); + ipcRenderer.sendToHost('feature:todos', { + action: 'create:todo', + data: { + title: textSelection, + url: window.location.href, + }, + }); + }, + }, { type: 'separator', }, { -- cgit v1.2.3-54-g00ecf From b9a8c4f12dfb97bd861075047b6ca24ea5f9e524 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 1 Aug 2019 15:40:14 +0200 Subject: remove debug logs Co-Authored-By: Dominik Guzei --- src/features/todos/store.js | 1 - 1 file changed, 1 deletion(-) (limited to 'src/features/todos/store.js') diff --git a/src/features/todos/store.js b/src/features/todos/store.js index 737902946..cd9c8e5f6 100644 --- a/src/features/todos/store.js +++ b/src/features/todos/store.js @@ -89,7 +89,6 @@ export default class TodoStore extends FeatureStore { @action _handleHostMessage = (message) => { debug('_handleHostMessage', message); if (message.action === 'create:todo') { - console.log(this.webview); this.webview.send('hostMessage', message); } }; -- cgit v1.2.3-54-g00ecf From 6297d46f370092598d2ebb973bb69f2c368d7904 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Fri, 2 Aug 2019 11:41:51 +0200 Subject: Add option to toggle the Todos panel --- packages/theme/src/themes/dark/index.ts | 5 + packages/theme/src/themes/default/index.ts | 7 +- src/features/todos/actions.js | 1 + src/features/todos/components/TodosWebview.js | 56 +++++- src/features/todos/containers/TodosScreen.js | 2 + src/features/todos/index.js | 1 + src/features/todos/store.js | 15 +- src/i18n/locales/defaultMessages.json | 271 +++++++++++++++----------- src/i18n/locales/en-US.json | 5 +- src/i18n/messages/src/lib/Menu.json | 271 +++++++++++++++----------- src/lib/Menu.js | 50 ++++- 11 files changed, 446 insertions(+), 238 deletions(-) (limited to 'src/features/todos/store.js') diff --git a/packages/theme/src/themes/dark/index.ts b/packages/theme/src/themes/dark/index.ts index cb1b33f2d..d29345298 100644 --- a/packages/theme/src/themes/dark/index.ts +++ b/packages/theme/src/themes/dark/index.ts @@ -124,6 +124,11 @@ export const todos = merge({}, defaultStyles.todos, { todosLayer: { borderLeftColor: legacyStyles.darkThemeGrayDarker, }, + toggleButton: { + background: defaultStyles.styleTypes.primary.accent, + textColor: defaultStyles.styleTypes.primary.contrast, + shadowColor: 'rgba(0, 0, 0, 0.2)', + }, dragIndicator: { background: legacyStyles.themeGrayLight, }, diff --git a/packages/theme/src/themes/default/index.ts b/packages/theme/src/themes/default/index.ts index d524b8ea7..ac6e3f7c7 100644 --- a/packages/theme/src/themes/default/index.ts +++ b/packages/theme/src/themes/default/index.ts @@ -211,7 +211,12 @@ export const announcements = { // Todos export const todos = { todosLayer: { - borderLeftColor: legacyStyles.themeGrayDark, + borderLeftColor: legacyStyles.themeGrayLighter, + }, + toggleButton: { + background: styleTypes.primary.accent, + textColor: styleTypes.primary.contrast, + shadowColor: 'rgba(0, 0, 0, 0.2)', }, dragIndicator: { background: legacyStyles.themeGrayLight, diff --git a/src/features/todos/actions.js b/src/features/todos/actions.js index a6090a259..dc63d5fcd 100644 --- a/src/features/todos/actions.js +++ b/src/features/todos/actions.js @@ -5,6 +5,7 @@ export const todoActions = createActionsFromDefinitions({ resize: { width: PropTypes.number.isRequired, }, + toggleTodosPanel: {}, setTodosWebview: { webview: PropTypes.instanceOf(Element).isRequired, }, diff --git a/src/features/todos/components/TodosWebview.js b/src/features/todos/components/TodosWebview.js index bc32ae728..819e599ca 100644 --- a/src/features/todos/components/TodosWebview.js +++ b/src/features/todos/components/TodosWebview.js @@ -3,16 +3,31 @@ import PropTypes from 'prop-types'; import { observer } from 'mobx-react'; import injectSheet from 'react-jss'; import Webview from 'react-electron-web-view'; +import { Icon } from '@meetfranz/ui'; import * as environment from '../../../environment'; +const TOGGLE_SIZE = 45; + const styles = theme => ({ root: { background: theme.colorBackground, position: 'relative', borderLeft: [1, 'solid', theme.todos.todosLayer.borderLeftColor], + zIndex: 300, + + transition: 'all 0.5s', + transform: props => `translateX(${props.isVisible ? 0 : props.width}px)`, + + '&:hover $toggleTodosButton': { + opacity: 1, + }, }, webview: { height: '100%', + + '& webview': { + height: '100%', + }, }, resizeHandler: { position: 'absolute', @@ -29,6 +44,31 @@ const styles = theme => ({ zIndex: 400, background: theme.todos.dragIndicator.background, }, + toggleTodosButton: { + width: TOGGLE_SIZE, + height: TOGGLE_SIZE, + background: theme.todos.toggleButton.background, + position: 'absolute', + bottom: 80, + right: props => (props.width + (props.isVisible ? -TOGGLE_SIZE / 2 : 0)), + borderRadius: TOGGLE_SIZE / 2, + opacity: props => (props.isVisible ? 0 : 1), + transition: 'all 0.5s', + zIndex: 600, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + boxShadow: [0, 0, 10, theme.todos.toggleButton.shadowColor], + // border: [1, 'solid', theme.todos.toggleButton.borderColor], + + borderTopRightRadius: props => (props.isVisible ? null : 0), + borderBottomRightRadius: props => (props.isVisible ? null : 0), + + '& svg': { + fill: theme.todos.toggleButton.textColor, + transition: 'all 0.5s', + }, + }, }); @injectSheet(styles) @observer @@ -36,6 +76,8 @@ class TodosWebview extends Component { static propTypes = { classes: PropTypes.object.isRequired, authToken: PropTypes.string.isRequired, + isVisible: PropTypes.bool.isRequired, + togglePanel: PropTypes.func.isRequired, handleClientMessage: PropTypes.func.isRequired, setTodosWebview: PropTypes.func.isRequired, resize: PropTypes.func.isRequired, @@ -123,16 +165,26 @@ class TodosWebview extends Component { } render() { - const { authToken, classes } = this.props; + const { + authToken, classes, isVisible, togglePanel, + } = this.props; const { width, delta, isDragging } = this.state; + return ( <>
this.stopResize()} ref={(node) => { this.node = node; }} > +
todoActions.setTodosWebview({ webview })} width={todosStore.width} diff --git a/src/features/todos/index.js b/src/features/todos/index.js index f741561d6..00b165cc5 100644 --- a/src/features/todos/index.js +++ b/src/features/todos/index.js @@ -7,6 +7,7 @@ export const GA_CATEGORY_TODOS = 'Todos'; export const DEFAULT_TODOS_WIDTH = 300; export const TODOS_MIN_WIDTH = 200; +export const DEFAULT_TODOS_VISIBLE = true; export const todosStore = new TodoStore(); diff --git a/src/features/todos/store.js b/src/features/todos/store.js index cd9c8e5f6..79c218b65 100644 --- a/src/features/todos/store.js +++ b/src/features/todos/store.js @@ -9,7 +9,7 @@ import { todoActions } from './actions'; import { FeatureStore } from '../utils/FeatureStore'; import { createReactions } from '../../stores/lib/Reaction'; import { createActionBindings } from '../utils/ActionBinding'; -import { DEFAULT_TODOS_WIDTH, TODOS_MIN_WIDTH } from '.'; +import { DEFAULT_TODOS_WIDTH, TODOS_MIN_WIDTH, DEFAULT_TODOS_VISIBLE } from '.'; const debug = require('debug')('Franz:feature:todos:store'); @@ -26,6 +26,12 @@ export default class TodoStore extends FeatureStore { return width < TODOS_MIN_WIDTH ? TODOS_MIN_WIDTH : width; } + @computed get isTodosPanelVisible() { + if (this.settings.isTodosPanelVisible === undefined) return DEFAULT_TODOS_VISIBLE; + + return this.settings.isTodosPanelVisible; + } + @computed get settings() { return localStorage.getItem('todos') || {}; } @@ -41,6 +47,7 @@ export default class TodoStore extends FeatureStore { this._registerActions(createActionBindings([ [todoActions.resize, this._resize], + [todoActions.toggleTodosPanel, this._toggleTodosPanel], [todoActions.setTodosWebview, this._setTodosWebview], [todoActions.handleHostMessage, this._handleHostMessage], [todoActions.handleClientMessage, this._handleClientMessage], @@ -81,6 +88,12 @@ export default class TodoStore extends FeatureStore { }); }; + @action _toggleTodosPanel = () => { + this._updateSettings({ + isTodosPanelVisible: !this.isTodosPanelVisible, + }); + }; + @action _setTodosWebview = ({ webview }) => { debug('_setTodosWebview', webview); this.webview = webview; diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json index a0654027b..5959fb059 100644 --- a/src/i18n/locales/defaultMessages.json +++ b/src/i18n/locales/defaultMessages.json @@ -3917,754 +3917,793 @@ "defaultMessage": "!!!Edit", "end": { "column": 3, - "line": 18 + "line": 21 }, "file": "src/lib/Menu.js", "id": "menu.edit", "start": { "column": 8, - "line": 15 + "line": 18 } }, { "defaultMessage": "!!!Undo", "end": { "column": 3, - "line": 22 + "line": 25 }, "file": "src/lib/Menu.js", "id": "menu.edit.undo", "start": { "column": 8, - "line": 19 + "line": 22 } }, { "defaultMessage": "!!!Redo", "end": { "column": 3, - "line": 26 + "line": 29 }, "file": "src/lib/Menu.js", "id": "menu.edit.redo", "start": { "column": 8, - "line": 23 + "line": 26 } }, { "defaultMessage": "!!!Cut", "end": { "column": 3, - "line": 30 + "line": 33 }, "file": "src/lib/Menu.js", "id": "menu.edit.cut", "start": { "column": 7, - "line": 27 + "line": 30 } }, { "defaultMessage": "!!!Copy", "end": { "column": 3, - "line": 34 + "line": 37 }, "file": "src/lib/Menu.js", "id": "menu.edit.copy", "start": { "column": 8, - "line": 31 + "line": 34 } }, { "defaultMessage": "!!!Paste", "end": { "column": 3, - "line": 38 + "line": 41 }, "file": "src/lib/Menu.js", "id": "menu.edit.paste", "start": { "column": 9, - "line": 35 + "line": 38 } }, { "defaultMessage": "!!!Paste And Match Style", "end": { "column": 3, - "line": 42 + "line": 45 }, "file": "src/lib/Menu.js", "id": "menu.edit.pasteAndMatchStyle", "start": { "column": 22, - "line": 39 + "line": 42 } }, { "defaultMessage": "!!!Delete", "end": { "column": 3, - "line": 46 + "line": 49 }, "file": "src/lib/Menu.js", "id": "menu.edit.delete", "start": { "column": 10, - "line": 43 + "line": 46 } }, { "defaultMessage": "!!!Select All", "end": { "column": 3, - "line": 50 + "line": 53 }, "file": "src/lib/Menu.js", "id": "menu.edit.selectAll", "start": { "column": 13, - "line": 47 + "line": 50 } }, { "defaultMessage": "!!!Speech", "end": { "column": 3, - "line": 54 + "line": 57 }, "file": "src/lib/Menu.js", "id": "menu.edit.speech", "start": { "column": 10, - "line": 51 + "line": 54 } }, { "defaultMessage": "!!!Start Speaking", "end": { "column": 3, - "line": 58 + "line": 61 }, "file": "src/lib/Menu.js", "id": "menu.edit.startSpeaking", "start": { "column": 17, - "line": 55 + "line": 58 } }, { "defaultMessage": "!!!Stop Speaking", "end": { "column": 3, - "line": 62 + "line": 65 }, "file": "src/lib/Menu.js", "id": "menu.edit.stopSpeaking", "start": { "column": 16, - "line": 59 + "line": 62 } }, { "defaultMessage": "!!!Start Dictation", "end": { "column": 3, - "line": 66 + "line": 69 }, "file": "src/lib/Menu.js", "id": "menu.edit.startDictation", "start": { "column": 18, - "line": 63 + "line": 66 } }, { "defaultMessage": "!!!Emoji & Symbols", "end": { "column": 3, - "line": 70 + "line": 73 }, "file": "src/lib/Menu.js", "id": "menu.edit.emojiSymbols", "start": { "column": 16, - "line": 67 + "line": 70 } }, { "defaultMessage": "!!!Actual Size", "end": { "column": 3, - "line": 74 + "line": 77 }, "file": "src/lib/Menu.js", "id": "menu.view.resetZoom", "start": { "column": 13, - "line": 71 + "line": 74 } }, { "defaultMessage": "!!!Zoom In", "end": { "column": 3, - "line": 78 + "line": 81 }, "file": "src/lib/Menu.js", "id": "menu.view.zoomIn", "start": { "column": 10, - "line": 75 + "line": 78 } }, { "defaultMessage": "!!!Zoom Out", "end": { "column": 3, - "line": 82 + "line": 85 }, "file": "src/lib/Menu.js", "id": "menu.view.zoomOut", "start": { "column": 11, - "line": 79 + "line": 82 } }, { "defaultMessage": "!!!Enter Full Screen", "end": { "column": 3, - "line": 86 + "line": 89 }, "file": "src/lib/Menu.js", "id": "menu.view.enterFullScreen", "start": { "column": 19, - "line": 83 + "line": 86 } }, { "defaultMessage": "!!!Exit Full Screen", "end": { "column": 3, - "line": 90 + "line": 93 }, "file": "src/lib/Menu.js", "id": "menu.view.exitFullScreen", "start": { "column": 18, - "line": 87 + "line": 90 } }, { "defaultMessage": "!!!Toggle Full Screen", "end": { "column": 3, - "line": 94 + "line": 97 }, "file": "src/lib/Menu.js", "id": "menu.view.toggleFullScreen", "start": { "column": 20, - "line": 91 + "line": 94 } }, { "defaultMessage": "!!!Toggle Developer Tools", "end": { "column": 3, - "line": 98 + "line": 101 }, "file": "src/lib/Menu.js", "id": "menu.view.toggleDevTools", "start": { "column": 18, - "line": 95 + "line": 98 } }, { "defaultMessage": "!!!Toggle Todos Developer Tools", "end": { "column": 3, - "line": 102 + "line": 105 }, "file": "src/lib/Menu.js", "id": "menu.view.toggleTodosDevTools", "start": { "column": 23, - "line": 99 + "line": 102 } }, { "defaultMessage": "!!!Toggle Service Developer Tools", "end": { "column": 3, - "line": 106 + "line": 109 }, "file": "src/lib/Menu.js", "id": "menu.view.toggleServiceDevTools", "start": { "column": 25, - "line": 103 + "line": 106 } }, { "defaultMessage": "!!!Reload Service", "end": { "column": 3, - "line": 110 + "line": 113 }, "file": "src/lib/Menu.js", "id": "menu.view.reloadService", "start": { "column": 17, - "line": 107 + "line": 110 } }, { "defaultMessage": "!!!Reload Franz", "end": { "column": 3, - "line": 114 + "line": 117 }, "file": "src/lib/Menu.js", "id": "menu.view.reloadFranz", "start": { "column": 15, - "line": 111 + "line": 114 } }, { "defaultMessage": "!!!Minimize", "end": { "column": 3, - "line": 118 + "line": 121 }, "file": "src/lib/Menu.js", "id": "menu.window.minimize", "start": { "column": 12, - "line": 115 + "line": 118 } }, { "defaultMessage": "!!!Close", "end": { "column": 3, - "line": 122 + "line": 125 }, "file": "src/lib/Menu.js", "id": "menu.window.close", "start": { "column": 9, - "line": 119 + "line": 122 } }, { "defaultMessage": "!!!Learn More", "end": { "column": 3, - "line": 126 + "line": 129 }, "file": "src/lib/Menu.js", "id": "menu.help.learnMore", "start": { "column": 13, - "line": 123 + "line": 126 } }, { "defaultMessage": "!!!Changelog", "end": { "column": 3, - "line": 130 + "line": 133 }, "file": "src/lib/Menu.js", "id": "menu.help.changelog", "start": { "column": 13, - "line": 127 + "line": 130 } }, { "defaultMessage": "!!!Support", "end": { "column": 3, - "line": 134 + "line": 137 }, "file": "src/lib/Menu.js", "id": "menu.help.support", "start": { "column": 11, - "line": 131 + "line": 134 } }, { "defaultMessage": "!!!Copy Debug Information", "end": { "column": 3, - "line": 138 + "line": 141 }, "file": "src/lib/Menu.js", "id": "menu.help.debugInfo", "start": { "column": 13, - "line": 135 + "line": 138 } }, { "defaultMessage": "!!!Franz Debug Information", "end": { "column": 3, - "line": 142 + "line": 145 }, "file": "src/lib/Menu.js", "id": "menu.help.debugInfoCopiedHeadline", "start": { "column": 27, - "line": 139 + "line": 142 } }, { "defaultMessage": "!!!Your Debug Information has been copied to your clipboard.", "end": { "column": 3, - "line": 146 + "line": 149 }, "file": "src/lib/Menu.js", "id": "menu.help.debugInfoCopiedBody", "start": { "column": 23, - "line": 143 + "line": 146 } }, { "defaultMessage": "!!!Terms of Service", "end": { "column": 3, - "line": 150 + "line": 153 }, "file": "src/lib/Menu.js", "id": "menu.help.tos", "start": { "column": 7, - "line": 147 + "line": 150 } }, { "defaultMessage": "!!!Privacy Statement", "end": { "column": 3, - "line": 154 + "line": 157 }, "file": "src/lib/Menu.js", "id": "menu.help.privacy", "start": { "column": 11, - "line": 151 + "line": 154 } }, { "defaultMessage": "!!!File", "end": { "column": 3, - "line": 158 + "line": 161 }, "file": "src/lib/Menu.js", "id": "menu.file", "start": { "column": 8, - "line": 155 + "line": 158 } }, { "defaultMessage": "!!!View", "end": { "column": 3, - "line": 162 + "line": 165 }, "file": "src/lib/Menu.js", "id": "menu.view", "start": { "column": 8, - "line": 159 + "line": 162 } }, { "defaultMessage": "!!!Services", "end": { "column": 3, - "line": 166 + "line": 169 }, "file": "src/lib/Menu.js", "id": "menu.services", "start": { "column": 12, - "line": 163 + "line": 166 } }, { "defaultMessage": "!!!Window", "end": { "column": 3, - "line": 170 + "line": 173 }, "file": "src/lib/Menu.js", "id": "menu.window", "start": { "column": 10, - "line": 167 + "line": 170 } }, { "defaultMessage": "!!!Help", "end": { "column": 3, - "line": 174 + "line": 177 }, "file": "src/lib/Menu.js", "id": "menu.help", "start": { "column": 8, - "line": 171 + "line": 174 } }, { "defaultMessage": "!!!About Franz", "end": { "column": 3, - "line": 178 + "line": 181 }, "file": "src/lib/Menu.js", "id": "menu.app.about", "start": { "column": 9, - "line": 175 + "line": 178 } }, { "defaultMessage": "!!!What's new?", "end": { "column": 3, - "line": 182 + "line": 185 }, "file": "src/lib/Menu.js", "id": "menu.app.announcement", "start": { "column": 16, - "line": 179 + "line": 182 } }, { "defaultMessage": "!!!Settings", "end": { "column": 3, - "line": 186 + "line": 189 }, "file": "src/lib/Menu.js", "id": "menu.app.settings", "start": { "column": 12, - "line": 183 + "line": 186 } }, { "defaultMessage": "!!!Check for updates", "end": { "column": 3, - "line": 190 + "line": 193 }, "file": "src/lib/Menu.js", "id": "menu.app.checkForUpdates", "start": { "column": 19, - "line": 187 + "line": 190 } }, { "defaultMessage": "!!!Hide", "end": { "column": 3, - "line": 194 + "line": 197 }, "file": "src/lib/Menu.js", "id": "menu.app.hide", "start": { "column": 8, - "line": 191 + "line": 194 } }, { "defaultMessage": "!!!Hide Others", "end": { "column": 3, - "line": 198 + "line": 201 }, "file": "src/lib/Menu.js", "id": "menu.app.hideOthers", "start": { "column": 14, - "line": 195 + "line": 198 } }, { "defaultMessage": "!!!Unhide", "end": { "column": 3, - "line": 202 + "line": 205 }, "file": "src/lib/Menu.js", "id": "menu.app.unhide", "start": { "column": 10, - "line": 199 + "line": 202 } }, { "defaultMessage": "!!!Quit", "end": { "column": 3, - "line": 206 + "line": 209 }, "file": "src/lib/Menu.js", "id": "menu.app.quit", "start": { "column": 8, - "line": 203 + "line": 206 } }, { "defaultMessage": "!!!Add New Service...", "end": { "column": 3, - "line": 210 + "line": 213 }, "file": "src/lib/Menu.js", "id": "menu.services.addNewService", "start": { "column": 17, - "line": 207 + "line": 210 } }, { "defaultMessage": "!!!Add New Workspace...", "end": { "column": 3, - "line": 214 + "line": 217 }, "file": "src/lib/Menu.js", "id": "menu.workspaces.addNewWorkspace", "start": { "column": 19, - "line": 211 + "line": 214 } }, { "defaultMessage": "!!!Open workspace drawer", "end": { "column": 3, - "line": 218 + "line": 221 }, "file": "src/lib/Menu.js", "id": "menu.workspaces.openWorkspaceDrawer", "start": { "column": 23, - "line": 215 + "line": 218 } }, { "defaultMessage": "!!!Close workspace drawer", "end": { "column": 3, - "line": 222 + "line": 225 }, "file": "src/lib/Menu.js", "id": "menu.workspaces.closeWorkspaceDrawer", "start": { "column": 24, - "line": 219 + "line": 222 } }, { "defaultMessage": "!!!Activate next service...", "end": { "column": 3, - "line": 226 + "line": 229 }, "file": "src/lib/Menu.js", "id": "menu.services.setNextServiceActive", "start": { "column": 23, - "line": 223 + "line": 226 } }, { "defaultMessage": "!!!Activate previous service...", "end": { "column": 3, - "line": 230 + "line": 233 }, "file": "src/lib/Menu.js", "id": "menu.services.activatePreviousService", "start": { "column": 27, - "line": 227 + "line": 230 } }, { "defaultMessage": "!!!Disable notifications & audio", "end": { "column": 3, - "line": 234 + "line": 237 }, "file": "src/lib/Menu.js", "id": "sidebar.muteApp", "start": { "column": 11, - "line": 231 + "line": 234 } }, { "defaultMessage": "!!!Enable notifications & audio", "end": { "column": 3, - "line": 238 + "line": 241 }, "file": "src/lib/Menu.js", "id": "sidebar.unmuteApp", "start": { "column": 13, - "line": 235 + "line": 238 } }, { "defaultMessage": "!!!Workspaces", "end": { "column": 3, - "line": 242 + "line": 245 }, "file": "src/lib/Menu.js", "id": "menu.workspaces", "start": { "column": 14, - "line": 239 + "line": 242 } }, { "defaultMessage": "!!!Default", "end": { "column": 3, - "line": 246 + "line": 249 }, "file": "src/lib/Menu.js", "id": "menu.workspaces.defaultWorkspace", "start": { "column": 20, - "line": 243 + "line": 246 + } + }, + { + "defaultMessage": "!!!Todos", + "end": { + "column": 3, + "line": 253 + }, + "file": "src/lib/Menu.js", + "id": "menu.todos", + "start": { + "column": 9, + "line": 250 + } + }, + { + "defaultMessage": "!!!Open Todos drawer", + "end": { + "column": 3, + "line": 257 + }, + "file": "src/lib/Menu.js", + "id": "menu.Todoss.openTodosDrawer", + "start": { + "column": 19, + "line": 254 + } + }, + { + "defaultMessage": "!!!Close Todos drawer", + "end": { + "column": 3, + "line": 261 + }, + "file": "src/lib/Menu.js", + "id": "menu.Todoss.closeTodosDrawer", + "start": { + "column": 20, + "line": 258 } } ], diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index 235d638b4..3cec9960e 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json @@ -43,6 +43,8 @@ "login.serverLogout": "Your session expired, please login again.", "login.submit.label": "Sign in", "login.tokenExpired": "Your session expired, please login again.", + "menu.Todoss.closeTodosDrawer": "Close Todos drawer", + "menu.Todoss.openTodosDrawer": "Open Todos drawer", "menu.app.about": "About Franz", "menu.app.announcement": "What's new?", "menu.app.checkForUpdates": "Check for updates", @@ -79,6 +81,7 @@ "menu.services.activatePreviousService": "Activate previous service", "menu.services.addNewService": "Add New Service...", "menu.services.setNextServiceActive": "Activate next service", + "menu.todos": "Todos", "menu.view": "View", "menu.view.enterFullScreen": "Enter Full Screen", "menu.view.exitFullScreen": "Exit Full Screen", @@ -333,4 +336,4 @@ "workspaceDrawer.workspaceFeatureInfo": "

Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.

You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.

", "workspaceDrawer.workspacesSettingsTooltip": "Edit workspaces settings", "workspaces.switchingIndicator.switchingTo": "Switching to" -} \ No newline at end of file +} diff --git a/src/i18n/messages/src/lib/Menu.json b/src/i18n/messages/src/lib/Menu.json index fa9509cbf..cee46608c 100644 --- a/src/i18n/messages/src/lib/Menu.json +++ b/src/i18n/messages/src/lib/Menu.json @@ -4,11 +4,11 @@ "defaultMessage": "!!!Edit", "file": "src/lib/Menu.js", "start": { - "line": 15, + "line": 18, "column": 8 }, "end": { - "line": 18, + "line": 21, "column": 3 } }, @@ -17,11 +17,11 @@ "defaultMessage": "!!!Undo", "file": "src/lib/Menu.js", "start": { - "line": 19, + "line": 22, "column": 8 }, "end": { - "line": 22, + "line": 25, "column": 3 } }, @@ -30,11 +30,11 @@ "defaultMessage": "!!!Redo", "file": "src/lib/Menu.js", "start": { - "line": 23, + "line": 26, "column": 8 }, "end": { - "line": 26, + "line": 29, "column": 3 } }, @@ -43,11 +43,11 @@ "defaultMessage": "!!!Cut", "file": "src/lib/Menu.js", "start": { - "line": 27, + "line": 30, "column": 7 }, "end": { - "line": 30, + "line": 33, "column": 3 } }, @@ -56,11 +56,11 @@ "defaultMessage": "!!!Copy", "file": "src/lib/Menu.js", "start": { - "line": 31, + "line": 34, "column": 8 }, "end": { - "line": 34, + "line": 37, "column": 3 } }, @@ -69,11 +69,11 @@ "defaultMessage": "!!!Paste", "file": "src/lib/Menu.js", "start": { - "line": 35, + "line": 38, "column": 9 }, "end": { - "line": 38, + "line": 41, "column": 3 } }, @@ -82,11 +82,11 @@ "defaultMessage": "!!!Paste And Match Style", "file": "src/lib/Menu.js", "start": { - "line": 39, + "line": 42, "column": 22 }, "end": { - "line": 42, + "line": 45, "column": 3 } }, @@ -95,11 +95,11 @@ "defaultMessage": "!!!Delete", "file": "src/lib/Menu.js", "start": { - "line": 43, + "line": 46, "column": 10 }, "end": { - "line": 46, + "line": 49, "column": 3 } }, @@ -108,11 +108,11 @@ "defaultMessage": "!!!Select All", "file": "src/lib/Menu.js", "start": { - "line": 47, + "line": 50, "column": 13 }, "end": { - "line": 50, + "line": 53, "column": 3 } }, @@ -121,11 +121,11 @@ "defaultMessage": "!!!Speech", "file": "src/lib/Menu.js", "start": { - "line": 51, + "line": 54, "column": 10 }, "end": { - "line": 54, + "line": 57, "column": 3 } }, @@ -134,11 +134,11 @@ "defaultMessage": "!!!Start Speaking", "file": "src/lib/Menu.js", "start": { - "line": 55, + "line": 58, "column": 17 }, "end": { - "line": 58, + "line": 61, "column": 3 } }, @@ -147,11 +147,11 @@ "defaultMessage": "!!!Stop Speaking", "file": "src/lib/Menu.js", "start": { - "line": 59, + "line": 62, "column": 16 }, "end": { - "line": 62, + "line": 65, "column": 3 } }, @@ -160,11 +160,11 @@ "defaultMessage": "!!!Start Dictation", "file": "src/lib/Menu.js", "start": { - "line": 63, + "line": 66, "column": 18 }, "end": { - "line": 66, + "line": 69, "column": 3 } }, @@ -173,11 +173,11 @@ "defaultMessage": "!!!Emoji & Symbols", "file": "src/lib/Menu.js", "start": { - "line": 67, + "line": 70, "column": 16 }, "end": { - "line": 70, + "line": 73, "column": 3 } }, @@ -186,11 +186,11 @@ "defaultMessage": "!!!Actual Size", "file": "src/lib/Menu.js", "start": { - "line": 71, + "line": 74, "column": 13 }, "end": { - "line": 74, + "line": 77, "column": 3 } }, @@ -199,11 +199,11 @@ "defaultMessage": "!!!Zoom In", "file": "src/lib/Menu.js", "start": { - "line": 75, + "line": 78, "column": 10 }, "end": { - "line": 78, + "line": 81, "column": 3 } }, @@ -212,11 +212,11 @@ "defaultMessage": "!!!Zoom Out", "file": "src/lib/Menu.js", "start": { - "line": 79, + "line": 82, "column": 11 }, "end": { - "line": 82, + "line": 85, "column": 3 } }, @@ -225,11 +225,11 @@ "defaultMessage": "!!!Enter Full Screen", "file": "src/lib/Menu.js", "start": { - "line": 83, + "line": 86, "column": 19 }, "end": { - "line": 86, + "line": 89, "column": 3 } }, @@ -238,11 +238,11 @@ "defaultMessage": "!!!Exit Full Screen", "file": "src/lib/Menu.js", "start": { - "line": 87, + "line": 90, "column": 18 }, "end": { - "line": 90, + "line": 93, "column": 3 } }, @@ -251,11 +251,11 @@ "defaultMessage": "!!!Toggle Full Screen", "file": "src/lib/Menu.js", "start": { - "line": 91, + "line": 94, "column": 20 }, "end": { - "line": 94, + "line": 97, "column": 3 } }, @@ -264,11 +264,11 @@ "defaultMessage": "!!!Toggle Developer Tools", "file": "src/lib/Menu.js", "start": { - "line": 95, + "line": 98, "column": 18 }, "end": { - "line": 98, + "line": 101, "column": 3 } }, @@ -277,11 +277,11 @@ "defaultMessage": "!!!Toggle Todos Developer Tools", "file": "src/lib/Menu.js", "start": { - "line": 99, + "line": 102, "column": 23 }, "end": { - "line": 102, + "line": 105, "column": 3 } }, @@ -290,11 +290,11 @@ "defaultMessage": "!!!Toggle Service Developer Tools", "file": "src/lib/Menu.js", "start": { - "line": 103, + "line": 106, "column": 25 }, "end": { - "line": 106, + "line": 109, "column": 3 } }, @@ -303,11 +303,11 @@ "defaultMessage": "!!!Reload Service", "file": "src/lib/Menu.js", "start": { - "line": 107, + "line": 110, "column": 17 }, "end": { - "line": 110, + "line": 113, "column": 3 } }, @@ -316,11 +316,11 @@ "defaultMessage": "!!!Reload Franz", "file": "src/lib/Menu.js", "start": { - "line": 111, + "line": 114, "column": 15 }, "end": { - "line": 114, + "line": 117, "column": 3 } }, @@ -329,11 +329,11 @@ "defaultMessage": "!!!Minimize", "file": "src/lib/Menu.js", "start": { - "line": 115, + "line": 118, "column": 12 }, "end": { - "line": 118, + "line": 121, "column": 3 } }, @@ -342,11 +342,11 @@ "defaultMessage": "!!!Close", "file": "src/lib/Menu.js", "start": { - "line": 119, + "line": 122, "column": 9 }, "end": { - "line": 122, + "line": 125, "column": 3 } }, @@ -355,11 +355,11 @@ "defaultMessage": "!!!Learn More", "file": "src/lib/Menu.js", "start": { - "line": 123, + "line": 126, "column": 13 }, "end": { - "line": 126, + "line": 129, "column": 3 } }, @@ -368,11 +368,11 @@ "defaultMessage": "!!!Changelog", "file": "src/lib/Menu.js", "start": { - "line": 127, + "line": 130, "column": 13 }, "end": { - "line": 130, + "line": 133, "column": 3 } }, @@ -381,11 +381,11 @@ "defaultMessage": "!!!Support", "file": "src/lib/Menu.js", "start": { - "line": 131, + "line": 134, "column": 11 }, "end": { - "line": 134, + "line": 137, "column": 3 } }, @@ -394,11 +394,11 @@ "defaultMessage": "!!!Copy Debug Information", "file": "src/lib/Menu.js", "start": { - "line": 135, + "line": 138, "column": 13 }, "end": { - "line": 138, + "line": 141, "column": 3 } }, @@ -407,11 +407,11 @@ "defaultMessage": "!!!Franz Debug Information", "file": "src/lib/Menu.js", "start": { - "line": 139, + "line": 142, "column": 27 }, "end": { - "line": 142, + "line": 145, "column": 3 } }, @@ -420,11 +420,11 @@ "defaultMessage": "!!!Your Debug Information has been copied to your clipboard.", "file": "src/lib/Menu.js", "start": { - "line": 143, + "line": 146, "column": 23 }, "end": { - "line": 146, + "line": 149, "column": 3 } }, @@ -433,11 +433,11 @@ "defaultMessage": "!!!Terms of Service", "file": "src/lib/Menu.js", "start": { - "line": 147, + "line": 150, "column": 7 }, "end": { - "line": 150, + "line": 153, "column": 3 } }, @@ -446,11 +446,11 @@ "defaultMessage": "!!!Privacy Statement", "file": "src/lib/Menu.js", "start": { - "line": 151, + "line": 154, "column": 11 }, "end": { - "line": 154, + "line": 157, "column": 3 } }, @@ -459,11 +459,11 @@ "defaultMessage": "!!!File", "file": "src/lib/Menu.js", "start": { - "line": 155, + "line": 158, "column": 8 }, "end": { - "line": 158, + "line": 161, "column": 3 } }, @@ -472,11 +472,11 @@ "defaultMessage": "!!!View", "file": "src/lib/Menu.js", "start": { - "line": 159, + "line": 162, "column": 8 }, "end": { - "line": 162, + "line": 165, "column": 3 } }, @@ -485,11 +485,11 @@ "defaultMessage": "!!!Services", "file": "src/lib/Menu.js", "start": { - "line": 163, + "line": 166, "column": 12 }, "end": { - "line": 166, + "line": 169, "column": 3 } }, @@ -498,11 +498,11 @@ "defaultMessage": "!!!Window", "file": "src/lib/Menu.js", "start": { - "line": 167, + "line": 170, "column": 10 }, "end": { - "line": 170, + "line": 173, "column": 3 } }, @@ -511,11 +511,11 @@ "defaultMessage": "!!!Help", "file": "src/lib/Menu.js", "start": { - "line": 171, + "line": 174, "column": 8 }, "end": { - "line": 174, + "line": 177, "column": 3 } }, @@ -524,11 +524,11 @@ "defaultMessage": "!!!About Franz", "file": "src/lib/Menu.js", "start": { - "line": 175, + "line": 178, "column": 9 }, "end": { - "line": 178, + "line": 181, "column": 3 } }, @@ -537,11 +537,11 @@ "defaultMessage": "!!!What's new?", "file": "src/lib/Menu.js", "start": { - "line": 179, + "line": 182, "column": 16 }, "end": { - "line": 182, + "line": 185, "column": 3 } }, @@ -550,11 +550,11 @@ "defaultMessage": "!!!Settings", "file": "src/lib/Menu.js", "start": { - "line": 183, + "line": 186, "column": 12 }, "end": { - "line": 186, + "line": 189, "column": 3 } }, @@ -563,11 +563,11 @@ "defaultMessage": "!!!Check for updates", "file": "src/lib/Menu.js", "start": { - "line": 187, + "line": 190, "column": 19 }, "end": { - "line": 190, + "line": 193, "column": 3 } }, @@ -576,11 +576,11 @@ "defaultMessage": "!!!Hide", "file": "src/lib/Menu.js", "start": { - "line": 191, + "line": 194, "column": 8 }, "end": { - "line": 194, + "line": 197, "column": 3 } }, @@ -589,11 +589,11 @@ "defaultMessage": "!!!Hide Others", "file": "src/lib/Menu.js", "start": { - "line": 195, + "line": 198, "column": 14 }, "end": { - "line": 198, + "line": 201, "column": 3 } }, @@ -602,11 +602,11 @@ "defaultMessage": "!!!Unhide", "file": "src/lib/Menu.js", "start": { - "line": 199, + "line": 202, "column": 10 }, "end": { - "line": 202, + "line": 205, "column": 3 } }, @@ -615,11 +615,11 @@ "defaultMessage": "!!!Quit", "file": "src/lib/Menu.js", "start": { - "line": 203, + "line": 206, "column": 8 }, "end": { - "line": 206, + "line": 209, "column": 3 } }, @@ -628,11 +628,11 @@ "defaultMessage": "!!!Add New Service...", "file": "src/lib/Menu.js", "start": { - "line": 207, + "line": 210, "column": 17 }, "end": { - "line": 210, + "line": 213, "column": 3 } }, @@ -641,11 +641,11 @@ "defaultMessage": "!!!Add New Workspace...", "file": "src/lib/Menu.js", "start": { - "line": 211, + "line": 214, "column": 19 }, "end": { - "line": 214, + "line": 217, "column": 3 } }, @@ -654,11 +654,11 @@ "defaultMessage": "!!!Open workspace drawer", "file": "src/lib/Menu.js", "start": { - "line": 215, + "line": 218, "column": 23 }, "end": { - "line": 218, + "line": 221, "column": 3 } }, @@ -667,11 +667,11 @@ "defaultMessage": "!!!Close workspace drawer", "file": "src/lib/Menu.js", "start": { - "line": 219, + "line": 222, "column": 24 }, "end": { - "line": 222, + "line": 225, "column": 3 } }, @@ -680,11 +680,11 @@ "defaultMessage": "!!!Activate next service...", "file": "src/lib/Menu.js", "start": { - "line": 223, + "line": 226, "column": 23 }, "end": { - "line": 226, + "line": 229, "column": 3 } }, @@ -693,11 +693,11 @@ "defaultMessage": "!!!Activate previous service...", "file": "src/lib/Menu.js", "start": { - "line": 227, + "line": 230, "column": 27 }, "end": { - "line": 230, + "line": 233, "column": 3 } }, @@ -706,11 +706,11 @@ "defaultMessage": "!!!Disable notifications & audio", "file": "src/lib/Menu.js", "start": { - "line": 231, + "line": 234, "column": 11 }, "end": { - "line": 234, + "line": 237, "column": 3 } }, @@ -719,11 +719,11 @@ "defaultMessage": "!!!Enable notifications & audio", "file": "src/lib/Menu.js", "start": { - "line": 235, + "line": 238, "column": 13 }, "end": { - "line": 238, + "line": 241, "column": 3 } }, @@ -732,11 +732,11 @@ "defaultMessage": "!!!Workspaces", "file": "src/lib/Menu.js", "start": { - "line": 239, + "line": 242, "column": 14 }, "end": { - "line": 242, + "line": 245, "column": 3 } }, @@ -745,11 +745,50 @@ "defaultMessage": "!!!Default", "file": "src/lib/Menu.js", "start": { - "line": 243, + "line": 246, "column": 20 }, "end": { - "line": 246, + "line": 249, + "column": 3 + } + }, + { + "id": "menu.todos", + "defaultMessage": "!!!Todos", + "file": "src/lib/Menu.js", + "start": { + "line": 250, + "column": 9 + }, + "end": { + "line": 253, + "column": 3 + } + }, + { + "id": "menu.Todoss.openTodosDrawer", + "defaultMessage": "!!!Open Todos drawer", + "file": "src/lib/Menu.js", + "start": { + "line": 254, + "column": 19 + }, + "end": { + "line": 257, + "column": 3 + } + }, + { + "id": "menu.Todoss.closeTodosDrawer", + "defaultMessage": "!!!Close Todos drawer", + "file": "src/lib/Menu.js", + "start": { + "line": 258, + "column": 20 + }, + "end": { + "line": 261, "column": 3 } } diff --git a/src/lib/Menu.js b/src/lib/Menu.js index 9e491e151..81efaf18f 100644 --- a/src/lib/Menu.js +++ b/src/lib/Menu.js @@ -8,6 +8,9 @@ import { workspaceActions } from '../features/workspaces/actions'; import { gaEvent } from './analytics'; import { announcementActions } from '../features/announcements/actions'; import { announcementsStore } from '../features/announcements'; +import TodoStore from '../features/todos/store'; +import { GA_CATEGORY_TODOS, todosStore } from '../features/todos'; +import { todoActions } from '../features/todos/actions'; const { app, Menu, dialog } = remote; @@ -244,7 +247,18 @@ const menuItems = defineMessages({ id: 'menu.workspaces.defaultWorkspace', defaultMessage: '!!!Default', }, - + todos: { + id: 'menu.todos', + defaultMessage: '!!!Todos', + }, + openTodosDrawer: { + id: 'menu.Todoss.openTodosDrawer', + defaultMessage: '!!!Open Todos drawer', + }, + closeTodosDrawer: { + id: 'menu.Todoss.closeTodosDrawer', + defaultMessage: '!!!Close Todos drawer', + }, }); function getActiveWebview() { @@ -352,6 +366,11 @@ const _templateFactory = intl => [ submenu: [], visible: workspaceStore.isFeatureEnabled, }, + { + label: intl.formatMessage(menuItems.todos), + submenu: [], + visible: todosStore.isFeatureEnabled, + }, { label: intl.formatMessage(menuItems.window), role: 'window', @@ -788,6 +807,10 @@ export default class FranzMenu { tpl[4].submenu = this.workspacesMenu(); } + if (todosStore.isFeatureEnabled) { + tpl[5].submenu = this.todosMenu(); + } + tpl[tpl.length - 1].submenu.push({ type: 'separator', }, this.debugMenu()); @@ -902,6 +925,31 @@ export default class FranzMenu { return menu; } + todosMenu() { + const { isTodosPanelVisible } = TodoStore; + const { intl } = window.franz; + const menu = []; + + // Open todos drawer: + const drawerLabel = ( + isTodosPanelVisible ? menuItems.closeTodosDrawer : menuItems.openTodosDrawer + ); + menu.push({ + label: intl.formatMessage(drawerLabel), + accelerator: `${cmdKey}+T`, + click: () => { + todoActions.toggleTodosPanel(); + gaEvent(GA_CATEGORY_TODOS, 'toggleDrawer', 'menu'); + }, + enabled: this.stores.user.isLoggedIn, + }, { + type: 'separator', + }); + + return menu; + } + + debugMenu() { const { intl } = window.franz; -- cgit v1.2.3-54-g00ecf From 81d368040d84a923941732ff0a696065764f12a6 Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Thu, 8 Aug 2019 01:00:02 +0200 Subject: send franz config to todos webview on init --- package-lock.json | 2 +- src/features/todos/constants.js | 4 ++++ src/features/todos/preload.js | 6 ++++-- src/features/todos/store.js | 36 ++++++++++++++++++++++++++++-------- 4 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 src/features/todos/constants.js (limited to 'src/features/todos/store.js') diff --git a/package-lock.json b/package-lock.json index 17513869a..607ebc31a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "franz", - "version": "5.2.0", + "version": "5.2.1-beta.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/src/features/todos/constants.js b/src/features/todos/constants.js new file mode 100644 index 000000000..2e8a431cc --- /dev/null +++ b/src/features/todos/constants.js @@ -0,0 +1,4 @@ +export const IPC = { + TODOS_HOST_CHANNEL: 'TODOS_HOST_CHANNEL', + TODOS_CLIENT_CHANNEL: 'TODOS_CLIENT_CHANNEL', +}; diff --git a/src/features/todos/preload.js b/src/features/todos/preload.js index 533c9aea3..6e38a2ef3 100644 --- a/src/features/todos/preload.js +++ b/src/features/todos/preload.js @@ -1,4 +1,5 @@ import { ipcRenderer } from 'electron'; +import { IPC } from './constants'; const debug = require('debug')('Franz:feature:todos:preload'); @@ -9,13 +10,14 @@ let hostMessageListener = () => {}; window.franz = { onInitialize(ipcHostMessageListener) { hostMessageListener = ipcHostMessageListener; + ipcRenderer.sendToHost(IPC.TODOS_CLIENT_CHANNEL, { action: 'todos:initialized' }); }, sendToHost(message) { - ipcRenderer.sendToHost('clientMessage', message); + ipcRenderer.sendToHost(IPC.TODOS_CLIENT_CHANNEL, message); }, }; -ipcRenderer.on('hostMessage', (event, message) => { +ipcRenderer.on(IPC.TODOS_HOST_CHANNEL, (event, message) => { debug('Received host message', event, message); hostMessageListener(message); }); diff --git a/src/features/todos/store.js b/src/features/todos/store.js index 79c218b65..acf95df0d 100644 --- a/src/features/todos/store.js +++ b/src/features/todos/store.js @@ -1,3 +1,4 @@ +import { ThemeType } from '@meetfranz/theme'; import { computed, action, @@ -10,6 +11,7 @@ import { FeatureStore } from '../utils/FeatureStore'; import { createReactions } from '../../stores/lib/Reaction'; import { createActionBindings } from '../utils/ActionBinding'; import { DEFAULT_TODOS_WIDTH, TODOS_MIN_WIDTH, DEFAULT_TODOS_VISIBLE } from '.'; +import { IPC } from './constants'; const debug = require('debug')('Franz:feature:todos:store'); @@ -101,22 +103,40 @@ export default class TodoStore extends FeatureStore { @action _handleHostMessage = (message) => { debug('_handleHostMessage', message); - if (message.action === 'create:todo') { - this.webview.send('hostMessage', message); + if (message.action === 'todos:create') { + this.webview.send(IPC.TODOS_HOST_CHANNEL, message); } }; @action _handleClientMessage = (message) => { debug('_handleClientMessage', message); - if (message.action === 'goToService') { - const { url, serviceId } = message.data; - if (url) { - this.stores.services.one(serviceId).webview.loadURL(url); - } - this.actions.service.setActive({ serviceId }); + switch (message.action) { + case 'todos:initialized': this._onTodosClientInitialized(); break; + case 'todos:goToService': this._goToService(message.data); break; + default: + debug('Unknown client message reiceived', message); } }; + // Todos client message handlers + + _onTodosClientInitialized = () => { + this.webview.send(IPC.TODOS_HOST_CHANNEL, { + action: 'todos:configure', + data: { + authToken: this.stores.user.authToken, + theme: this.stores.ui.isDarkThemeActive ? ThemeType.dark : ThemeType.default, + }, + }); + }; + + _goToService = ({ url, serviceId }) => { + if (url) { + this.stores.services.one(serviceId).webview.loadURL(url); + } + this.actions.service.setActive({ serviceId }); + }; + // Reactions _setFeatureEnabledReaction = () => { -- cgit v1.2.3-54-g00ecf From 71544483caadbdd240f423e7660c242ef458a1d2 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Wed, 4 Sep 2019 11:51:28 +0200 Subject: Add pre-launch notice --- src/features/todos/components/TodosWebview.js | 104 +++++++++++++++++---- src/features/todos/containers/TodosScreen.js | 19 +++- src/features/todos/store.js | 1 + .../workspaces/components/WorkspaceDrawer.js | 7 +- .../components/WorkspaceSwitchingIndicator.js | 8 +- src/i18n/locales/defaultMessages.json | 76 +++++++++++---- src/i18n/locales/en-US.json | 5 +- .../features/todos/components/TodosWebview.json | 41 ++++++++ .../workspaces/components/WorkspaceDrawer.json | 32 +++---- src/stores/UIStore.js | 1 + 10 files changed, 234 insertions(+), 60 deletions(-) create mode 100644 src/i18n/messages/src/features/todos/components/TodosWebview.json (limited to 'src/features/todos/store.js') diff --git a/src/features/todos/components/TodosWebview.js b/src/features/todos/components/TodosWebview.js index 288c1906f..d8d96ba85 100644 --- a/src/features/todos/components/TodosWebview.js +++ b/src/features/todos/components/TodosWebview.js @@ -4,12 +4,31 @@ import { observer } from 'mobx-react'; import injectSheet from 'react-jss'; import Webview from 'react-electron-web-view'; import { Icon } from '@meetfranz/ui'; +import { defineMessages, intlShape } from 'react-intl'; +import { mdiChevronRight, mdiCheckAll } from '@mdi/js'; +import { Button } from '@meetfranz/forms'; import * as environment from '../../../environment'; +import Appear from '../../../components/ui/effects/Appear'; const OPEN_TODOS_BUTTON_SIZE = 45; const CLOSE_TODOS_BUTTON_SIZE = 35; +const messages = defineMessages({ + premiumInfo: { + id: 'feature.todos.premium.info', + defaultMessage: '!!!The Franz Todos Preview is currently only available for Franz Premium accounts.', + }, + upgradeCTA: { + id: 'feature.todos.premium.upgrade', + defaultMessage: '!!!Upgrade Account', + }, + rolloutInfo: { + id: 'feature.todos.premium.rollout', + defaultMessage: '!!!Franz Todos will be available to everyone soon.', + }, +}); + const styles = theme => ({ root: { background: theme.colorBackground, @@ -78,7 +97,7 @@ const styles = theme => ({ bottom: 80, right: ({ width }) => (width + -CLOSE_TODOS_BUTTON_SIZE / 2), borderRadius: CLOSE_TODOS_BUTTON_SIZE / 2, - opacity: 0, + opacity: ({ isTodosIncludedInCurrentPlan }) => (!isTodosIncludedInCurrentPlan ? 1 : 0), transition: 'opacity 0.5s', zIndex: 600, display: 'flex', @@ -90,6 +109,26 @@ const styles = theme => ({ fill: theme.todos.toggleButton.textColor, }, }, + premiumContainer: { + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + width: '80%', + maxWidth: 300, + margin: [-50, 'auto', 0], + textAlign: 'center', + }, + premiumIcon: { + marginBottom: 40, + background: theme.styleTypes.primary.accent, + fill: theme.styleTypes.primary.contrast, + padding: 10, + borderRadius: 10, + }, + premiumCTA: { + marginTop: 40, + }, }); @injectSheet(styles) @observer @@ -103,6 +142,8 @@ class TodosWebview extends Component { resize: PropTypes.func.isRequired, width: PropTypes.number.isRequired, minWidth: PropTypes.number.isRequired, + isTodosIncludedInCurrentPlan: PropTypes.bool.isRequired, + upgradeAccount: PropTypes.func.isRequired, }; state = { @@ -110,6 +151,10 @@ class TodosWebview extends Component { width: 300, }; + static contextTypes = { + intl: intlShape, + }; + componentWillMount() { const { width } = this.props; @@ -186,9 +231,20 @@ class TodosWebview extends Component { render() { const { - classes, isVisible, togglePanel, + classes, + isVisible, + togglePanel, + isTodosIncludedInCurrentPlan, + upgradeAccount, } = this.props; - const { width, delta, isDragging } = this.state; + + const { + width, + delta, + isDragging, + } = this.state; + + const { intl } = this.context; return ( <> @@ -203,7 +259,7 @@ class TodosWebview extends Component { className={isVisible ? classes.closeTodosButton : classes.openTodosButton} type="button" > - +
)} - { - const { setTodosWebview } = this.props; - setTodosWebview(this.webview); - this.startListeningToIpcMessages(); - }} - partition="persist:todos" - preload="./features/todos/preload.js" - ref={(webview) => { this.webview = webview ? webview.view : null; }} - src={environment.TODOS_FRONTEND} - /> + {isTodosIncludedInCurrentPlan ? ( + { + const { setTodosWebview } = this.props; + setTodosWebview(this.webview); + this.startListeningToIpcMessages(); + }} + partition="persist:todos" + preload="./features/todos/preload.js" + ref={(webview) => { this.webview = webview ? webview.view : null; }} + src={environment.TODOS_FRONTEND} + /> + ) : ( + +
+ +

{intl.formatMessage(messages.premiumInfo)}

+

{intl.formatMessage(messages.rolloutInfo)}

+
+
+ )}
); diff --git a/src/features/todos/containers/TodosScreen.js b/src/features/todos/containers/TodosScreen.js index d071d0677..7f3688828 100644 --- a/src/features/todos/containers/TodosScreen.js +++ b/src/features/todos/containers/TodosScreen.js @@ -1,12 +1,14 @@ import React, { Component } from 'react'; -import { observer } from 'mobx-react'; +import { observer, inject } from 'mobx-react'; +import PropTypes from 'prop-types'; +import FeaturesStore from '../../../stores/FeaturesStore'; import TodosWebview from '../components/TodosWebview'; import ErrorBoundary from '../../../components/util/ErrorBoundary'; import { TODOS_MIN_WIDTH, todosStore } from '..'; import { todoActions } from '../actions'; -@observer +@inject('stores', 'actions') @observer class TodosScreen extends Component { render() { if (!todosStore || !todosStore.isFeatureActive) { @@ -23,6 +25,8 @@ class TodosScreen extends Component { width={todosStore.width} minWidth={TODOS_MIN_WIDTH} resize={width => todoActions.resize({ width })} + isTodosIncludedInCurrentPlan={this.props.stores.features.features.isTodosIncludedInCurrentPlan || false} + upgradeAccount={() => this.props.actions.ui.openSettings({ path: 'user' })} /> ); @@ -30,3 +34,14 @@ class TodosScreen extends Component { } export default TodosScreen; + +TodosScreen.wrappedComponent.propTypes = { + stores: PropTypes.shape({ + features: PropTypes.instanceOf(FeaturesStore).isRequired, + }).isRequired, + actions: PropTypes.shape({ + ui: PropTypes.shape({ + openSettings: PropTypes.func.isRequired, + }).isRequired, + }).isRequired, +}; diff --git a/src/features/todos/store.js b/src/features/todos/store.js index acf95df0d..7da3b7f49 100644 --- a/src/features/todos/store.js +++ b/src/features/todos/store.js @@ -29,6 +29,7 @@ export default class TodoStore extends FeatureStore { } @computed get isTodosPanelVisible() { + if (this.stores.services.all.length === 0) return false; if (this.settings.isTodosPanelVisible === undefined) return DEFAULT_TODOS_VISIBLE; return this.settings.isTodosPanelVisible; diff --git a/src/features/workspaces/components/WorkspaceDrawer.js b/src/features/workspaces/components/WorkspaceDrawer.js index 684e50dd0..e7bc0b157 100644 --- a/src/features/workspaces/components/WorkspaceDrawer.js +++ b/src/features/workspaces/components/WorkspaceDrawer.js @@ -7,6 +7,7 @@ import { H1, Icon, ProBadge } from '@meetfranz/ui'; import { Button } from '@meetfranz/forms/lib'; import ReactTooltip from 'react-tooltip'; +import { mdiPlusBox, mdiSettings } from '@mdi/js'; import WorkspaceDrawerItem from './WorkspaceDrawerItem'; import { workspaceActions } from '../actions'; import { GA_CATEGORY_WORKSPACES, workspaceStore } from '../index'; @@ -159,7 +160,7 @@ class WorkspaceDrawer extends Component { data-tip={`${intl.formatMessage(messages.workspacesSettingsTooltip)}`} > @@ -184,7 +185,7 @@ class WorkspaceDrawer extends Component { className={classes.premiumCtaButton} buttonType="primary" label={intl.formatMessage(messages.premiumCtaButtonLabel)} - icon="mdiPlusBox" + icon={mdiPlusBox} onClick={() => { workspaceActions.openWorkspaceSettings(); gaEvent(GA_CATEGORY_WORKSPACES, 'add', 'drawerPremiumCta'); @@ -227,7 +228,7 @@ class WorkspaceDrawer extends Component { }} > diff --git a/src/features/workspaces/components/WorkspaceSwitchingIndicator.js b/src/features/workspaces/components/WorkspaceSwitchingIndicator.js index c4a800a7b..a70d1d66f 100644 --- a/src/features/workspaces/components/WorkspaceSwitchingIndicator.js +++ b/src/features/workspaces/components/WorkspaceSwitchingIndicator.js @@ -21,11 +21,8 @@ const styles = theme => ({ alignItems: 'flex-start', position: 'absolute', transition: 'width 0.5s ease', - width: '100%', - marginTop: '20px', - }, - wrapperWhenDrawerIsOpen: { width: `calc(100% - ${theme.workspaces.drawer.width}px)`, + marginTop: '20px', }, component: { background: 'rgba(20, 20, 20, 0.4)', @@ -64,14 +61,13 @@ class WorkspaceSwitchingIndicator extends Component { render() { const { classes, theme } = this.props; const { intl } = this.context; - const { isSwitchingWorkspace, isWorkspaceDrawerOpen, nextWorkspace } = workspaceStore; + const { isSwitchingWorkspace, nextWorkspace } = workspaceStore; if (!isSwitchingWorkspace) return null; const nextWorkspaceName = nextWorkspace ? nextWorkspace.name : 'All services'; return (
diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json index 62d56ad1f..dabe2f11f 100644 --- a/src/i18n/locales/defaultMessages.json +++ b/src/i18n/locales/defaultMessages.json @@ -3810,6 +3810,50 @@ ], "path": "src/features/shareFranz/Component.json" }, + { + "descriptors": [ + { + "defaultMessage": "!!!The Franz Todos Preview is currently only available for Franz Premium accounts.", + "end": { + "column": 3, + "line": 21 + }, + "file": "src/features/todos/components/TodosWebview.js", + "id": "feature.todos.premium.info", + "start": { + "column": 15, + "line": 18 + } + }, + { + "defaultMessage": "!!!Upgrade Account", + "end": { + "column": 3, + "line": 25 + }, + "file": "src/features/todos/components/TodosWebview.js", + "id": "feature.todos.premium.upgrade", + "start": { + "column": 14, + "line": 22 + } + }, + { + "defaultMessage": "!!!Franz Todos will be available to everyone soon.", + "end": { + "column": 3, + "line": 29 + }, + "file": "src/features/todos/components/TodosWebview.js", + "id": "feature.todos.premium.rollout", + "start": { + "column": 15, + "line": 26 + } + } + ], + "path": "src/features/todos/components/TodosWebview.json" + }, { "descriptors": [ { @@ -3943,104 +3987,104 @@ "defaultMessage": "!!!Workspaces", "end": { "column": 3, - "line": 19 + "line": 20 }, "file": "src/features/workspaces/components/WorkspaceDrawer.js", "id": "workspaceDrawer.headline", "start": { "column": 12, - "line": 16 + "line": 17 } }, { "defaultMessage": "!!!All services", "end": { "column": 3, - "line": 23 + "line": 24 }, "file": "src/features/workspaces/components/WorkspaceDrawer.js", "id": "workspaceDrawer.allServices", "start": { "column": 15, - "line": 20 + "line": 21 } }, { "defaultMessage": "!!!Workspaces settings", "end": { "column": 3, - "line": 27 + "line": 28 }, "file": "src/features/workspaces/components/WorkspaceDrawer.js", "id": "workspaceDrawer.workspacesSettingsTooltip", "start": { "column": 29, - "line": 24 + "line": 25 } }, { "defaultMessage": "!!!Info about workspace feature", "end": { "column": 3, - "line": 31 + "line": 32 }, "file": "src/features/workspaces/components/WorkspaceDrawer.js", "id": "workspaceDrawer.workspaceFeatureInfo", "start": { "column": 24, - "line": 28 + "line": 29 } }, { "defaultMessage": "!!!Create your first workspace", "end": { "column": 3, - "line": 35 + "line": 36 }, "file": "src/features/workspaces/components/WorkspaceDrawer.js", "id": "workspaceDrawer.premiumCtaButtonLabel", "start": { "column": 25, - "line": 32 + "line": 33 } }, { "defaultMessage": "!!!Reactivate premium account", "end": { "column": 3, - "line": 39 + "line": 40 }, "file": "src/features/workspaces/components/WorkspaceDrawer.js", "id": "workspaceDrawer.reactivatePremiumAccountLabel", "start": { "column": 28, - "line": 36 + "line": 37 } }, { "defaultMessage": "!!!add new workspace", "end": { "column": 3, - "line": 43 + "line": 44 }, "file": "src/features/workspaces/components/WorkspaceDrawer.js", "id": "workspaceDrawer.addNewWorkspaceLabel", "start": { "column": 24, - "line": 40 + "line": 41 } }, { "defaultMessage": "!!!Premium feature", "end": { "column": 3, - "line": 47 + "line": 48 }, "file": "src/features/workspaces/components/WorkspaceDrawer.js", "id": "workspaceDrawer.proFeatureBadge", "start": { "column": 23, - "line": 44 + "line": 45 } } ], diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index 727eb2884..2bfe5a670 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json @@ -15,6 +15,9 @@ "feature.shareFranz.shareText.email": "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com", "feature.shareFranz.shareText.twitter": "I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com /cc @FranzMessenger", "feature.shareFranz.text": "Tell your friends and colleagues how awesome Franz is and help us to spread the word.", + "feature.todos.premium.info": "The Franz Todos Preview is currently only available for Franz Premium accounts.", + "feature.todos.premium.rollout": "Franz Todos will be available to everyone soon.", + "feature.todos.premium.upgrade": "Upgrade Account", "global.api.unhealthy": "Can't connect to Franz online services", "global.notConnectedToTheInternet": "You are not connected to the internet.", "global.spellchecker.useDefault": "Use System Default ({default})", @@ -371,4 +374,4 @@ "workspaceDrawer.workspaceFeatureInfo": "

Franz Workspaces let you focus on what’s important right now. Set up different sets of services and easily switch between them at any time.

You decide which services you need when and where, so we can help you stay on top of your game - or easily switch off from work whenever you want.

", "workspaceDrawer.workspacesSettingsTooltip": "Edit workspaces settings", "workspaces.switchingIndicator.switchingTo": "Switching to" -} \ No newline at end of file +} diff --git a/src/i18n/messages/src/features/todos/components/TodosWebview.json b/src/i18n/messages/src/features/todos/components/TodosWebview.json new file mode 100644 index 000000000..2387112b4 --- /dev/null +++ b/src/i18n/messages/src/features/todos/components/TodosWebview.json @@ -0,0 +1,41 @@ +[ + { + "id": "feature.todos.premium.info", + "defaultMessage": "!!!The Franz Todos Preview is currently only available for Franz Premium accounts.", + "file": "src/features/todos/components/TodosWebview.js", + "start": { + "line": 18, + "column": 15 + }, + "end": { + "line": 21, + "column": 3 + } + }, + { + "id": "feature.todos.premium.upgrade", + "defaultMessage": "!!!Upgrade Account", + "file": "src/features/todos/components/TodosWebview.js", + "start": { + "line": 22, + "column": 14 + }, + "end": { + "line": 25, + "column": 3 + } + }, + { + "id": "feature.todos.premium.rollout", + "defaultMessage": "!!!Franz Todos will be available to everyone soon.", + "file": "src/features/todos/components/TodosWebview.js", + "start": { + "line": 26, + "column": 15 + }, + "end": { + "line": 29, + "column": 3 + } + } +] \ No newline at end of file diff --git a/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json b/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json index 9f0935620..2f340f1e9 100644 --- a/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json +++ b/src/i18n/messages/src/features/workspaces/components/WorkspaceDrawer.json @@ -4,11 +4,11 @@ "defaultMessage": "!!!Workspaces", "file": "src/features/workspaces/components/WorkspaceDrawer.js", "start": { - "line": 16, + "line": 17, "column": 12 }, "end": { - "line": 19, + "line": 20, "column": 3 } }, @@ -17,11 +17,11 @@ "defaultMessage": "!!!All services", "file": "src/features/workspaces/components/WorkspaceDrawer.js", "start": { - "line": 20, + "line": 21, "column": 15 }, "end": { - "line": 23, + "line": 24, "column": 3 } }, @@ -30,11 +30,11 @@ "defaultMessage": "!!!Workspaces settings", "file": "src/features/workspaces/components/WorkspaceDrawer.js", "start": { - "line": 24, + "line": 25, "column": 29 }, "end": { - "line": 27, + "line": 28, "column": 3 } }, @@ -43,11 +43,11 @@ "defaultMessage": "!!!Info about workspace feature", "file": "src/features/workspaces/components/WorkspaceDrawer.js", "start": { - "line": 28, + "line": 29, "column": 24 }, "end": { - "line": 31, + "line": 32, "column": 3 } }, @@ -56,11 +56,11 @@ "defaultMessage": "!!!Create your first workspace", "file": "src/features/workspaces/components/WorkspaceDrawer.js", "start": { - "line": 32, + "line": 33, "column": 25 }, "end": { - "line": 35, + "line": 36, "column": 3 } }, @@ -69,11 +69,11 @@ "defaultMessage": "!!!Reactivate premium account", "file": "src/features/workspaces/components/WorkspaceDrawer.js", "start": { - "line": 36, + "line": 37, "column": 28 }, "end": { - "line": 39, + "line": 40, "column": 3 } }, @@ -82,11 +82,11 @@ "defaultMessage": "!!!add new workspace", "file": "src/features/workspaces/components/WorkspaceDrawer.js", "start": { - "line": 40, + "line": 41, "column": 24 }, "end": { - "line": 43, + "line": 44, "column": 3 } }, @@ -95,11 +95,11 @@ "defaultMessage": "!!!Premium feature", "file": "src/features/workspaces/components/WorkspaceDrawer.js", "start": { - "line": 44, + "line": 45, "column": 23 }, "end": { - "line": 47, + "line": 48, "column": 3 } } diff --git a/src/stores/UIStore.js b/src/stores/UIStore.js index 9680c5bcc..2c785111f 100644 --- a/src/stores/UIStore.js +++ b/src/stores/UIStore.js @@ -46,6 +46,7 @@ export default class UIStore extends Store { // Actions @action _openSettings({ path = '/settings' }) { const settingsPath = path !== '/settings' ? `/settings/${path}` : path; + console.log(settingsPath); this.stores.router.push(settingsPath); } -- cgit v1.2.3-54-g00ecf From c6dda35baf7eb9a7d89bf224c38973a1b6171c14 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Wed, 4 Sep 2019 15:37:56 +0200 Subject: bugfixing & polishing --- packages/theme/src/themes/dark/index.ts | 2 + packages/theme/src/themes/default/index.ts | 2 + src/assets/images/workspaces/teaser_dark.png | Bin 0 -> 179047 bytes src/assets/images/workspaces/teaser_light.png | Bin 0 -> 182321 bytes .../settings/account/AccountDashboard.js | 19 ++- .../settings/recipes/RecipesDashboard.js | 4 +- src/components/subscription/TrialForm.js | 3 +- src/components/ui/ActivateTrialButton/index.js | 115 ++++++++++++++++++ src/components/ui/FeatureItem.js | 2 +- src/components/ui/PremiumFeatureContainer/index.js | 22 +++- src/config.js | 4 +- src/containers/settings/AccountScreen.js | 1 + src/features/todos/components/TodosWebview.js | 14 +-- src/features/todos/containers/TodosScreen.js | 6 - src/features/todos/store.js | 3 +- .../workspaces/components/WorkspacesDashboard.js | 50 ++++++-- src/features/workspaces/store.js | 5 +- src/helpers/plan-helpers.js | 10 ++ src/i18n/locales/defaultMessages.json | 133 +++++++++++++++------ src/i18n/locales/en-US.json | 2 + .../components/ui/ActivateTrialButton/index.json | 54 +++++++++ .../ui/PremiumFeatureContainer/index.json | 4 +- .../features/todos/components/TodosWebview.json | 12 +- .../workspaces/components/WorkspacesDashboard.json | 32 ++--- src/stores/UserStore.js | 22 ++++ 25 files changed, 415 insertions(+), 106 deletions(-) create mode 100644 src/assets/images/workspaces/teaser_dark.png create mode 100644 src/assets/images/workspaces/teaser_light.png create mode 100644 src/components/ui/ActivateTrialButton/index.js create mode 100644 src/i18n/messages/src/components/ui/ActivateTrialButton/index.json (limited to 'src/features/todos/store.js') diff --git a/packages/theme/src/themes/dark/index.ts b/packages/theme/src/themes/dark/index.ts index 93c18efde..e94f54c55 100644 --- a/packages/theme/src/themes/dark/index.ts +++ b/packages/theme/src/themes/dark/index.ts @@ -11,6 +11,8 @@ export const colorBackgroundSubscriptionContainer = legacyStyles.themeBrandInfo; export const colorHeadline = legacyStyles.darkThemeTextColor; export const colorText = legacyStyles.darkThemeTextColor; +export const defaultContentBorder = legacyStyles.themeGrayDark; + // Loader export const colorFullscreenLoaderSpinner = '#FFF'; export const colorWebviewLoaderBackground = color(legacyStyles.darkThemeGrayDarkest).alpha(0.5).rgb().string(); diff --git a/packages/theme/src/themes/default/index.ts b/packages/theme/src/themes/default/index.ts index 7edf8331f..4e042afce 100644 --- a/packages/theme/src/themes/default/index.ts +++ b/packages/theme/src/themes/default/index.ts @@ -28,6 +28,8 @@ export const colorHeadline = legacyStyles.themeGrayDark; export const colorText = legacyStyles.themeTextColor; +export const defaultContentBorder = color(legacyStyles.themeGrayLighter).darken(0.1).rgb().string(); + // Subscription Container Component export const colorSubscriptionContainerBackground = 'none'; export const colorSubscriptionContainerBorder = `1px solid ${brandPrimary}`; diff --git a/src/assets/images/workspaces/teaser_dark.png b/src/assets/images/workspaces/teaser_dark.png new file mode 100644 index 000000000..5b6d7334b Binary files /dev/null and b/src/assets/images/workspaces/teaser_dark.png differ diff --git a/src/assets/images/workspaces/teaser_light.png b/src/assets/images/workspaces/teaser_light.png new file mode 100644 index 000000000..635af43fa Binary files /dev/null and b/src/assets/images/workspaces/teaser_light.png differ diff --git a/src/components/settings/account/AccountDashboard.js b/src/components/settings/account/AccountDashboard.js index 900a83a78..4fd1e8163 100644 --- a/src/components/settings/account/AccountDashboard.js +++ b/src/components/settings/account/AccountDashboard.js @@ -93,9 +93,11 @@ const messages = defineMessages({ }, }); -export default @observer class AccountDashboard extends Component { +@observer +class AccountDashboard extends Component { static propTypes = { user: MobxPropTypes.observableObject.isRequired, + isProUser: PropTypes.bool.isRequired, isLoading: PropTypes.bool.isRequired, userInfoRequestFailed: PropTypes.bool.isRequired, retryUserInfoRequest: PropTypes.func.isRequired, @@ -115,6 +117,7 @@ export default @observer class AccountDashboard extends Component { render() { const { user, + isProUser, isLoading, userInfoRequestFailed, retryUserInfoRequest, @@ -234,11 +237,13 @@ export default @observer class AccountDashboard extends Component { )}
-
diff --git a/src/features/todos/containers/TodosScreen.js b/src/features/todos/containers/TodosScreen.js index 7f3688828..65afc985b 100644 --- a/src/features/todos/containers/TodosScreen.js +++ b/src/features/todos/containers/TodosScreen.js @@ -26,7 +26,6 @@ class TodosScreen extends Component { minWidth={TODOS_MIN_WIDTH} resize={width => todoActions.resize({ width })} isTodosIncludedInCurrentPlan={this.props.stores.features.features.isTodosIncludedInCurrentPlan || false} - upgradeAccount={() => this.props.actions.ui.openSettings({ path: 'user' })} /> ); @@ -39,9 +38,4 @@ TodosScreen.wrappedComponent.propTypes = { stores: PropTypes.shape({ features: PropTypes.instanceOf(FeaturesStore).isRequired, }).isRequired, - actions: PropTypes.shape({ - ui: PropTypes.shape({ - openSettings: PropTypes.func.isRequired, - }).isRequired, - }).isRequired, }; diff --git a/src/features/todos/store.js b/src/features/todos/store.js index 7da3b7f49..56e117c6c 100644 --- a/src/features/todos/store.js +++ b/src/features/todos/store.js @@ -12,6 +12,7 @@ import { createReactions } from '../../stores/lib/Reaction'; import { createActionBindings } from '../utils/ActionBinding'; import { DEFAULT_TODOS_WIDTH, TODOS_MIN_WIDTH, DEFAULT_TODOS_VISIBLE } from '.'; import { IPC } from './constants'; +import { state as delayAppState } from '../delayApp'; const debug = require('debug')('Franz:feature:todos:store'); @@ -29,7 +30,7 @@ export default class TodoStore extends FeatureStore { } @computed get isTodosPanelVisible() { - if (this.stores.services.all.length === 0) return false; + if (this.stores.services.all.length === 0 || delayAppState.isDelayAppScreenVisible) return false; if (this.settings.isTodosPanelVisible === undefined) return DEFAULT_TODOS_VISIBLE; return this.settings.isTodosPanelVisible; diff --git a/src/features/workspaces/components/WorkspacesDashboard.js b/src/features/workspaces/components/WorkspacesDashboard.js index 09c98ab8c..9e06a78e3 100644 --- a/src/features/workspaces/components/WorkspacesDashboard.js +++ b/src/features/workspaces/components/WorkspacesDashboard.js @@ -1,6 +1,6 @@ import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; -import { observer, PropTypes as MobxPropTypes } from 'mobx-react'; +import { observer, PropTypes as MobxPropTypes, inject } from 'mobx-react'; import { defineMessages, intlShape } from 'react-intl'; import injectSheet from 'react-jss'; import { Infobox } from '@meetfranz/ui'; @@ -12,6 +12,8 @@ import Request from '../../../stores/lib/Request'; import Appear from '../../../components/ui/effects/Appear'; import { workspaceStore } from '../index'; import PremiumFeatureContainer from '../../../components/ui/PremiumFeatureContainer'; +import UIStore from '../../../stores/UIStore'; +import ActivateTrialButton from '../../../components/ui/activateTrialButton'; const messages = defineMessages({ headline: { @@ -62,17 +64,27 @@ const styles = theme => ({ height: 'auto', }, premiumAnnouncement: { - padding: '20px', - backgroundColor: '#3498db', - marginLeft: '-20px', - marginBottom: '20px', + padding: 20, + // backgroundColor: '#3498db', + marginLeft: -20, + marginBottom: 40, + paddingBottom: 40, height: 'auto', - color: 'white', - borderRadius: theme.borderRadius, + display: 'flex', + borderBottom: [1, 'solid', theme.inputBackground], + }, + teaserImage: { + width: 200, + height: '100%', + float: 'left', + margin: [-8, 0, 0, -20], + }, + upgradeCTA: { + marginTop: 20, }, }); -@injectSheet(styles) @observer +@inject('stores') @injectSheet(styles) @observer class WorkspacesDashboard extends Component { static propTypes = { classes: PropTypes.object.isRequired, @@ -100,7 +112,9 @@ class WorkspacesDashboard extends Component { onWorkspaceClick, workspaces, } = this.props; + const { intl } = this.context; + return (
@@ -138,13 +152,21 @@ class WorkspacesDashboard extends Component { {workspaceStore.isPremiumUpgradeRequired && (
-

{intl.formatMessage(messages.workspaceFeatureHeadline)}

-

{intl.formatMessage(messages.workspaceFeatureInfo)}

+ +
+

{intl.formatMessage(messages.workspaceFeatureHeadline)}

+

{intl.formatMessage(messages.workspaceFeatureInfo)}

+ +
)} workspaceStore.isPremiumUpgradeRequired} gaEventInfo={{ category: 'User', event: 'upgrade', label: 'workspaces' }} > {/* ===== Create workspace form ===== */} @@ -207,3 +229,9 @@ class WorkspacesDashboard extends Component { } export default WorkspacesDashboard; + +WorkspacesDashboard.wrappedComponent.propTypes = { + stores: PropTypes.shape({ + ui: PropTypes.instanceOf(UIStore).isRequired, + }).isRequired, +}; diff --git a/src/features/workspaces/store.js b/src/features/workspaces/store.js index e44569be9..4a1f80b4e 100644 --- a/src/features/workspaces/store.js +++ b/src/features/workspaces/store.js @@ -253,11 +253,10 @@ export default class WorkspacesStore extends FeatureStore { }; _setIsPremiumFeatureReaction = () => { - const { features, user } = this.stores; - const { isPremium } = user.data; + const { features } = this.stores; const { isWorkspaceIncludedInCurrentPlan } = features.features; this.isPremiumFeature = !isWorkspaceIncludedInCurrentPlan; - this.isPremiumUpgradeRequired = !isWorkspaceIncludedInCurrentPlan && !isPremium; + this.isPremiumUpgradeRequired = !isWorkspaceIncludedInCurrentPlan; }; _setWorkspaceBeingEditedReaction = () => { diff --git a/src/helpers/plan-helpers.js b/src/helpers/plan-helpers.js index 19392585e..e0f1fd89a 100644 --- a/src/helpers/plan-helpers.js +++ b/src/helpers/plan-helpers.js @@ -33,3 +33,13 @@ export function i18nPlanName(planId, intl) { return intl.formatMessage(messages[plan]); } + +export function getPlan(planId) { + if (!planId) { + throw new Error('planId is required'); + } + + const plan = PLANS_MAPPING[planId]; + + return plan; +} diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json index dabe2f11f..367184c01 100644 --- a/src/i18n/locales/defaultMessages.json +++ b/src/i18n/locales/defaultMessages.json @@ -2892,6 +2892,63 @@ ], "path": "src/components/TrialActivationInfoBar.json" }, + { + "descriptors": [ + { + "defaultMessage": "!!!Get a Franz Supporter License", + "end": { + "column": 3, + "line": 16 + }, + "file": "src/components/ui/ActivateTrialButton/index.js", + "id": "feature.delayApp.upgrade.action", + "start": { + "column": 10, + "line": 13 + } + }, + { + "defaultMessage": "!!!Yes, I want the free 14 day trial of Franz Professional", + "end": { + "column": 3, + "line": 20 + }, + "file": "src/components/ui/ActivateTrialButton/index.js", + "id": "feature.delayApp.trial.action", + "start": { + "column": 15, + "line": 17 + } + }, + { + "defaultMessage": "!!!Upgrade account", + "end": { + "column": 3, + "line": 24 + }, + "file": "src/components/ui/ActivateTrialButton/index.js", + "id": "feature.delayApp.upgrade.actionShort", + "start": { + "column": 15, + "line": 21 + } + }, + { + "defaultMessage": "!!!Activate the free Franz Professional trial", + "end": { + "column": 3, + "line": 28 + }, + "file": "src/components/ui/ActivateTrialButton/index.js", + "id": "feature.delayApp.trial.actionShort", + "start": { + "column": 20, + "line": 25 + } + } + ], + "path": "src/components/ui/ActivateTrialButton/index.json" + }, { "descriptors": [ { @@ -3033,13 +3090,13 @@ "defaultMessage": "!!!Upgrade account", "end": { "column": 3, - "line": 18 + "line": 19 }, "file": "src/components/ui/PremiumFeatureContainer/index.js", "id": "premiumFeature.button.upgradeAccount", "start": { "column": 10, - "line": 15 + "line": 16 } } ], @@ -3720,91 +3777,91 @@ "defaultMessage": "!!!Franz is better together!", "end": { "column": 3, - "line": 19 + "line": 21 }, "file": "src/features/shareFranz/Component.js", "id": "feature.shareFranz.headline", "start": { "column": 12, - "line": 16 + "line": 18 } }, { "defaultMessage": "!!!Tell your friends and colleagues how awesome Franz is and help us to spread the word.", "end": { "column": 3, - "line": 23 + "line": 25 }, "file": "src/features/shareFranz/Component.js", "id": "feature.shareFranz.text", "start": { "column": 8, - "line": 20 + "line": 22 } }, { "defaultMessage": "!!!Share as email", "end": { "column": 3, - "line": 27 + "line": 29 }, "file": "src/features/shareFranz/Component.js", "id": "feature.shareFranz.action.email", "start": { "column": 16, - "line": 24 + "line": 26 } }, { "defaultMessage": "!!!Share on Facebook", "end": { "column": 3, - "line": 31 + "line": 33 }, "file": "src/features/shareFranz/Component.js", "id": "feature.shareFranz.action.facebook", "start": { "column": 19, - "line": 28 + "line": 30 } }, { "defaultMessage": "!!!Share on Twitter", "end": { "column": 3, - "line": 35 + "line": 37 }, "file": "src/features/shareFranz/Component.js", "id": "feature.shareFranz.action.twitter", "start": { "column": 18, - "line": 32 + "line": 34 } }, { "defaultMessage": "!!! I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com", "end": { "column": 3, - "line": 39 + "line": 41 }, "file": "src/features/shareFranz/Component.js", "id": "feature.shareFranz.shareText.email", "start": { "column": 18, - "line": 36 + "line": 38 } }, { "defaultMessage": "!!! I've added {count} services to Franz! Get the free app for WhatsApp, Messenger, Slack, Skype and co at www.meetfranz.com /cc @FranzMessenger", "end": { "column": 3, - "line": 43 + "line": 45 }, "file": "src/features/shareFranz/Component.js", "id": "feature.shareFranz.shareText.twitter", "start": { "column": 20, - "line": 40 + "line": 42 } } ], @@ -3816,39 +3873,39 @@ "defaultMessage": "!!!The Franz Todos Preview is currently only available for Franz Premium accounts.", "end": { "column": 3, - "line": 21 + "line": 22 }, "file": "src/features/todos/components/TodosWebview.js", "id": "feature.todos.premium.info", "start": { "column": 15, - "line": 18 + "line": 19 } }, { "defaultMessage": "!!!Upgrade Account", "end": { "column": 3, - "line": 25 + "line": 26 }, "file": "src/features/todos/components/TodosWebview.js", "id": "feature.todos.premium.upgrade", "start": { "column": 14, - "line": 22 + "line": 23 } }, { "defaultMessage": "!!!Franz Todos will be available to everyone soon.", "end": { "column": 3, - "line": 29 + "line": 30 }, "file": "src/features/todos/components/TodosWebview.js", "id": "feature.todos.premium.rollout", "start": { "column": 15, - "line": 26 + "line": 27 } } ], @@ -4127,104 +4184,104 @@ "defaultMessage": "!!!Your workspaces", "end": { "column": 3, - "line": 20 + "line": 22 }, "file": "src/features/workspaces/components/WorkspacesDashboard.js", "id": "settings.workspaces.headline", "start": { "column": 12, - "line": 17 + "line": 19 } }, { "defaultMessage": "!!!You haven't added any workspaces yet.", "end": { "column": 3, - "line": 24 + "line": 26 }, "file": "src/features/workspaces/components/WorkspacesDashboard.js", "id": "settings.workspaces.noWorkspacesAdded", "start": { "column": 19, - "line": 21 + "line": 23 } }, { "defaultMessage": "!!!Could not load your workspaces", "end": { "column": 3, - "line": 28 + "line": 30 }, "file": "src/features/workspaces/components/WorkspacesDashboard.js", "id": "settings.workspaces.workspacesRequestFailed", "start": { "column": 27, - "line": 25 + "line": 27 } }, { "defaultMessage": "!!!Try again", "end": { "column": 3, - "line": 32 + "line": 34 }, "file": "src/features/workspaces/components/WorkspacesDashboard.js", "id": "settings.workspaces.tryReloadWorkspaces", "start": { "column": 23, - "line": 29 + "line": 31 } }, { "defaultMessage": "!!!Your changes have been saved", "end": { "column": 3, - "line": 36 + "line": 38 }, "file": "src/features/workspaces/components/WorkspacesDashboard.js", "id": "settings.workspaces.updatedInfo", "start": { "column": 15, - "line": 33 + "line": 35 } }, { "defaultMessage": "!!!Workspace has been deleted", "end": { "column": 3, - "line": 40 + "line": 42 }, "file": "src/features/workspaces/components/WorkspacesDashboard.js", "id": "settings.workspaces.deletedInfo", "start": { "column": 15, - "line": 37 + "line": 39 } }, { "defaultMessage": "!!!Info about workspace feature", "end": { "column": 3, - "line": 44 + "line": 46 }, "file": "src/features/workspaces/components/WorkspacesDashboard.js", "id": "settings.workspaces.workspaceFeatureInfo", "start": { "column": 24, - "line": 41 + "line": 43 } }, { "defaultMessage": "!!!Less is More: Introducing Franz Workspaces", "end": { "column": 3, - "line": 48 + "line": 50 }, "file": "src/features/workspaces/components/WorkspacesDashboard.js", "id": "settings.workspaces.workspaceFeatureHeadline", "start": { "column": 28, - "line": 45 + "line": 47 } } ], diff --git a/src/i18n/locales/en-US.json b/src/i18n/locales/en-US.json index 32e9c743a..f11d5ca91 100644 --- a/src/i18n/locales/en-US.json +++ b/src/i18n/locales/en-US.json @@ -5,8 +5,10 @@ "feature.delayApp.headline": "Please purchase a Franz Supporter License to skip waiting", "feature.delayApp.text": "Franz will continue in {seconds} seconds.", "feature.delayApp.trial.action": "Yes, I want the free 14 day trial of Franz Professional", + "feature.delayApp.trial.actionShort": "Activate the free Franz Professional trial", "feature.delayApp.trial.headline": "Get the free Franz Professional 14 day trial and skip the line", "feature.delayApp.upgrade.action": "Get a Franz Supporter License", + "feature.delayApp.upgrade.actionShort": "Upgrade account", "feature.serviceLimit.limitReached": "You have added {amount} out of {limit} services that are included in your plan. Please upgrade your account to add more services.", "feature.shareFranz.action.email": "Send as email", "feature.shareFranz.action.facebook": "Share on Facebook", diff --git a/src/i18n/messages/src/components/ui/ActivateTrialButton/index.json b/src/i18n/messages/src/components/ui/ActivateTrialButton/index.json new file mode 100644 index 000000000..08c1a9293 --- /dev/null +++ b/src/i18n/messages/src/components/ui/ActivateTrialButton/index.json @@ -0,0 +1,54 @@ +[ + { + "id": "feature.delayApp.upgrade.action", + "defaultMessage": "!!!Get a Franz Supporter License", + "file": "src/components/ui/ActivateTrialButton/index.js", + "start": { + "line": 13, + "column": 10 + }, + "end": { + "line": 16, + "column": 3 + } + }, + { + "id": "feature.delayApp.trial.action", + "defaultMessage": "!!!Yes, I want the free 14 day trial of Franz Professional", + "file": "src/components/ui/ActivateTrialButton/index.js", + "start": { + "line": 17, + "column": 15 + }, + "end": { + "line": 20, + "column": 3 + } + }, + { + "id": "feature.delayApp.upgrade.actionShort", + "defaultMessage": "!!!Upgrade account", + "file": "src/components/ui/ActivateTrialButton/index.js", + "start": { + "line": 21, + "column": 15 + }, + "end": { + "line": 24, + "column": 3 + } + }, + { + "id": "feature.delayApp.trial.actionShort", + "defaultMessage": "!!!Activate the free Franz Professional trial", + "file": "src/components/ui/ActivateTrialButton/index.js", + "start": { + "line": 25, + "column": 20 + }, + "end": { + "line": 28, + "column": 3 + } + } +] \ No newline at end of file diff --git a/src/i18n/messages/src/components/ui/PremiumFeatureContainer/index.json b/src/i18n/messages/src/components/ui/PremiumFeatureContainer/index.json index 320d3ca3e..0cde4cee5 100644 --- a/src/i18n/messages/src/components/ui/PremiumFeatureContainer/index.json +++ b/src/i18n/messages/src/components/ui/PremiumFeatureContainer/index.json @@ -4,11 +4,11 @@ "defaultMessage": "!!!Upgrade account", "file": "src/components/ui/PremiumFeatureContainer/index.js", "start": { - "line": 15, + "line": 16, "column": 10 }, "end": { - "line": 18, + "line": 19, "column": 3 } } diff --git a/src/i18n/messages/src/features/todos/components/TodosWebview.json b/src/i18n/messages/src/features/todos/components/TodosWebview.json index 2387112b4..7d26342b7 100644 --- a/src/i18n/messages/src/features/todos/components/TodosWebview.json +++ b/src/i18n/messages/src/features/todos/components/TodosWebview.json @@ -4,11 +4,11 @@ "defaultMessage": "!!!The Franz Todos Preview is currently only available for Franz Premium accounts.", "file": "src/features/todos/components/TodosWebview.js", "start": { - "line": 18, + "line": 19, "column": 15 }, "end": { - "line": 21, + "line": 22, "column": 3 } }, @@ -17,11 +17,11 @@ "defaultMessage": "!!!Upgrade Account", "file": "src/features/todos/components/TodosWebview.js", "start": { - "line": 22, + "line": 23, "column": 14 }, "end": { - "line": 25, + "line": 26, "column": 3 } }, @@ -30,11 +30,11 @@ "defaultMessage": "!!!Franz Todos will be available to everyone soon.", "file": "src/features/todos/components/TodosWebview.js", "start": { - "line": 26, + "line": 27, "column": 15 }, "end": { - "line": 29, + "line": 30, "column": 3 } } diff --git a/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json b/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json index ef8f1bebc..7eb4fab50 100644 --- a/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json +++ b/src/i18n/messages/src/features/workspaces/components/WorkspacesDashboard.json @@ -4,11 +4,11 @@ "defaultMessage": "!!!Your workspaces", "file": "src/features/workspaces/components/WorkspacesDashboard.js", "start": { - "line": 17, + "line": 19, "column": 12 }, "end": { - "line": 20, + "line": 22, "column": 3 } }, @@ -17,11 +17,11 @@ "defaultMessage": "!!!You haven't added any workspaces yet.", "file": "src/features/workspaces/components/WorkspacesDashboard.js", "start": { - "line": 21, + "line": 23, "column": 19 }, "end": { - "line": 24, + "line": 26, "column": 3 } }, @@ -30,11 +30,11 @@ "defaultMessage": "!!!Could not load your workspaces", "file": "src/features/workspaces/components/WorkspacesDashboard.js", "start": { - "line": 25, + "line": 27, "column": 27 }, "end": { - "line": 28, + "line": 30, "column": 3 } }, @@ -43,11 +43,11 @@ "defaultMessage": "!!!Try again", "file": "src/features/workspaces/components/WorkspacesDashboard.js", "start": { - "line": 29, + "line": 31, "column": 23 }, "end": { - "line": 32, + "line": 34, "column": 3 } }, @@ -56,11 +56,11 @@ "defaultMessage": "!!!Your changes have been saved", "file": "src/features/workspaces/components/WorkspacesDashboard.js", "start": { - "line": 33, + "line": 35, "column": 15 }, "end": { - "line": 36, + "line": 38, "column": 3 } }, @@ -69,11 +69,11 @@ "defaultMessage": "!!!Workspace has been deleted", "file": "src/features/workspaces/components/WorkspacesDashboard.js", "start": { - "line": 37, + "line": 39, "column": 15 }, "end": { - "line": 40, + "line": 42, "column": 3 } }, @@ -82,11 +82,11 @@ "defaultMessage": "!!!Info about workspace feature", "file": "src/features/workspaces/components/WorkspacesDashboard.js", "start": { - "line": 41, + "line": 43, "column": 24 }, "end": { - "line": 44, + "line": 46, "column": 3 } }, @@ -95,11 +95,11 @@ "defaultMessage": "!!!Less is More: Introducing Franz Workspaces", "file": "src/features/workspaces/components/WorkspacesDashboard.js", "start": { - "line": 45, + "line": 47, "column": 28 }, "end": { - "line": 48, + "line": 50, "column": 3 } } diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js index f3dfbdbf0..7ac7d2375 100644 --- a/src/stores/UserStore.js +++ b/src/stores/UserStore.js @@ -10,6 +10,8 @@ import Request from './lib/Request'; import CachedRequest from './lib/CachedRequest'; import { gaEvent } from '../lib/analytics'; import { sleep } from '../helpers/async-helpers'; +import { getPlan } from '../helpers/plan-helpers'; +import { PLANS } from '../config'; const debug = require('debug')('Franz:UserStore'); @@ -150,10 +152,30 @@ export default class UserStore extends Store { return this.getUserInfoRequest.execute().result || {}; } + @computed get team() { + return this.data.team || null; + } + @computed get isPremium() { return !!this.data.isPremium; } + @computed get isPersonal() { + if (!this.team.plan) return false; + const plan = getPlan(this.team.plan); + + return plan === PLANS.PERSONAL; + } + + @computed get isPro() { + if (!this.team.plan && this.isPremium) return true; + + if (!this.team.plan) return false; + const plan = getPlan(this.team.plan); + + return plan === PLANS.PRO; + } + @computed get legacyServices() { return this.getLegacyServicesRequest.execute() || {}; } -- cgit v1.2.3-54-g00ecf From 3843c2488df81840960d8db3cfdec33597e17159 Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Wed, 4 Sep 2019 15:44:36 +0200 Subject: Resend todos config on Franz setting changes --- src/features/todos/components/TodosWebview.js | 74 ++++++++++++--------------- src/features/todos/store.js | 13 ++++- 2 files changed, 45 insertions(+), 42 deletions(-) (limited to 'src/features/todos/store.js') diff --git a/src/features/todos/components/TodosWebview.js b/src/features/todos/components/TodosWebview.js index 288c1906f..9dd313109 100644 --- a/src/features/todos/components/TodosWebview.js +++ b/src/features/todos/components/TodosWebview.js @@ -22,10 +22,6 @@ const styles = theme => ({ '&:hover $closeTodosButton': { opacity: 1, }, - }, - webview: { - height: '100%', - '& webview': { height: '100%', }, @@ -191,45 +187,43 @@ class TodosWebview extends Component { const { width, delta, isDragging } = this.state; return ( - <> -
this.stopResize()} - ref={(node) => { this.node = node; }} +
this.stopResize()} + ref={(node) => { this.node = node; }} + > + + + +
this.startResize(e)} + /> + {isDragging && (
this.startResize(e)} - /> - {isDragging && ( -
- )} - { - const { setTodosWebview } = this.props; - setTodosWebview(this.webview); - this.startListeningToIpcMessages(); - }} - partition="persist:todos" - preload="./features/todos/preload.js" - ref={(webview) => { this.webview = webview ? webview.view : null; }} - src={environment.TODOS_FRONTEND} + className={classes.dragIndicator} + style={{ left: delta }} // This hack is required as resizing with webviews beneath behaves quite bad /> -
- + )} + { + const { setTodosWebview } = this.props; + setTodosWebview(this.webview); + this.startListeningToIpcMessages(); + }} + partition="persist:todos" + preload="./features/todos/preload.js" + ref={(webview) => { this.webview = webview ? webview.view : null; }} + src={environment.TODOS_FRONTEND} + /> +
); } } diff --git a/src/features/todos/store.js b/src/features/todos/store.js index acf95df0d..bb1df9415 100644 --- a/src/features/todos/store.js +++ b/src/features/todos/store.js @@ -59,6 +59,7 @@ export default class TodoStore extends FeatureStore { this._allReactions = createReactions([ this._setFeatureEnabledReaction, + this._updateTodosConfig, ]); this._registerReactions(this._allReactions); @@ -121,11 +122,14 @@ export default class TodoStore extends FeatureStore { // Todos client message handlers _onTodosClientInitialized = () => { + const { authToken } = this.stores.user; + const { isDarkThemeActive } = this.stores.ui; + if (!this.webview) return; this.webview.send(IPC.TODOS_HOST_CHANNEL, { action: 'todos:configure', data: { - authToken: this.stores.user.authToken, - theme: this.stores.ui.isDarkThemeActive ? ThemeType.dark : ThemeType.default, + authToken, + theme: isDarkThemeActive ? ThemeType.dark : ThemeType.default, }, }); }; @@ -144,4 +148,9 @@ export default class TodoStore extends FeatureStore { this.isFeatureEnabled = isTodosEnabled; }; + + _updateTodosConfig = () => { + // Resend the config if any part changes in Franz: + this._onTodosClientInitialized(); + } } -- cgit v1.2.3-54-g00ecf From 0fdf2677a9d01123b4d0a30ad10f717f972c6749 Mon Sep 17 00:00:00 2001 From: Dominik Guzei Date: Wed, 4 Sep 2019 16:29:27 +0200 Subject: Add locale to todos config --- src/features/todos/store.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/features/todos/store.js') diff --git a/src/features/todos/store.js b/src/features/todos/store.js index bb1df9415..242b38bf7 100644 --- a/src/features/todos/store.js +++ b/src/features/todos/store.js @@ -124,11 +124,13 @@ export default class TodoStore extends FeatureStore { _onTodosClientInitialized = () => { const { authToken } = this.stores.user; const { isDarkThemeActive } = this.stores.ui; + const { locale } = this.stores.app; if (!this.webview) return; this.webview.send(IPC.TODOS_HOST_CHANNEL, { action: 'todos:configure', data: { authToken, + locale, theme: isDarkThemeActive ? ThemeType.dark : ThemeType.default, }, }); -- cgit v1.2.3-54-g00ecf From 24d0223fee38c36ec19d9c662579dba7d787f8b4 Mon Sep 17 00:00:00 2001 From: Stefan Malzner Date: Thu, 5 Sep 2019 09:49:25 +0200 Subject: polishing --- src/assets/images/workspaces/teaser_dark.png | Bin 179047 -> 0 bytes src/assets/images/workspaces/teaser_light.png | Bin 182321 -> 0 bytes src/components/settings/team/TeamDashboard.js | 62 ++++++-- src/components/ui/UpgradeButton/index.js | 90 +++++++++++ src/config.js | 2 +- src/containers/settings/TeamScreen.js | 1 + .../subscription/SubscriptionFormScreen.js | 2 +- src/environment.js | 6 +- src/features/todos/components/TodosWebview.js | 8 +- src/features/todos/store.js | 18 ++- .../workspaces/components/WorkspacesDashboard.js | 167 +++++++++++---------- .../workspaces/containers/WorkspacesScreen.js | 13 +- src/i18n/globalMessages.js | 4 + src/i18n/locales/defaultMessages.json | 67 ++++++--- src/i18n/locales/en-US.json | 4 +- .../components/settings/team/TeamDashboard.json | 24 +-- .../src/components/ui/UpgradeButton/index.json | 15 ++ src/i18n/messages/src/i18n/globalMessages.json | 13 ++ src/stores/UIStore.js | 1 - src/stores/UserStore.js | 4 +- 20 files changed, 360 insertions(+), 141 deletions(-) delete mode 100644 src/assets/images/workspaces/teaser_dark.png delete mode 100644 src/assets/images/workspaces/teaser_light.png create mode 100644 src/components/ui/UpgradeButton/index.js create mode 100644 src/i18n/messages/src/components/ui/UpgradeButton/index.json (limited to 'src/features/todos/store.js') diff --git a/src/assets/images/workspaces/teaser_dark.png b/src/assets/images/workspaces/teaser_dark.png deleted file mode 100644 index 5b6d7334b..000000000 Binary files a/src/assets/images/workspaces/teaser_dark.png and /dev/null differ diff --git a/src/assets/images/workspaces/teaser_light.png b/src/assets/images/workspaces/teaser_light.png deleted file mode 100644 index 635af43fa..000000000 Binary files a/src/assets/images/workspaces/teaser_light.png and /dev/null differ diff --git a/src/components/settings/team/TeamDashboard.js b/src/components/settings/team/TeamDashboard.js index 990ee52e7..51a3f375d 100644 --- a/src/components/settings/team/TeamDashboard.js +++ b/src/components/settings/team/TeamDashboard.js @@ -5,10 +5,14 @@ import { defineMessages, intlShape } from 'react-intl'; import ReactTooltip from 'react-tooltip'; import injectSheet from 'react-jss'; +import { Badge } from '@meetfranz/ui'; import Loader from '../../ui/Loader'; import Button from '../../ui/Button'; import Infobox from '../../ui/Infobox'; import PremiumFeatureContainer from '../../ui/PremiumFeatureContainer'; +import globalMessages from '../../../i18n/globalMessages'; +import ActivateTrialButton from '../../ui/ActivateTrialButton'; +import UpgradeButton from '../../ui/UpgradeButton'; const messages = defineMessages({ headline: { @@ -40,6 +44,7 @@ const messages = defineMessages({ const styles = { cta: { margin: [40, 'auto'], + height: 'auto', }, container: { display: 'flex', @@ -69,6 +74,17 @@ const styles = { order: 1, }, }, + headline: { + marginBottom: 0, + }, + proRequired: { + margin: [10, 0, 40], + height: 'auto', + }, + buttonContainer: { + display: 'flex', + height: 'auto', + }, }; @@ -79,6 +95,7 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon retryUserInfoRequest: PropTypes.func.isRequired, openTeamManagement: PropTypes.func.isRequired, classes: PropTypes.object.isRequired, + isProUser: PropTypes.bool.isRequired, }; static contextTypes = { @@ -91,6 +108,7 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon userInfoRequestFailed, retryUserInfoRequest, openTeamManagement, + isProUser, classes, } = this.props; const { intl } = this.context; @@ -123,23 +141,35 @@ export default @injectSheet(styles) @observer class TeamDashboard extends Compon <> {!isLoading && ( <> - - <> -

{intl.formatMessage(messages.contentHeadline)}

-
-
-

{intl.formatMessage(messages.intro)}

-

{intl.formatMessage(messages.copy)}

-
- Franz for Teams + <> +

{intl.formatMessage(messages.contentHeadline)}

+ {!isProUser && ( + {intl.formatMessage(globalMessages.proRequired)} + )} +
+
+

{intl.formatMessage(messages.intro)}

+

{intl.formatMessage(messages.copy)}

- - -
+
+ {!isProUser ? ( + + ) : ( +
+ )} diff --git a/src/components/ui/UpgradeButton/index.js b/src/components/ui/UpgradeButton/index.js new file mode 100644 index 000000000..4aa494e38 --- /dev/null +++ b/src/components/ui/UpgradeButton/index.js @@ -0,0 +1,90 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { inject, observer } from 'mobx-react'; +import { defineMessages, intlShape } from 'react-intl'; +import classnames from 'classnames'; + +import { Button } from '@meetfranz/forms'; +import { gaEvent } from '../../../lib/analytics'; + +import UserStore from '../../../stores/UserStore'; +import ActivateTrialButton from '../ActivateTrialButton'; + +const messages = defineMessages({ + upgradeToPro: { + id: 'global.upgradeButton.upgradeToPro', + defaultMessage: '!!!Upgrade to Franz Professional', + }, +}); + +@inject('stores', 'actions') @observer +class UpgradeButton extends Component { + static propTypes = { + // eslint-disable-next-line + classes: PropTypes.object.isRequired, + className: PropTypes.string, + gaEventInfo: PropTypes.shape({ + category: PropTypes.string.isRequired, + event: PropTypes.string.isRequired, + label: PropTypes.string, + }), + requiresPro: PropTypes.bool, + }; + + static defaultProps = { + className: '', + gaEventInfo: null, + requiresPro: false, + } + + static contextTypes = { + intl: intlShape, + }; + + handleCTAClick() { + const { actions, gaEventInfo } = this.props; + + actions.ui.openSettings({ path: 'user' }); + if (gaEventInfo) { + const { category, event } = gaEventInfo; + gaEvent(category, event, 'Upgrade Account'); + } + } + + render() { + const { stores, requiresPro } = this.props; + const { intl } = this.context; + + const { isPremium, isPersonal } = stores.user; + + if (isPremium && isPersonal && requiresPro) { + return ( +