diff options
-rw-r--r-- | packages/theme/src/themes/dark/index.ts | 2 | ||||
-rw-r--r-- | src/actions/service.js | 1 | ||||
-rw-r--r-- | src/app.js | 3 | ||||
-rw-r--r-- | src/components/layout/AppLayout.js | 5 | ||||
-rw-r--r-- | src/containers/layout/AppLayoutContainer.js | 1 | ||||
-rw-r--r-- | src/features/announcements/components/AnnouncementScreen.js | 2 | ||||
-rw-r--r-- | src/features/announcements/index.js | 4 | ||||
-rw-r--r-- | src/features/announcements/store.js | 41 | ||||
-rw-r--r-- | src/features/workspaces/store.js | 8 | ||||
-rw-r--r-- | src/stores/ServicesStore.js | 3 |
10 files changed, 38 insertions, 32 deletions
diff --git a/packages/theme/src/themes/dark/index.ts b/packages/theme/src/themes/dark/index.ts index d48dbf916..bd9f001e8 100644 --- a/packages/theme/src/themes/dark/index.ts +++ b/packages/theme/src/themes/dark/index.ts | |||
@@ -113,7 +113,7 @@ export const workspaces = merge({}, defaultStyles.workspaces, { | |||
113 | }); | 113 | }); |
114 | 114 | ||
115 | // Announcements | 115 | // Announcements |
116 | export const announcements = merge({}, defaultStyles.workspaces, { | 116 | export const announcements = merge({}, defaultStyles.announcements, { |
117 | spotlight: { | 117 | spotlight: { |
118 | background: legacyStyles.darkThemeGrayDark, | 118 | background: legacyStyles.darkThemeGrayDark, |
119 | }, | 119 | }, |
diff --git a/src/actions/service.js b/src/actions/service.js index ce62560a9..68c62d594 100644 --- a/src/actions/service.js +++ b/src/actions/service.js | |||
@@ -4,6 +4,7 @@ import ServiceModel from '../models/Service'; | |||
4 | export default { | 4 | export default { |
5 | setActive: { | 5 | setActive: { |
6 | serviceId: PropTypes.string.isRequired, | 6 | serviceId: PropTypes.string.isRequired, |
7 | keepActiveRoute: PropTypes.bool, | ||
7 | }, | 8 | }, |
8 | blurActive: {}, | 9 | blurActive: {}, |
9 | setActiveNext: {}, | 10 | setActiveNext: {}, |
diff --git a/src/app.js b/src/app.js index f6092bf60..cb3e37c64 100644 --- a/src/app.js +++ b/src/app.js | |||
@@ -43,6 +43,8 @@ import SubscriptionPopupScreen from './containers/subscription/SubscriptionPopup | |||
43 | import WorkspacesScreen from './features/workspaces/containers/WorkspacesScreen'; | 43 | import WorkspacesScreen from './features/workspaces/containers/WorkspacesScreen'; |
44 | import EditWorkspaceScreen from './features/workspaces/containers/EditWorkspaceScreen'; | 44 | import EditWorkspaceScreen from './features/workspaces/containers/EditWorkspaceScreen'; |
45 | import { WORKSPACES_ROUTES } from './features/workspaces'; | 45 | import { WORKSPACES_ROUTES } from './features/workspaces'; |
46 | import AnnouncementScreen from './features/announcements/components/AnnouncementScreen'; | ||
47 | import { ANNOUNCEMENTS_ROUTES } from './features/announcements'; | ||
46 | 48 | ||
47 | // Add Polyfills | 49 | // Add Polyfills |
48 | smoothScroll.polyfill(); | 50 | smoothScroll.polyfill(); |
@@ -73,6 +75,7 @@ window.addEventListener('load', () => { | |||
73 | <I18N> | 75 | <I18N> |
74 | <Router history={history}> | 76 | <Router history={history}> |
75 | <Route path="/" component={AppLayoutContainer}> | 77 | <Route path="/" component={AppLayoutContainer}> |
78 | <Route path={ANNOUNCEMENTS_ROUTES.TARGET} component={AnnouncementScreen} /> | ||
76 | <Route path="/settings" component={SettingsWindow}> | 79 | <Route path="/settings" component={SettingsWindow}> |
77 | <IndexRedirect to="/settings/recipes" /> | 80 | <IndexRedirect to="/settings/recipes" /> |
78 | <Route path="/settings/recipes" component={RecipesScreen} /> | 81 | <Route path="/settings/recipes" component={RecipesScreen} /> |
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js index d5febfaf4..fa83842a4 100644 --- a/src/components/layout/AppLayout.js +++ b/src/components/layout/AppLayout.js | |||
@@ -83,7 +83,6 @@ class AppLayout extends Component { | |||
83 | areRequiredRequestsLoading: PropTypes.bool.isRequired, | 83 | areRequiredRequestsLoading: PropTypes.bool.isRequired, |
84 | darkMode: PropTypes.bool.isRequired, | 84 | darkMode: PropTypes.bool.isRequired, |
85 | isDelayAppScreenVisible: PropTypes.bool.isRequired, | 85 | isDelayAppScreenVisible: PropTypes.bool.isRequired, |
86 | isAnnouncementVisible: PropTypes.bool.isRequired, | ||
87 | }; | 86 | }; |
88 | 87 | ||
89 | static defaultProps = { | 88 | static defaultProps = { |
@@ -117,7 +116,6 @@ class AppLayout extends Component { | |||
117 | areRequiredRequestsLoading, | 116 | areRequiredRequestsLoading, |
118 | darkMode, | 117 | darkMode, |
119 | isDelayAppScreenVisible, | 118 | isDelayAppScreenVisible, |
120 | isAnnouncementVisible, | ||
121 | } = this.props; | 119 | } = this.props; |
122 | 120 | ||
123 | const { intl } = this.context; | 121 | const { intl } = this.context; |
@@ -197,12 +195,11 @@ class AppLayout extends Component { | |||
197 | {isDelayAppScreenVisible && (<DelayApp />)} | 195 | {isDelayAppScreenVisible && (<DelayApp />)} |
198 | <BasicAuth /> | 196 | <BasicAuth /> |
199 | <ShareFranz /> | 197 | <ShareFranz /> |
200 | {isAnnouncementVisible && (<AnnouncementScreen />)} | ||
201 | {services} | 198 | {services} |
199 | {children} | ||
202 | </div> | 200 | </div> |
203 | </div> | 201 | </div> |
204 | </div> | 202 | </div> |
205 | {children} | ||
206 | </div> | 203 | </div> |
207 | </ErrorBoundary> | 204 | </ErrorBoundary> |
208 | ); | 205 | ); |
diff --git a/src/containers/layout/AppLayoutContainer.js b/src/containers/layout/AppLayoutContainer.js index d2891a6a4..83b3c27da 100644 --- a/src/containers/layout/AppLayoutContainer.js +++ b/src/containers/layout/AppLayoutContainer.js | |||
@@ -151,7 +151,6 @@ export default @inject('stores', 'actions') @observer class AppLayoutContainer e | |||
151 | areRequiredRequestsLoading={requests.areRequiredRequestsLoading} | 151 | areRequiredRequestsLoading={requests.areRequiredRequestsLoading} |
152 | darkMode={settings.all.app.darkMode} | 152 | darkMode={settings.all.app.darkMode} |
153 | isDelayAppScreenVisible={delayAppState.isDelayAppScreenVisible} | 153 | isDelayAppScreenVisible={delayAppState.isDelayAppScreenVisible} |
154 | isAnnouncementVisible={announcementsStore.isAnnouncementVisible} | ||
155 | > | 154 | > |
156 | {React.Children.count(children) > 0 ? children : null} | 155 | {React.Children.count(children) > 0 ? children : null} |
157 | </AppLayout> | 156 | </AppLayout> |
diff --git a/src/features/announcements/components/AnnouncementScreen.js b/src/features/announcements/components/AnnouncementScreen.js index dfce6cdd5..e7c5fe395 100644 --- a/src/features/announcements/components/AnnouncementScreen.js +++ b/src/features/announcements/components/AnnouncementScreen.js | |||
@@ -268,7 +268,7 @@ class AnnouncementScreen extends Component { | |||
268 | <div className={classes.changelog}> | 268 | <div className={classes.changelog}> |
269 | <h1 className={classes.headline}> | 269 | <h1 className={classes.headline}> |
270 | {intl.formatMessage(messages.headline, { | 270 | {intl.formatMessage(messages.headline, { |
271 | version: announcementsStore.currentVersion, | 271 | version: announcementsStore.targetVersion, |
272 | })} | 272 | })} |
273 | </h1> | 273 | </h1> |
274 | <div | 274 | <div |
diff --git a/src/features/announcements/index.js b/src/features/announcements/index.js index 4658b976f..f14e7c9a5 100644 --- a/src/features/announcements/index.js +++ b/src/features/announcements/index.js | |||
@@ -7,6 +7,10 @@ export const GA_CATEGORY_ANNOUNCEMENTS = 'Announcements'; | |||
7 | 7 | ||
8 | export const announcementsStore = new AnnouncementsStore(); | 8 | export const announcementsStore = new AnnouncementsStore(); |
9 | 9 | ||
10 | export const ANNOUNCEMENTS_ROUTES = { | ||
11 | TARGET: '/announcements/:id', | ||
12 | }; | ||
13 | |||
10 | export default function initAnnouncements(stores, actions) { | 14 | export default function initAnnouncements(stores, actions) { |
11 | // const { features } = stores; | 15 | // const { features } = stores; |
12 | 16 | ||
diff --git a/src/features/announcements/store.js b/src/features/announcements/store.js index 6e7ca1dd7..27be86144 100644 --- a/src/features/announcements/store.js +++ b/src/features/announcements/store.js | |||
@@ -8,12 +8,13 @@ import semver from 'semver'; | |||
8 | import localStorage from 'mobx-localstorage'; | 8 | import localStorage from 'mobx-localstorage'; |
9 | 9 | ||
10 | import { FeatureStore } from '../utils/FeatureStore'; | 10 | import { FeatureStore } from '../utils/FeatureStore'; |
11 | import { GA_CATEGORY_ANNOUNCEMENTS } from '.'; | 11 | import { ANNOUNCEMENTS_ROUTES, GA_CATEGORY_ANNOUNCEMENTS } from '.'; |
12 | import { getAnnouncementRequest, getChangelogRequest, getCurrentVersionRequest } from './api'; | 12 | import { getAnnouncementRequest, getChangelogRequest, getCurrentVersionRequest } from './api'; |
13 | import { announcementActions } from './actions'; | 13 | import { announcementActions } from './actions'; |
14 | import { createActionBindings } from '../utils/ActionBinding'; | 14 | import { createActionBindings } from '../utils/ActionBinding'; |
15 | import { createReactions } from '../../stores/lib/Reaction'; | 15 | import { createReactions } from '../../stores/lib/Reaction'; |
16 | import { gaEvent } from '../../lib/analytics'; | 16 | import { gaEvent } from '../../lib/analytics'; |
17 | import { matchRoute } from '../../helpers/routing-helpers'; | ||
17 | 18 | ||
18 | const LOCAL_STORAGE_KEY = 'announcements'; | 19 | const LOCAL_STORAGE_KEY = 'announcements'; |
19 | 20 | ||
@@ -22,8 +23,6 @@ const debug = require('debug')('Franz:feature:announcements:store'); | |||
22 | export class AnnouncementsStore extends FeatureStore { | 23 | export class AnnouncementsStore extends FeatureStore { |
23 | @observable targetVersion = null; | 24 | @observable targetVersion = null; |
24 | 25 | ||
25 | @observable isAnnouncementVisible = false; | ||
26 | |||
27 | @observable isFeatureActive = false; | 26 | @observable isFeatureActive = false; |
28 | 27 | ||
29 | @computed get changelog() { | 28 | @computed get changelog() { |
@@ -37,6 +36,7 @@ export class AnnouncementsStore extends FeatureStore { | |||
37 | @computed get areNewsAvailable() { | 36 | @computed get areNewsAvailable() { |
38 | const isChangelogAvailable = getChangelogRequest.wasExecuted && !!this.changelog; | 37 | const isChangelogAvailable = getChangelogRequest.wasExecuted && !!this.changelog; |
39 | const isAnnouncementAvailable = getAnnouncementRequest.wasExecuted && !!this.announcement; | 38 | const isAnnouncementAvailable = getAnnouncementRequest.wasExecuted && !!this.announcement; |
39 | console.log(isChangelogAvailable, isAnnouncementAvailable); | ||
40 | return isChangelogAvailable || isAnnouncementAvailable; | 40 | return isChangelogAvailable || isAnnouncementAvailable; |
41 | } | 41 | } |
42 | 42 | ||
@@ -67,8 +67,9 @@ export class AnnouncementsStore extends FeatureStore { | |||
67 | ])); | 67 | ])); |
68 | 68 | ||
69 | this._reactions = createReactions([ | 69 | this._reactions = createReactions([ |
70 | this._fetchAnnouncements, | 70 | this._showAnnouncementOnRouteMatch, |
71 | this._showAnnouncementToUsersWhoUpdatedApp, | 71 | this._showAnnouncementToUsersWhoUpdatedApp, |
72 | this._fetchAnnouncements, | ||
72 | ]); | 73 | ]); |
73 | this._registerReactions(this._reactions); | 74 | this._registerReactions(this._reactions); |
74 | this.isFeatureActive = true; | 75 | this.isFeatureActive = true; |
@@ -78,7 +79,6 @@ export class AnnouncementsStore extends FeatureStore { | |||
78 | super.stop(); | 79 | super.stop(); |
79 | debug('AnnouncementsStore::stop'); | 80 | debug('AnnouncementsStore::stop'); |
80 | this.isFeatureActive = false; | 81 | this.isFeatureActive = false; |
81 | this.isAnnouncementVisible = false; | ||
82 | } | 82 | } |
83 | 83 | ||
84 | // ======= HELPERS ======= // | 84 | // ======= HELPERS ======= // |
@@ -93,33 +93,23 @@ export class AnnouncementsStore extends FeatureStore { | |||
93 | // ======= ACTIONS ======= // | 93 | // ======= ACTIONS ======= // |
94 | 94 | ||
95 | @action _showAnnouncement = ({ targetVersion } = {}) => { | 95 | @action _showAnnouncement = ({ targetVersion } = {}) => { |
96 | if (!this.areNewsAvailable) return; | 96 | const { router } = this.stores; |
97 | this.targetVersion = targetVersion || this.currentVersion; | 97 | this.targetVersion = targetVersion || this.currentVersion; |
98 | this.isAnnouncementVisible = true; | ||
99 | this.actions.service.blurActive(); | ||
100 | this._updateSettings({ | 98 | this._updateSettings({ |
101 | lastSeenAnnouncementVersion: this.currentVersion, | 99 | lastSeenAnnouncementVersion: this.currentVersion, |
102 | }); | 100 | }); |
103 | const dispose = reaction( | 101 | const targetRoute = `/announcements/${this.targetVersion}`; |
104 | () => this.stores.services.active, | 102 | if (router.location.pathname !== targetRoute) { |
105 | () => { | 103 | this.stores.router.push(targetRoute); |
106 | this._hideAnnouncement(); | 104 | } |
107 | dispose(); | ||
108 | }, | ||
109 | ); | ||
110 | |||
111 | gaEvent(GA_CATEGORY_ANNOUNCEMENTS, 'show'); | 105 | gaEvent(GA_CATEGORY_ANNOUNCEMENTS, 'show'); |
112 | }; | 106 | }; |
113 | 107 | ||
114 | @action _hideAnnouncement() { | ||
115 | this.isAnnouncementVisible = false; | ||
116 | } | ||
117 | |||
118 | // ======= REACTIONS ======== | 108 | // ======= REACTIONS ======== |
119 | 109 | ||
120 | _showAnnouncementToUsersWhoUpdatedApp = () => { | 110 | _showAnnouncementToUsersWhoUpdatedApp = () => { |
121 | const { announcement, isNewUser } = this; | 111 | const { announcement, isNewUser } = this; |
122 | // Check if there is an announcement and on't show announcements to new users | 112 | // Check if there is an announcement and don't show announcements to new users |
123 | if (!announcement || isNewUser) return; | 113 | if (!announcement || isNewUser) return; |
124 | 114 | ||
125 | // Check if the user has already used current version (= has seen the announcement) | 115 | // Check if the user has already used current version (= has seen the announcement) |
@@ -140,5 +130,14 @@ export class AnnouncementsStore extends FeatureStore { | |||
140 | } else { | 130 | } else { |
141 | getAnnouncementRequest.reset(); | 131 | getAnnouncementRequest.reset(); |
142 | } | 132 | } |
133 | }; | ||
134 | |||
135 | _showAnnouncementOnRouteMatch = () => { | ||
136 | const { router } = this.stores; | ||
137 | const match = matchRoute(ANNOUNCEMENTS_ROUTES.TARGET, router.location.pathname); | ||
138 | if (match) { | ||
139 | const targetVersion = match.id; | ||
140 | this._showAnnouncement({ targetVersion }); | ||
141 | } | ||
143 | } | 142 | } |
144 | } | 143 | } |
diff --git a/src/features/workspaces/store.js b/src/features/workspaces/store.js index e11513d1f..3d7043413 100644 --- a/src/features/workspaces/store.js +++ b/src/features/workspaces/store.js | |||
@@ -255,13 +255,15 @@ export default class WorkspacesStore extends FeatureStore { | |||
255 | _setActiveServiceOnWorkspaceSwitchReaction = () => { | 255 | _setActiveServiceOnWorkspaceSwitchReaction = () => { |
256 | if (!this.isFeatureActive) return; | 256 | if (!this.isFeatureActive) return; |
257 | if (this.activeWorkspace) { | 257 | if (this.activeWorkspace) { |
258 | const services = this.stores.services.allDisplayed; | 258 | const activeService = this.stores.services.active; |
259 | const activeService = services.find(s => s.isActive); | ||
260 | const workspaceServices = this.getWorkspaceServices(this.activeWorkspace); | 259 | const workspaceServices = this.getWorkspaceServices(this.activeWorkspace); |
261 | if (workspaceServices.length <= 0) return; | 260 | if (workspaceServices.length <= 0) return; |
262 | const isActiveServiceInWorkspace = workspaceServices.includes(activeService); | 261 | const isActiveServiceInWorkspace = workspaceServices.includes(activeService); |
263 | if (!isActiveServiceInWorkspace) { | 262 | if (!isActiveServiceInWorkspace) { |
264 | this.actions.service.setActive({ serviceId: workspaceServices[0].id }); | 263 | this.actions.service.setActive({ |
264 | serviceId: workspaceServices[0].id, | ||
265 | keepActiveRoute: true, | ||
266 | }); | ||
265 | } | 267 | } |
266 | } | 268 | } |
267 | }; | 269 | }; |
diff --git a/src/stores/ServicesStore.js b/src/stores/ServicesStore.js index 13f929c2f..17150a023 100644 --- a/src/stores/ServicesStore.js +++ b/src/stores/ServicesStore.js | |||
@@ -291,7 +291,8 @@ export default class ServicesStore extends Store { | |||
291 | gaEvent('Service', 'clear cache'); | 291 | gaEvent('Service', 'clear cache'); |
292 | } | 292 | } |
293 | 293 | ||
294 | @action _setActive({ serviceId }) { | 294 | @action _setActive({ serviceId, keepActiveRoute }) { |
295 | if (!keepActiveRoute) this.stores.router.push('/'); | ||
295 | const service = this.one(serviceId); | 296 | const service = this.one(serviceId); |
296 | 297 | ||
297 | this.all.forEach((s, index) => { | 298 | this.all.forEach((s, index) => { |