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.
Files changed (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +174 -0
  3. package/dist/cozy-bar.min.js +77 -0
  4. package/dist/cozy-bar.min.js.map +1 -0
  5. package/package.json +165 -0
  6. package/src/assets/icons/16/icon-storage-16.svg +3 -0
  7. package/src/assets/icons/24/icon-arrow-left.svg +3 -0
  8. package/src/assets/icons/32/icon-claudy.svg +1 -0
  9. package/src/assets/icons/apps/icon-collect.svg +25 -0
  10. package/src/assets/icons/apps/icon-drive.svg +17 -0
  11. package/src/assets/icons/apps/icon-market-soon.svg +25 -0
  12. package/src/assets/icons/apps/icon-photos.svg +19 -0
  13. package/src/assets/icons/apps/icon-soon.svg +21 -0
  14. package/src/assets/icons/apps/icon-store.svg +19 -0
  15. package/src/assets/icons/claudyActions/icon-bills.svg +6 -0
  16. package/src/assets/icons/claudyActions/icon-laptop.svg +7 -0
  17. package/src/assets/icons/claudyActions/icon-phone.svg +8 -0
  18. package/src/assets/icons/claudyActions/icon-question-mark.svg +6 -0
  19. package/src/assets/icons/comingsoon/icon-bank.svg +12 -0
  20. package/src/assets/icons/comingsoon/icon-sante.svg +12 -0
  21. package/src/assets/icons/comingsoon/icon-store.svg +6 -0
  22. package/src/assets/icons/icon-cozy.svg +3 -0
  23. package/src/assets/icons/icon-shield.svg +3 -0
  24. package/src/assets/icons/spinner.svg +4 -0
  25. package/src/assets/sprites/icon-apps.svg +1 -0
  26. package/src/assets/sprites/icon-cozy-home.svg +16 -0
  27. package/src/components/Apps/AppItem.jsx +117 -0
  28. package/src/components/Apps/AppItemPlaceholder.jsx +12 -0
  29. package/src/components/Apps/AppNavButtons.jsx +94 -0
  30. package/src/components/Apps/AppsContent.jsx +91 -0
  31. package/src/components/Apps/ButtonCozyHome.jsx +30 -0
  32. package/src/components/Apps/ButtonCozyHome.spec.jsx +53 -0
  33. package/src/components/Apps/IconCozyHome.jsx +38 -0
  34. package/src/components/Apps/index.jsx +72 -0
  35. package/src/components/Banner.jsx +41 -0
  36. package/src/components/Bar.jsx +295 -0
  37. package/src/components/Bar.spec.jsx +133 -0
  38. package/src/components/Claudy.jsx +81 -0
  39. package/src/components/ClaudyIcon.jsx +18 -0
  40. package/src/components/Drawer.jsx +227 -0
  41. package/src/components/Drawer.spec.jsx +98 -0
  42. package/src/components/SearchBar.jsx +358 -0
  43. package/src/components/Settings/SettingsContent.jsx +163 -0
  44. package/src/components/Settings/StorageData.jsx +29 -0
  45. package/src/components/Settings/helper.js +8 -0
  46. package/src/components/Settings/index.jsx +220 -0
  47. package/src/components/StorageIcon.jsx +16 -0
  48. package/src/components/SupportModal.jsx +59 -0
  49. package/src/components/__snapshots__/Bar.spec.jsx.snap +302 -0
  50. package/src/config/claudyActions.json +20 -0
  51. package/src/config/persistWhitelist.json +4 -0
  52. package/src/dom.js +80 -0
  53. package/src/index.jsx +242 -0
  54. package/src/index.spec.jsx +34 -0
  55. package/src/lib/api/helpers.js +13 -0
  56. package/src/lib/api/index.jsx +145 -0
  57. package/src/lib/exceptions.js +89 -0
  58. package/src/lib/expiringMemoize.js +13 -0
  59. package/src/lib/icon.js +77 -0
  60. package/src/lib/intents.js +16 -0
  61. package/src/lib/logger.js +11 -0
  62. package/src/lib/middlewares/appsI18n.js +57 -0
  63. package/src/lib/realtime.js +43 -0
  64. package/src/lib/reducers/apps.js +175 -0
  65. package/src/lib/reducers/apps.spec.js +59 -0
  66. package/src/lib/reducers/content.js +50 -0
  67. package/src/lib/reducers/context.js +86 -0
  68. package/src/lib/reducers/index.js +73 -0
  69. package/src/lib/reducers/locale.js +22 -0
  70. package/src/lib/reducers/settings.js +111 -0
  71. package/src/lib/reducers/theme.js +48 -0
  72. package/src/lib/reducers/unserializable.js +26 -0
  73. package/src/lib/stack-client.js +401 -0
  74. package/src/lib/stack.js +79 -0
  75. package/src/lib/store/index.js +44 -0
  76. package/src/locales/de.json +57 -0
  77. package/src/locales/en.json +57 -0
  78. package/src/locales/es.json +57 -0
  79. package/src/locales/fr.json +57 -0
  80. package/src/locales/it.json +57 -0
  81. package/src/locales/ja.json +57 -0
  82. package/src/locales/nl_NL.json +57 -0
  83. package/src/locales/pl.json +57 -0
  84. package/src/locales/ru.json +57 -0
  85. package/src/locales/sq.json +57 -0
  86. package/src/locales/zh_CN.json +57 -0
  87. package/src/proptypes/index.js +10 -0
  88. package/src/queries/index.js +16 -0
  89. package/src/styles/apps.css +248 -0
  90. package/src/styles/banner.css +64 -0
  91. package/src/styles/bar.css +106 -0
  92. package/src/styles/base.css +21 -0
  93. package/src/styles/claudy.css +98 -0
  94. package/src/styles/drawer.css +126 -0
  95. package/src/styles/index.styl +33 -0
  96. package/src/styles/indicators.css +58 -0
  97. package/src/styles/nav.css +81 -0
  98. package/src/styles/navigation_item.css +34 -0
  99. package/src/styles/searchbar.css +156 -0
  100. package/src/styles/settings.css +34 -0
  101. package/src/styles/storage.css +22 -0
  102. package/src/styles/supportModal.css +20 -0
  103. package/src/styles/theme.styl +25 -0
@@ -0,0 +1,401 @@
1
+ /* eslint-env browser */
2
+ import compare from 'semver-compare'
3
+ import { Intents } from 'cozy-interapp'
4
+ import getIcon from 'lib/icon'
5
+ import initializeRealtime from 'lib/realtime'
6
+
7
+ import {
8
+ ForbiddenException,
9
+ ServerErrorException,
10
+ NotFoundException,
11
+ MethodNotAllowedException,
12
+ UnavailableSettingsException,
13
+ UnavailableStackException,
14
+ UnauthorizedStackException
15
+ } from 'lib/exceptions'
16
+ import { isMobileApp } from 'cozy-device-helper'
17
+
18
+ const errorStatuses = {
19
+ '401': UnauthorizedStackException,
20
+ '403': ForbiddenException,
21
+ '404': NotFoundException,
22
+ '405': MethodNotAllowedException,
23
+ '500': ServerErrorException
24
+ }
25
+
26
+ /**
27
+ * Cozy client instance
28
+ * @private
29
+ */
30
+ let cozyClient
31
+
32
+ /**
33
+ * Get the client instance
34
+ *
35
+ * @private
36
+ * @function
37
+ * @returns {Object} cozy-client instance
38
+ */
39
+ const getIntents = function() {
40
+ return new Intents({ client: cozyClient })
41
+ }
42
+
43
+ /**
44
+ * Get the stackClient from the cozy-client instance
45
+ *
46
+ * @private
47
+ * @function
48
+ * @returns {Object} cozy-stack-client instance
49
+ */
50
+ const getStackClient = function() {
51
+ return cozyClient.getStackClient()
52
+ }
53
+
54
+ /**
55
+ * Logout and disconnect the user
56
+ * @function
57
+ * @TODO move this to cozy-stack-client
58
+ * @returns {Promise}
59
+ */
60
+ const logout = function() {
61
+ return getStackClient()
62
+ .fetch('DELETE', '/auth/login')
63
+ .then(resp => {
64
+ if (resp.status === 401) {
65
+ throw new UnauthorizedStackException()
66
+ } else if (resp.status === 204) {
67
+ window.location.reload()
68
+ }
69
+ return true
70
+ })
71
+ .catch(() => {
72
+ throw new UnavailableStackException()
73
+ })
74
+ }
75
+
76
+ /**
77
+ * Get a cozy URL object
78
+ *
79
+ * @function
80
+ * @returns {URL}
81
+ */
82
+ const getCozyURL = function() {
83
+ return new URL(getStackClient().uri)
84
+ }
85
+
86
+ /**
87
+ * Get a the cozy origin as an URL string
88
+ *
89
+ * @function
90
+ * @returns {string}
91
+ */
92
+ const getCozyURLOrigin = function() {
93
+ return getCozyURL().origin
94
+ }
95
+
96
+ /**
97
+ * @deprecated
98
+ * @private
99
+ */
100
+ const updateAccessToken = function() {
101
+ throw new Error(
102
+ 'updateAccessToken should not be used with a cozy-client instance initialization'
103
+ )
104
+ }
105
+
106
+ /**
107
+ * Fetch a resource with cozy-client
108
+ *
109
+ * Utility to maintain the compatibility with the legacy
110
+ * standalone cozy-bar client
111
+ *
112
+ * @function
113
+ * @private
114
+ * @returns {Promise} the full raw JSON payload
115
+ */
116
+ const fetchJSON = function(method, path, body, options = {}) {
117
+ // We mirror here a few lines from cozy-stack-client
118
+ // because we want a customized fetchJSON
119
+ const headers = (options.headers = options.headers || {})
120
+ headers['Accept'] = 'application/json'
121
+ if (method !== 'GET' && method !== 'HEAD' && body !== undefined) {
122
+ if (!headers['Content-Type']) {
123
+ headers['Content-Type'] = 'application/json'
124
+ body = JSON.stringify(body)
125
+ }
126
+ }
127
+
128
+ return getStackClient()
129
+ .fetch(method, path, body, options)
130
+ .then(resp => {
131
+ if (typeof errorStatuses[resp.status] === 'function') {
132
+ throw new errorStatuses[resp.status]()
133
+ }
134
+ const contentType = resp.headers.get('content-type')
135
+ const isJson = contentType.includes('json')
136
+ if (!isJson) {
137
+ throw new Error('Server response not in JSON')
138
+ }
139
+ return resp.json()
140
+ })
141
+ }
142
+
143
+ /**
144
+ * Test if an error is from an HTTP 404
145
+ *
146
+ * @function
147
+ * @private
148
+ * @param {Function} error - received from a fetch
149
+ * @returns {boolean}
150
+ */
151
+ const is404 = function(error) {
152
+ return (
153
+ ['NotFoundException', 'NotFound', 'FetchError'].includes(error.name) &&
154
+ error.status &&
155
+ error.status === 404
156
+ )
157
+ }
158
+
159
+ /**
160
+ * Memoize the result of a function which does an HTTP fetch
161
+ *
162
+ * If a call throws an error because the
163
+ * underlying HTTP request returned a 404
164
+ * then this function returns a default value
165
+ *
166
+ * In the absence of any other error, the result is
167
+ * cached and reused in the next call to the function.
168
+ *
169
+ *
170
+ * @function
171
+ * @param {Function} fn - the function to memoize. It will be
172
+ * called without any parameter
173
+ * @param {Object} defaultValue - returned in case of 404
174
+ * @returns {Function} async function
175
+ */
176
+
177
+ const withCache = function(fn, defaultValue) {
178
+ let cache = undefined
179
+ return async function() {
180
+ if (cache === undefined) {
181
+ try {
182
+ cache = await fn()
183
+ } catch (error) {
184
+ cache = is404(error) ? defaultValue : undefined
185
+ }
186
+ }
187
+ return cache
188
+ }
189
+ }
190
+
191
+ /**
192
+ * List all installed applications
193
+ *
194
+ * Returns only the `data` key of the
195
+ * whole JSON payload from the server
196
+ *
197
+ * @function
198
+ * @returns {Promise}
199
+ */
200
+ const getApps = function() {
201
+ return fetchJSON('GET', '/apps/').then(json => {
202
+ if (json.error) {
203
+ throw new Error(json.error)
204
+ }
205
+ return json.data
206
+ })
207
+ }
208
+
209
+ /**
210
+ * Detail of an installed application by its slug
211
+ *
212
+ * Returns only the `data` key of the
213
+ * whole JSON payload from the server
214
+ *
215
+ * @function
216
+ * @param {string} slug
217
+ * @returns {Promise}
218
+ */
219
+ const getApp = function(slug) {
220
+ if (!slug) {
221
+ throw new Error('Missing slug')
222
+ }
223
+ return fetchJSON('GET', `/apps/${slug}`).then(json => {
224
+ if (json.error) {
225
+ throw new Error(json.error)
226
+ }
227
+ return json.data
228
+ })
229
+ }
230
+
231
+ /**
232
+ * default value when no quota is provided
233
+ * @private
234
+ */
235
+ const defaultQuota = 10 ** 12 // 1 Tera
236
+
237
+ /**
238
+ * Get storage and quota usage
239
+ *
240
+ * When no quota is returned by the server
241
+ * the quota used is the larger between
242
+ * `defaultQuota` and 10 * usage
243
+ *
244
+ * @function
245
+ * @returns {Object} {usage, quota, isLimited}
246
+ */
247
+ const getStorageData = function() {
248
+ return fetchJSON('GET', '/settings/disk-usage')
249
+ .then(json => {
250
+ // parseInt because responses from the server are in text
251
+ const usage = parseInt(json.data.attributes.used, 10)
252
+ const realQuota = parseInt(json.data.attributes.quota, 10)
253
+ // @TODO this is a workaround, we should certainly do smarter
254
+ // and either not requiring this attribute
255
+ // or set it to something more real
256
+ const quota = realQuota || Math.max(defaultQuota, 10 * usage)
257
+ const isLimited = json.data.attributes.is_limited
258
+ return { usage, quota, isLimited }
259
+ })
260
+ .catch(() => {
261
+ throw new UnavailableStackException()
262
+ })
263
+ }
264
+
265
+ /**
266
+ * Fetch an icon data from its path
267
+ *
268
+ * The purpose of this function is to be sent
269
+ * to AppIcon components for mobile devices.
270
+ *
271
+ * @private
272
+ * @function
273
+ * @param {string} iconPath - path of the icon in the stack
274
+ * @returns {Blob}
275
+ */
276
+ const iconFetcher = function(iconPath) {
277
+ return getStackClient().fetch('GET', iconPath)
278
+ }
279
+
280
+ /**
281
+ * Get a props object that can be sent to an AppIcon component
282
+ *
283
+ * Mobile devices and web browsers need different props
284
+ *
285
+ * @function
286
+ * @returns {Object}
287
+ */
288
+ const getAppIconProps = function() {
289
+ const mobileAppIconProps = {
290
+ fetchIcon: app => getIcon(iconFetcher, app, true)
291
+ }
292
+
293
+ const browserAppIconProps = {
294
+ // we mustn't give the protocol here
295
+ domain: getCozyURL().host,
296
+ secure: getCozyURL().protocol === 'https:'
297
+ }
298
+ return isMobileApp() ? mobileAppIconProps : browserAppIconProps
299
+ }
300
+
301
+ /**
302
+ * Get settings context
303
+ *
304
+ * @function
305
+ * @return {Promise}
306
+ * @see https://docs.cozy.io/en/cozy-stack/settings/#get-settingscontext
307
+ */
308
+ const getContext = function() {
309
+ return fetchJSON('GET', '/settings/context')
310
+ }
311
+
312
+ /**
313
+ * Fetch a resource on the cozy stack
314
+ * with a prototype compatible with the legacy cozy-client-js
315
+ *
316
+ * @function
317
+ * @param {object} cozy - cozy-client-js
318
+ * @param {string} method - HTTP method
319
+ * @param {string} path
320
+ * @param {object} body
321
+ * @returns {Promise}
322
+ */
323
+ const cozyFetchJSON = function(cozy, method, path, body) {
324
+ return fetchJSON(method, path, body).then(json => {
325
+ const responseData = Object.assign({}, json.data)
326
+ if (responseData.id) {
327
+ responseData._id = responseData.id
328
+ }
329
+ return responseData
330
+ })
331
+ }
332
+
333
+ const getSettingsAppURL = function() {
334
+ return getApp('settings').then(settings => {
335
+ if (!settings) {
336
+ throw new UnavailableSettingsException()
337
+ }
338
+ return settings.links.related
339
+ })
340
+ }
341
+
342
+ /**
343
+ *
344
+ * @param {cozyClient} forcedCozyClient only used to test purpose
345
+ *
346
+ * We can not read `version` from `import CozyClient from cozy-client`
347
+ * since in that case, we'll read version from the cozy-bar node modules
348
+ * and not from the app one.
349
+ *
350
+ * In order to avoid this issue, we get the instance passed by the app to the bar),
351
+ * then read the constructor and then read the version from it
352
+ */
353
+ const compareClientVersion = function(targetVersion, forcedCozyClient = null) {
354
+ const usedClient = cozyClient ? cozyClient.constructor : {}
355
+ const cozyClientToUse =
356
+ forcedCozyClient !== null ? forcedCozyClient : usedClient
357
+
358
+ if (!cozyClientToUse.version) return false
359
+ const result = compare(cozyClientToUse.version, targetVersion)
360
+ return result >= 0
361
+ }
362
+
363
+ /**
364
+ * Initializes the functions to call the cozy stack
365
+ *
366
+ * @function
367
+ * @param {Object} arg
368
+ * @param {Object} arg.cozyClient - a cozy client instance
369
+ * @param {Function} arg.onCreate
370
+ * @param {Function} arg.onDelete
371
+ * @returns {Promise}
372
+ */
373
+ const init = function({ cozyClient: client, onCreate, onDelete }) {
374
+ cozyClient = client
375
+ if (!cozyClient.isLogged) return
376
+ initializeRealtime({
377
+ getApp,
378
+ onCreate,
379
+ onDelete,
380
+ cozyClient
381
+ })
382
+ }
383
+
384
+ export { compareClientVersion }
385
+
386
+ export default {
387
+ get: {
388
+ app: getApp,
389
+ apps: getApps,
390
+ context: withCache(getContext, {}),
391
+ storageData: getStorageData,
392
+ iconProps: getAppIconProps,
393
+ cozyURL: getCozyURLOrigin,
394
+ intents: getIntents,
395
+ settingsAppURL: getSettingsAppURL
396
+ },
397
+ updateAccessToken,
398
+ cozyFetchJSON,
399
+ logout,
400
+ init
401
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * This file served as a proxy between the old internal stack client from the
3
+ * bar and the new stack-client included in cozy-client. It is no longer
4
+ * necessary as there is no more internal-client. It is there only temporarily
5
+ * and should be removed as soon as possible.
6
+ *
7
+ * @TODO remove this and update the tests.
8
+ */
9
+
10
+ import client from 'lib/stack-client'
11
+
12
+ /**
13
+ * Reference to the current client depending
14
+ * on which one has been initialized
15
+ *
16
+ * @private
17
+ */
18
+ let stack
19
+
20
+ /**
21
+ * Get the current stack client (legacy or cozy-client based)
22
+ * based on which one has been initialized
23
+ *
24
+ * @returns {Object} functions to call the stack
25
+ */
26
+ const current = function() {
27
+ if (!stack) {
28
+ throw new Error('client not initialized in cozy-bar')
29
+ }
30
+ return stack
31
+ }
32
+
33
+ /**
34
+ * Initializes the functions to call the cozy stack
35
+ *
36
+ * It can be initialized either with a cozy-client instance
37
+ * or a { cozyURL, ssl, token } tupple.
38
+ *
39
+ * @function
40
+ * @param {Object} arg
41
+ * @param {Object} arg.cozyClient - a cozy client instance
42
+ * @param {string} arg.cozyURL - URL or domain of the stack
43
+ * @param {boolean} arg.ssl - Tells if we should use a secure protocol
44
+ * required if cozyURL does not have a protocol
45
+ * @param {string} arg.token - Access token for the stack
46
+ * @param {Function} arg.onCreateApp
47
+ * @param {Function} arg.onDeleteApp
48
+ * @param {Boolean} arg.isPublic
49
+ * @returns {Promise}
50
+ */
51
+ const init = function(options) {
52
+ stack = client
53
+ return stack.init(options)
54
+ }
55
+
56
+ const get = {
57
+ app: (...args) => current().get.app(...args),
58
+ apps: (...args) => current().get.apps(...args),
59
+ context: (...args) => current().get.context(...args),
60
+ storageData: (...args) => current().get.storageData(...args),
61
+ iconProps: (...args) => current().get.iconProps(...args),
62
+ cozyURL: (...args) => current().get.cozyURL(...args),
63
+ settingsAppURL: (...args) => current().get.settingsAppURL(...args)
64
+ }
65
+
66
+ const stackProxy = {
67
+ init,
68
+ get,
69
+ updateAccessToken: (...args) => current().updateAccessToken(...args),
70
+ logout: (...args) => current().logout(...args),
71
+ cozyFetchJSON: (...args) => current().cozyFetchJSON(...args),
72
+ // useful to connect some getters outside of this file without exposing
73
+ // directly the private stack variable
74
+ getStack: current,
75
+ getIntents: () => current().get.intents()
76
+ }
77
+
78
+ export default stackProxy
79
+ export const { cozyFetchJSON, getIntents } = stackProxy
@@ -0,0 +1,44 @@
1
+ import { createStore as createReduxStore, applyMiddleware } from 'redux'
2
+ import appsI18nMiddleware from 'lib/middlewares/appsI18n'
3
+ import thunkMiddleware from 'redux-thunk'
4
+ import { persistStore, persistCombineReducers } from 'redux-persist'
5
+ import { reducers } from 'lib/reducers'
6
+ import { createLogger } from 'redux-logger'
7
+ import storage from 'redux-persist/lib/storage'
8
+ import persistWhitelist from 'config/persistWhitelist.json'
9
+ import logger from '../logger'
10
+ import flag from 'cozy-flags'
11
+
12
+ const config = {
13
+ storage,
14
+ key: 'cozy-bar',
15
+ whitelist: persistWhitelist
16
+ }
17
+
18
+ const loggerMiddleware = createLogger({
19
+ logger
20
+ })
21
+
22
+ const reducer = persistCombineReducers(config, { ...reducers })
23
+
24
+ const middlewares = [appsI18nMiddleware, thunkMiddleware]
25
+
26
+ if (flag('bar.debug')) {
27
+ middlewares.push(loggerMiddleware)
28
+ }
29
+
30
+ export const createStore = () => {
31
+ store = createReduxStore(reducer, applyMiddleware.apply(null, middlewares))
32
+ persistStore(store)
33
+ return store
34
+ }
35
+
36
+ let store
37
+ const getOrCreateStore = () => {
38
+ if (!store) {
39
+ store = createStore()
40
+ }
41
+ return store
42
+ }
43
+
44
+ export default getOrCreateStore
@@ -0,0 +1,57 @@
1
+ {
2
+ "drawer": "Menü anzeigen",
3
+ "profile": "Profile",
4
+ "connectedDevices": "Verbundene Geräte",
5
+ "storage": "Speicher",
6
+ "storage_phrase": "%{diskUsage} GB von %{diskQuota} GB benutzt",
7
+ "view_offers": "View offers",
8
+ "view_my_offer": "My offer",
9
+ "help": "Hilfe",
10
+ "logout": "Ausloggen",
11
+ "soon": "Später",
12
+ "error_UnavailableStack": "Der Stapel ist nicht erreichbar (Verbindung Zeitüberschreitung).",
13
+ "error_UnauthorizedStack": "Einige Berechtigungen fehlen, die Anwendung kann nicht auf die angeforderte Ressource auf dem Stapel zugreifen.",
14
+ "no_apps": "Keine Anwendungen für Cozy gefunden.",
15
+
16
+ "menu": {
17
+ "apps": "Anwendungen",
18
+ "settings": "Einstellungen",
19
+ "home_mobile": "Back to home...",
20
+ "home": "Back to home",
21
+ "home_title": "Home"
22
+ },
23
+
24
+ "Categories": {
25
+ "cozy": "Cozy Anwendungen",
26
+ "partners": "Partner Anwendungen",
27
+ "ptnb": "expPTNB",
28
+ "others": "Andere Anwendungen"
29
+ },
30
+
31
+ "claudy": {
32
+ "title": "Wie willst du dein Cozy steuern?"
33
+ },
34
+
35
+ "searchbar": {
36
+ "placeholder": "Alle Dateien durchsuchen",
37
+ "empty": "Es wurde kein Ergebnis für die Suche \"%{query}\" gefunden"
38
+ },
39
+
40
+ "permsModal": {
41
+ "title": "Greife von deiner Anwendung aus auf dein komplettes Cozy zu",
42
+ "description": "Erlaube %{app} den Zugriff auf deine Cozy Anwendungen auf diesem Gerät",
43
+ "button": "Erlaube Zugriff"
44
+ },
45
+ "comingSoon": {
46
+ "store": {
47
+ "title": "Die Store Anwendung wird in deinem Cozy bald verfügbar sein.",
48
+ "description": "Dank Cozy Store wird es bald möglich sein gewünschte Anwendungen in dein Cozy zu installieren."
49
+ }
50
+ },
51
+ "banner": {
52
+ "tos-updated": {
53
+ "description": "To comply with the GDPR, Cozy Cloud has updated its Terms of Services that have taken effect on May 25, 2018",
54
+ "CTA": "Jetzt lesen"
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,57 @@
1
+ {
2
+ "drawer": "Show menu drawer",
3
+ "profile": "Profile",
4
+ "connectedDevices": "Connected devices",
5
+ "storage": "Storage",
6
+ "storage_phrase": "%{diskUsage} GB of %{diskQuota} GB used",
7
+ "view_offers": "View offers",
8
+ "view_my_offer": "My offer",
9
+ "help": "Help",
10
+ "logout": "Sign out",
11
+ "soon": "soon",
12
+ "error_UnavailableStack": "The stack is unreachable (connection timed-out).",
13
+ "error_UnauthorizedStack": "Some permissions are missing, the application can't access the requested resource on the stack.",
14
+ "no_apps": "No applications found on the Cozy.",
15
+
16
+ "menu": {
17
+ "apps": "Apps",
18
+ "settings": "Settings",
19
+ "home_mobile": "Back to home...",
20
+ "home": "Back to home",
21
+ "home_title": "Home"
22
+ },
23
+
24
+ "Categories": {
25
+ "cozy": "Cozy apps",
26
+ "partners": "Partners apps",
27
+ "ptnb": "expPTNB",
28
+ "others": "Other apps"
29
+ },
30
+
31
+ "claudy": {
32
+ "title": "How to drive your Cozy?"
33
+ },
34
+
35
+ "searchbar": {
36
+ "placeholder": "Search anything",
37
+ "empty": "No result has been found for the query “%{query}”"
38
+ },
39
+
40
+ "permsModal": {
41
+ "title": "Access your whole Cozy from your application",
42
+ "description": "Authorize %{app} to display your Cozy applications on this device",
43
+ "button": "Authorize access"
44
+ },
45
+ "comingSoon": {
46
+ "store": {
47
+ "title": "The Store application will be available soon in your Cozy.",
48
+ "description": "Thanks to Cozy Store you will be able to install the applications that you want in your Cozy."
49
+ }
50
+ },
51
+ "banner": {
52
+ "tos-updated": {
53
+ "description": "To comply with the GDPR, Cozy Cloud has updated its Terms of Services that have taken effect on May 25, 2018",
54
+ "CTA": "Read now"
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,57 @@
1
+ {
2
+ "drawer": "Mostrar el menu lateral",
3
+ "profile": "Perfil",
4
+ "connectedDevices": "Aparatos conectados",
5
+ "storage": "Espacio en el disco",
6
+ "storage_phrase": "%{diskUsage} Go de %{diskQuota} Go",
7
+ "view_offers": "Ver ofertas",
8
+ "view_my_offer": "Mi oferta",
9
+ "help": "Ayuda",
10
+ "logout": "Desconectar",
11
+ "soon": "pronto",
12
+ "error_UnavailableStack": "Conexión a la stack imposible ( se agotó el tiempo para la conexión ).",
13
+ "error_UnauthorizedStack": "Faltan algunos permisos, la aplicación no puede acceder a los recursos solicitados.",
14
+ "no_apps": "No se han encontrado aplicaciones en su Cozy.",
15
+
16
+ "menu": {
17
+ "apps": "Aplicaciones",
18
+ "settings": "Parámetros",
19
+ "home_mobile": "Regresar a Inicio...",
20
+ "home": "Regresar a Inicio",
21
+ "home_title": "Inicio"
22
+ },
23
+
24
+ "Categories": {
25
+ "cozy": "Aplicaciones Cozy",
26
+ "partners": "Aplicaciones de asociados",
27
+ "ptnb": "expPTNB",
28
+ "others": "Otras aplicaciones"
29
+ },
30
+
31
+ "claudy": {
32
+ "title": "¿Cómo utilizar su Cozy?"
33
+ },
34
+
35
+ "searchbar": {
36
+ "placeholder": "Buscar",
37
+ "empty": "No se ha encontrado ningún resultado para su consulta “%{query}”"
38
+ },
39
+
40
+ "permsModal": {
41
+ "title": "Acceder a su Cozy desde su aplicación",
42
+ "description": "Autorizar a %{app} para mostrar sus aplicaciones Cozy en este aparato",
43
+ "button": "Autorizar el acceso"
44
+ },
45
+ "comingSoon": {
46
+ "store": {
47
+ "title": "En breve, la aplicación Store estará disponible en su Cozy",
48
+ "description": "Gracias a Cozy Store usted podrá instalar en su Cozy las aplicaciones que desee."
49
+ }
50
+ },
51
+ "banner": {
52
+ "tos-updated": {
53
+ "description": "Para cumplir con el RGPD, Cozy Cloud ha actualizado sus Condiciones de utilización que entraron en vigor desde el 25 de mayo de 2018.",
54
+ "CTA": "Leerlo ahora"
55
+ }
56
+ }
57
+ }