aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/layout
diff options
context:
space:
mode:
authorLibravatar Stefan Malzner <stefan@adlk.io>2017-10-13 12:29:40 +0200
committerLibravatar Stefan Malzner <stefan@adlk.io>2017-10-13 12:29:40 +0200
commit58cda9cc7fb79ca9df6746de7f9662bc08dc156a (patch)
tree1211600c2a5d3b5f81c435c6896618111a611720 /src/components/layout
downloadferdium-app-58cda9cc7fb79ca9df6746de7f9662bc08dc156a.tar.gz
ferdium-app-58cda9cc7fb79ca9df6746de7f9662bc08dc156a.tar.zst
ferdium-app-58cda9cc7fb79ca9df6746de7f9662bc08dc156a.zip
initial commit
Diffstat (limited to 'src/components/layout')
-rw-r--r--src/components/layout/AppLayout.js148
-rw-r--r--src/components/layout/Sidebar.js75
2 files changed, 223 insertions, 0 deletions
diff --git a/src/components/layout/AppLayout.js b/src/components/layout/AppLayout.js
new file mode 100644
index 000000000..f60c170a8
--- /dev/null
+++ b/src/components/layout/AppLayout.js
@@ -0,0 +1,148 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
4import { defineMessages, intlShape } from 'react-intl';
5
6import InfoBar from '../ui/InfoBar';
7import globalMessages from '../../i18n/globalMessages';
8
9function createMarkup(HTMLString) {
10 return { __html: HTMLString };
11}
12
13const messages = defineMessages({
14 servicesUpdated: {
15 id: 'infobar.servicesUpdated',
16 defaultMessage: '!!!Your services have been updated.',
17 },
18 updateAvailable: {
19 id: 'infobar.updateAvailable',
20 defaultMessage: '!!!A new update for Franz is available.',
21 },
22 buttonReloadServices: {
23 id: 'infobar.buttonReloadServices',
24 defaultMessage: '!!!Reload services',
25 },
26 buttonInstallUpdate: {
27 id: 'infobar.buttonInstallUpdate',
28 defaultMessage: '!!!Restart & install update',
29 },
30 requiredRequestsFailed: {
31 id: 'infobar.requiredRequestsFailed',
32 defaultMessage: '!!!Could not load services and user information',
33 },
34});
35
36@observer
37export default class AppLayout extends Component {
38 static propTypes = {
39 sidebar: PropTypes.element.isRequired,
40 services: PropTypes.element.isRequired,
41 children: PropTypes.element,
42 news: MobxPropTypes.arrayOrObservableArray.isRequired,
43 isOnline: PropTypes.bool.isRequired,
44 showServicesUpdatedInfoBar: PropTypes.bool.isRequired,
45 appUpdateIsDownloaded: PropTypes.bool.isRequired,
46 removeNewsItem: PropTypes.func.isRequired,
47 reloadServicesAfterUpdate: PropTypes.func.isRequired,
48 installAppUpdate: PropTypes.func.isRequired,
49 showRequiredRequestsError: PropTypes.bool.isRequired,
50 areRequiredRequestsSuccessful: PropTypes.bool.isRequired,
51 retryRequiredRequests: PropTypes.func.isRequired,
52 areRequiredRequestsLoading: PropTypes.bool.isRequired,
53 };
54
55 static defaultProps = {
56 children: [],
57 };
58
59 static contextTypes = {
60 intl: intlShape,
61 };
62
63 render() {
64 const {
65 sidebar,
66 services,
67 children,
68 isOnline,
69 news,
70 showServicesUpdatedInfoBar,
71 appUpdateIsDownloaded,
72 removeNewsItem,
73 reloadServicesAfterUpdate,
74 installAppUpdate,
75 showRequiredRequestsError,
76 areRequiredRequestsSuccessful,
77 retryRequiredRequests,
78 areRequiredRequestsLoading,
79 } = this.props;
80
81 const { intl } = this.context;
82
83 return (
84 <div>
85 <div className="app">
86 {sidebar}
87 <div className="app__service">
88 {news.length > 0 && news.map(item => (
89 <InfoBar
90 key={item.id}
91 position="top"
92 type={item.type}
93 sticky={item.sticky}
94 onHide={() => removeNewsItem({ newsId: item.id })}
95 >
96 <span dangerouslySetInnerHTML={createMarkup(item.message)} />
97 </InfoBar>
98 ))}
99 {!isOnline && (
100 <InfoBar
101 type="danger"
102 >
103 <span className="mdi mdi-flash" />
104 {intl.formatMessage(globalMessages.notConnectedToTheInternet)}
105 </InfoBar>
106 )}
107 {!areRequiredRequestsSuccessful && showRequiredRequestsError && (
108 <InfoBar
109 type="danger"
110 ctaLabel="Try again"
111 ctaLoading={areRequiredRequestsLoading}
112 sticky
113 onClick={retryRequiredRequests}
114 >
115 <span className="mdi mdi-flash" />
116 {intl.formatMessage(messages.requiredRequestsFailed)}
117 </InfoBar>
118 )}
119 {showServicesUpdatedInfoBar && (
120 <InfoBar
121 type="primary"
122 ctaLabel={intl.formatMessage(messages.buttonReloadServices)}
123 onClick={reloadServicesAfterUpdate}
124 sticky
125 >
126 <span className="mdi mdi-power-plug" />
127 {intl.formatMessage(messages.servicesUpdated)}
128 </InfoBar>
129 )}
130 {appUpdateIsDownloaded && (
131 <InfoBar
132 type="primary"
133 ctaLabel={intl.formatMessage(messages.buttonInstallUpdate)}
134 onClick={installAppUpdate}
135 sticky
136 >
137 <span className="mdi mdi-information" />
138 {intl.formatMessage(messages.updateAvailable)}
139 </InfoBar>
140 )}
141 {services}
142 </div>
143 </div>
144 {children}
145 </div>
146 );
147 }
148}
diff --git a/src/components/layout/Sidebar.js b/src/components/layout/Sidebar.js
new file mode 100644
index 000000000..4aee1ec60
--- /dev/null
+++ b/src/components/layout/Sidebar.js
@@ -0,0 +1,75 @@
1import React, { Component } from 'react';
2import PropTypes from 'prop-types';
3import ReactTooltip from 'react-tooltip';
4import { defineMessages, intlShape } from 'react-intl';
5
6import Tabbar from '../services/tabs/Tabbar';
7import { ctrlKey } from '../../environment';
8
9const messages = defineMessages({
10 settings: {
11 id: 'sidebar.settings',
12 defaultMessage: '!!!Settings',
13 },
14});
15
16export default class Sidebar extends Component {
17 static propTypes = {
18 openSettings: PropTypes.func.isRequired,
19 isPremiumUser: PropTypes.bool,
20 }
21
22 static defaultProps = {
23 isPremiumUser: false,
24 }
25
26 static contextTypes = {
27 intl: intlShape,
28 };
29
30 state = {
31 tooltipEnabled: true,
32 };
33
34 enableToolTip() {
35 this.setState({ tooltipEnabled: true });
36 }
37
38 disableToolTip() {
39 this.setState({ tooltipEnabled: false });
40 }
41
42 render() {
43 const { openSettings, isPremiumUser } = this.props;
44 const { intl } = this.context;
45 return (
46 <div className="sidebar">
47 <Tabbar
48 {...this.props}
49 enableToolTip={() => this.enableToolTip()}
50 disableToolTip={() => this.disableToolTip()}
51 />
52 <button
53 onClick={openSettings}
54 className="sidebar__settings-button"
55 data-tip={`Settings (${ctrlKey}+,)`}
56 >
57 {isPremiumUser && (
58 <span className="emoji">
59 <img src="./assets/images/emoji/star.png" alt="" />
60 </span>
61 )}
62 <img
63 src="./assets/images/logo.svg"
64 className="sidebar__logo"
65 alt=""
66 />
67 {intl.formatMessage(messages.settings)}
68 </button>
69 {this.state.tooltipEnabled && (
70 <ReactTooltip place="right" type="dark" effect="solid" />
71 )}
72 </div>
73 );
74 }
75}