aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/components/settings/navigation/SettingsNavigation.js50
-rw-r--r--src/components/ui/AppLoader/index.js9
-rw-r--r--src/containers/auth/AuthLayoutContainer.js13
-rw-r--r--src/i18n/locales/defaultMessages.json32
-rw-r--r--src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json32
-rw-r--r--src/stores/UserStore.js2
6 files changed, 99 insertions, 39 deletions
diff --git a/src/components/settings/navigation/SettingsNavigation.js b/src/components/settings/navigation/SettingsNavigation.js
index 2711bc107..49e73e569 100644
--- a/src/components/settings/navigation/SettingsNavigation.js
+++ b/src/components/settings/navigation/SettingsNavigation.js
@@ -3,10 +3,13 @@ import PropTypes from 'prop-types';
3import { defineMessages, intlShape } from 'react-intl'; 3import { defineMessages, intlShape } from 'react-intl';
4import { inject, observer } from 'mobx-react'; 4import { inject, observer } from 'mobx-react';
5import { ProBadge } from '@meetfranz/ui'; 5import { ProBadge } from '@meetfranz/ui';
6import { RouterStore } from 'mobx-react-router';
6 7
8import { LOCAL_SERVER, LIVE_API } from '../../../config';
7import Link from '../../ui/Link'; 9import Link from '../../ui/Link';
8import { workspaceStore } from '../../../features/workspaces'; 10import { workspaceStore } from '../../../features/workspaces';
9import UIStore from '../../../stores/UIStore'; 11import UIStore from '../../../stores/UIStore';
12import SettingsStore from '../../../stores/SettingsStore';
10import UserStore from '../../../stores/UserStore'; 13import UserStore from '../../../stores/UserStore';
11import { serviceLimitStore } from '../../../features/serviceLimit'; 14import { serviceLimitStore } from '../../../features/serviceLimit';
12 15
@@ -45,11 +48,18 @@ const messages = defineMessages({
45 }, 48 },
46}); 49});
47 50
48export default @inject('stores') @observer class SettingsNavigation extends Component { 51export default @inject('stores', 'actions') @observer class SettingsNavigation extends Component {
49 static propTypes = { 52 static propTypes = {
50 stores: PropTypes.shape({ 53 stores: PropTypes.shape({
51 ui: PropTypes.instanceOf(UIStore).isRequired, 54 ui: PropTypes.instanceOf(UIStore).isRequired,
52 user: PropTypes.instanceOf(UserStore).isRequired, 55 user: PropTypes.instanceOf(UserStore).isRequired,
56 settings: PropTypes.instanceOf(SettingsStore).isRequired,
57 router: PropTypes.instanceOf(RouterStore).isRequired,
58 }).isRequired,
59 actions: PropTypes.shape({
60 settings: PropTypes.shape({
61 update: PropTypes.func.isRequired,
62 }).isRequired,
53 }).isRequired, 63 }).isRequired,
54 serviceCount: PropTypes.number.isRequired, 64 serviceCount: PropTypes.number.isRequired,
55 workspaceCount: PropTypes.number.isRequired, 65 workspaceCount: PropTypes.number.isRequired,
@@ -59,12 +69,42 @@ export default @inject('stores') @observer class SettingsNavigation extends Comp
59 intl: intlShape, 69 intl: intlShape,
60 }; 70 };
61 71
72 handleLoginLogout() {
73 const isLoggedIn = Boolean(localStorage.getItem('authToken'));
74 const isUsingWithoutAccount = this.props.stores.settings.app.server === LOCAL_SERVER;
75
76 if (isLoggedIn) {
77 // Remove current auth token
78 localStorage.removeItem('authToken');
79
80 if (isUsingWithoutAccount) {
81 // Reset server back to Ferdi API
82 this.props.actions.settings.update({
83 type: 'app',
84 data: {
85 server: LIVE_API,
86 },
87 });
88 }
89 }
90
91 this.props.stores.user.isLoggingOut = true;
92 this.props.stores.router.push(isLoggedIn ? '/auth/logout' : '/auth/welcome');
93
94 if (isLoggedIn) {
95 // Reload Ferdi, otherwise many settings won't sync correctly with the server
96 // after logging into another account
97 window.location.reload();
98 }
99 }
100
62 render() { 101 render() {
63 const { serviceCount, workspaceCount, stores } = this.props; 102 const { serviceCount, workspaceCount, stores } = this.props;
64 const { isDarkThemeActive } = stores.ui; 103 const { isDarkThemeActive } = stores.ui;
65 const { router, user } = stores; 104 const { router, user } = stores;
66 const { intl } = this.context; 105 const { intl } = this.context;
67 const isLoggedIn = Boolean(localStorage.getItem('authToken')); 106 const isLoggedIn = Boolean(localStorage.getItem('authToken'));
107 const isUsingWithoutAccount = stores.settings.app.server === LOCAL_SERVER;
68 108
69 return ( 109 return (
70 <div className="settings-navigation"> 110 <div className="settings-navigation">
@@ -136,12 +176,14 @@ export default @inject('stores') @observer class SettingsNavigation extends Comp
136 {intl.formatMessage(messages.supportFerdi)} 176 {intl.formatMessage(messages.supportFerdi)}
137 </Link> 177 </Link>
138 <span className="settings-navigation__expander" /> 178 <span className="settings-navigation__expander" />
139 <Link 179 <button
180 type="button"
140 to={isLoggedIn ? '/auth/logout' : '/auth/welcome'} 181 to={isLoggedIn ? '/auth/logout' : '/auth/welcome'}
141 className="settings-navigation__link" 182 className="settings-navigation__link"
183 onClick={this.handleLoginLogout.bind(this)}
142 > 184 >
143 { isLoggedIn ? intl.formatMessage(messages.logout) : 'Login'} 185 { isLoggedIn && !isUsingWithoutAccount ? intl.formatMessage(messages.logout) : 'Login'}
144 </Link> 186 </button>
145 </div> 187 </div>
146 ); 188 );
147 } 189 }
diff --git a/src/components/ui/AppLoader/index.js b/src/components/ui/AppLoader/index.js
index 1fd247d17..a7f6f4545 100644
--- a/src/components/ui/AppLoader/index.js
+++ b/src/components/ui/AppLoader/index.js
@@ -22,8 +22,13 @@ export default @injectSheet(styles) @withTheme class AppLoader extends Component
22 static propTypes = { 22 static propTypes = {
23 classes: PropTypes.object.isRequired, 23 classes: PropTypes.object.isRequired,
24 theme: PropTypes.object.isRequired, 24 theme: PropTypes.object.isRequired,
25 texts: PropTypes.array,
25 }; 26 };
26 27
28 static defaultProps = {
29 texts: textList,
30 }
31
27 state = { 32 state = {
28 step: 0, 33 step: 0,
29 }; 34 };
@@ -43,7 +48,7 @@ export default @injectSheet(styles) @withTheme class AppLoader extends Component
43 } 48 }
44 49
45 render() { 50 render() {
46 const { classes, theme } = this.props; 51 const { classes, theme, texts } = this.props;
47 const { step } = this.state; 52 const { step } = this.state;
48 53
49 return ( 54 return (
@@ -52,7 +57,7 @@ export default @injectSheet(styles) @withTheme class AppLoader extends Component
52 className={classes.component} 57 className={classes.component}
53 spinnerColor={theme.colorAppLoaderSpinner} 58 spinnerColor={theme.colorAppLoaderSpinner}
54 > 59 >
55 {textList.map((text, i) => ( 60 {texts.map((text, i) => (
56 <span 61 <span
57 key={text} 62 key={text}
58 className={classnames({ 63 className={classnames({
diff --git a/src/containers/auth/AuthLayoutContainer.js b/src/containers/auth/AuthLayoutContainer.js
index 427054d3d..883a6ea60 100644
--- a/src/containers/auth/AuthLayoutContainer.js
+++ b/src/containers/auth/AuthLayoutContainer.js
@@ -5,6 +5,7 @@ import { ThemeProvider } from 'react-jss';
5 5
6import AuthLayout from '../../components/auth/AuthLayout'; 6import AuthLayout from '../../components/auth/AuthLayout';
7import AppStore from '../../stores/AppStore'; 7import AppStore from '../../stores/AppStore';
8import UserStore from '../../stores/UserStore';
8import GlobalErrorStore from '../../stores/GlobalErrorStore'; 9import GlobalErrorStore from '../../stores/GlobalErrorStore';
9import AppLoader from '../../components/ui/AppLoader'; 10import AppLoader from '../../components/ui/AppLoader';
10 11
@@ -23,7 +24,7 @@ export default @inject('stores', 'actions') @observer class AuthLayoutContainer
23 stores, actions, children, location, 24 stores, actions, children, location,
24 } = this.props; 25 } = this.props;
25 const { 26 const {
26 app, features, globalError, 27 app, features, globalError, user,
27 } = stores; 28 } = stores;
28 29
29 const isLoadingBaseFeatures = features.defaultFeaturesRequest.isExecuting 30 const isLoadingBaseFeatures = features.defaultFeaturesRequest.isExecuting
@@ -37,6 +38,15 @@ export default @inject('stores', 'actions') @observer class AuthLayoutContainer
37 ); 38 );
38 } 39 }
39 40
41 const { isLoggingOut } = user;
42 if (isLoggingOut) {
43 return (
44 <ThemeProvider theme={stores.ui.theme}>
45 <AppLoader texts={['Logging you out...']} />
46 </ThemeProvider>
47 );
48 }
49
40 return ( 50 return (
41 <ThemeProvider theme={stores.ui.theme}> 51 <ThemeProvider theme={stores.ui.theme}>
42 <AuthLayout 52 <AuthLayout
@@ -62,6 +72,7 @@ AuthLayoutContainer.wrappedComponent.propTypes = {
62 stores: PropTypes.shape({ 72 stores: PropTypes.shape({
63 app: PropTypes.instanceOf(AppStore).isRequired, 73 app: PropTypes.instanceOf(AppStore).isRequired,
64 globalError: PropTypes.instanceOf(GlobalErrorStore).isRequired, 74 globalError: PropTypes.instanceOf(GlobalErrorStore).isRequired,
75 user: PropTypes.instanceOf(UserStore).isRequired,
65 }).isRequired, 76 }).isRequired,
66 actions: PropTypes.shape({ 77 actions: PropTypes.shape({
67 app: PropTypes.shape({ 78 app: PropTypes.shape({
diff --git a/src/i18n/locales/defaultMessages.json b/src/i18n/locales/defaultMessages.json
index e188c1d23..b056f0d1b 100644
--- a/src/i18n/locales/defaultMessages.json
+++ b/src/i18n/locales/defaultMessages.json
@@ -1733,104 +1733,104 @@
1733 "defaultMessage": "!!!Available services", 1733 "defaultMessage": "!!!Available services",
1734 "end": { 1734 "end": {
1735 "column": 3, 1735 "column": 3,
1736 "line": 17 1736 "line": 20
1737 }, 1737 },
1738 "file": "src/components/settings/navigation/SettingsNavigation.js", 1738 "file": "src/components/settings/navigation/SettingsNavigation.js",
1739 "id": "settings.navigation.availableServices", 1739 "id": "settings.navigation.availableServices",
1740 "start": { 1740 "start": {
1741 "column": 21, 1741 "column": 21,
1742 "line": 14 1742 "line": 17
1743 } 1743 }
1744 }, 1744 },
1745 { 1745 {
1746 "defaultMessage": "!!!Your services", 1746 "defaultMessage": "!!!Your services",
1747 "end": { 1747 "end": {
1748 "column": 3, 1748 "column": 3,
1749 "line": 21 1749 "line": 24
1750 }, 1750 },
1751 "file": "src/components/settings/navigation/SettingsNavigation.js", 1751 "file": "src/components/settings/navigation/SettingsNavigation.js",
1752 "id": "settings.navigation.yourServices", 1752 "id": "settings.navigation.yourServices",
1753 "start": { 1753 "start": {
1754 "column": 16, 1754 "column": 16,
1755 "line": 18 1755 "line": 21
1756 } 1756 }
1757 }, 1757 },
1758 { 1758 {
1759 "defaultMessage": "!!!Your workspaces", 1759 "defaultMessage": "!!!Your workspaces",
1760 "end": { 1760 "end": {
1761 "column": 3, 1761 "column": 3,
1762 "line": 25 1762 "line": 28
1763 }, 1763 },
1764 "file": "src/components/settings/navigation/SettingsNavigation.js", 1764 "file": "src/components/settings/navigation/SettingsNavigation.js",
1765 "id": "settings.navigation.yourWorkspaces", 1765 "id": "settings.navigation.yourWorkspaces",
1766 "start": { 1766 "start": {
1767 "column": 18, 1767 "column": 18,
1768 "line": 22 1768 "line": 25
1769 } 1769 }
1770 }, 1770 },
1771 { 1771 {
1772 "defaultMessage": "!!!Account", 1772 "defaultMessage": "!!!Account",
1773 "end": { 1773 "end": {
1774 "column": 3, 1774 "column": 3,
1775 "line": 29 1775 "line": 32
1776 }, 1776 },
1777 "file": "src/components/settings/navigation/SettingsNavigation.js", 1777 "file": "src/components/settings/navigation/SettingsNavigation.js",
1778 "id": "settings.navigation.account", 1778 "id": "settings.navigation.account",
1779 "start": { 1779 "start": {
1780 "column": 11, 1780 "column": 11,
1781 "line": 26 1781 "line": 29
1782 } 1782 }
1783 }, 1783 },
1784 { 1784 {
1785 "defaultMessage": "!!!Manage Team", 1785 "defaultMessage": "!!!Manage Team",
1786 "end": { 1786 "end": {
1787 "column": 3, 1787 "column": 3,
1788 "line": 33 1788 "line": 36
1789 }, 1789 },
1790 "file": "src/components/settings/navigation/SettingsNavigation.js", 1790 "file": "src/components/settings/navigation/SettingsNavigation.js",
1791 "id": "settings.navigation.team", 1791 "id": "settings.navigation.team",
1792 "start": { 1792 "start": {
1793 "column": 8, 1793 "column": 8,
1794 "line": 30 1794 "line": 33
1795 } 1795 }
1796 }, 1796 },
1797 { 1797 {
1798 "defaultMessage": "!!!Settings", 1798 "defaultMessage": "!!!Settings",
1799 "end": { 1799 "end": {
1800 "column": 3, 1800 "column": 3,
1801 "line": 37 1801 "line": 40
1802 }, 1802 },
1803 "file": "src/components/settings/navigation/SettingsNavigation.js", 1803 "file": "src/components/settings/navigation/SettingsNavigation.js",
1804 "id": "settings.navigation.settings", 1804 "id": "settings.navigation.settings",
1805 "start": { 1805 "start": {
1806 "column": 12, 1806 "column": 12,
1807 "line": 34 1807 "line": 37
1808 } 1808 }
1809 }, 1809 },
1810 { 1810 {
1811 "defaultMessage": "!!!Support Ferdi", 1811 "defaultMessage": "!!!Support Ferdi",
1812 "end": { 1812 "end": {
1813 "column": 3, 1813 "column": 3,
1814 "line": 41 1814 "line": 44
1815 }, 1815 },
1816 "file": "src/components/settings/navigation/SettingsNavigation.js", 1816 "file": "src/components/settings/navigation/SettingsNavigation.js",
1817 "id": "settings.navigation.supportFerdi", 1817 "id": "settings.navigation.supportFerdi",
1818 "start": { 1818 "start": {
1819 "column": 16, 1819 "column": 16,
1820 "line": 38 1820 "line": 41
1821 } 1821 }
1822 }, 1822 },
1823 { 1823 {
1824 "defaultMessage": "!!!Logout", 1824 "defaultMessage": "!!!Logout",
1825 "end": { 1825 "end": {
1826 "column": 3, 1826 "column": 3,
1827 "line": 45 1827 "line": 48
1828 }, 1828 },
1829 "file": "src/components/settings/navigation/SettingsNavigation.js", 1829 "file": "src/components/settings/navigation/SettingsNavigation.js",
1830 "id": "settings.navigation.logout", 1830 "id": "settings.navigation.logout",
1831 "start": { 1831 "start": {
1832 "column": 10, 1832 "column": 10,
1833 "line": 42 1833 "line": 45
1834 } 1834 }
1835 } 1835 }
1836 ], 1836 ],
diff --git a/src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json b/src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json
index b7309469e..154cdbe84 100644
--- a/src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json
+++ b/src/i18n/messages/src/components/settings/navigation/SettingsNavigation.json
@@ -4,11 +4,11 @@
4 "defaultMessage": "!!!Available services", 4 "defaultMessage": "!!!Available services",
5 "file": "src/components/settings/navigation/SettingsNavigation.js", 5 "file": "src/components/settings/navigation/SettingsNavigation.js",
6 "start": { 6 "start": {
7 "line": 14, 7 "line": 17,
8 "column": 21 8 "column": 21
9 }, 9 },
10 "end": { 10 "end": {
11 "line": 17, 11 "line": 20,
12 "column": 3 12 "column": 3
13 } 13 }
14 }, 14 },
@@ -17,11 +17,11 @@
17 "defaultMessage": "!!!Your services", 17 "defaultMessage": "!!!Your services",
18 "file": "src/components/settings/navigation/SettingsNavigation.js", 18 "file": "src/components/settings/navigation/SettingsNavigation.js",
19 "start": { 19 "start": {
20 "line": 18, 20 "line": 21,
21 "column": 16 21 "column": 16
22 }, 22 },
23 "end": { 23 "end": {
24 "line": 21, 24 "line": 24,
25 "column": 3 25 "column": 3
26 } 26 }
27 }, 27 },
@@ -30,11 +30,11 @@
30 "defaultMessage": "!!!Your workspaces", 30 "defaultMessage": "!!!Your workspaces",
31 "file": "src/components/settings/navigation/SettingsNavigation.js", 31 "file": "src/components/settings/navigation/SettingsNavigation.js",
32 "start": { 32 "start": {
33 "line": 22, 33 "line": 25,
34 "column": 18 34 "column": 18
35 }, 35 },
36 "end": { 36 "end": {
37 "line": 25, 37 "line": 28,
38 "column": 3 38 "column": 3
39 } 39 }
40 }, 40 },
@@ -43,11 +43,11 @@
43 "defaultMessage": "!!!Account", 43 "defaultMessage": "!!!Account",
44 "file": "src/components/settings/navigation/SettingsNavigation.js", 44 "file": "src/components/settings/navigation/SettingsNavigation.js",
45 "start": { 45 "start": {
46 "line": 26, 46 "line": 29,
47 "column": 11 47 "column": 11
48 }, 48 },
49 "end": { 49 "end": {
50 "line": 29, 50 "line": 32,
51 "column": 3 51 "column": 3
52 } 52 }
53 }, 53 },
@@ -56,11 +56,11 @@
56 "defaultMessage": "!!!Manage Team", 56 "defaultMessage": "!!!Manage Team",
57 "file": "src/components/settings/navigation/SettingsNavigation.js", 57 "file": "src/components/settings/navigation/SettingsNavigation.js",
58 "start": { 58 "start": {
59 "line": 30, 59 "line": 33,
60 "column": 8 60 "column": 8
61 }, 61 },
62 "end": { 62 "end": {
63 "line": 33, 63 "line": 36,
64 "column": 3 64 "column": 3
65 } 65 }
66 }, 66 },
@@ -69,11 +69,11 @@
69 "defaultMessage": "!!!Settings", 69 "defaultMessage": "!!!Settings",
70 "file": "src/components/settings/navigation/SettingsNavigation.js", 70 "file": "src/components/settings/navigation/SettingsNavigation.js",
71 "start": { 71 "start": {
72 "line": 34, 72 "line": 37,
73 "column": 12 73 "column": 12
74 }, 74 },
75 "end": { 75 "end": {
76 "line": 37, 76 "line": 40,
77 "column": 3 77 "column": 3
78 } 78 }
79 }, 79 },
@@ -82,11 +82,11 @@
82 "defaultMessage": "!!!Support Ferdi", 82 "defaultMessage": "!!!Support Ferdi",
83 "file": "src/components/settings/navigation/SettingsNavigation.js", 83 "file": "src/components/settings/navigation/SettingsNavigation.js",
84 "start": { 84 "start": {
85 "line": 38, 85 "line": 41,
86 "column": 16 86 "column": 16
87 }, 87 },
88 "end": { 88 "end": {
89 "line": 41, 89 "line": 44,
90 "column": 3 90 "column": 3
91 } 91 }
92 }, 92 },
@@ -95,11 +95,11 @@
95 "defaultMessage": "!!!Logout", 95 "defaultMessage": "!!!Logout",
96 "file": "src/components/settings/navigation/SettingsNavigation.js", 96 "file": "src/components/settings/navigation/SettingsNavigation.js",
97 "start": { 97 "start": {
98 "line": 42, 98 "line": 45,
99 "column": 10 99 "column": 10
100 }, 100 },
101 "end": { 101 "end": {
102 "line": 45, 102 "line": 48,
103 "column": 3 103 "column": 3
104 } 104 }
105 } 105 }
diff --git a/src/stores/UserStore.js b/src/stores/UserStore.js
index 61b7d4adf..03aa79606 100644
--- a/src/stores/UserStore.js
+++ b/src/stores/UserStore.js
@@ -56,6 +56,8 @@ export default class UserStore extends Store {
56 56
57 @observable isImportLegacyServicesCompleted = false; 57 @observable isImportLegacyServicesCompleted = false;
58 58
59 @observable isLoggingOut = false;
60
59 @observable id; 61 @observable id;
60 62
61 @observable authToken = localStorage.getItem('authToken') || null; 63 @observable authToken = localStorage.getItem('authToken') || null;