aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/theme/src/themes/dark/index.ts2
-rw-r--r--src/actions/service.js1
-rw-r--r--src/app.js3
-rw-r--r--src/components/layout/AppLayout.js5
-rw-r--r--src/containers/layout/AppLayoutContainer.js1
-rw-r--r--src/features/announcements/components/AnnouncementScreen.js2
-rw-r--r--src/features/announcements/index.js4
-rw-r--r--src/features/announcements/store.js41
-rw-r--r--src/features/workspaces/store.js8
-rw-r--r--src/stores/ServicesStore.js3
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
116export const announcements = merge({}, defaultStyles.workspaces, { 116export 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';
4export default { 4export 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
43import WorkspacesScreen from './features/workspaces/containers/WorkspacesScreen'; 43import WorkspacesScreen from './features/workspaces/containers/WorkspacesScreen';
44import EditWorkspaceScreen from './features/workspaces/containers/EditWorkspaceScreen'; 44import EditWorkspaceScreen from './features/workspaces/containers/EditWorkspaceScreen';
45import { WORKSPACES_ROUTES } from './features/workspaces'; 45import { WORKSPACES_ROUTES } from './features/workspaces';
46import AnnouncementScreen from './features/announcements/components/AnnouncementScreen';
47import { ANNOUNCEMENTS_ROUTES } from './features/announcements';
46 48
47// Add Polyfills 49// Add Polyfills
48smoothScroll.polyfill(); 50smoothScroll.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
8export const announcementsStore = new AnnouncementsStore(); 8export const announcementsStore = new AnnouncementsStore();
9 9
10export const ANNOUNCEMENTS_ROUTES = {
11 TARGET: '/announcements/:id',
12};
13
10export default function initAnnouncements(stores, actions) { 14export 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';
8import localStorage from 'mobx-localstorage'; 8import localStorage from 'mobx-localstorage';
9 9
10import { FeatureStore } from '../utils/FeatureStore'; 10import { FeatureStore } from '../utils/FeatureStore';
11import { GA_CATEGORY_ANNOUNCEMENTS } from '.'; 11import { ANNOUNCEMENTS_ROUTES, GA_CATEGORY_ANNOUNCEMENTS } from '.';
12import { getAnnouncementRequest, getChangelogRequest, getCurrentVersionRequest } from './api'; 12import { getAnnouncementRequest, getChangelogRequest, getCurrentVersionRequest } from './api';
13import { announcementActions } from './actions'; 13import { announcementActions } from './actions';
14import { createActionBindings } from '../utils/ActionBinding'; 14import { createActionBindings } from '../utils/ActionBinding';
15import { createReactions } from '../../stores/lib/Reaction'; 15import { createReactions } from '../../stores/lib/Reaction';
16import { gaEvent } from '../../lib/analytics'; 16import { gaEvent } from '../../lib/analytics';
17import { matchRoute } from '../../helpers/routing-helpers';
17 18
18const LOCAL_STORAGE_KEY = 'announcements'; 19const LOCAL_STORAGE_KEY = 'announcements';
19 20
@@ -22,8 +23,6 @@ const debug = require('debug')('Franz:feature:announcements:store');
22export class AnnouncementsStore extends FeatureStore { 23export 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) => {