diff options
Diffstat (limited to 'src/components/layout')
-rw-r--r-- | src/components/layout/AppLayout.js | 24 | ||||
-rw-r--r-- | src/components/layout/Sidebar.js | 137 |
2 files changed, 105 insertions, 56 deletions
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js index 200777ae6..e82275b9f 100644 --- a/src/components/layout/AppLayout.js +++ b/src/components/layout/AppLayout.js | |||
@@ -6,7 +6,6 @@ import { TitleBar } from 'electron-react-titlebar'; | |||
6 | import injectSheet from 'react-jss'; | 6 | import injectSheet from 'react-jss'; |
7 | 7 | ||
8 | import InfoBar from '../ui/InfoBar'; | 8 | import InfoBar from '../ui/InfoBar'; |
9 | import { Component as DelayApp } from '../../features/delayApp'; | ||
10 | import { Component as BasicAuth } from '../../features/basicAuth'; | 9 | import { Component as BasicAuth } from '../../features/basicAuth'; |
11 | import { Component as ShareFranz } from '../../features/shareFranz'; | 10 | import { Component as ShareFranz } from '../../features/shareFranz'; |
12 | import ErrorBoundary from '../util/ErrorBoundary'; | 11 | import ErrorBoundary from '../util/ErrorBoundary'; |
@@ -37,6 +36,10 @@ const messages = defineMessages({ | |||
37 | id: 'infobar.requiredRequestsFailed', | 36 | id: 'infobar.requiredRequestsFailed', |
38 | defaultMessage: '!!!Could not load services and user information', | 37 | defaultMessage: '!!!Could not load services and user information', |
39 | }, | 38 | }, |
39 | authRequestFailed: { | ||
40 | id: 'infobar.authRequestFailed', | ||
41 | defaultMessage: '!!!There were errors while trying to perform an authenticated request. Please try logging out and back in if this error persists.', | ||
42 | }, | ||
40 | }); | 43 | }); |
41 | 44 | ||
42 | const styles = theme => ({ | 45 | const styles = theme => ({ |
@@ -63,6 +66,7 @@ class AppLayout extends Component { | |||
63 | showServicesUpdatedInfoBar: PropTypes.bool.isRequired, | 66 | showServicesUpdatedInfoBar: PropTypes.bool.isRequired, |
64 | appUpdateIsDownloaded: PropTypes.bool.isRequired, | 67 | appUpdateIsDownloaded: PropTypes.bool.isRequired, |
65 | nextAppReleaseVersion: PropTypes.string, | 68 | nextAppReleaseVersion: PropTypes.string, |
69 | authRequestFailed: PropTypes.bool.isRequired, | ||
66 | removeNewsItem: PropTypes.func.isRequired, | 70 | removeNewsItem: PropTypes.func.isRequired, |
67 | reloadServicesAfterUpdate: PropTypes.func.isRequired, | 71 | reloadServicesAfterUpdate: PropTypes.func.isRequired, |
68 | installAppUpdate: PropTypes.func.isRequired, | 72 | installAppUpdate: PropTypes.func.isRequired, |
@@ -70,7 +74,6 @@ class AppLayout extends Component { | |||
70 | areRequiredRequestsSuccessful: PropTypes.bool.isRequired, | 74 | areRequiredRequestsSuccessful: PropTypes.bool.isRequired, |
71 | retryRequiredRequests: PropTypes.func.isRequired, | 75 | retryRequiredRequests: PropTypes.func.isRequired, |
72 | areRequiredRequestsLoading: PropTypes.bool.isRequired, | 76 | areRequiredRequestsLoading: PropTypes.bool.isRequired, |
73 | isDelayAppScreenVisible: PropTypes.bool.isRequired, | ||
74 | hasActivatedTrial: PropTypes.bool.isRequired, | 77 | hasActivatedTrial: PropTypes.bool.isRequired, |
75 | }; | 78 | }; |
76 | 79 | ||
@@ -95,6 +98,7 @@ class AppLayout extends Component { | |||
95 | showServicesUpdatedInfoBar, | 98 | showServicesUpdatedInfoBar, |
96 | appUpdateIsDownloaded, | 99 | appUpdateIsDownloaded, |
97 | nextAppReleaseVersion, | 100 | nextAppReleaseVersion, |
101 | authRequestFailed, | ||
98 | removeNewsItem, | 102 | removeNewsItem, |
99 | reloadServicesAfterUpdate, | 103 | reloadServicesAfterUpdate, |
100 | installAppUpdate, | 104 | installAppUpdate, |
@@ -102,7 +106,6 @@ class AppLayout extends Component { | |||
102 | areRequiredRequestsSuccessful, | 106 | areRequiredRequestsSuccessful, |
103 | retryRequiredRequests, | 107 | retryRequiredRequests, |
104 | areRequiredRequestsLoading, | 108 | areRequiredRequestsLoading, |
105 | isDelayAppScreenVisible, | ||
106 | hasActivatedTrial, | 109 | hasActivatedTrial, |
107 | } = this.props; | 110 | } = this.props; |
108 | 111 | ||
@@ -111,7 +114,7 @@ class AppLayout extends Component { | |||
111 | return ( | 114 | return ( |
112 | <ErrorBoundary> | 115 | <ErrorBoundary> |
113 | <div className="app"> | 116 | <div className="app"> |
114 | {isWindows && !isFullScreen && <TitleBar menu={window.franz.menu.template} icon="assets/images/logo.svg" />} | 117 | {isWindows && !isFullScreen && <TitleBar menu={window.ferdi.menu.template} icon="assets/images/logo.svg" />} |
115 | <div className={`app__content ${classes.appContent}`}> | 118 | <div className={`app__content ${classes.appContent}`}> |
116 | {workspacesDrawer} | 119 | {workspacesDrawer} |
117 | {sidebar} | 120 | {sidebar} |
@@ -151,6 +154,18 @@ class AppLayout extends Component { | |||
151 | {intl.formatMessage(messages.requiredRequestsFailed)} | 154 | {intl.formatMessage(messages.requiredRequestsFailed)} |
152 | </InfoBar> | 155 | </InfoBar> |
153 | )} | 156 | )} |
157 | {authRequestFailed && ( | ||
158 | <InfoBar | ||
159 | type="danger" | ||
160 | ctaLabel="Try again" | ||
161 | ctaLoading={areRequiredRequestsLoading} | ||
162 | sticky | ||
163 | onClick={retryRequiredRequests} | ||
164 | > | ||
165 | <span className="mdi mdi-flash" /> | ||
166 | {intl.formatMessage(messages.authRequestFailed)} | ||
167 | </InfoBar> | ||
168 | )} | ||
154 | {showServicesUpdatedInfoBar && ( | 169 | {showServicesUpdatedInfoBar && ( |
155 | <InfoBar | 170 | <InfoBar |
156 | type="primary" | 171 | type="primary" |
@@ -168,7 +183,6 @@ class AppLayout extends Component { | |||
168 | onInstallUpdate={installAppUpdate} | 183 | onInstallUpdate={installAppUpdate} |
169 | /> | 184 | /> |
170 | )} | 185 | )} |
171 | {isDelayAppScreenVisible && (<DelayApp />)} | ||
172 | <BasicAuth /> | 186 | <BasicAuth /> |
173 | <ShareFranz /> | 187 | <ShareFranz /> |
174 | {services} | 188 | {services} |
diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js index 918298011..52de16508 100644 --- a/src/components/layout/Sidebar.js +++ b/src/components/layout/Sidebar.js | |||
@@ -2,13 +2,13 @@ import React, { Component } from 'react'; | |||
2 | import PropTypes from 'prop-types'; | 2 | import PropTypes from 'prop-types'; |
3 | import ReactTooltip from 'react-tooltip'; | 3 | import ReactTooltip from 'react-tooltip'; |
4 | import { defineMessages, intlShape } from 'react-intl'; | 4 | import { defineMessages, intlShape } from 'react-intl'; |
5 | import { observer } from 'mobx-react'; | 5 | import { inject, observer } from 'mobx-react'; |
6 | import { Link } from 'react-router'; | ||
6 | 7 | ||
7 | import Tabbar from '../services/tabs/Tabbar'; | 8 | import Tabbar from '../services/tabs/Tabbar'; |
8 | import { ctrlKey } from '../../environment'; | 9 | import { ctrlKey } from '../../environment'; |
9 | import { GA_CATEGORY_WORKSPACES, workspaceStore } from '../../features/workspaces'; | 10 | import { workspaceStore } from '../../features/workspaces'; |
10 | import { gaEvent } from '../../lib/analytics'; | 11 | import { todosStore } from '../../features/todos'; |
11 | import { todosStore, GA_CATEGORY_TODOS } from '../../features/todos'; | ||
12 | import { todoActions } from '../../features/todos/actions'; | 12 | import { todoActions } from '../../features/todos/actions'; |
13 | 13 | ||
14 | const messages = defineMessages({ | 14 | const messages = defineMessages({ |
@@ -44,9 +44,13 @@ const messages = defineMessages({ | |||
44 | id: 'sidebar.closeTodosDrawer', | 44 | id: 'sidebar.closeTodosDrawer', |
45 | defaultMessage: '!!!Close Franz Todos', | 45 | defaultMessage: '!!!Close Franz Todos', |
46 | }, | 46 | }, |
47 | lockFerdi: { | ||
48 | id: 'sidebar.lockFerdi', | ||
49 | defaultMessage: '!!!Lock Ferdi', | ||
50 | }, | ||
47 | }); | 51 | }); |
48 | 52 | ||
49 | export default @observer class Sidebar extends Component { | 53 | export default @inject('stores', 'actions') @observer class Sidebar extends Component { |
50 | static propTypes = { | 54 | static propTypes = { |
51 | openSettings: PropTypes.func.isRequired, | 55 | openSettings: PropTypes.func.isRequired, |
52 | toggleMuteApp: PropTypes.func.isRequired, | 56 | toggleMuteApp: PropTypes.func.isRequired, |
@@ -87,6 +91,8 @@ export default @observer class Sidebar extends Component { | |||
87 | isAppMuted, | 91 | isAppMuted, |
88 | isWorkspaceDrawerOpen, | 92 | isWorkspaceDrawerOpen, |
89 | toggleWorkspaceDrawer, | 93 | toggleWorkspaceDrawer, |
94 | stores, | ||
95 | actions, | ||
90 | } = this.props; | 96 | } = this.props; |
91 | const { intl } = this.context; | 97 | const { intl } = this.context; |
92 | const todosToggleMessage = ( | 98 | const todosToggleMessage = ( |
@@ -96,6 +102,7 @@ export default @observer class Sidebar extends Component { | |||
96 | const workspaceToggleMessage = ( | 102 | const workspaceToggleMessage = ( |
97 | isWorkspaceDrawerOpen ? messages.closeWorkspaceDrawer : messages.openWorkspaceDrawer | 103 | isWorkspaceDrawerOpen ? messages.closeWorkspaceDrawer : messages.openWorkspaceDrawer |
98 | ); | 104 | ); |
105 | const isLoggedIn = Boolean(localStorage.getItem('authToken')); | ||
99 | 106 | ||
100 | return ( | 107 | return ( |
101 | <div className="sidebar"> | 108 | <div className="sidebar"> |
@@ -104,53 +111,81 @@ export default @observer class Sidebar extends Component { | |||
104 | enableToolTip={() => this.enableToolTip()} | 111 | enableToolTip={() => this.enableToolTip()} |
105 | disableToolTip={() => this.disableToolTip()} | 112 | disableToolTip={() => this.disableToolTip()} |
106 | /> | 113 | /> |
107 | {todosStore.isFeatureEnabled && todosStore.isFeatureEnabledByUser ? ( | 114 | { isLoggedIn ? ( |
108 | <button | 115 | <> |
109 | type="button" | 116 | { stores.settings.all.app.lockingFeatureEnabled ? ( |
110 | onClick={() => { | 117 | <button |
111 | todoActions.toggleTodosPanel(); | 118 | type="button" |
112 | this.updateToolTip(); | 119 | className={`sidebar__button sidebar__button--audio ${isAppMuted ? 'is-muted' : ''}`} |
113 | gaEvent(GA_CATEGORY_TODOS, 'toggleDrawer', 'sidebar'); | 120 | onClick={() => { |
114 | }} | 121 | actions.settings.update({ |
115 | className={`sidebar__button sidebar__button--todos ${todosStore.isTodosPanelVisible ? 'is-active' : ''}`} | 122 | type: 'app', |
116 | data-tip={`${intl.formatMessage(todosToggleMessage)} (${ctrlKey}+T)`} | 123 | data: { |
117 | > | 124 | locked: true, |
118 | <i className="mdi mdi-check-all" /> | 125 | }, |
119 | </button> | 126 | }); |
120 | ) : null} | 127 | }} |
121 | {workspaceStore.isFeatureEnabled ? ( | 128 | data-tip={`${intl.formatMessage(messages.lockFerdi)} (${ctrlKey}+Shift+L)`} |
122 | <button | 129 | > |
123 | type="button" | 130 | <i className="mdi mdi-lock" /> |
124 | onClick={() => { | 131 | </button> |
125 | toggleWorkspaceDrawer(); | 132 | ) : null} |
126 | this.updateToolTip(); | 133 | {todosStore.isFeatureEnabled && todosStore.isFeatureEnabledByUser ? ( |
127 | gaEvent(GA_CATEGORY_WORKSPACES, 'toggleDrawer', 'sidebar'); | 134 | <button |
128 | }} | 135 | type="button" |
129 | className={`sidebar__button sidebar__button--workspaces ${isWorkspaceDrawerOpen ? 'is-active' : ''}`} | 136 | onClick={() => { |
130 | data-tip={`${intl.formatMessage(workspaceToggleMessage)} (${ctrlKey}+D)`} | 137 | todoActions.toggleTodosPanel(); |
138 | this.updateToolTip(); | ||
139 | gaEvent(GA_CATEGORY_TODOS, 'toggleDrawer', 'sidebar'); | ||
140 | }} | ||
141 | className={`sidebar__button sidebar__button--todos ${todosStore.isTodosPanelVisible ? 'is-active' : ''}`} | ||
142 | data-tip={`${intl.formatMessage(todosToggleMessage)} (${ctrlKey}+T)`} | ||
143 | > | ||
144 | <i className="mdi mdi-check-all" /> | ||
145 | </button> | ||
146 | ) : null} | ||
147 | {workspaceStore.isFeatureEnabled ? ( | ||
148 | <button | ||
149 | type="button" | ||
150 | onClick={() => { | ||
151 | toggleWorkspaceDrawer(); | ||
152 | this.updateToolTip(); | ||
153 | }} | ||
154 | className={`sidebar__button sidebar__button--workspaces ${isWorkspaceDrawerOpen ? 'is-active' : ''}`} | ||
155 | data-tip={`${intl.formatMessage(workspaceToggleMessage)} (${ctrlKey}+D)`} | ||
156 | > | ||
157 | <i className="mdi mdi-view-grid" /> | ||
158 | </button> | ||
159 | ) : null} | ||
160 | <button | ||
161 | type="button" | ||
162 | onClick={() => { | ||
163 | toggleMuteApp(); | ||
164 | this.updateToolTip(); | ||
165 | }} | ||
166 | className={`sidebar__button sidebar__button--audio ${isAppMuted ? 'is-muted' : ''}`} | ||
167 | data-tip={`${intl.formatMessage(isAppMuted ? messages.unmute : messages.mute)} (${ctrlKey}+Shift+M)`} | ||
168 | > | ||
169 | <i className={`mdi mdi-bell${isAppMuted ? '-off' : ''}`} /> | ||
170 | </button> | ||
171 | <button | ||
172 | type="button" | ||
173 | onClick={() => openSettings({ path: 'recipes' })} | ||
174 | className="sidebar__button sidebar__button--new-service" | ||
175 | data-tip={`${intl.formatMessage(messages.addNewService)} (${ctrlKey}+N)`} | ||
176 | > | ||
177 | <i className="mdi mdi-plus-box" /> | ||
178 | </button> | ||
179 | </> | ||
180 | ) : ( | ||
181 | <Link | ||
182 | to="/auth/welcome" | ||
183 | className="sidebar__button sidebar__button--new-service" | ||
184 | data-tip="Login" | ||
131 | > | 185 | > |
132 | <i className="mdi mdi-view-grid" /> | 186 | <i className="mdi mdi-login-variant" /> |
133 | </button> | 187 | </Link> |
134 | ) : null} | 188 | )} |
135 | <button | ||
136 | type="button" | ||
137 | onClick={() => { | ||
138 | toggleMuteApp(); | ||
139 | this.updateToolTip(); | ||
140 | }} | ||
141 | className={`sidebar__button sidebar__button--audio ${isAppMuted ? 'is-muted' : ''}`} | ||
142 | data-tip={`${intl.formatMessage(isAppMuted ? messages.unmute : messages.mute)} (${ctrlKey}+Shift+M)`} | ||
143 | > | ||
144 | <i className={`mdi mdi-bell${isAppMuted ? '-off' : ''}`} /> | ||
145 | </button> | ||
146 | <button | ||
147 | type="button" | ||
148 | onClick={() => openSettings({ path: 'recipes' })} | ||
149 | className="sidebar__button sidebar__button--new-service" | ||
150 | data-tip={`${intl.formatMessage(messages.addNewService)} (${ctrlKey}+N)`} | ||
151 | > | ||
152 | <i className="mdi mdi-plus-box" /> | ||
153 | </button> | ||
154 | <button | 189 | <button |
155 | type="button" | 190 | type="button" |
156 | onClick={() => openSettings({ path: 'app' })} | 191 | onClick={() => openSettings({ path: 'app' })} |