cozy-ui 111.6.0 → 111.7.0
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/CHANGELOG.md +7 -0
- package/package.json +1 -1
- package/react/AppIcon/index.jsx +9 -0
- package/react/AppSections/Sections.jsx +48 -1
- package/react/AppSections/__snapshots__/index.spec.jsx.snap +10 -0
- package/react/AppSections/categories.js +35 -11
- package/react/AppSections/categories.spec.js +6 -0
- package/react/AppSections/components/__snapshots__/AppsSection.spec.jsx.snap +1 -1
- package/react/AppSections/constants.js +6 -1
- package/react/AppSections/generateI18nConfig.ts +23 -0
- package/react/AppSections/helpers.js +8 -0
- package/react/AppSections/locales/en.json +4 -2
- package/react/AppSections/locales/fr.json +4 -2
- package/react/AppTile/AppTile.spec.jsx +4 -3
- package/react/AppTile/index.jsx +32 -11
- package/react/AppTile/locales/en.json +2 -1
- package/react/AppTile/locales/fr.json +2 -1
- package/react/ShortcutTile/index.tsx +63 -0
- package/react/types.d.ts +4 -0
- package/transpiled/react/AppIcon/index.js +11 -1
- package/transpiled/react/AppSections/Sections.js +39 -5
- package/transpiled/react/AppSections/categories.js +31 -3
- package/transpiled/react/AppSections/constants.js +5 -1
- package/transpiled/react/AppSections/generateI18nConfig.d.ts +6 -0
- package/transpiled/react/AppSections/generateI18nConfig.js +25 -0
- package/transpiled/react/AppSections/helpers.js +5 -0
- package/transpiled/react/AppTile/index.js +21 -6
- package/transpiled/react/ShortcutTile/index.d.ts +15 -0
- package/transpiled/react/ShortcutTile/index.js +53 -0
- package/transpiled/react/Tile/index.d.ts +68 -0
- package/transpiled/react/Typography/index.d.ts +3 -0
- package/transpiled/react/types.d.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [111.7.0](https://github.com/cozy/cozy-ui/compare/v111.6.0...v111.7.0) (2024-08-14)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* handle shortcuttiles ([e5ff800](https://github.com/cozy/cozy-ui/commit/e5ff800))
|
|
7
|
+
|
|
1
8
|
# [111.6.0](https://github.com/cozy/cozy-ui/compare/v111.5.0...v111.6.0) (2024-08-14)
|
|
2
9
|
|
|
3
10
|
|
package/package.json
CHANGED
package/react/AppIcon/index.jsx
CHANGED
|
@@ -5,8 +5,10 @@ import React, { Component } from 'react'
|
|
|
5
5
|
import { withClient } from 'cozy-client'
|
|
6
6
|
|
|
7
7
|
import styles from './styles.styl'
|
|
8
|
+
import { isShortcutFile } from '../AppSections/helpers'
|
|
8
9
|
import Icon, { iconPropType } from '../Icon'
|
|
9
10
|
import CubeIcon from '../Icons/Cube'
|
|
11
|
+
import { ShortcutTile } from '../ShortcutTile'
|
|
10
12
|
import palette from '../palette'
|
|
11
13
|
import { AppDoctype } from '../proptypes'
|
|
12
14
|
|
|
@@ -45,6 +47,9 @@ export class AppIcon extends Component {
|
|
|
45
47
|
fetchIcon() {
|
|
46
48
|
const { app, type, priority, client } = this.props
|
|
47
49
|
|
|
50
|
+
// Shortcut files used in cozy-store have their own icon in their doctype metadata
|
|
51
|
+
if (isShortcutFile(app)) return
|
|
52
|
+
|
|
48
53
|
return client.getStackClient().getIconURL({
|
|
49
54
|
type,
|
|
50
55
|
slug: app.slug || app,
|
|
@@ -93,6 +98,10 @@ export class AppIcon extends Component {
|
|
|
93
98
|
const { alt, className, fallbackIcon } = this.props
|
|
94
99
|
const { icon, status } = this.state
|
|
95
100
|
|
|
101
|
+
if (isShortcutFile(this.props.app)) {
|
|
102
|
+
return <ShortcutTile file={this.props.app} />
|
|
103
|
+
}
|
|
104
|
+
|
|
96
105
|
switch (status) {
|
|
97
106
|
case FETCHING:
|
|
98
107
|
return (
|
|
@@ -2,11 +2,16 @@ import cx from 'classnames'
|
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import React, { Component } from 'react'
|
|
4
4
|
|
|
5
|
+
import flag from 'cozy-flags'
|
|
6
|
+
import { useExtendI18n } from 'cozy-ui/transpiled/react/providers/I18n'
|
|
7
|
+
|
|
5
8
|
import styles from './Sections.styl'
|
|
6
9
|
import * as catUtils from './categories'
|
|
7
10
|
import AppsSection from './components/AppsSection'
|
|
8
11
|
import DropdownFilter from './components/DropdownFilter'
|
|
9
12
|
import { APP_TYPE } from './constants'
|
|
13
|
+
import { generateI18nConfig } from './generateI18nConfig'
|
|
14
|
+
import { isShortcutFile } from './helpers'
|
|
10
15
|
import en from './locales/en.json'
|
|
11
16
|
import fr from './locales/fr.json'
|
|
12
17
|
import * as searchUtils from './search'
|
|
@@ -105,12 +110,19 @@ export class Sections extends Component {
|
|
|
105
110
|
const webAppGroups = catUtils.groupApps(
|
|
106
111
|
filteredApps.filter(a => a.type === APP_TYPE.WEBAPP)
|
|
107
112
|
)
|
|
113
|
+
const shortcutsGroups = catUtils.groupApps(
|
|
114
|
+
filteredApps.filter(a => isShortcutFile(a))
|
|
115
|
+
)
|
|
116
|
+
|
|
108
117
|
const webAppsCategories = Object.keys(webAppGroups)
|
|
109
118
|
.map(cat => catUtils.addLabel({ value: cat }, t))
|
|
110
119
|
.sort(catUtils.sorter)
|
|
111
120
|
const konnectorsCategories = Object.keys(konnectorGroups)
|
|
112
121
|
.map(cat => catUtils.addLabel({ value: cat }, t))
|
|
113
122
|
.sort(catUtils.sorter)
|
|
123
|
+
const shortcutsCategories = Object.keys(shortcutsGroups)
|
|
124
|
+
.map(cat => catUtils.addLabel({ value: cat }, t))
|
|
125
|
+
.sort(catUtils.sorter)
|
|
114
126
|
|
|
115
127
|
const dropdownDisplayed =
|
|
116
128
|
hasNav && (isMobile || isTablet) && showFilterDropdown
|
|
@@ -154,6 +166,33 @@ export class Sections extends Component {
|
|
|
154
166
|
})}
|
|
155
167
|
</div>
|
|
156
168
|
)}
|
|
169
|
+
{!!shortcutsCategories.length && (
|
|
170
|
+
<div>
|
|
171
|
+
{showSubTitles && (
|
|
172
|
+
<SectionSubtitle>{t('sections.shortcuts')}</SectionSubtitle>
|
|
173
|
+
)}
|
|
174
|
+
|
|
175
|
+
{shortcutsCategories.map(cat => {
|
|
176
|
+
return (
|
|
177
|
+
<AppsSection
|
|
178
|
+
key={cat.value}
|
|
179
|
+
{...componentsProps?.appsSection}
|
|
180
|
+
appsList={shortcutsGroups[cat.value]}
|
|
181
|
+
subtitle={
|
|
182
|
+
showSubSubTitles ? (
|
|
183
|
+
<SectionSubSubtitle>{cat.label}</SectionSubSubtitle>
|
|
184
|
+
) : null
|
|
185
|
+
}
|
|
186
|
+
IconComponent={IconComponent}
|
|
187
|
+
onAppClick={onAppClick}
|
|
188
|
+
displaySpecificMaintenanceStyle={
|
|
189
|
+
displaySpecificMaintenanceStyle
|
|
190
|
+
}
|
|
191
|
+
/>
|
|
192
|
+
)
|
|
193
|
+
})}
|
|
194
|
+
</div>
|
|
195
|
+
)}
|
|
157
196
|
{!!konnectorsCategories.length && (
|
|
158
197
|
<div>
|
|
159
198
|
{showSubTitles && (
|
|
@@ -186,6 +225,14 @@ export class Sections extends Component {
|
|
|
186
225
|
}
|
|
187
226
|
}
|
|
188
227
|
|
|
228
|
+
const SectionsWrapper = props => {
|
|
229
|
+
const config = flag('store.alternative-source')
|
|
230
|
+
const i18nConfig = generateI18nConfig(config?.categories)
|
|
231
|
+
useExtendI18n(i18nConfig)
|
|
232
|
+
|
|
233
|
+
return <Sections {...props} />
|
|
234
|
+
}
|
|
235
|
+
|
|
189
236
|
Sections.propTypes = {
|
|
190
237
|
t: PropTypes.func.isRequired,
|
|
191
238
|
|
|
@@ -230,6 +277,6 @@ Sections.defaultProps = {
|
|
|
230
277
|
})
|
|
231
278
|
}
|
|
232
279
|
|
|
233
|
-
export const Untranslated = withBreakpoints()(
|
|
280
|
+
export const Untranslated = withBreakpoints()(SectionsWrapper)
|
|
234
281
|
|
|
235
282
|
export default withLocales(locales)(translate()(Untranslated))
|
|
@@ -1075,6 +1075,11 @@ exports[`AppsSection component should render dropdown filter on mobile if no nav
|
|
|
1075
1075
|
"type": "webapp",
|
|
1076
1076
|
"value": "partners",
|
|
1077
1077
|
},
|
|
1078
|
+
Object {
|
|
1079
|
+
"label": "Shortcuts",
|
|
1080
|
+
"secondary": false,
|
|
1081
|
+
"value": "shortcuts",
|
|
1082
|
+
},
|
|
1078
1083
|
Object {
|
|
1079
1084
|
"label": "Services",
|
|
1080
1085
|
"secondary": false,
|
|
@@ -1476,6 +1481,11 @@ exports[`AppsSection component should render dropdown filter on tablet if no nav
|
|
|
1476
1481
|
"type": "webapp",
|
|
1477
1482
|
"value": "partners",
|
|
1478
1483
|
},
|
|
1484
|
+
Object {
|
|
1485
|
+
"label": "Shortcuts",
|
|
1486
|
+
"secondary": false,
|
|
1487
|
+
"value": "shortcuts",
|
|
1488
|
+
},
|
|
1479
1489
|
Object {
|
|
1480
1490
|
"label": "Services",
|
|
1481
1491
|
"secondary": false,
|
|
@@ -38,21 +38,37 @@ export const groupApps = apps => multiGroupBy(apps, getAppCategory)
|
|
|
38
38
|
* Alphabetical sort on label except for
|
|
39
39
|
* - 'all' value always at the beginning
|
|
40
40
|
* - 'others' value always at the end
|
|
41
|
+
* - 'cozy' value should be near the beginning, right after 'all'
|
|
42
|
+
* - items of type 'file' should appear alphabetically between 'webapp' and 'konnector'
|
|
41
43
|
*
|
|
42
44
|
* @param {CategoryOption} categoryA
|
|
43
45
|
* @param {CategoryOption} categoryB
|
|
44
46
|
* @return {Number}
|
|
45
47
|
*/
|
|
46
48
|
export const sorter = (categoryA, categoryB) => {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
// Always keep 'all' at the beginning
|
|
50
|
+
if (categoryA.value === 'all') return -1
|
|
51
|
+
if (categoryB.value === 'all') return 1
|
|
52
|
+
|
|
53
|
+
// Always keep 'others' at the end
|
|
54
|
+
if (categoryA.value === 'others') return 1
|
|
55
|
+
if (categoryB.value === 'others') return -1
|
|
56
|
+
|
|
57
|
+
// Keep 'cozy' near the beginning, right after 'all'
|
|
58
|
+
if (categoryA.value === 'cozy') return -1
|
|
59
|
+
if (categoryB.value === 'cozy') return 1
|
|
60
|
+
|
|
61
|
+
// Sort by type order: webapp < file < konnector
|
|
62
|
+
const typeOrder = ['webapp', 'file', 'konnector']
|
|
63
|
+
const typeAIndex = typeOrder.indexOf(categoryA.type)
|
|
64
|
+
const typeBIndex = typeOrder.indexOf(categoryB.type)
|
|
65
|
+
|
|
66
|
+
if (typeAIndex !== typeBIndex) {
|
|
67
|
+
return typeAIndex - typeBIndex
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Alphabetical sort on label for the rest
|
|
71
|
+
return categoryA.label.localeCompare(categoryB.label)
|
|
56
72
|
}
|
|
57
73
|
|
|
58
74
|
export const addLabel = (cat, t) => ({
|
|
@@ -82,7 +98,7 @@ export const generateOptionsFromApps = (apps, options = {}) => {
|
|
|
82
98
|
]
|
|
83
99
|
: []
|
|
84
100
|
|
|
85
|
-
for (const type of [APP_TYPE.WEBAPP, APP_TYPE.KONNECTOR]) {
|
|
101
|
+
for (const type of [APP_TYPE.WEBAPP, APP_TYPE.FILE, APP_TYPE.KONNECTOR]) {
|
|
86
102
|
const catApps = groupApps(apps.filter(a => a.type === type))
|
|
87
103
|
// Add an entry to filter by all konnectors
|
|
88
104
|
if (type === APP_TYPE.KONNECTOR) {
|
|
@@ -93,11 +109,19 @@ export const generateOptionsFromApps = (apps, options = {}) => {
|
|
|
93
109
|
})
|
|
94
110
|
)
|
|
95
111
|
}
|
|
112
|
+
if (type === APP_TYPE.FILE) {
|
|
113
|
+
allCategoryOptions.push(
|
|
114
|
+
addLabel({
|
|
115
|
+
value: 'shortcuts',
|
|
116
|
+
secondary: false
|
|
117
|
+
})
|
|
118
|
+
)
|
|
119
|
+
}
|
|
96
120
|
const categoryOptions = Object.keys(catApps).map(cat => {
|
|
97
121
|
return addLabel({
|
|
98
122
|
value: cat,
|
|
99
123
|
type: type,
|
|
100
|
-
secondary: type === APP_TYPE.KONNECTOR
|
|
124
|
+
secondary: type === APP_TYPE.KONNECTOR || type === APP_TYPE.FILE
|
|
101
125
|
})
|
|
102
126
|
})
|
|
103
127
|
|
|
@@ -104,6 +104,7 @@ describe('generateOptionsFromApps', () => {
|
|
|
104
104
|
type: 'webapp',
|
|
105
105
|
value: 'others'
|
|
106
106
|
},
|
|
107
|
+
{ label: 'Shortcuts', secondary: false, value: 'shortcuts' },
|
|
107
108
|
{
|
|
108
109
|
label: 'Services',
|
|
109
110
|
secondary: false,
|
|
@@ -156,6 +157,11 @@ describe('generateOptionsFromApps', () => {
|
|
|
156
157
|
type: 'webapp',
|
|
157
158
|
value: 'others'
|
|
158
159
|
},
|
|
160
|
+
{
|
|
161
|
+
label: 'Shortcuts',
|
|
162
|
+
secondary: false,
|
|
163
|
+
value: 'shortcuts'
|
|
164
|
+
},
|
|
159
165
|
{
|
|
160
166
|
label: 'Services',
|
|
161
167
|
secondary: false,
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const generateI18nConfig = (categories?: {
|
|
2
|
+
[key: string]: string
|
|
3
|
+
}): {
|
|
4
|
+
en: Record<string, string>
|
|
5
|
+
fr: Record<string, string>
|
|
6
|
+
} => {
|
|
7
|
+
if (!categories) return { en: {}, fr: {} }
|
|
8
|
+
|
|
9
|
+
const i18nConfig: Record<string, string> = {}
|
|
10
|
+
|
|
11
|
+
for (const [key, value] of Object.entries(categories)) {
|
|
12
|
+
// Extract the final part of the path as the display name
|
|
13
|
+
const displayName =
|
|
14
|
+
value?.split('/').pop() ?? ''.replace(/([A-Z])/g, ' $1').trim()
|
|
15
|
+
|
|
16
|
+
i18nConfig[`app_categories.${key}`] = displayName
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
en: i18nConfig,
|
|
21
|
+
fr: i18nConfig
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import _get from 'lodash/get'
|
|
2
2
|
|
|
3
|
+
import { APP_CLASS, APP_TYPE } from './constants'
|
|
4
|
+
|
|
3
5
|
export const getTranslatedManifestProperty = (app, path, t) => {
|
|
4
6
|
if (!t || !app || !path) return _get(app, path, '')
|
|
5
7
|
return t(`apps.${app.slug}.${path}`, {
|
|
6
8
|
_: _get(app, path, '')
|
|
7
9
|
})
|
|
8
10
|
}
|
|
11
|
+
|
|
12
|
+
export const isShortcutFile = app => {
|
|
13
|
+
if (!app) return false
|
|
14
|
+
|
|
15
|
+
return app.type === APP_TYPE.FILE && app.class === APP_CLASS.SHORTCUT
|
|
16
|
+
}
|
|
@@ -26,10 +26,12 @@
|
|
|
26
26
|
"tech": "Tech",
|
|
27
27
|
"telecom": "Telecom",
|
|
28
28
|
"transport": "Transportation",
|
|
29
|
-
"pro": "Work"
|
|
29
|
+
"pro": "Work",
|
|
30
|
+
"shortcuts": "Shortcuts"
|
|
30
31
|
},
|
|
31
32
|
"sections": {
|
|
32
33
|
"applications": "Applications",
|
|
33
|
-
"konnectors": "Services"
|
|
34
|
+
"konnectors": "Services",
|
|
35
|
+
"shortcuts": "Shortcuts"
|
|
34
36
|
}
|
|
35
37
|
}
|
|
@@ -26,10 +26,12 @@
|
|
|
26
26
|
"tech": "Tech",
|
|
27
27
|
"telecom": "Mobile",
|
|
28
28
|
"transport": "Voyage et transport",
|
|
29
|
-
"pro": "Travail"
|
|
29
|
+
"pro": "Travail",
|
|
30
|
+
"shortcuts": "Raccourcis"
|
|
30
31
|
},
|
|
31
32
|
"sections": {
|
|
32
33
|
"applications": "Applications",
|
|
33
|
-
"konnectors": "Services"
|
|
34
|
+
"konnectors": "Services",
|
|
35
|
+
"shortcuts": "Raccourcis"
|
|
34
36
|
}
|
|
35
37
|
}
|
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
import { render } from '@testing-library/react'
|
|
6
6
|
import React from 'react'
|
|
7
7
|
|
|
8
|
-
import CozyClient
|
|
8
|
+
import CozyClient from 'cozy-client'
|
|
9
9
|
|
|
10
10
|
import AppTile from '.'
|
|
11
11
|
import en from '../AppSections/locales/en.json'
|
|
12
|
+
import DemoProvider from '../providers/DemoProvider'
|
|
12
13
|
import I18n from '../providers/I18n'
|
|
13
14
|
|
|
14
15
|
const appMock = {
|
|
@@ -41,11 +42,11 @@ const appMock2 = {
|
|
|
41
42
|
const client = new CozyClient({})
|
|
42
43
|
const Wrapper = props => {
|
|
43
44
|
return (
|
|
44
|
-
<
|
|
45
|
+
<DemoProvider client={client}>
|
|
45
46
|
<I18n dictRequire={() => en} lang="en">
|
|
46
47
|
<AppTile {...props} />
|
|
47
48
|
</I18n>
|
|
48
|
-
</
|
|
49
|
+
</DemoProvider>
|
|
49
50
|
)
|
|
50
51
|
}
|
|
51
52
|
|
package/react/AppTile/index.jsx
CHANGED
|
@@ -7,8 +7,10 @@ import en from './locales/en.json'
|
|
|
7
7
|
import fr from './locales/fr.json'
|
|
8
8
|
import styles from './styles.styl'
|
|
9
9
|
import AppIcon from '../AppIcon'
|
|
10
|
+
import { isShortcutFile } from '../AppSections/helpers.js'
|
|
10
11
|
import Icon from '../Icon'
|
|
11
12
|
import WrenchCircleIcon from '../Icons/WrenchCircle'
|
|
13
|
+
import { ShortcutTile } from '../ShortcutTile'
|
|
12
14
|
import Tile, {
|
|
13
15
|
TileTitle,
|
|
14
16
|
TileSubtitle,
|
|
@@ -18,6 +20,7 @@ import Tile, {
|
|
|
18
20
|
} from '../Tile'
|
|
19
21
|
import palette from '../palette'
|
|
20
22
|
import { AppDoctype } from '../proptypes'
|
|
23
|
+
import useBreakpoints from '../providers/Breakpoints'
|
|
21
24
|
import { createUseI18n } from '../providers/I18n'
|
|
22
25
|
|
|
23
26
|
const locales = { en, fr }
|
|
@@ -47,16 +50,30 @@ export const AppTile = ({
|
|
|
47
50
|
IconComponent: IconComponentProp,
|
|
48
51
|
displaySpecificMaintenanceStyle
|
|
49
52
|
}) => {
|
|
50
|
-
const name = nameProp || app.name
|
|
51
53
|
const { t } = useI18n()
|
|
52
54
|
const { developer = {} } = app
|
|
55
|
+
const { isMobile } = useBreakpoints()
|
|
56
|
+
|
|
57
|
+
const name = nameProp || app.name
|
|
58
|
+
|
|
53
59
|
const statusLabel = getCurrentStatusLabel(app)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
|
|
61
|
+
const isStatusArray = Array.isArray(showStatus)
|
|
62
|
+
|
|
63
|
+
const statusToDisplay =
|
|
64
|
+
isShortcutFile(app) && statusLabel === APP_STATUS.installed && isMobile
|
|
65
|
+
? 'favorite'
|
|
66
|
+
: isStatusArray
|
|
67
|
+
? showStatus.indexOf(statusLabel) > -1 && statusLabel
|
|
68
|
+
: showStatus && statusLabel
|
|
69
|
+
|
|
57
70
|
const IconComponent = IconComponentProp || AppIcon
|
|
71
|
+
|
|
58
72
|
const isInMaintenanceWithSpecificDisplay =
|
|
59
73
|
displaySpecificMaintenanceStyle && statusLabel === APP_STATUS.maintenance
|
|
74
|
+
const tileSubtitle = isShortcutFile(app)
|
|
75
|
+
? app.metadata?.source
|
|
76
|
+
: developer.name
|
|
60
77
|
|
|
61
78
|
return (
|
|
62
79
|
<Tile
|
|
@@ -70,11 +87,15 @@ export const AppTile = ({
|
|
|
70
87
|
isSecondary={statusLabel === APP_STATUS.installed}
|
|
71
88
|
>
|
|
72
89
|
<TileIcon>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
90
|
+
{isShortcutFile(app) ? (
|
|
91
|
+
<ShortcutTile file={app} />
|
|
92
|
+
) : (
|
|
93
|
+
<IconComponent
|
|
94
|
+
app={app}
|
|
95
|
+
className={styles['AppTile-icon']}
|
|
96
|
+
{...getAppIconProps()}
|
|
97
|
+
/>
|
|
98
|
+
)}
|
|
78
99
|
{isInMaintenanceWithSpecificDisplay && (
|
|
79
100
|
<Icon
|
|
80
101
|
data-testid="icon-maintenance"
|
|
@@ -88,8 +109,8 @@ export const AppTile = ({
|
|
|
88
109
|
<TileTitle isMultiline={!statusLabel}>
|
|
89
110
|
{namePrefix ? `${namePrefix} ${name}` : name}
|
|
90
111
|
</TileTitle>
|
|
91
|
-
{
|
|
92
|
-
<TileSubtitle>{`${t('app_item.by')} ${
|
|
112
|
+
{showDeveloper && (
|
|
113
|
+
<TileSubtitle>{`${t('app_item.by')} ${tileSubtitle}`}</TileSubtitle>
|
|
93
114
|
)}
|
|
94
115
|
{statusToDisplay && (
|
|
95
116
|
<TileFooter isAccent={statusLabel === APP_STATUS.update}>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import { IOCozyFile } from 'cozy-client/types/types'
|
|
4
|
+
// @ts-expect-error - The following component is not typed
|
|
5
|
+
import { nameToColor } from 'cozy-ui/react/Avatar/helpers'
|
|
6
|
+
// @ts-expect-error - The following component is not typed
|
|
7
|
+
import Typography from 'cozy-ui/react/Typography'
|
|
8
|
+
|
|
9
|
+
import styles from '../AppTile/styles.styl'
|
|
10
|
+
import { TileIcon } from '../Tile'
|
|
11
|
+
import { makeStyles } from '../styles'
|
|
12
|
+
|
|
13
|
+
interface ShortcutTileProps {
|
|
14
|
+
file: Partial<IOCozyFile> & {
|
|
15
|
+
name: string
|
|
16
|
+
attributes?: { metadata?: { icon?: string; iconMimeType?: string } }
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const useStyles = makeStyles({
|
|
21
|
+
letter: {
|
|
22
|
+
color: 'white',
|
|
23
|
+
margin: 'auto'
|
|
24
|
+
},
|
|
25
|
+
letterWrapper: {
|
|
26
|
+
backgroundColor: ({ name }: { name: string }) =>
|
|
27
|
+
(nameToColor as (name: string) => string)(name)
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
export const ShortcutTile = ({ file }: ShortcutTileProps): JSX.Element => {
|
|
32
|
+
const classes = useStyles({ name: file.name })
|
|
33
|
+
const icon = file.attributes?.metadata?.icon
|
|
34
|
+
const iconMimeType = file.attributes?.metadata?.iconMimeType
|
|
35
|
+
|
|
36
|
+
if (icon) {
|
|
37
|
+
return (
|
|
38
|
+
<TileIcon>
|
|
39
|
+
<img
|
|
40
|
+
className={styles['AppTile-icon']}
|
|
41
|
+
src={
|
|
42
|
+
iconMimeType
|
|
43
|
+
? `data:${iconMimeType};base64,${icon}`
|
|
44
|
+
: `data:image/svg+xml;base64,${window.btoa(icon)}`
|
|
45
|
+
}
|
|
46
|
+
width={48}
|
|
47
|
+
height={48}
|
|
48
|
+
alt={file.name}
|
|
49
|
+
/>
|
|
50
|
+
</TileIcon>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<TileIcon>
|
|
56
|
+
<div className={classes.letterWrapper}>
|
|
57
|
+
<Typography className={classes.letter} variant="h2" align="center">
|
|
58
|
+
{file.name[0].toUpperCase()}
|
|
59
|
+
</Typography>
|
|
60
|
+
</div>
|
|
61
|
+
</TileIcon>
|
|
62
|
+
)
|
|
63
|
+
}
|
package/react/types.d.ts
ADDED
|
@@ -22,8 +22,10 @@ var styles = {
|
|
|
22
22
|
"c-app-icon": "styles__c-app-icon___2_O40",
|
|
23
23
|
"c-app-icon-default": "styles__c-app-icon-default___3CEmt"
|
|
24
24
|
};
|
|
25
|
+
import { isShortcutFile } from "cozy-ui/transpiled/react/AppSections/helpers";
|
|
25
26
|
import Icon, { iconPropType } from "cozy-ui/transpiled/react/Icon";
|
|
26
27
|
import CubeIcon from "cozy-ui/transpiled/react/Icons/Cube";
|
|
28
|
+
import { ShortcutTile } from "cozy-ui/transpiled/react/ShortcutTile";
|
|
27
29
|
import palette from "cozy-ui/transpiled/react/palette";
|
|
28
30
|
import { AppDoctype } from "cozy-ui/transpiled/react/proptypes";
|
|
29
31
|
var DONE = 'done';
|
|
@@ -78,7 +80,9 @@ export var AppIcon = /*#__PURE__*/function (_Component) {
|
|
|
78
80
|
app = _this$props.app,
|
|
79
81
|
type = _this$props.type,
|
|
80
82
|
priority = _this$props.priority,
|
|
81
|
-
client = _this$props.client;
|
|
83
|
+
client = _this$props.client; // Shortcut files used in cozy-store have their own icon in their doctype metadata
|
|
84
|
+
|
|
85
|
+
if (isShortcutFile(app)) return;
|
|
82
86
|
return client.getStackClient().getIconURL({
|
|
83
87
|
type: type,
|
|
84
88
|
slug: app.slug || app,
|
|
@@ -164,6 +168,12 @@ export var AppIcon = /*#__PURE__*/function (_Component) {
|
|
|
164
168
|
icon = _this$state.icon,
|
|
165
169
|
status = _this$state.status;
|
|
166
170
|
|
|
171
|
+
if (isShortcutFile(this.props.app)) {
|
|
172
|
+
return /*#__PURE__*/React.createElement(ShortcutTile, {
|
|
173
|
+
file: this.props.app
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
167
177
|
switch (status) {
|
|
168
178
|
case FETCHING:
|
|
169
179
|
return /*#__PURE__*/React.createElement("div", {
|
|
@@ -13,6 +13,8 @@ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Re
|
|
|
13
13
|
import cx from 'classnames';
|
|
14
14
|
import PropTypes from 'prop-types';
|
|
15
15
|
import React, { Component } from 'react';
|
|
16
|
+
import flag from 'cozy-flags';
|
|
17
|
+
import { useExtendI18n } from 'cozy-ui/transpiled/react/providers/I18n';
|
|
16
18
|
var styles = {
|
|
17
19
|
"Sections__section": "Sections__Sections__section___2onYy"
|
|
18
20
|
};
|
|
@@ -20,6 +22,8 @@ import * as catUtils from "cozy-ui/transpiled/react/AppSections/categories";
|
|
|
20
22
|
import AppsSection from "cozy-ui/transpiled/react/AppSections/components/AppsSection";
|
|
21
23
|
import DropdownFilter from "cozy-ui/transpiled/react/AppSections/components/DropdownFilter";
|
|
22
24
|
import { APP_TYPE } from "cozy-ui/transpiled/react/AppSections/constants";
|
|
25
|
+
import { generateI18nConfig } from "cozy-ui/transpiled/react/AppSections/generateI18nConfig";
|
|
26
|
+
import { isShortcutFile } from "cozy-ui/transpiled/react/AppSections/helpers";
|
|
23
27
|
var en = {
|
|
24
28
|
app_categories: {
|
|
25
29
|
all: "All categories",
|
|
@@ -48,11 +52,13 @@ var en = {
|
|
|
48
52
|
tech: "Tech",
|
|
49
53
|
telecom: "Telecom",
|
|
50
54
|
transport: "Transportation",
|
|
51
|
-
pro: "Work"
|
|
55
|
+
pro: "Work",
|
|
56
|
+
shortcuts: "Shortcuts"
|
|
52
57
|
},
|
|
53
58
|
sections: {
|
|
54
59
|
applications: "Applications",
|
|
55
|
-
konnectors: "Services"
|
|
60
|
+
konnectors: "Services",
|
|
61
|
+
shortcuts: "Shortcuts"
|
|
56
62
|
}
|
|
57
63
|
};
|
|
58
64
|
var fr = {
|
|
@@ -83,11 +89,13 @@ var fr = {
|
|
|
83
89
|
tech: "Tech",
|
|
84
90
|
telecom: "Mobile",
|
|
85
91
|
transport: "Voyage et transport",
|
|
86
|
-
pro: "Travail"
|
|
92
|
+
pro: "Travail",
|
|
93
|
+
shortcuts: "Raccourcis"
|
|
87
94
|
},
|
|
88
95
|
sections: {
|
|
89
96
|
applications: "Applications",
|
|
90
|
-
konnectors: "Services"
|
|
97
|
+
konnectors: "Services",
|
|
98
|
+
shortcuts: "Raccourcis"
|
|
91
99
|
}
|
|
92
100
|
};
|
|
93
101
|
import * as searchUtils from "cozy-ui/transpiled/react/AppSections/search";
|
|
@@ -210,6 +218,9 @@ export var Sections = /*#__PURE__*/function (_Component) {
|
|
|
210
218
|
var webAppGroups = catUtils.groupApps(filteredApps.filter(function (a) {
|
|
211
219
|
return a.type === APP_TYPE.WEBAPP;
|
|
212
220
|
}));
|
|
221
|
+
var shortcutsGroups = catUtils.groupApps(filteredApps.filter(function (a) {
|
|
222
|
+
return isShortcutFile(a);
|
|
223
|
+
}));
|
|
213
224
|
var webAppsCategories = Object.keys(webAppGroups).map(function (cat) {
|
|
214
225
|
return catUtils.addLabel({
|
|
215
226
|
value: cat
|
|
@@ -220,6 +231,11 @@ export var Sections = /*#__PURE__*/function (_Component) {
|
|
|
220
231
|
value: cat
|
|
221
232
|
}, t);
|
|
222
233
|
}).sort(catUtils.sorter);
|
|
234
|
+
var shortcutsCategories = Object.keys(shortcutsGroups).map(function (cat) {
|
|
235
|
+
return catUtils.addLabel({
|
|
236
|
+
value: cat
|
|
237
|
+
}, t);
|
|
238
|
+
}).sort(catUtils.sorter);
|
|
223
239
|
var dropdownDisplayed = hasNav && (isMobile || isTablet) && showFilterDropdown;
|
|
224
240
|
var rawSelectOptions = catUtils.generateOptionsFromApps(apps, {
|
|
225
241
|
includeAll: true
|
|
@@ -244,6 +260,16 @@ export var Sections = /*#__PURE__*/function (_Component) {
|
|
|
244
260
|
IconComponent: IconComponent,
|
|
245
261
|
displaySpecificMaintenanceStyle: displaySpecificMaintenanceStyle
|
|
246
262
|
});
|
|
263
|
+
})), !!shortcutsCategories.length && /*#__PURE__*/React.createElement("div", null, showSubTitles && /*#__PURE__*/React.createElement(SectionSubtitle, null, t('sections.shortcuts')), shortcutsCategories.map(function (cat) {
|
|
264
|
+
return /*#__PURE__*/React.createElement(AppsSection, _extends({
|
|
265
|
+
key: cat.value
|
|
266
|
+
}, componentsProps === null || componentsProps === void 0 ? void 0 : componentsProps.appsSection, {
|
|
267
|
+
appsList: shortcutsGroups[cat.value],
|
|
268
|
+
subtitle: showSubSubTitles ? /*#__PURE__*/React.createElement(SectionSubSubtitle, null, cat.label) : null,
|
|
269
|
+
IconComponent: IconComponent,
|
|
270
|
+
onAppClick: onAppClick,
|
|
271
|
+
displaySpecificMaintenanceStyle: displaySpecificMaintenanceStyle
|
|
272
|
+
}));
|
|
247
273
|
})), !!konnectorsCategories.length && /*#__PURE__*/React.createElement("div", null, showSubTitles && /*#__PURE__*/React.createElement(SectionSubtitle, null, t('sections.konnectors')), konnectorsCategories.map(function (cat) {
|
|
248
274
|
return /*#__PURE__*/React.createElement(AppsSection, _extends({
|
|
249
275
|
key: cat.value
|
|
@@ -260,6 +286,14 @@ export var Sections = /*#__PURE__*/function (_Component) {
|
|
|
260
286
|
|
|
261
287
|
return Sections;
|
|
262
288
|
}(Component);
|
|
289
|
+
|
|
290
|
+
var SectionsWrapper = function SectionsWrapper(props) {
|
|
291
|
+
var config = flag('store.alternative-source');
|
|
292
|
+
var i18nConfig = generateI18nConfig(config === null || config === void 0 ? void 0 : config.categories);
|
|
293
|
+
useExtendI18n(i18nConfig);
|
|
294
|
+
return /*#__PURE__*/React.createElement(Sections, props);
|
|
295
|
+
};
|
|
296
|
+
|
|
263
297
|
Sections.propTypes = {
|
|
264
298
|
t: PropTypes.func.isRequired,
|
|
265
299
|
|
|
@@ -300,5 +334,5 @@ Sections.defaultProps = {
|
|
|
300
334
|
})
|
|
301
335
|
})
|
|
302
336
|
};
|
|
303
|
-
export var Untranslated = withBreakpoints()(
|
|
337
|
+
export var Untranslated = withBreakpoints()(SectionsWrapper);
|
|
304
338
|
export default withLocales(locales)(translate()(Untranslated));
|
|
@@ -69,6 +69,8 @@ export var groupApps = function groupApps(apps) {
|
|
|
69
69
|
* Alphabetical sort on label except for
|
|
70
70
|
* - 'all' value always at the beginning
|
|
71
71
|
* - 'others' value always at the end
|
|
72
|
+
* - 'cozy' value should be near the beginning, right after 'all'
|
|
73
|
+
* - items of type 'file' should appear alphabetically between 'webapp' and 'konnector'
|
|
72
74
|
*
|
|
73
75
|
* @param {CategoryOption} categoryA
|
|
74
76
|
* @param {CategoryOption} categoryB
|
|
@@ -76,7 +78,26 @@ export var groupApps = function groupApps(apps) {
|
|
|
76
78
|
*/
|
|
77
79
|
|
|
78
80
|
export var sorter = function sorter(categoryA, categoryB) {
|
|
79
|
-
|
|
81
|
+
// Always keep 'all' at the beginning
|
|
82
|
+
if (categoryA.value === 'all') return -1;
|
|
83
|
+
if (categoryB.value === 'all') return 1; // Always keep 'others' at the end
|
|
84
|
+
|
|
85
|
+
if (categoryA.value === 'others') return 1;
|
|
86
|
+
if (categoryB.value === 'others') return -1; // Keep 'cozy' near the beginning, right after 'all'
|
|
87
|
+
|
|
88
|
+
if (categoryA.value === 'cozy') return -1;
|
|
89
|
+
if (categoryB.value === 'cozy') return 1; // Sort by type order: webapp < file < konnector
|
|
90
|
+
|
|
91
|
+
var typeOrder = ['webapp', 'file', 'konnector'];
|
|
92
|
+
var typeAIndex = typeOrder.indexOf(categoryA.type);
|
|
93
|
+
var typeBIndex = typeOrder.indexOf(categoryB.type);
|
|
94
|
+
|
|
95
|
+
if (typeAIndex !== typeBIndex) {
|
|
96
|
+
return typeAIndex - typeBIndex;
|
|
97
|
+
} // Alphabetical sort on label for the rest
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
return categoryA.label.localeCompare(categoryB.label);
|
|
80
101
|
};
|
|
81
102
|
export var addLabel = function addLabel(cat, t) {
|
|
82
103
|
return _objectSpread(_objectSpread({}, cat), {}, {
|
|
@@ -120,11 +141,18 @@ export var generateOptionsFromApps = function generateOptionsFromApps(apps) {
|
|
|
120
141
|
}));
|
|
121
142
|
}
|
|
122
143
|
|
|
144
|
+
if (type === APP_TYPE.FILE) {
|
|
145
|
+
allCategoryOptions.push(addLabel({
|
|
146
|
+
value: 'shortcuts',
|
|
147
|
+
secondary: false
|
|
148
|
+
}));
|
|
149
|
+
}
|
|
150
|
+
|
|
123
151
|
var categoryOptions = Object.keys(catApps).map(function (cat) {
|
|
124
152
|
return addLabel({
|
|
125
153
|
value: cat,
|
|
126
154
|
type: type,
|
|
127
|
-
secondary: type === APP_TYPE.KONNECTOR
|
|
155
|
+
secondary: type === APP_TYPE.KONNECTOR || type === APP_TYPE.FILE
|
|
128
156
|
});
|
|
129
157
|
}); // Since options have been labelled, it's possible to sort them
|
|
130
158
|
|
|
@@ -135,7 +163,7 @@ export var generateOptionsFromApps = function generateOptionsFromApps(apps) {
|
|
|
135
163
|
allCategoryOptions = allCategoryOptions.concat(categoryOptions);
|
|
136
164
|
};
|
|
137
165
|
|
|
138
|
-
for (var _i = 0, _arr = [APP_TYPE.WEBAPP, APP_TYPE.KONNECTOR]; _i < _arr.length; _i++) {
|
|
166
|
+
for (var _i = 0, _arr = [APP_TYPE.WEBAPP, APP_TYPE.FILE, APP_TYPE.KONNECTOR]; _i < _arr.length; _i++) {
|
|
139
167
|
_loop2();
|
|
140
168
|
}
|
|
141
169
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
|
+
export var generateI18nConfig = function generateI18nConfig(categories) {
|
|
3
|
+
if (!categories) return {
|
|
4
|
+
en: {},
|
|
5
|
+
fr: {}
|
|
6
|
+
};
|
|
7
|
+
var i18nConfig = {};
|
|
8
|
+
|
|
9
|
+
for (var _i = 0, _Object$entries = Object.entries(categories); _i < _Object$entries.length; _i++) {
|
|
10
|
+
var _value$split$pop;
|
|
11
|
+
|
|
12
|
+
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
13
|
+
_key = _Object$entries$_i[0],
|
|
14
|
+
value = _Object$entries$_i[1];
|
|
15
|
+
|
|
16
|
+
// Extract the final part of the path as the display name
|
|
17
|
+
var displayName = (_value$split$pop = value === null || value === void 0 ? void 0 : value.split('/').pop()) !== null && _value$split$pop !== void 0 ? _value$split$pop : ''.replace(/([A-Z])/g, ' $1').trim();
|
|
18
|
+
i18nConfig["app_categories.".concat(_key)] = displayName;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
en: i18nConfig,
|
|
23
|
+
fr: i18nConfig
|
|
24
|
+
};
|
|
25
|
+
};
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import _get from 'lodash/get';
|
|
2
|
+
import { APP_CLASS, APP_TYPE } from "cozy-ui/transpiled/react/AppSections/constants";
|
|
2
3
|
export var getTranslatedManifestProperty = function getTranslatedManifestProperty(app, path, t) {
|
|
3
4
|
if (!t || !app || !path) return _get(app, path, '');
|
|
4
5
|
return t("apps.".concat(app.slug, ".").concat(path), {
|
|
5
6
|
_: _get(app, path, '')
|
|
6
7
|
});
|
|
8
|
+
};
|
|
9
|
+
export var isShortcutFile = function isShortcutFile(app) {
|
|
10
|
+
if (!app) return false;
|
|
11
|
+
return app.type === APP_TYPE.FILE && app.class === APP_CLASS.SHORTCUT;
|
|
7
12
|
};
|
|
@@ -9,7 +9,8 @@ var en = {
|
|
|
9
9
|
by: "By",
|
|
10
10
|
installed: "Installed",
|
|
11
11
|
maintenance: "In maintenance",
|
|
12
|
-
update: "Update available"
|
|
12
|
+
update: "Update available",
|
|
13
|
+
favorite: "Added to home page"
|
|
13
14
|
}
|
|
14
15
|
};
|
|
15
16
|
var fr = {
|
|
@@ -17,7 +18,8 @@ var fr = {
|
|
|
17
18
|
by: "Par",
|
|
18
19
|
installed: "Install\xE9e",
|
|
19
20
|
maintenance: "En maintenance",
|
|
20
|
-
update: "Mise \xE0 jour dispo."
|
|
21
|
+
update: "Mise \xE0 jour dispo.",
|
|
22
|
+
favorite: "Ajout\xE9 sur la page d'accueil"
|
|
21
23
|
}
|
|
22
24
|
};
|
|
23
25
|
var styles = {
|
|
@@ -27,11 +29,14 @@ var styles = {
|
|
|
27
29
|
"AppTile-container-maintenance": "styles__AppTile-container-maintenance___u1a1M"
|
|
28
30
|
};
|
|
29
31
|
import AppIcon from "cozy-ui/transpiled/react/AppIcon";
|
|
32
|
+
import { isShortcutFile } from "cozy-ui/transpiled/react/AppSections/helpers.js";
|
|
30
33
|
import Icon from "cozy-ui/transpiled/react/Icon";
|
|
31
34
|
import WrenchCircleIcon from "cozy-ui/transpiled/react/Icons/WrenchCircle";
|
|
35
|
+
import { ShortcutTile } from "cozy-ui/transpiled/react/ShortcutTile";
|
|
32
36
|
import Tile, { TileTitle, TileSubtitle, TileFooter, TileIcon, TileDescription } from "cozy-ui/transpiled/react/Tile";
|
|
33
37
|
import palette from "cozy-ui/transpiled/react/palette";
|
|
34
38
|
import { AppDoctype } from "cozy-ui/transpiled/react/proptypes";
|
|
39
|
+
import useBreakpoints from "cozy-ui/transpiled/react/providers/Breakpoints";
|
|
35
40
|
import { createUseI18n } from "cozy-ui/transpiled/react/providers/I18n";
|
|
36
41
|
var locales = {
|
|
37
42
|
en: en,
|
|
@@ -55,6 +60,8 @@ var getAppIconProps = function getAppIconProps() {
|
|
|
55
60
|
|
|
56
61
|
var useI18n = createUseI18n(locales);
|
|
57
62
|
export var AppTile = function AppTile(_ref) {
|
|
63
|
+
var _app$metadata;
|
|
64
|
+
|
|
58
65
|
var app = _ref.app,
|
|
59
66
|
nameProp = _ref.name,
|
|
60
67
|
namePrefix = _ref.namePrefix,
|
|
@@ -63,24 +70,32 @@ export var AppTile = function AppTile(_ref) {
|
|
|
63
70
|
showStatus = _ref.showStatus,
|
|
64
71
|
IconComponentProp = _ref.IconComponent,
|
|
65
72
|
displaySpecificMaintenanceStyle = _ref.displaySpecificMaintenanceStyle;
|
|
66
|
-
var name = nameProp || app.name;
|
|
67
73
|
|
|
68
74
|
var _useI18n = useI18n(),
|
|
69
75
|
t = _useI18n.t;
|
|
70
76
|
|
|
71
77
|
var _app$developer = app.developer,
|
|
72
78
|
developer = _app$developer === void 0 ? {} : _app$developer;
|
|
79
|
+
|
|
80
|
+
var _useBreakpoints = useBreakpoints(),
|
|
81
|
+
isMobile = _useBreakpoints.isMobile;
|
|
82
|
+
|
|
83
|
+
var name = nameProp || app.name;
|
|
73
84
|
var statusLabel = getCurrentStatusLabel(app);
|
|
74
|
-
var
|
|
85
|
+
var isStatusArray = Array.isArray(showStatus);
|
|
86
|
+
var statusToDisplay = isShortcutFile(app) && statusLabel === APP_STATUS.installed && isMobile ? 'favorite' : isStatusArray ? showStatus.indexOf(statusLabel) > -1 && statusLabel : showStatus && statusLabel;
|
|
75
87
|
var IconComponent = IconComponentProp || AppIcon;
|
|
76
88
|
var isInMaintenanceWithSpecificDisplay = displaySpecificMaintenanceStyle && statusLabel === APP_STATUS.maintenance;
|
|
89
|
+
var tileSubtitle = isShortcutFile(app) ? (_app$metadata = app.metadata) === null || _app$metadata === void 0 ? void 0 : _app$metadata.source : developer.name;
|
|
77
90
|
return /*#__PURE__*/React.createElement(Tile, {
|
|
78
91
|
tag: "button",
|
|
79
92
|
type: "button",
|
|
80
93
|
onClick: onClick,
|
|
81
94
|
className: cx(_defineProperty({}, styles['AppTile-container-maintenance'], isInMaintenanceWithSpecificDisplay)),
|
|
82
95
|
isSecondary: statusLabel === APP_STATUS.installed
|
|
83
|
-
}, /*#__PURE__*/React.createElement(TileIcon, null, /*#__PURE__*/React.createElement(
|
|
96
|
+
}, /*#__PURE__*/React.createElement(TileIcon, null, isShortcutFile(app) ? /*#__PURE__*/React.createElement(ShortcutTile, {
|
|
97
|
+
file: app
|
|
98
|
+
}) : /*#__PURE__*/React.createElement(IconComponent, _extends({
|
|
84
99
|
app: app,
|
|
85
100
|
className: styles['AppTile-icon']
|
|
86
101
|
}, getAppIconProps())), isInMaintenanceWithSpecificDisplay && /*#__PURE__*/React.createElement(Icon, {
|
|
@@ -92,7 +107,7 @@ export var AppTile = function AppTile(_ref) {
|
|
|
92
107
|
className: styles["AppTile-description"]
|
|
93
108
|
}, /*#__PURE__*/React.createElement(TileTitle, {
|
|
94
109
|
isMultiline: !statusLabel
|
|
95
|
-
}, namePrefix ? "".concat(namePrefix, " ").concat(name) : name),
|
|
110
|
+
}, namePrefix ? "".concat(namePrefix, " ").concat(name) : name), showDeveloper && /*#__PURE__*/React.createElement(TileSubtitle, null, "".concat(t('app_item.by'), " ").concat(tileSubtitle)), statusToDisplay && /*#__PURE__*/React.createElement(TileFooter, {
|
|
96
111
|
isAccent: statusLabel === APP_STATUS.update
|
|
97
112
|
}, t("app_item.".concat(statusToDisplay)))));
|
|
98
113
|
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { IOCozyFile } from 'cozy-client/types/types';
|
|
3
|
+
interface ShortcutTileProps {
|
|
4
|
+
file: Partial<IOCozyFile> & {
|
|
5
|
+
name: string;
|
|
6
|
+
attributes?: {
|
|
7
|
+
metadata?: {
|
|
8
|
+
icon?: string;
|
|
9
|
+
iconMimeType?: string;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export declare const ShortcutTile: ({ file }: ShortcutTileProps) => JSX.Element;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
// @ts-expect-error - The following component is not typed
|
|
3
|
+
import { nameToColor } from 'cozy-ui/react/Avatar/helpers'; // @ts-expect-error - The following component is not typed
|
|
4
|
+
|
|
5
|
+
import Typography from 'cozy-ui/react/Typography';
|
|
6
|
+
var styles = {
|
|
7
|
+
"AppTile-icon": "styles__AppTile-icon___1f0c0",
|
|
8
|
+
"AppTile-icon--default": "styles__AppTile-icon--default___1tjiF",
|
|
9
|
+
"AppTile-icon-maintenance": "styles__AppTile-icon-maintenance___2VOvO",
|
|
10
|
+
"AppTile-container-maintenance": "styles__AppTile-container-maintenance___u1a1M"
|
|
11
|
+
};
|
|
12
|
+
import { TileIcon } from "cozy-ui/transpiled/react/Tile";
|
|
13
|
+
import { makeStyles } from "cozy-ui/transpiled/react/styles";
|
|
14
|
+
var useStyles = makeStyles({
|
|
15
|
+
letter: {
|
|
16
|
+
color: 'white',
|
|
17
|
+
margin: 'auto'
|
|
18
|
+
},
|
|
19
|
+
letterWrapper: {
|
|
20
|
+
backgroundColor: function backgroundColor(_ref) {
|
|
21
|
+
var name = _ref.name;
|
|
22
|
+
return nameToColor(name);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
export var ShortcutTile = function ShortcutTile(_ref2) {
|
|
27
|
+
var _file$attributes, _file$attributes$meta, _file$attributes2, _file$attributes2$met;
|
|
28
|
+
|
|
29
|
+
var file = _ref2.file;
|
|
30
|
+
var classes = useStyles({
|
|
31
|
+
name: file.name
|
|
32
|
+
});
|
|
33
|
+
var icon = (_file$attributes = file.attributes) === null || _file$attributes === void 0 ? void 0 : (_file$attributes$meta = _file$attributes.metadata) === null || _file$attributes$meta === void 0 ? void 0 : _file$attributes$meta.icon;
|
|
34
|
+
var iconMimeType = (_file$attributes2 = file.attributes) === null || _file$attributes2 === void 0 ? void 0 : (_file$attributes2$met = _file$attributes2.metadata) === null || _file$attributes2$met === void 0 ? void 0 : _file$attributes2$met.iconMimeType;
|
|
35
|
+
|
|
36
|
+
if (icon) {
|
|
37
|
+
return /*#__PURE__*/React.createElement(TileIcon, null, /*#__PURE__*/React.createElement("img", {
|
|
38
|
+
className: styles['AppTile-icon'],
|
|
39
|
+
src: iconMimeType ? "data:".concat(iconMimeType, ";base64,").concat(icon) : "data:image/svg+xml;base64,".concat(window.btoa(icon)),
|
|
40
|
+
width: 48,
|
|
41
|
+
height: 48,
|
|
42
|
+
alt: file.name
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return /*#__PURE__*/React.createElement(TileIcon, null, /*#__PURE__*/React.createElement("div", {
|
|
47
|
+
className: classes.letterWrapper
|
|
48
|
+
}, /*#__PURE__*/React.createElement(Typography, {
|
|
49
|
+
className: classes.letter,
|
|
50
|
+
variant: "h2",
|
|
51
|
+
align: "center"
|
|
52
|
+
}, file.name[0].toUpperCase())));
|
|
53
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export function TileDescription({ children, className }: {
|
|
2
|
+
children: any;
|
|
3
|
+
className: any;
|
|
4
|
+
}): JSX.Element;
|
|
5
|
+
export function TileTitle({ children, className, isMultiline }: {
|
|
6
|
+
children: any;
|
|
7
|
+
className: any;
|
|
8
|
+
isMultiline: any;
|
|
9
|
+
}): JSX.Element;
|
|
10
|
+
export namespace TileTitle {
|
|
11
|
+
namespace propTypes {
|
|
12
|
+
const className: PropTypes.Requireable<string>;
|
|
13
|
+
const isMultiline: PropTypes.Requireable<boolean>;
|
|
14
|
+
}
|
|
15
|
+
namespace defaultProps {
|
|
16
|
+
const isMultiline_1: boolean;
|
|
17
|
+
export { isMultiline_1 as isMultiline };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function TileSubtitle({ children }: {
|
|
21
|
+
children: any;
|
|
22
|
+
}): JSX.Element;
|
|
23
|
+
export function TileFooter({ children, className, isAccent }: {
|
|
24
|
+
children: any;
|
|
25
|
+
className: any;
|
|
26
|
+
isAccent: any;
|
|
27
|
+
}): JSX.Element;
|
|
28
|
+
export namespace TileFooter {
|
|
29
|
+
export namespace propTypes_1 {
|
|
30
|
+
const className_1: PropTypes.Requireable<string>;
|
|
31
|
+
export { className_1 as className };
|
|
32
|
+
export const isAccent: PropTypes.Requireable<boolean>;
|
|
33
|
+
}
|
|
34
|
+
export { propTypes_1 as propTypes };
|
|
35
|
+
export namespace defaultProps_1 {
|
|
36
|
+
const isAccent_1: boolean;
|
|
37
|
+
export { isAccent_1 as isAccent };
|
|
38
|
+
}
|
|
39
|
+
export { defaultProps_1 as defaultProps };
|
|
40
|
+
}
|
|
41
|
+
export function TileIcon({ children }: {
|
|
42
|
+
children: any;
|
|
43
|
+
}): JSX.Element;
|
|
44
|
+
export default Tile;
|
|
45
|
+
import PropTypes from "prop-types";
|
|
46
|
+
declare function Tile({ children, className, tag: Tag, isSecondary, ...props }: {
|
|
47
|
+
[x: string]: any;
|
|
48
|
+
children: any;
|
|
49
|
+
className: any;
|
|
50
|
+
tag: any;
|
|
51
|
+
isSecondary: any;
|
|
52
|
+
}): JSX.Element;
|
|
53
|
+
declare namespace Tile {
|
|
54
|
+
export namespace propTypes_2 {
|
|
55
|
+
const className_2: PropTypes.Requireable<string>;
|
|
56
|
+
export { className_2 as className };
|
|
57
|
+
export const isSecondary: PropTypes.Requireable<boolean>;
|
|
58
|
+
export const tag: PropTypes.Requireable<string>;
|
|
59
|
+
}
|
|
60
|
+
export { propTypes_2 as propTypes };
|
|
61
|
+
export namespace defaultProps_2 {
|
|
62
|
+
const isSecondary_1: boolean;
|
|
63
|
+
export { isSecondary_1 as isSecondary };
|
|
64
|
+
const tag_1: string;
|
|
65
|
+
export { tag_1 as tag };
|
|
66
|
+
}
|
|
67
|
+
export { defaultProps_2 as defaultProps };
|
|
68
|
+
}
|
|
File without changes
|