cozy-bar 0.0.0-development
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +174 -0
- package/dist/cozy-bar.min.js +77 -0
- package/dist/cozy-bar.min.js.map +1 -0
- package/package.json +165 -0
- package/src/assets/icons/16/icon-storage-16.svg +3 -0
- package/src/assets/icons/24/icon-arrow-left.svg +3 -0
- package/src/assets/icons/32/icon-claudy.svg +1 -0
- package/src/assets/icons/apps/icon-collect.svg +25 -0
- package/src/assets/icons/apps/icon-drive.svg +17 -0
- package/src/assets/icons/apps/icon-market-soon.svg +25 -0
- package/src/assets/icons/apps/icon-photos.svg +19 -0
- package/src/assets/icons/apps/icon-soon.svg +21 -0
- package/src/assets/icons/apps/icon-store.svg +19 -0
- package/src/assets/icons/claudyActions/icon-bills.svg +6 -0
- package/src/assets/icons/claudyActions/icon-laptop.svg +7 -0
- package/src/assets/icons/claudyActions/icon-phone.svg +8 -0
- package/src/assets/icons/claudyActions/icon-question-mark.svg +6 -0
- package/src/assets/icons/comingsoon/icon-bank.svg +12 -0
- package/src/assets/icons/comingsoon/icon-sante.svg +12 -0
- package/src/assets/icons/comingsoon/icon-store.svg +6 -0
- package/src/assets/icons/icon-cozy.svg +3 -0
- package/src/assets/icons/icon-shield.svg +3 -0
- package/src/assets/icons/spinner.svg +4 -0
- package/src/assets/sprites/icon-apps.svg +1 -0
- package/src/assets/sprites/icon-cozy-home.svg +16 -0
- package/src/components/Apps/AppItem.jsx +117 -0
- package/src/components/Apps/AppItemPlaceholder.jsx +12 -0
- package/src/components/Apps/AppNavButtons.jsx +94 -0
- package/src/components/Apps/AppsContent.jsx +91 -0
- package/src/components/Apps/ButtonCozyHome.jsx +30 -0
- package/src/components/Apps/ButtonCozyHome.spec.jsx +53 -0
- package/src/components/Apps/IconCozyHome.jsx +38 -0
- package/src/components/Apps/index.jsx +72 -0
- package/src/components/Banner.jsx +41 -0
- package/src/components/Bar.jsx +295 -0
- package/src/components/Bar.spec.jsx +133 -0
- package/src/components/Claudy.jsx +81 -0
- package/src/components/ClaudyIcon.jsx +18 -0
- package/src/components/Drawer.jsx +227 -0
- package/src/components/Drawer.spec.jsx +98 -0
- package/src/components/SearchBar.jsx +358 -0
- package/src/components/Settings/SettingsContent.jsx +163 -0
- package/src/components/Settings/StorageData.jsx +29 -0
- package/src/components/Settings/helper.js +8 -0
- package/src/components/Settings/index.jsx +220 -0
- package/src/components/StorageIcon.jsx +16 -0
- package/src/components/SupportModal.jsx +59 -0
- package/src/components/__snapshots__/Bar.spec.jsx.snap +302 -0
- package/src/config/claudyActions.json +20 -0
- package/src/config/persistWhitelist.json +4 -0
- package/src/dom.js +80 -0
- package/src/index.jsx +242 -0
- package/src/index.spec.jsx +34 -0
- package/src/lib/api/helpers.js +13 -0
- package/src/lib/api/index.jsx +145 -0
- package/src/lib/exceptions.js +89 -0
- package/src/lib/expiringMemoize.js +13 -0
- package/src/lib/icon.js +77 -0
- package/src/lib/intents.js +16 -0
- package/src/lib/logger.js +11 -0
- package/src/lib/middlewares/appsI18n.js +57 -0
- package/src/lib/realtime.js +43 -0
- package/src/lib/reducers/apps.js +175 -0
- package/src/lib/reducers/apps.spec.js +59 -0
- package/src/lib/reducers/content.js +50 -0
- package/src/lib/reducers/context.js +86 -0
- package/src/lib/reducers/index.js +73 -0
- package/src/lib/reducers/locale.js +22 -0
- package/src/lib/reducers/settings.js +111 -0
- package/src/lib/reducers/theme.js +48 -0
- package/src/lib/reducers/unserializable.js +26 -0
- package/src/lib/stack-client.js +401 -0
- package/src/lib/stack.js +79 -0
- package/src/lib/store/index.js +44 -0
- package/src/locales/de.json +57 -0
- package/src/locales/en.json +57 -0
- package/src/locales/es.json +57 -0
- package/src/locales/fr.json +57 -0
- package/src/locales/it.json +57 -0
- package/src/locales/ja.json +57 -0
- package/src/locales/nl_NL.json +57 -0
- package/src/locales/pl.json +57 -0
- package/src/locales/ru.json +57 -0
- package/src/locales/sq.json +57 -0
- package/src/locales/zh_CN.json +57 -0
- package/src/proptypes/index.js +10 -0
- package/src/queries/index.js +16 -0
- package/src/styles/apps.css +248 -0
- package/src/styles/banner.css +64 -0
- package/src/styles/bar.css +106 -0
- package/src/styles/base.css +21 -0
- package/src/styles/claudy.css +98 -0
- package/src/styles/drawer.css +126 -0
- package/src/styles/index.styl +33 -0
- package/src/styles/indicators.css +58 -0
- package/src/styles/nav.css +81 -0
- package/src/styles/navigation_item.css +34 -0
- package/src/styles/searchbar.css +156 -0
- package/src/styles/settings.css +34 -0
- package/src/styles/storage.css +22 -0
- package/src/styles/supportModal.css +20 -0
- package/src/styles/theme.styl +25 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`Bar should change allow theme overrides 1`] = `
|
|
4
|
+
<div
|
|
5
|
+
className="coz-bar-wrapper coz-theme-primary"
|
|
6
|
+
style={
|
|
7
|
+
Object {
|
|
8
|
+
"--cozBarThemePrimaryColor": "red",
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
>
|
|
12
|
+
<div
|
|
13
|
+
id="cozy-bar-modal-dom-place"
|
|
14
|
+
/>
|
|
15
|
+
<div
|
|
16
|
+
className="coz-bar-container"
|
|
17
|
+
>
|
|
18
|
+
<button
|
|
19
|
+
className="coz-bar-btn coz-bar-burger"
|
|
20
|
+
data-tutorial="apps-mobile"
|
|
21
|
+
onClick={[Function]}
|
|
22
|
+
type="button"
|
|
23
|
+
>
|
|
24
|
+
<Icon
|
|
25
|
+
color="currentColor"
|
|
26
|
+
height={16}
|
|
27
|
+
icon={[Function]}
|
|
28
|
+
spin={false}
|
|
29
|
+
width={16}
|
|
30
|
+
/>
|
|
31
|
+
<span
|
|
32
|
+
className="coz-bar-hidden"
|
|
33
|
+
>
|
|
34
|
+
drawer
|
|
35
|
+
</span>
|
|
36
|
+
</button>
|
|
37
|
+
<Apps />
|
|
38
|
+
<div
|
|
39
|
+
className="u-flex-grow"
|
|
40
|
+
/>
|
|
41
|
+
<withI18n(Connect(Settings))
|
|
42
|
+
toggleSupport={[Function]}
|
|
43
|
+
/>
|
|
44
|
+
<Connect(Drawer)
|
|
45
|
+
drawerListener={[Function]}
|
|
46
|
+
isClaudyLoading={false}
|
|
47
|
+
onClaudy={false}
|
|
48
|
+
onClose={[Function]}
|
|
49
|
+
toggleSupport={[Function]}
|
|
50
|
+
visible={false}
|
|
51
|
+
/>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
exports[`Bar should change theme 1`] = `
|
|
57
|
+
<div
|
|
58
|
+
className="coz-bar-wrapper coz-theme-primary"
|
|
59
|
+
style={Object {}}
|
|
60
|
+
>
|
|
61
|
+
<div
|
|
62
|
+
id="cozy-bar-modal-dom-place"
|
|
63
|
+
/>
|
|
64
|
+
<div
|
|
65
|
+
className="coz-bar-container"
|
|
66
|
+
>
|
|
67
|
+
<button
|
|
68
|
+
className="coz-bar-btn coz-bar-burger"
|
|
69
|
+
data-tutorial="apps-mobile"
|
|
70
|
+
onClick={[Function]}
|
|
71
|
+
type="button"
|
|
72
|
+
>
|
|
73
|
+
<Icon
|
|
74
|
+
color="currentColor"
|
|
75
|
+
height={16}
|
|
76
|
+
icon={[Function]}
|
|
77
|
+
spin={false}
|
|
78
|
+
width={16}
|
|
79
|
+
/>
|
|
80
|
+
<span
|
|
81
|
+
className="coz-bar-hidden"
|
|
82
|
+
>
|
|
83
|
+
drawer
|
|
84
|
+
</span>
|
|
85
|
+
</button>
|
|
86
|
+
<Apps />
|
|
87
|
+
<div
|
|
88
|
+
className="u-flex-grow"
|
|
89
|
+
/>
|
|
90
|
+
<withI18n(Connect(Settings))
|
|
91
|
+
toggleSupport={[Function]}
|
|
92
|
+
/>
|
|
93
|
+
<Connect(Drawer)
|
|
94
|
+
drawerListener={[Function]}
|
|
95
|
+
isClaudyLoading={false}
|
|
96
|
+
onClaudy={false}
|
|
97
|
+
onClose={[Function]}
|
|
98
|
+
toggleSupport={[Function]}
|
|
99
|
+
visible={false}
|
|
100
|
+
/>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
`;
|
|
104
|
+
|
|
105
|
+
exports[`Bar should display the Searchbar 1`] = `
|
|
106
|
+
<div
|
|
107
|
+
className="coz-bar-wrapper coz-theme-default"
|
|
108
|
+
style={Object {}}
|
|
109
|
+
>
|
|
110
|
+
<div
|
|
111
|
+
id="cozy-bar-modal-dom-place"
|
|
112
|
+
/>
|
|
113
|
+
<div
|
|
114
|
+
className="coz-bar-container"
|
|
115
|
+
>
|
|
116
|
+
<button
|
|
117
|
+
className="coz-bar-btn coz-bar-burger"
|
|
118
|
+
data-tutorial="apps-mobile"
|
|
119
|
+
onClick={[Function]}
|
|
120
|
+
type="button"
|
|
121
|
+
>
|
|
122
|
+
<Icon
|
|
123
|
+
color="currentColor"
|
|
124
|
+
height={16}
|
|
125
|
+
icon={[Function]}
|
|
126
|
+
spin={false}
|
|
127
|
+
width={16}
|
|
128
|
+
/>
|
|
129
|
+
<span
|
|
130
|
+
className="coz-bar-hidden"
|
|
131
|
+
>
|
|
132
|
+
drawer
|
|
133
|
+
</span>
|
|
134
|
+
</button>
|
|
135
|
+
<Apps
|
|
136
|
+
isPublic={false}
|
|
137
|
+
/>
|
|
138
|
+
<div
|
|
139
|
+
className="u-flex-grow"
|
|
140
|
+
>
|
|
141
|
+
<withI18n(SearchBar) />
|
|
142
|
+
</div>
|
|
143
|
+
<withI18n(Connect(Settings))
|
|
144
|
+
toggleSupport={[Function]}
|
|
145
|
+
/>
|
|
146
|
+
<Connect(Drawer)
|
|
147
|
+
drawerListener={[Function]}
|
|
148
|
+
isClaudyLoading={false}
|
|
149
|
+
onClaudy={false}
|
|
150
|
+
onClose={[Function]}
|
|
151
|
+
toggleSupport={[Function]}
|
|
152
|
+
visible={false}
|
|
153
|
+
/>
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
`;
|
|
157
|
+
|
|
158
|
+
exports[`Bar should have correct dispatch props provided by the store 1`] = `
|
|
159
|
+
Object {
|
|
160
|
+
"fetchApps": [Function],
|
|
161
|
+
"fetchContext": [Function],
|
|
162
|
+
"fetchSettingsData": [Function],
|
|
163
|
+
}
|
|
164
|
+
`;
|
|
165
|
+
|
|
166
|
+
exports[`Bar should have correct state props provided by the store with the initial state 1`] = `
|
|
167
|
+
Object {
|
|
168
|
+
"barCenter": undefined,
|
|
169
|
+
"barLeft": undefined,
|
|
170
|
+
"barRight": undefined,
|
|
171
|
+
"barSearch": undefined,
|
|
172
|
+
"claudyEnabled": false,
|
|
173
|
+
"hasFetchedApps": false,
|
|
174
|
+
"isDrive": false,
|
|
175
|
+
"theme": "default",
|
|
176
|
+
"themeOverrides": Object {},
|
|
177
|
+
"webviewContext": undefined,
|
|
178
|
+
}
|
|
179
|
+
`;
|
|
180
|
+
|
|
181
|
+
exports[`Bar should not display searchbar if we are not on a public page 1`] = `
|
|
182
|
+
<div
|
|
183
|
+
className="coz-bar-wrapper coz-theme-default"
|
|
184
|
+
style={Object {}}
|
|
185
|
+
>
|
|
186
|
+
<div
|
|
187
|
+
id="cozy-bar-modal-dom-place"
|
|
188
|
+
/>
|
|
189
|
+
<div
|
|
190
|
+
className="coz-bar-container"
|
|
191
|
+
>
|
|
192
|
+
<Apps
|
|
193
|
+
isPublic={true}
|
|
194
|
+
/>
|
|
195
|
+
<div
|
|
196
|
+
className="u-flex-grow"
|
|
197
|
+
/>
|
|
198
|
+
</div>
|
|
199
|
+
</div>
|
|
200
|
+
`;
|
|
201
|
+
|
|
202
|
+
exports[`Bar should not display searchbar if we are not on Cozy Drive 1`] = `
|
|
203
|
+
<div
|
|
204
|
+
className="coz-bar-wrapper coz-theme-default"
|
|
205
|
+
style={Object {}}
|
|
206
|
+
>
|
|
207
|
+
<div
|
|
208
|
+
id="cozy-bar-modal-dom-place"
|
|
209
|
+
/>
|
|
210
|
+
<div
|
|
211
|
+
className="coz-bar-container"
|
|
212
|
+
>
|
|
213
|
+
<button
|
|
214
|
+
className="coz-bar-btn coz-bar-burger"
|
|
215
|
+
data-tutorial="apps-mobile"
|
|
216
|
+
onClick={[Function]}
|
|
217
|
+
type="button"
|
|
218
|
+
>
|
|
219
|
+
<Icon
|
|
220
|
+
color="currentColor"
|
|
221
|
+
height={16}
|
|
222
|
+
icon={[Function]}
|
|
223
|
+
spin={false}
|
|
224
|
+
width={16}
|
|
225
|
+
/>
|
|
226
|
+
<span
|
|
227
|
+
className="coz-bar-hidden"
|
|
228
|
+
>
|
|
229
|
+
drawer
|
|
230
|
+
</span>
|
|
231
|
+
</button>
|
|
232
|
+
<Apps
|
|
233
|
+
isPublic={false}
|
|
234
|
+
/>
|
|
235
|
+
<div
|
|
236
|
+
className="u-flex-grow"
|
|
237
|
+
/>
|
|
238
|
+
<withI18n(Connect(Settings))
|
|
239
|
+
toggleSupport={[Function]}
|
|
240
|
+
/>
|
|
241
|
+
<Connect(Drawer)
|
|
242
|
+
drawerListener={[Function]}
|
|
243
|
+
isClaudyLoading={false}
|
|
244
|
+
onClaudy={false}
|
|
245
|
+
onClose={[Function]}
|
|
246
|
+
toggleSupport={[Function]}
|
|
247
|
+
visible={false}
|
|
248
|
+
/>
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
251
|
+
`;
|
|
252
|
+
|
|
253
|
+
exports[`Bar should not display searchbar if we are on mobile 1`] = `
|
|
254
|
+
<div
|
|
255
|
+
className="coz-bar-wrapper coz-theme-default"
|
|
256
|
+
style={Object {}}
|
|
257
|
+
>
|
|
258
|
+
<div
|
|
259
|
+
id="cozy-bar-modal-dom-place"
|
|
260
|
+
/>
|
|
261
|
+
<div
|
|
262
|
+
className="coz-bar-container"
|
|
263
|
+
>
|
|
264
|
+
<button
|
|
265
|
+
className="coz-bar-btn coz-bar-burger"
|
|
266
|
+
data-tutorial="apps-mobile"
|
|
267
|
+
onClick={[Function]}
|
|
268
|
+
type="button"
|
|
269
|
+
>
|
|
270
|
+
<Icon
|
|
271
|
+
color="currentColor"
|
|
272
|
+
height={16}
|
|
273
|
+
icon={[Function]}
|
|
274
|
+
spin={false}
|
|
275
|
+
width={16}
|
|
276
|
+
/>
|
|
277
|
+
<span
|
|
278
|
+
className="coz-bar-hidden"
|
|
279
|
+
>
|
|
280
|
+
drawer
|
|
281
|
+
</span>
|
|
282
|
+
</button>
|
|
283
|
+
<Apps
|
|
284
|
+
isPublic={false}
|
|
285
|
+
/>
|
|
286
|
+
<div
|
|
287
|
+
className="u-flex-grow"
|
|
288
|
+
/>
|
|
289
|
+
<withI18n(Connect(Settings))
|
|
290
|
+
toggleSupport={[Function]}
|
|
291
|
+
/>
|
|
292
|
+
<Connect(Drawer)
|
|
293
|
+
drawerListener={[Function]}
|
|
294
|
+
isClaudyLoading={false}
|
|
295
|
+
onClaudy={false}
|
|
296
|
+
onClose={[Function]}
|
|
297
|
+
toggleSupport={[Function]}
|
|
298
|
+
visible={false}
|
|
299
|
+
/>
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
`;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"desktop": {
|
|
3
|
+
"icon": "icon-laptop.svg",
|
|
4
|
+
"link": {
|
|
5
|
+
"type": "external"
|
|
6
|
+
}
|
|
7
|
+
},
|
|
8
|
+
"mobile": {
|
|
9
|
+
"icon": "icon-phone.svg",
|
|
10
|
+
"link": {
|
|
11
|
+
"type": "external"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"support": {
|
|
15
|
+
"icon": "icon-question-mark.svg",
|
|
16
|
+
"link": {
|
|
17
|
+
"type": "external"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
package/src/dom.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const APP_SELECTOR = '[role=application]'
|
|
2
|
+
|
|
3
|
+
// return an empty object by default to avoid checking existance
|
|
4
|
+
const getAppNodeDataSet = () => {
|
|
5
|
+
const appNode = document.querySelector(APP_SELECTOR)
|
|
6
|
+
if (!appNode || !appNode.dataset) return {}
|
|
7
|
+
return appNode.dataset
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const getDefaultStackURL = isPublic => {
|
|
11
|
+
const data = getAppNodeDataSet()
|
|
12
|
+
if (!data.cozyDomain) {
|
|
13
|
+
if (!isPublic) {
|
|
14
|
+
// eslint-disable-next-line no-console
|
|
15
|
+
console.warn(
|
|
16
|
+
`Cozy-bar can't discover the cozy's URL, and will probably fail to initialize the connection with the stack.`
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
return ''
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const protocol = window.location.protocol
|
|
23
|
+
return `${protocol}//${data.cozyDomain}`
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const getDefaultToken = isPublic => {
|
|
27
|
+
const data = getAppNodeDataSet()
|
|
28
|
+
if (!data.cozyToken) {
|
|
29
|
+
if (!isPublic) {
|
|
30
|
+
// eslint-disable-next-line no-console
|
|
31
|
+
console.warn(
|
|
32
|
+
`Cozy-bar can't discover the app's token, and will probably fail to initialize the connection with the stack.`
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
return ''
|
|
36
|
+
}
|
|
37
|
+
return data.cozyToken
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const getDefaultIcon = () => {
|
|
41
|
+
const linkNode = document.querySelector('link[rel="icon"][sizes^="32"]')
|
|
42
|
+
if (linkNode !== null) {
|
|
43
|
+
return linkNode.getAttribute('href')
|
|
44
|
+
} else {
|
|
45
|
+
return 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const getAppNamePrefix = () => {
|
|
50
|
+
const data = getAppNodeDataSet()
|
|
51
|
+
return data.cozyAppNamePrefix || null
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const getAppSlug = () => {
|
|
55
|
+
const data = getAppNodeDataSet()
|
|
56
|
+
return data.cozyAppSlug || null
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const getUserActionRequired = () => {
|
|
60
|
+
const meta = document.querySelector('meta[name=user-action-required]')
|
|
61
|
+
const data = meta && meta.dataset
|
|
62
|
+
if (data) {
|
|
63
|
+
const { title, code, detail, links } = data
|
|
64
|
+
if (code) {
|
|
65
|
+
// we suppose that at least code will always exist
|
|
66
|
+
return { title, code, detail, links }
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return undefined
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export {
|
|
73
|
+
getDefaultStackURL,
|
|
74
|
+
getDefaultToken,
|
|
75
|
+
getDefaultIcon,
|
|
76
|
+
getAppNamePrefix,
|
|
77
|
+
getAppSlug,
|
|
78
|
+
getUserActionRequired,
|
|
79
|
+
APP_SELECTOR
|
|
80
|
+
}
|
package/src/index.jsx
ADDED
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/* global __VERSION__ */
|
|
2
|
+
|
|
3
|
+
import { isMobileApp } from 'cozy-device-helper'
|
|
4
|
+
|
|
5
|
+
import stack from 'lib/stack'
|
|
6
|
+
import {
|
|
7
|
+
getLocale,
|
|
8
|
+
onRealtimeCreate,
|
|
9
|
+
onRealtimeDelete,
|
|
10
|
+
setLocale,
|
|
11
|
+
setInfos
|
|
12
|
+
} from 'lib/reducers'
|
|
13
|
+
|
|
14
|
+
import { createBarAPI, createBarProxiedAPI } from 'lib/api'
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
getAppNamePrefix,
|
|
18
|
+
getAppSlug,
|
|
19
|
+
getDefaultIcon,
|
|
20
|
+
getDefaultStackURL,
|
|
21
|
+
getDefaultToken,
|
|
22
|
+
getUserActionRequired,
|
|
23
|
+
APP_SELECTOR
|
|
24
|
+
} from './dom'
|
|
25
|
+
|
|
26
|
+
import enLocale from 'locales/en.json'
|
|
27
|
+
import frLocale from 'locales/fr.json'
|
|
28
|
+
import esLocale from 'locales/es.json'
|
|
29
|
+
|
|
30
|
+
const locales = {
|
|
31
|
+
en: enLocale,
|
|
32
|
+
fr: frLocale,
|
|
33
|
+
es: esLocale
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const createBarElement = () => {
|
|
37
|
+
const targetName = isMobileApp() ? 'mobile' : 'browser'
|
|
38
|
+
const barNode = document.createElement('div')
|
|
39
|
+
barNode.setAttribute('id', 'coz-bar')
|
|
40
|
+
barNode.setAttribute('role', 'banner')
|
|
41
|
+
barNode.classList.add(`coz-target--${targetName}`)
|
|
42
|
+
return barNode
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const injectBarInDOM = data => {
|
|
46
|
+
if (document.getElementById('coz-bar') !== null) {
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const barNode = createBarElement()
|
|
51
|
+
const appNode = document.querySelector(APP_SELECTOR)
|
|
52
|
+
if (!appNode) {
|
|
53
|
+
// eslint-disable-next-line no-console
|
|
54
|
+
console.warn(
|
|
55
|
+
`Cozy-bar is looking for a "${APP_SELECTOR}" tag that contains your application and can't find it :'(… The BAR is now disabled`
|
|
56
|
+
)
|
|
57
|
+
return null
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
document.body.insertBefore(barNode, appNode)
|
|
61
|
+
|
|
62
|
+
// method to put cozy-bar z-index on the top when Drawer visible and vice versa
|
|
63
|
+
data.onDrawer = visible => {
|
|
64
|
+
barNode.dataset.drawerVisible = visible
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// specific layout behaviour if banner displayed
|
|
68
|
+
if (data.userActionRequired) {
|
|
69
|
+
document.body.classList.add('has-banner')
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return barNode
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const renderBar = (barNode, options) => {
|
|
76
|
+
// import React related modules on init only
|
|
77
|
+
const React = require('react')
|
|
78
|
+
const { render } = require('react-dom')
|
|
79
|
+
const { connect, Provider } = require('react-redux')
|
|
80
|
+
const I18n = require('cozy-ui/react/I18n').default
|
|
81
|
+
const Bar = require('components/Bar').default
|
|
82
|
+
const CozyProvider = require('cozy-client').CozyProvider
|
|
83
|
+
|
|
84
|
+
const { cozyClient } = options
|
|
85
|
+
|
|
86
|
+
// we connect the I18n component to the store to listen
|
|
87
|
+
// locale change from the api setLocale()
|
|
88
|
+
const EnhancedI18n = connect(state => ({
|
|
89
|
+
lang: getLocale(state)
|
|
90
|
+
}))(I18n)
|
|
91
|
+
|
|
92
|
+
const barComponent = (
|
|
93
|
+
<Provider store={options.reduxStore}>
|
|
94
|
+
<EnhancedI18n dictRequire={lang => locales[lang]}>
|
|
95
|
+
{cozyClient ? (
|
|
96
|
+
<CozyProvider client={cozyClient}>
|
|
97
|
+
<Bar {...options} />
|
|
98
|
+
</CozyProvider>
|
|
99
|
+
) : (
|
|
100
|
+
<Bar {...options} />
|
|
101
|
+
)}
|
|
102
|
+
</EnhancedI18n>
|
|
103
|
+
</Provider>
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
render(barComponent, barNode)
|
|
107
|
+
// for testing only
|
|
108
|
+
return barComponent
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const makeCozyClientAutomatically = ({ cozyURL, token, isPublic }) => {
|
|
112
|
+
const ccURI = cozyURL || getDefaultStackURL(isPublic)
|
|
113
|
+
const ccToken = token || getDefaultToken(isPublic)
|
|
114
|
+
const ccOptions = {
|
|
115
|
+
uri: ccURI,
|
|
116
|
+
token: ccToken
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const CozyClient = require('cozy-client').default
|
|
120
|
+
|
|
121
|
+
// eslint-disable-next-line no-console
|
|
122
|
+
console.warn('Automatically made cozyClient. Options: ', ccOptions)
|
|
123
|
+
return new CozyClient(ccOptions)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
let exposedAPI = {}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Initializes the cozy bar
|
|
130
|
+
*
|
|
131
|
+
* It can be initialized either with a cozyClient instance
|
|
132
|
+
* or a { cozyURL, ssl, token } tupple.
|
|
133
|
+
*
|
|
134
|
+
* @function
|
|
135
|
+
* @param {Object} options
|
|
136
|
+
* @param {string} options.appName - App name to be displayed in the bar
|
|
137
|
+
* @param {string} options.appNamePrefix
|
|
138
|
+
* @param {string} options.lang - Language for the bar
|
|
139
|
+
* @param {string} options.iconPath -
|
|
140
|
+
* @param {Object} options.cozyClient - a cozy client instance
|
|
141
|
+
* @param {string} options.cozyURL - URL or domain of the stack
|
|
142
|
+
* @param {boolean} options.ssl - Tells if we should use a secure
|
|
143
|
+
* protocol required if cozyURL does
|
|
144
|
+
* not have a protocol
|
|
145
|
+
* @param {string} arg.token - Access token for the stack
|
|
146
|
+
* @param {boolean} arg.isPublic
|
|
147
|
+
* @param {Function} arg.onLogout
|
|
148
|
+
*/
|
|
149
|
+
const init = async ({
|
|
150
|
+
appName,
|
|
151
|
+
appNamePrefix = getAppNamePrefix(),
|
|
152
|
+
appSlug = getAppSlug(),
|
|
153
|
+
lang,
|
|
154
|
+
iconPath = getDefaultIcon(),
|
|
155
|
+
cozyClient,
|
|
156
|
+
cozyURL,
|
|
157
|
+
token,
|
|
158
|
+
replaceTitleOnMobile = false,
|
|
159
|
+
isPublic = false,
|
|
160
|
+
onLogOut
|
|
161
|
+
} = {}) => {
|
|
162
|
+
// Force public mode in `/public` URLs
|
|
163
|
+
if (!isPublic && /^\/public/.test(window.location.pathname)) {
|
|
164
|
+
isPublic = true
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (!cozyClient) {
|
|
168
|
+
cozyClient = makeCozyClientAutomatically({ cozyURL, token, isPublic })
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// store
|
|
172
|
+
const getOrCreateStore = require('lib/store').default
|
|
173
|
+
const reduxStore = getOrCreateStore()
|
|
174
|
+
|
|
175
|
+
reduxStore.dispatch(setInfos(appName, appNamePrefix, appSlug))
|
|
176
|
+
stack.init({
|
|
177
|
+
cozyClient,
|
|
178
|
+
onCreate: data => reduxStore.dispatch(onRealtimeCreate(data)),
|
|
179
|
+
onDelete: data => reduxStore.dispatch(onRealtimeDelete(data))
|
|
180
|
+
})
|
|
181
|
+
if (lang) {
|
|
182
|
+
reduxStore.dispatch(setLocale(lang))
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Assign all api methods to the bar object
|
|
186
|
+
const apiMethods = createBarAPI(reduxStore)
|
|
187
|
+
Object.assign(exposedAPI, apiMethods)
|
|
188
|
+
|
|
189
|
+
const options = {
|
|
190
|
+
appName,
|
|
191
|
+
appNamePrefix,
|
|
192
|
+
appSlug,
|
|
193
|
+
cozyClient,
|
|
194
|
+
iconPath,
|
|
195
|
+
replaceTitleOnMobile,
|
|
196
|
+
isPublic,
|
|
197
|
+
onLogOut,
|
|
198
|
+
userActionRequired: getUserActionRequired(),
|
|
199
|
+
reduxStore
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const barNode = injectBarInDOM(options)
|
|
203
|
+
renderBar(barNode, options)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const updateAccessToken = accessToken => {
|
|
207
|
+
stack.updateAccessToken(accessToken)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const proxiedAPI = createBarProxiedAPI(exposedAPI)
|
|
211
|
+
|
|
212
|
+
const {
|
|
213
|
+
setBarCenter,
|
|
214
|
+
setBarLeft,
|
|
215
|
+
setBarRight,
|
|
216
|
+
setBarSearch,
|
|
217
|
+
BarCenter,
|
|
218
|
+
BarRight,
|
|
219
|
+
BarLeft,
|
|
220
|
+
BarSearch,
|
|
221
|
+
setTheme,
|
|
222
|
+
setWebviewContext
|
|
223
|
+
} = proxiedAPI
|
|
224
|
+
|
|
225
|
+
const version = __VERSION__
|
|
226
|
+
|
|
227
|
+
export {
|
|
228
|
+
init,
|
|
229
|
+
version,
|
|
230
|
+
setBarCenter,
|
|
231
|
+
setBarLeft,
|
|
232
|
+
setBarRight,
|
|
233
|
+
setBarSearch,
|
|
234
|
+
BarLeft,
|
|
235
|
+
BarRight,
|
|
236
|
+
BarCenter,
|
|
237
|
+
BarSearch,
|
|
238
|
+
setTheme,
|
|
239
|
+
setWebviewContext,
|
|
240
|
+
setLocale,
|
|
241
|
+
updateAccessToken
|
|
242
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import CozyClient from 'cozy-client'
|
|
2
|
+
import jestFetchMock from 'jest-fetch-mock'
|
|
3
|
+
|
|
4
|
+
import * as cozyBar from './index'
|
|
5
|
+
|
|
6
|
+
describe('init', () => {
|
|
7
|
+
beforeAll(() => {
|
|
8
|
+
global.fetch = jestFetchMock
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
jest.spyOn(console, 'error')
|
|
13
|
+
const div = document.createElement('div')
|
|
14
|
+
div.setAttribute('role', 'application')
|
|
15
|
+
document.body.appendChild(div)
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
// eslint-disable-next-line no-console
|
|
20
|
+
console.error.mockRestore()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
it('should init the bar', () => {
|
|
24
|
+
const client = new CozyClient({})
|
|
25
|
+
cozyBar.init({
|
|
26
|
+
appName: 'App',
|
|
27
|
+
cozyClient: client,
|
|
28
|
+
lang: 'fr'
|
|
29
|
+
})
|
|
30
|
+
cozyBar.setBarCenter('Page title')
|
|
31
|
+
// eslint-disable-next-line no-console
|
|
32
|
+
expect(console.error).not.toHaveBeenCalled()
|
|
33
|
+
})
|
|
34
|
+
})
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const locations = ['left', 'center', 'right', 'search']
|
|
2
|
+
|
|
3
|
+
const upperFirstLetter = val => {
|
|
4
|
+
return val[0].toUpperCase() + val.slice(1)
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const getJsApiName = location => {
|
|
8
|
+
return `setBar${upperFirstLetter(location)}`
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const getReactApiName = location => {
|
|
12
|
+
return `Bar${upperFirstLetter(location)}`
|
|
13
|
+
}
|