diff options
Diffstat (limited to 'src/features')
-rw-r--r-- | src/features/announcements/actions.js | 10 | ||||
-rw-r--r-- | src/features/announcements/api.js | 35 | ||||
-rw-r--r-- | src/features/announcements/components/AnnouncementScreen.js | 300 | ||||
-rw-r--r-- | src/features/announcements/constants.js | 5 | ||||
-rw-r--r-- | src/features/announcements/index.js | 29 | ||||
-rw-r--r-- | src/features/announcements/store.js | 148 | ||||
-rw-r--r-- | src/features/todos/store.js | 79 | ||||
-rw-r--r-- | src/features/workspaces/components/WorkspacesDashboard.js | 14 |
8 files changed, 54 insertions, 566 deletions
diff --git a/src/features/announcements/actions.js b/src/features/announcements/actions.js deleted file mode 100644 index bab496314..000000000 --- a/src/features/announcements/actions.js +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | import PropTypes from 'prop-types'; | ||
2 | import { createActionsFromDefinitions } from '../../actions/lib/actions'; | ||
3 | |||
4 | export const announcementActions = createActionsFromDefinitions({ | ||
5 | show: { | ||
6 | targetVersion: PropTypes.string, | ||
7 | }, | ||
8 | }, PropTypes.checkPropTypes); | ||
9 | |||
10 | export default announcementActions; | ||
diff --git a/src/features/announcements/api.js b/src/features/announcements/api.js deleted file mode 100644 index 962f3e694..000000000 --- a/src/features/announcements/api.js +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | import Request from '../../stores/lib/Request'; | ||
2 | import apiBase from '../../api/apiBase'; | ||
3 | import { GITHUB_FERDI_REPO_NAME, GITHUB_NIGHTLIES_REPO_NAME, GITHUB_ORG_NAME } from '../../config'; | ||
4 | import { ferdiVersion } from '../../environment'; | ||
5 | |||
6 | const debug = require('debug')('Ferdi:feature:announcements:api'); | ||
7 | |||
8 | export const announcementsApi = { | ||
9 | async getCurrentVersion() { | ||
10 | debug('getting current version of electron app'); | ||
11 | return Promise.resolve(ferdiVersion); | ||
12 | }, | ||
13 | |||
14 | async getChangelog(version) { | ||
15 | const ferdiRepoName = version.includes('nightly') ? GITHUB_NIGHTLIES_REPO_NAME : GITHUB_FERDI_REPO_NAME; | ||
16 | const url = `https://api.github.com/repos/${GITHUB_ORG_NAME}/${ferdiRepoName}/releases/tags/v${version}`; | ||
17 | debug(`fetching release changelog from Github url: ${url}`); | ||
18 | const request = await window.fetch(url, { method: 'GET' }); | ||
19 | if (!request.ok) return null; | ||
20 | const data = await request.json(); | ||
21 | return data.body; | ||
22 | }, | ||
23 | |||
24 | async getAnnouncement(version) { | ||
25 | const url = `${apiBase()}/announcements/${version}`; | ||
26 | debug(`fetching release announcement from api url: ${url}`); | ||
27 | const response = await window.fetch(url, { method: 'GET' }); | ||
28 | if (!response.ok) return null; | ||
29 | return response.json(); | ||
30 | }, | ||
31 | }; | ||
32 | |||
33 | export const getCurrentVersionRequest = new Request(announcementsApi, 'getCurrentVersion'); | ||
34 | export const getChangelogRequest = new Request(announcementsApi, 'getChangelog'); | ||
35 | export const getAnnouncementRequest = new Request(announcementsApi, 'getAnnouncement'); | ||
diff --git a/src/features/announcements/components/AnnouncementScreen.js b/src/features/announcements/components/AnnouncementScreen.js deleted file mode 100644 index 315843db3..000000000 --- a/src/features/announcements/components/AnnouncementScreen.js +++ /dev/null | |||
@@ -1,300 +0,0 @@ | |||
1 | import React, { Component } from 'react'; | ||
2 | import marked from 'marked'; | ||
3 | import PropTypes from 'prop-types'; | ||
4 | import { inject, observer } from 'mobx-react'; | ||
5 | import { defineMessages, intlShape } from 'react-intl'; | ||
6 | import injectSheet from 'react-jss'; | ||
7 | import { Button } from '@meetfranz/forms'; | ||
8 | |||
9 | import { announcementsStore } from '../index'; | ||
10 | import UIStore from '../../../stores/UIStore'; | ||
11 | import AppStore from '../../../stores/AppStore'; | ||
12 | |||
13 | const renderer = new marked.Renderer(); | ||
14 | |||
15 | renderer.link = (href, title, text) => `<a target="_blank" href="${href}" title="${title}">${text}</a>`; | ||
16 | |||
17 | const markedOptions = { sanitize: true, renderer }; | ||
18 | |||
19 | const messages = defineMessages({ | ||
20 | headline: { | ||
21 | id: 'feature.announcements.changelog.headline', | ||
22 | defaultMessage: '!!!Changes in Ferdi {version}', | ||
23 | }, | ||
24 | }); | ||
25 | |||
26 | const smallScreen = '1000px'; | ||
27 | |||
28 | const styles = (theme) => ({ | ||
29 | container: { | ||
30 | background: theme.colorBackground, | ||
31 | position: 'relative', | ||
32 | top: 0, | ||
33 | zIndex: 140, | ||
34 | width: '100%', | ||
35 | height: '100%', | ||
36 | overflowY: 'auto', | ||
37 | }, | ||
38 | headline: { | ||
39 | color: theme.colorHeadline, | ||
40 | margin: [25, 0, 40], | ||
41 | // 'max-width': 500, | ||
42 | 'text-align': 'center', | ||
43 | 'line-height': '1.3em', | ||
44 | }, | ||
45 | announcement: { | ||
46 | height: 'auto', | ||
47 | |||
48 | [`@media(min-width: ${smallScreen})`]: { | ||
49 | display: 'flex', | ||
50 | flexDirection: 'column', | ||
51 | justifyContent: 'center', | ||
52 | height: '100vh', | ||
53 | }, | ||
54 | }, | ||
55 | main: { | ||
56 | display: 'flex', | ||
57 | flexDirection: 'column', | ||
58 | flexGrow: 1, | ||
59 | justifyContent: 'center', | ||
60 | |||
61 | '& h1': { | ||
62 | margin: [40, 0, 15], | ||
63 | fontSize: 70, | ||
64 | color: theme.styleTypes.primary.accent, | ||
65 | textAlign: 'center', | ||
66 | |||
67 | [`@media(min-width: ${smallScreen})`]: { | ||
68 | marginTop: 0, | ||
69 | }, | ||
70 | }, | ||
71 | '& h2': { | ||
72 | fontSize: 30, | ||
73 | fontWeight: 300, | ||
74 | color: theme.colorText, | ||
75 | textAlign: 'center', | ||
76 | marginBottom: 60, | ||
77 | }, | ||
78 | }, | ||
79 | mainBody: { | ||
80 | display: 'flex', | ||
81 | flexDirection: 'column', | ||
82 | alignItems: 'center', | ||
83 | width: 'calc(100% - 80px)', | ||
84 | height: 'auto', | ||
85 | margin: '0 auto', | ||
86 | [`@media(min-width: ${smallScreen})`]: { | ||
87 | flexDirection: 'row', | ||
88 | justifyContent: 'center', | ||
89 | }, | ||
90 | }, | ||
91 | mainImage: { | ||
92 | minWidth: 250, | ||
93 | maxWidth: 400, | ||
94 | margin: '0 auto', | ||
95 | marginBottom: 40, | ||
96 | '& img': { | ||
97 | width: '100%', | ||
98 | }, | ||
99 | [`@media(min-width: ${smallScreen})`]: { | ||
100 | margin: 0, | ||
101 | }, | ||
102 | }, | ||
103 | mainText: { | ||
104 | height: 'auto', | ||
105 | maxWidth: 600, | ||
106 | textAlign: 'center', | ||
107 | '& p': { | ||
108 | lineHeight: '1.5em', | ||
109 | }, | ||
110 | [`@media(min-width: ${smallScreen})`]: { | ||
111 | textAlign: 'left', | ||
112 | }, | ||
113 | }, | ||
114 | mainCtaButton: { | ||
115 | textAlign: 'center', | ||
116 | marginTop: 40, | ||
117 | [`@media(min-width: ${smallScreen})`]: { | ||
118 | textAlign: 'left', | ||
119 | }, | ||
120 | }, | ||
121 | spotlight: { | ||
122 | height: 'auto', | ||
123 | background: theme.announcements.spotlight.background, | ||
124 | padding: [40, 0], | ||
125 | marginTop: 80, | ||
126 | [`@media(min-width: ${smallScreen})`]: { | ||
127 | marginTop: 0, | ||
128 | justifyContent: 'center', | ||
129 | alignItems: 'flex-start', | ||
130 | display: 'flex', | ||
131 | flexDirection: 'row', | ||
132 | }, | ||
133 | }, | ||
134 | spotlightTopicContainer: { | ||
135 | textAlign: 'center', | ||
136 | marginBottom: 20, | ||
137 | |||
138 | [`@media(min-width: ${smallScreen})`]: { | ||
139 | marginBottom: 0, | ||
140 | minWidth: 250, | ||
141 | maxWidth: 330, | ||
142 | width: '100%', | ||
143 | textAlign: 'right', | ||
144 | marginRight: 60, | ||
145 | }, | ||
146 | }, | ||
147 | spotlightContentContainer: { | ||
148 | textAlign: 'center', | ||
149 | [`@media(min-width: ${smallScreen})`]: { | ||
150 | height: 'auto', | ||
151 | maxWidth: 600, | ||
152 | paddingRight: 40, | ||
153 | textAlign: 'left', | ||
154 | }, | ||
155 | '& p': { | ||
156 | lineHeight: '1.5em', | ||
157 | }, | ||
158 | }, | ||
159 | spotlightTopic: { | ||
160 | fontSize: 20, | ||
161 | marginBottom: 5, | ||
162 | letterSpacing: 0, | ||
163 | fontWeight: 100, | ||
164 | }, | ||
165 | spotlightSubject: { | ||
166 | fontSize: 20, | ||
167 | }, | ||
168 | changelog: { | ||
169 | padding: [0, 60], | ||
170 | maxWidth: 700, | ||
171 | margin: [100, 'auto'], | ||
172 | height: 'auto', | ||
173 | |||
174 | '& h3': { | ||
175 | fontSize: '24px', | ||
176 | margin: '1.5em 0 1em 0', | ||
177 | }, | ||
178 | '& li': { | ||
179 | marginBottom: '1em', | ||
180 | lineHeight: '1.4em', | ||
181 | }, | ||
182 | '& div': { | ||
183 | height: 'auto', | ||
184 | }, | ||
185 | }, | ||
186 | }); | ||
187 | |||
188 | @inject('stores', 'actions') @injectSheet(styles) @observer | ||
189 | class AnnouncementScreen extends Component { | ||
190 | static propTypes = { | ||
191 | classes: PropTypes.object.isRequired, | ||
192 | stores: PropTypes.shape({ | ||
193 | ui: PropTypes.instanceOf(UIStore).isRequired, | ||
194 | }).isRequired, | ||
195 | actions: PropTypes.shape({ | ||
196 | app: PropTypes.instanceOf(AppStore).isRequired, | ||
197 | }).isRequired, | ||
198 | }; | ||
199 | |||
200 | static contextTypes = { | ||
201 | intl: intlShape, | ||
202 | }; | ||
203 | |||
204 | render() { | ||
205 | const { classes, stores, actions } = this.props; | ||
206 | const { intl } = this.context; | ||
207 | const { changelog, announcement } = announcementsStore; | ||
208 | const themeImage = stores.ui.isDarkThemeActive ? 'dark' : 'light'; | ||
209 | return ( | ||
210 | <div className={classes.container}> | ||
211 | {announcement && ( | ||
212 | <div className={classes.announcement}> | ||
213 | <div className={classes.main}> | ||
214 | <h1>{announcement.main.headline}</h1> | ||
215 | <h2>{announcement.main.subHeadline}</h2> | ||
216 | <div className={classes.mainBody}> | ||
217 | <div className={classes.mainImage}> | ||
218 | <img | ||
219 | src={announcement.main.image[themeImage]} | ||
220 | alt="" | ||
221 | /> | ||
222 | </div> | ||
223 | <div className={classes.mainText}> | ||
224 | <div | ||
225 | dangerouslySetInnerHTML={{ | ||
226 | __html: marked(announcement.main.text, markedOptions), | ||
227 | }} | ||
228 | /> | ||
229 | {(announcement.main.cta.label || announcement.main.cta.href) && ( | ||
230 | <div className={classes.mainCtaButton}> | ||
231 | <Button | ||
232 | label={announcement.main.cta.label} | ||
233 | onClick={() => { | ||
234 | const { | ||
235 | href, | ||
236 | } = announcement.main.cta; | ||
237 | if (announcement.main.cta.href.startsWith('http')) { | ||
238 | actions.app.openExternalUrl({ url: href }); | ||
239 | } else { | ||
240 | window.location.href = `#${href}`; | ||
241 | } | ||
242 | }} | ||
243 | /> | ||
244 | </div> | ||
245 | )} | ||
246 | </div> | ||
247 | </div> | ||
248 | </div> | ||
249 | {announcement.spotlight && ( | ||
250 | <div className={classes.spotlight}> | ||
251 | <div className={classes.spotlightTopicContainer}> | ||
252 | <h2 className={classes.spotlightTopic}>{announcement.spotlight.title}</h2> | ||
253 | <h3 className={classes.spotlightSubject}>{announcement.spotlight.subject}</h3> | ||
254 | </div> | ||
255 | <div className={classes.spotlightContentContainer}> | ||
256 | <div | ||
257 | dangerouslySetInnerHTML={{ | ||
258 | __html: marked(announcement.spotlight.text, markedOptions), | ||
259 | }} | ||
260 | /> | ||
261 | <div className={classes.mainCtaButton}> | ||
262 | <Button | ||
263 | label={announcement.spotlight.cta.label} | ||
264 | onClick={() => { | ||
265 | const { | ||
266 | href, | ||
267 | } = announcement.spotlight.cta; | ||
268 | if (announcement.spotlight.cta.href.startsWith('http')) { | ||
269 | actions.app.openExternalUrl({ url: href }); | ||
270 | } else { | ||
271 | window.location.href = `#${href}`; | ||
272 | } | ||
273 | }} | ||
274 | /> | ||
275 | </div> | ||
276 | </div> | ||
277 | </div> | ||
278 | )} | ||
279 | </div> | ||
280 | )} | ||
281 | {changelog && ( | ||
282 | <div className={classes.changelog}> | ||
283 | <h1 className={classes.headline}> | ||
284 | {intl.formatMessage(messages.headline, { | ||
285 | version: announcementsStore.targetVersion, | ||
286 | })} | ||
287 | </h1> | ||
288 | <div | ||
289 | dangerouslySetInnerHTML={{ | ||
290 | __html: marked(changelog, markedOptions), | ||
291 | }} | ||
292 | /> | ||
293 | </div> | ||
294 | )} | ||
295 | </div> | ||
296 | ); | ||
297 | } | ||
298 | } | ||
299 | |||
300 | export default AnnouncementScreen; | ||
diff --git a/src/features/announcements/constants.js b/src/features/announcements/constants.js deleted file mode 100644 index 284226fdf..000000000 --- a/src/features/announcements/constants.js +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | export const ANNOUNCEMENTS_ROUTES = { | ||
2 | TARGET: '/announcements/:id', | ||
3 | }; | ||
4 | |||
5 | export const GA_CATEGORY_ANNOUNCEMENTS = 'Announcements'; | ||
diff --git a/src/features/announcements/index.js b/src/features/announcements/index.js deleted file mode 100644 index 19930c5b1..000000000 --- a/src/features/announcements/index.js +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | import { reaction } from 'mobx'; | ||
2 | import { AnnouncementsStore } from './store'; | ||
3 | |||
4 | const debug = require('debug')('Ferdi:feature:announcements'); | ||
5 | |||
6 | export const GA_CATEGORY_ANNOUNCEMENTS = 'Announcements'; | ||
7 | |||
8 | export const announcementsStore = new AnnouncementsStore(); | ||
9 | |||
10 | export default function initAnnouncements(stores, actions) { | ||
11 | const { features } = stores; | ||
12 | |||
13 | // Toggle announcement feature | ||
14 | reaction( | ||
15 | () => ( | ||
16 | features.features.isAnnouncementsEnabled | ||
17 | ), | ||
18 | (isEnabled) => { | ||
19 | if (isEnabled) { | ||
20 | debug('Initializing `announcements` feature'); | ||
21 | announcementsStore.start(stores, actions); | ||
22 | } else if (announcementsStore.isFeatureActive) { | ||
23 | debug('Disabling `announcements` feature'); | ||
24 | announcementsStore.stop(); | ||
25 | } | ||
26 | }, | ||
27 | { fireImmediately: true }, | ||
28 | ); | ||
29 | } | ||
diff --git a/src/features/announcements/store.js b/src/features/announcements/store.js deleted file mode 100644 index 794d20142..000000000 --- a/src/features/announcements/store.js +++ /dev/null | |||
@@ -1,148 +0,0 @@ | |||
1 | import { | ||
2 | action, | ||
3 | computed, | ||
4 | observable, | ||
5 | } from 'mobx'; | ||
6 | import semver from 'semver'; | ||
7 | import localStorage from 'mobx-localstorage'; | ||
8 | |||
9 | import { FeatureStore } from '../utils/FeatureStore'; | ||
10 | import { ANNOUNCEMENTS_ROUTES } from './constants'; | ||
11 | import { getAnnouncementRequest, getChangelogRequest, getCurrentVersionRequest } from './api'; | ||
12 | import { announcementActions } from './actions'; | ||
13 | import { createActionBindings } from '../utils/ActionBinding'; | ||
14 | import { createReactions } from '../../stores/lib/Reaction'; | ||
15 | import { matchRoute } from '../../helpers/routing-helpers'; | ||
16 | import { DEFAULT_APP_SETTINGS } from '../../environment'; | ||
17 | |||
18 | const LOCAL_STORAGE_KEY = 'announcements'; | ||
19 | |||
20 | const debug = require('debug')('Ferdi:feature:announcements:store'); | ||
21 | |||
22 | export class AnnouncementsStore extends FeatureStore { | ||
23 | @observable targetVersion = null; | ||
24 | |||
25 | @observable isFeatureActive = false; | ||
26 | |||
27 | @computed get changelog() { | ||
28 | return getChangelogRequest.result; | ||
29 | } | ||
30 | |||
31 | @computed get announcement() { | ||
32 | if (!this.stores || !getAnnouncementRequest.result) return null; | ||
33 | const { locale } = this.stores.app; | ||
34 | const announcement = getAnnouncementRequest.result; | ||
35 | // User locale | ||
36 | if (announcement[locale]) return announcement[locale]; | ||
37 | // Default locale | ||
38 | if (announcement[DEFAULT_APP_SETTINGS.fallbackLocale]) return announcement[DEFAULT_APP_SETTINGS.fallbackLocale]; | ||
39 | // No locales specified | ||
40 | return announcement; | ||
41 | } | ||
42 | |||
43 | @computed get areNewsAvailable() { | ||
44 | const isChangelogAvailable = getChangelogRequest.wasExecuted && !!this.changelog; | ||
45 | const isAnnouncementAvailable = getAnnouncementRequest.wasExecuted && !!this.announcement; | ||
46 | return isChangelogAvailable || isAnnouncementAvailable; | ||
47 | } | ||
48 | |||
49 | @computed get settings() { | ||
50 | return localStorage.getItem(LOCAL_STORAGE_KEY) || {}; | ||
51 | } | ||
52 | |||
53 | @computed get lastSeenAnnouncementVersion() { | ||
54 | return this.settings.lastSeenAnnouncementVersion || null; | ||
55 | } | ||
56 | |||
57 | @computed get currentVersion() { | ||
58 | return getCurrentVersionRequest.result; | ||
59 | } | ||
60 | |||
61 | @computed get isNewUser() { | ||
62 | return this.stores.settings.stats.appStarts <= 1; | ||
63 | } | ||
64 | |||
65 | @computed get isAnnouncementShown() { | ||
66 | const { router } = this.stores; | ||
67 | return router.location.pathname.includes('/announcements'); | ||
68 | } | ||
69 | |||
70 | async start(stores, actions) { | ||
71 | debug('AnnouncementsStore::start'); | ||
72 | this.stores = stores; | ||
73 | this.actions = actions; | ||
74 | getCurrentVersionRequest.execute(); | ||
75 | |||
76 | this._registerActions(createActionBindings([ | ||
77 | [announcementActions.show, this._showAnnouncement], | ||
78 | ])); | ||
79 | |||
80 | this._reactions = createReactions([ | ||
81 | this._showAnnouncementOnRouteMatch, | ||
82 | this._showAnnouncementToUsersWhoUpdatedApp, | ||
83 | this._fetchAnnouncements, | ||
84 | ]); | ||
85 | this._registerReactions(this._reactions); | ||
86 | this.isFeatureActive = true; | ||
87 | } | ||
88 | |||
89 | stop() { | ||
90 | super.stop(); | ||
91 | debug('AnnouncementsStore::stop'); | ||
92 | this.isFeatureActive = false; | ||
93 | } | ||
94 | |||
95 | // ======= HELPERS ======= // | ||
96 | |||
97 | _updateSettings = (changes) => { | ||
98 | localStorage.setItem(LOCAL_STORAGE_KEY, { | ||
99 | ...this.settings, | ||
100 | ...changes, | ||
101 | }); | ||
102 | }; | ||
103 | |||
104 | // ======= ACTIONS ======= // | ||
105 | |||
106 | @action _showAnnouncement = ({ targetVersion } = {}) => { | ||
107 | const { router } = this.stores; | ||
108 | this.targetVersion = targetVersion || this.currentVersion; | ||
109 | this._updateSettings({ | ||
110 | lastSeenAnnouncementVersion: this.currentVersion, | ||
111 | }); | ||
112 | const targetRoute = `/announcements/${this.targetVersion}`; | ||
113 | if (router.location.pathname !== targetRoute) { | ||
114 | this.stores.router.push(targetRoute); | ||
115 | } | ||
116 | }; | ||
117 | |||
118 | // ======= REACTIONS ======== | ||
119 | |||
120 | _showAnnouncementToUsersWhoUpdatedApp = () => { | ||
121 | const { announcement, isNewUser } = this; | ||
122 | // Check if there is an announcement and don't show announcements to new users | ||
123 | if (!announcement || isNewUser) return; | ||
124 | |||
125 | // Check if the user has already used current version (= has seen the announcement) | ||
126 | const { currentVersion, lastSeenAnnouncementVersion } = this; | ||
127 | if (semver.gt(currentVersion, lastSeenAnnouncementVersion || '0.0.0')) { | ||
128 | debug(`${currentVersion} > ${lastSeenAnnouncementVersion}: announcement is shown`); | ||
129 | this._showAnnouncement(); | ||
130 | } | ||
131 | }; | ||
132 | |||
133 | _fetchAnnouncements = () => { | ||
134 | const targetVersion = this.targetVersion || this.currentVersion; | ||
135 | if (!targetVersion) return; | ||
136 | getChangelogRequest.reset().execute(targetVersion); | ||
137 | getAnnouncementRequest.reset().execute(targetVersion); | ||
138 | }; | ||
139 | |||
140 | _showAnnouncementOnRouteMatch = () => { | ||
141 | const { router } = this.stores; | ||
142 | const match = matchRoute(ANNOUNCEMENTS_ROUTES.TARGET, router.location.pathname); | ||
143 | if (match) { | ||
144 | const targetVersion = match.id; | ||
145 | this._showAnnouncement({ targetVersion }); | ||
146 | } | ||
147 | } | ||
148 | } | ||
diff --git a/src/features/todos/store.js b/src/features/todos/store.js index f283c1e59..ec06c279d 100644 --- a/src/features/todos/store.js +++ b/src/features/todos/store.js | |||
@@ -1,9 +1,5 @@ | |||
1 | import { ThemeType } from '@meetfranz/theme'; | 1 | import { ThemeType } from '@meetfranz/theme'; |
2 | import { | 2 | import { computed, action, observable } from 'mobx'; |
3 | computed, | ||
4 | action, | ||
5 | observable, | ||
6 | } from 'mobx'; | ||
7 | import localStorage from 'mobx-localstorage'; | 3 | import localStorage from 'mobx-localstorage'; |
8 | 4 | ||
9 | import { todoActions } from './actions'; | 5 | import { todoActions } from './actions'; |
@@ -44,12 +40,13 @@ export default class TodoStore extends FeatureStore { | |||
44 | } | 40 | } |
45 | 41 | ||
46 | @computed get isTodosPanelForceHidden() { | 42 | @computed get isTodosPanelForceHidden() { |
47 | const { isAnnouncementShown } = this.stores.announcements; | 43 | return !this.isFeatureEnabledByUser; |
48 | return !this.isFeatureEnabledByUser || isAnnouncementShown; | ||
49 | } | 44 | } |
50 | 45 | ||
51 | @computed get isTodosPanelVisible() { | 46 | @computed get isTodosPanelVisible() { |
52 | if (this.settings.isTodosPanelVisible === undefined) return DEFAULT_TODOS_VISIBLE; | 47 | if (this.settings.isTodosPanelVisible === undefined) { |
48 | return DEFAULT_TODOS_VISIBLE; | ||
49 | } | ||
53 | return this.settings.isTodosPanelVisible; | 50 | return this.settings.isTodosPanelVisible; |
54 | } | 51 | } |
55 | 52 | ||
@@ -66,7 +63,10 @@ export default class TodoStore extends FeatureStore { | |||
66 | } | 63 | } |
67 | 64 | ||
68 | @computed get isUsingPredefinedTodoServer() { | 65 | @computed get isUsingPredefinedTodoServer() { |
69 | return this.stores && this.stores.settings.app.predefinedTodoServer !== CUSTOM_TODO_SERVICE; | 66 | return ( |
67 | this.stores && | ||
68 | this.stores.settings.app.predefinedTodoServer !== CUSTOM_TODO_SERVICE | ||
69 | ); | ||
70 | } | 70 | } |
71 | 71 | ||
72 | @computed get todoUrl() { | 72 | @computed get todoUrl() { |
@@ -79,12 +79,17 @@ export default class TodoStore extends FeatureStore { | |||
79 | } | 79 | } |
80 | 80 | ||
81 | @computed get isTodoUrlValid() { | 81 | @computed get isTodoUrlValid() { |
82 | return !this.isUsingPredefinedTodoServer || isValidExternalURL(this.todoUrl); | 82 | return ( |
83 | !this.isUsingPredefinedTodoServer || isValidExternalURL(this.todoUrl) | ||
84 | ); | ||
83 | } | 85 | } |
84 | 86 | ||
85 | @computed get todoRecipeId() { | 87 | @computed get todoRecipeId() { |
86 | if (this.isFeatureEnabledByUser && this.isUsingPredefinedTodoServer | 88 | if ( |
87 | && this.todoUrl in TODO_SERVICE_RECIPE_IDS) { | 89 | this.isFeatureEnabledByUser && |
90 | this.isUsingPredefinedTodoServer && | ||
91 | this.todoUrl in TODO_SERVICE_RECIPE_IDS | ||
92 | ) { | ||
88 | return TODO_SERVICE_RECIPE_IDS[this.todoUrl]; | 93 | return TODO_SERVICE_RECIPE_IDS[this.todoUrl]; |
89 | } | 94 | } |
90 | return null; | 95 | return null; |
@@ -99,16 +104,21 @@ export default class TodoStore extends FeatureStore { | |||
99 | 104 | ||
100 | // ACTIONS | 105 | // ACTIONS |
101 | 106 | ||
102 | this._registerActions(createActionBindings([ | 107 | this._registerActions( |
103 | [todoActions.resize, this._resize], | 108 | createActionBindings([ |
104 | [todoActions.toggleTodosPanel, this._toggleTodosPanel], | 109 | [todoActions.resize, this._resize], |
105 | [todoActions.setTodosWebview, this._setTodosWebview], | 110 | [todoActions.toggleTodosPanel, this._toggleTodosPanel], |
106 | [todoActions.handleHostMessage, this._handleHostMessage], | 111 | [todoActions.setTodosWebview, this._setTodosWebview], |
107 | [todoActions.handleClientMessage, this._handleClientMessage], | 112 | [todoActions.handleHostMessage, this._handleHostMessage], |
108 | [todoActions.toggleTodosFeatureVisibility, this._toggleTodosFeatureVisibility], | 113 | [todoActions.handleClientMessage, this._handleClientMessage], |
109 | [todoActions.openDevTools, this._openDevTools], | 114 | [ |
110 | [todoActions.reload, this._reload], | 115 | todoActions.toggleTodosFeatureVisibility, |
111 | ])); | 116 | this._toggleTodosFeatureVisibility, |
117 | ], | ||
118 | [todoActions.openDevTools, this._openDevTools], | ||
119 | [todoActions.reload, this._reload], | ||
120 | ]), | ||
121 | ); | ||
112 | 122 | ||
113 | // REACTIONS | 123 | // REACTIONS |
114 | 124 | ||
@@ -133,7 +143,7 @@ export default class TodoStore extends FeatureStore { | |||
133 | 143 | ||
134 | // ========== PRIVATE METHODS ========= // | 144 | // ========== PRIVATE METHODS ========= // |
135 | 145 | ||
136 | _updateSettings = (changes) => { | 146 | _updateSettings = changes => { |
137 | localStorage.setItem('todos', { | 147 | localStorage.setItem('todos', { |
138 | ...this.settings, | 148 | ...this.settings, |
139 | ...changes, | 149 | ...changes, |
@@ -162,7 +172,7 @@ export default class TodoStore extends FeatureStore { | |||
162 | } | 172 | } |
163 | }; | 173 | }; |
164 | 174 | ||
165 | @action _handleHostMessage = (message) => { | 175 | @action _handleHostMessage = message => { |
166 | debug('_handleHostMessage', message); | 176 | debug('_handleHostMessage', message); |
167 | if (message.action === 'todos:create') { | 177 | if (message.action === 'todos:create') { |
168 | this.webview.send(IPC.TODOS_HOST_CHANNEL, message); | 178 | this.webview.send(IPC.TODOS_HOST_CHANNEL, message); |
@@ -172,11 +182,18 @@ export default class TodoStore extends FeatureStore { | |||
172 | @action _handleClientMessage = ({ channel, message = {} }) => { | 182 | @action _handleClientMessage = ({ channel, message = {} }) => { |
173 | debug('_handleClientMessage', channel, message); | 183 | debug('_handleClientMessage', channel, message); |
174 | switch (message.action) { | 184 | switch (message.action) { |
175 | case 'todos:initialized': this._onTodosClientInitialized(); break; | 185 | case 'todos:initialized': |
176 | case 'todos:goToService': this._goToService(message.data); break; | 186 | this._onTodosClientInitialized(); |
187 | break; | ||
188 | case 'todos:goToService': | ||
189 | this._goToService(message.data); | ||
190 | break; | ||
177 | default: | 191 | default: |
178 | debug('Other message received', channel, message); | 192 | debug('Other message received', channel, message); |
179 | console.log('this.stores.services.isTodosServiceAdded', this.stores.services.isTodosServiceAdded); | 193 | console.log( |
194 | 'this.stores.services.isTodosServiceAdded', | ||
195 | this.stores.services.isTodosServiceAdded, | ||
196 | ); | ||
180 | if (this.stores.services.isTodosServiceAdded) { | 197 | if (this.stores.services.isTodosServiceAdded) { |
181 | this.actions.service.handleIPCMessage({ | 198 | this.actions.service.handleIPCMessage({ |
182 | serviceId: this.stores.services.isTodosServiceAdded.id, | 199 | serviceId: this.stores.services.isTodosServiceAdded.id, |
@@ -189,7 +206,7 @@ export default class TodoStore extends FeatureStore { | |||
189 | 206 | ||
190 | _handleNewWindowEvent = ({ url }) => { | 207 | _handleNewWindowEvent = ({ url }) => { |
191 | this.actions.app.openExternalUrl({ url }); | 208 | this.actions.app.openExternalUrl({ url }); |
192 | } | 209 | }; |
193 | 210 | ||
194 | @action _toggleTodosFeatureVisibility = () => { | 211 | @action _toggleTodosFeatureVisibility = () => { |
195 | debug('_toggleTodosFeatureVisibility'); | 212 | debug('_toggleTodosFeatureVisibility'); |
@@ -204,14 +221,14 @@ export default class TodoStore extends FeatureStore { | |||
204 | 221 | ||
205 | const webview = document.querySelector('#todos-panel webview'); | 222 | const webview = document.querySelector('#todos-panel webview'); |
206 | if (webview) webview.openDevTools(); | 223 | if (webview) webview.openDevTools(); |
207 | } | 224 | }; |
208 | 225 | ||
209 | _reload = () => { | 226 | _reload = () => { |
210 | debug('_reload'); | 227 | debug('_reload'); |
211 | 228 | ||
212 | const webview = document.querySelector('#todos-panel webview'); | 229 | const webview = document.querySelector('#todos-panel webview'); |
213 | if (webview) webview.reload(); | 230 | if (webview) webview.reload(); |
214 | } | 231 | }; |
215 | 232 | ||
216 | // Todos client message handlers | 233 | // Todos client message handlers |
217 | 234 | ||
@@ -291,5 +308,5 @@ export default class TodoStore extends FeatureStore { | |||
291 | }); | 308 | }); |
292 | } | 309 | } |
293 | } | 310 | } |
294 | } | 311 | }; |
295 | } | 312 | } |
diff --git a/src/features/workspaces/components/WorkspacesDashboard.js b/src/features/workspaces/components/WorkspacesDashboard.js index 8319d3bc6..5f34204f1 100644 --- a/src/features/workspaces/components/WorkspacesDashboard.js +++ b/src/features/workspaces/components/WorkspacesDashboard.js | |||
@@ -20,7 +20,7 @@ const messages = defineMessages({ | |||
20 | }, | 20 | }, |
21 | noServicesAdded: { | 21 | noServicesAdded: { |
22 | id: 'settings.workspaces.noWorkspacesAdded', | 22 | id: 'settings.workspaces.noWorkspacesAdded', |
23 | defaultMessage: '!!!You haven\'t created any workspaces yet.', | 23 | defaultMessage: "!!!You haven't created any workspaces yet.", |
24 | }, | 24 | }, |
25 | workspacesRequestFailed: { | 25 | workspacesRequestFailed: { |
26 | id: 'settings.workspaces.workspacesRequestFailed', | 26 | id: 'settings.workspaces.workspacesRequestFailed', |
@@ -61,9 +61,6 @@ const styles = () => ({ | |||
61 | appear: { | 61 | appear: { |
62 | height: 'auto', | 62 | height: 'auto', |
63 | }, | 63 | }, |
64 | announcementHeadline: { | ||
65 | marginBottom: 0, | ||
66 | }, | ||
67 | teaserImage: { | 64 | teaserImage: { |
68 | width: 250, | 65 | width: 250, |
69 | margin: [-8, 0, 0, 20], | 66 | margin: [-8, 0, 0, 20], |
@@ -71,7 +68,9 @@ const styles = () => ({ | |||
71 | }, | 68 | }, |
72 | }); | 69 | }); |
73 | 70 | ||
74 | @inject('stores') @injectSheet(styles) @observer | 71 | @inject('stores') |
72 | @injectSheet(styles) | ||
73 | @observer | ||
75 | class WorkspacesDashboard extends Component { | 74 | class WorkspacesDashboard extends Component { |
76 | static propTypes = { | 75 | static propTypes = { |
77 | classes: PropTypes.object.isRequired, | 76 | classes: PropTypes.object.isRequired, |
@@ -108,7 +107,6 @@ class WorkspacesDashboard extends Component { | |||
108 | <h1>{intl.formatMessage(messages.headline)}</h1> | 107 | <h1>{intl.formatMessage(messages.headline)}</h1> |
109 | </div> | 108 | </div> |
110 | <div className="settings__body"> | 109 | <div className="settings__body"> |
111 | |||
112 | {/* ===== Workspace updated info ===== */} | 110 | {/* ===== Workspace updated info ===== */} |
113 | {updateWorkspaceRequest.wasExecuted && updateWorkspaceRequest.result && ( | 111 | {updateWorkspaceRequest.wasExecuted && updateWorkspaceRequest.result && ( |
114 | <Appear className={classes.appear}> | 112 | <Appear className={classes.appear}> |
@@ -175,11 +173,11 @@ class WorkspacesDashboard extends Component { | |||
175 | <table className={classes.table}> | 173 | <table className={classes.table}> |
176 | {/* ===== Workspaces list ===== */} | 174 | {/* ===== Workspaces list ===== */} |
177 | <tbody> | 175 | <tbody> |
178 | {workspaces.map((workspace) => ( | 176 | {workspaces.map(workspace => ( |
179 | <WorkspaceItem | 177 | <WorkspaceItem |
180 | key={workspace.id} | 178 | key={workspace.id} |
181 | workspace={workspace} | 179 | workspace={workspace} |
182 | onItemClick={(w) => onWorkspaceClick(w)} | 180 | onItemClick={w => onWorkspaceClick(w)} |
183 | /> | 181 | /> |
184 | ))} | 182 | ))} |
185 | </tbody> | 183 | </tbody> |