cozy-ui 113.9.0 → 114.0.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 CHANGED
@@ -1,3 +1,16 @@
1
+ # [114.0.0](https://github.com/cozy/cozy-ui/compare/v113.9.0...v114.0.0) (2024-12-12)
2
+
3
+
4
+ ### Features
5
+
6
+ * Add QualificationModal component ([e2ebcc0](https://github.com/cozy/cozy-ui/commit/e2ebcc0))
7
+ * Upgrade packages ([4ca7867](https://github.com/cozy/cozy-ui/commit/4ca7867))
8
+
9
+
10
+ ### BREAKING CHANGES
11
+
12
+ * You must have `cozy-client >= 51.6.0` and `cozy-intent >= 2.29.1`
13
+
1
14
  # [113.9.0](https://github.com/cozy/cozy-ui/compare/v113.8.0...v113.9.0) (2024-12-10)
2
15
 
3
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-ui",
3
- "version": "113.9.0",
3
+ "version": "114.0.0",
4
4
  "description": "Cozy apps UI SDK",
5
5
  "main": "./index.js",
6
6
  "bin": {
@@ -92,12 +92,12 @@
92
92
  "browserslist-config-cozy": "0.4.0",
93
93
  "bundlemon": "3.1.0",
94
94
  "copyfiles": "2.4.1",
95
- "cozy-client": "^48.8.0",
95
+ "cozy-client": "^51.6.0",
96
96
  "cozy-device-helper": "2.0.0",
97
97
  "cozy-flags": "^2.10.1",
98
- "cozy-intent": "1.16.1",
98
+ "cozy-intent": "^2.29.1",
99
99
  "cozy-logger": "^1.9.0",
100
- "cozy-stack-client": "^47.4.0",
100
+ "cozy-stack-client": "^51.6.0",
101
101
  "css-loader": "0.28.11",
102
102
  "cssnano": "4.1.11",
103
103
  "cssnano-preset-advanced": "4.0.8",
@@ -181,9 +181,9 @@
181
181
  "rooks": "^5.11.2"
182
182
  },
183
183
  "peerDependencies": {
184
- "cozy-client": ">=48.8.0",
184
+ "cozy-client": ">=51.6.0",
185
185
  "cozy-device-helper": "^2.0.0",
186
- "cozy-intent": ">=1.3.0",
186
+ "cozy-intent": ">=2.29.1",
187
187
  "react": "^16.8.6",
188
188
  "react-dom": "^16.8.6"
189
189
  },
@@ -42,15 +42,13 @@ describe('Paywall', () => {
42
42
  useInstanceInfo.mockReturnValue({
43
43
  context: {
44
44
  data: {
45
- attributes: {
46
- enable_premium_links: enablePremiumLinks,
47
- manager_url: 'http://mycozy.cloud'
48
- }
45
+ enable_premium_links: enablePremiumLinks,
46
+ manager_url: 'http://mycozy.cloud'
49
47
  }
50
48
  },
51
49
  instance: {
52
50
  data: {
53
- attributes: { uuid: hasUuid ? '123' : null }
51
+ uuid: hasUuid ? '123' : null
54
52
  }
55
53
  },
56
54
  isLoaded: true
@@ -0,0 +1,28 @@
1
+ ```jsx
2
+ import DemoProvider from 'cozy-ui/docs/components/DemoProvider'
3
+ import QualificationModal from 'cozy-ui/transpiled/react/QualificationModal'
4
+ import Typography from 'cozy-ui/transpiled/react/Typography'
5
+ import CloudIcon from 'cozy-ui/transpiled/react/Icons/Cloud'
6
+ import FormControlLabel from 'cozy-ui/transpiled/react/FormControlLabel'
7
+ import RadioGroup from 'cozy-ui/transpiled/react/RadioGroup'
8
+ import Radio from 'cozy-ui/transpiled/react/Radios'
9
+ import FormControl from 'cozy-ui/transpiled/react/FormControl'
10
+ import Button from 'cozy-ui/transpiled/react/Buttons'
11
+
12
+ initialState = { show: isTesting() ? true : false }
13
+
14
+ const show = () => setState({show: true})
15
+ const hide = () => setState({show: false})
16
+
17
+ ;
18
+
19
+ <DemoProvider client={{ collection: () => ({ updateMetadataAttribute: () => {}}) }}>
20
+ <Button label={state.show ? "Close modal" : "Open modal"} variant="ghost" onClick={show} />
21
+ {state.show &&
22
+ <QualificationModal
23
+ file={{ name: "toto.txt", metadata: { qualification: { label: 'isp_invoice' } } }}
24
+ onClose={hide}
25
+ />
26
+ }
27
+ </DemoProvider>
28
+ ```
@@ -0,0 +1,94 @@
1
+ import PropTypes from 'prop-types'
2
+ import React, { useMemo } from 'react'
3
+
4
+ import { useClient } from 'cozy-client'
5
+ import { themesList } from 'cozy-client/dist/models/document/documentTypeData'
6
+ import { isQualificationNote } from 'cozy-client/dist/models/document/documentTypeDataHelpers'
7
+ import { getBoundT } from 'cozy-client/dist/models/document/locales'
8
+ import { getQualification } from 'cozy-client/dist/models/document/qualification'
9
+
10
+ import { locales } from './locales'
11
+ import Icon from '../Icon'
12
+ import FileTypeNoteIcon from '../Icons/FileTypeNote'
13
+ import NestedSelectResponsive from '../NestedSelect/NestedSelectResponsive'
14
+ import QualificationIconStack from '../QualificationIconStack'
15
+ import { useI18n, useExtendI18n } from '../providers/I18n'
16
+
17
+ const makeOptions = lang => {
18
+ const qualifT = getBoundT(lang)
19
+
20
+ return {
21
+ children: [
22
+ {
23
+ id: 'none',
24
+ title: qualifT('Scan.themes.none'),
25
+ icon: <QualificationIconStack />
26
+ },
27
+ ...themesList.map(theme => ({
28
+ id: theme.id,
29
+ title: qualifT(`Scan.themes.${theme.label}`),
30
+ icon: <QualificationIconStack theme={theme.label} />,
31
+ children: theme.items.map(item => ({
32
+ id: item.label,
33
+ item,
34
+ title: qualifT(`Scan.items.${item.label}`),
35
+ icon: isQualificationNote(item) ? (
36
+ <Icon icon={FileTypeNoteIcon} size={64} />
37
+ ) : (
38
+ <QualificationIconStack qualification={item.label} />
39
+ )
40
+ }))
41
+ }))
42
+ ]
43
+ }
44
+ }
45
+
46
+ const QualificationModal = ({ file, title, onClose }) => {
47
+ useExtendI18n(locales)
48
+ const client = useClient()
49
+ const { t, lang } = useI18n()
50
+
51
+ const qualificationLabel = getQualification(file)?.label
52
+ const options = useMemo(() => makeOptions(lang), [lang])
53
+
54
+ const isSelected = ({ id, item }) => {
55
+ return qualificationLabel
56
+ ? qualificationLabel === item?.label
57
+ : id === 'none'
58
+ }
59
+
60
+ const handleClick = async ({ id, item }) => {
61
+ const fileCollection = client.collection('io.cozy.files')
62
+ const removeQualification = qualificationLabel && id === 'none'
63
+
64
+ /*
65
+ In the case where we remove the qualification it's necessary to define the attribute to `null` and not `undefined`, with `undefined` the stack does not return the attribute and today the Redux store is not updated for a missing attribute.
66
+ As a result, the UI is not updated and continues to display the qualification on the document, even though it has been deleted in CouchDB.
67
+ */
68
+ await fileCollection.updateMetadataAttribute(file._id, {
69
+ qualification: removeQualification ? null : item
70
+ })
71
+
72
+ onClose()
73
+ }
74
+
75
+ return (
76
+ <NestedSelectResponsive
77
+ title={title || t('QualificationModal.title')}
78
+ options={options}
79
+ noDivider
80
+ document={file}
81
+ isSelected={isSelected}
82
+ onSelect={handleClick}
83
+ onClose={onClose}
84
+ />
85
+ )
86
+ }
87
+
88
+ QualificationModal.propTypes = {
89
+ file: PropTypes.object,
90
+ title: PropTypes.string,
91
+ onClose: PropTypes.func
92
+ }
93
+
94
+ export default QualificationModal
@@ -0,0 +1,5 @@
1
+ {
2
+ "QualificationModal": {
3
+ "title": "Document type"
4
+ }
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "QualificationModal": {
3
+ "title": "Type de document"
4
+ }
5
+ }
@@ -0,0 +1,7 @@
1
+ import en from './en.json'
2
+ import fr from './fr.json'
3
+
4
+ export const locales = {
5
+ en,
6
+ fr
7
+ }
package/react/index.js CHANGED
@@ -125,6 +125,8 @@ export { default as Thumbnail } from './Thumbnail'
125
125
  export { default as ButtonBase } from './ButtonBase'
126
126
  export { default as QualificationGrid } from './QualificationGrid'
127
127
  export { default as QualificationItem } from './QualificationItem'
128
+ export { default as QualificationIconStack } from './QualificationIconStack'
129
+ export { default as QualificationModal } from './QualificationModal'
128
130
  export { default as Timeline } from './Timeline'
129
131
  export { default as TimelineConnector } from './TimelineConnector'
130
132
  export { default as TimelineContent } from './TimelineContent'
@@ -0,0 +1,126 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
4
+ import PropTypes from 'prop-types';
5
+ import React, { useMemo } from 'react';
6
+ import { useClient } from 'cozy-client';
7
+ import { themesList } from 'cozy-client/dist/models/document/documentTypeData';
8
+ import { isQualificationNote } from 'cozy-client/dist/models/document/documentTypeDataHelpers';
9
+ import { getBoundT } from 'cozy-client/dist/models/document/locales';
10
+ import { getQualification } from 'cozy-client/dist/models/document/qualification';
11
+ import { locales } from "cozy-ui/transpiled/react/QualificationModal/locales";
12
+ import Icon from "cozy-ui/transpiled/react/Icon";
13
+ import FileTypeNoteIcon from "cozy-ui/transpiled/react/Icons/FileTypeNote";
14
+ import NestedSelectResponsive from "cozy-ui/transpiled/react/NestedSelect/NestedSelectResponsive";
15
+ import QualificationIconStack from "cozy-ui/transpiled/react/QualificationIconStack";
16
+ import { useI18n, useExtendI18n } from "cozy-ui/transpiled/react/providers/I18n";
17
+
18
+ var makeOptions = function makeOptions(lang) {
19
+ var qualifT = getBoundT(lang);
20
+ return {
21
+ children: [{
22
+ id: 'none',
23
+ title: qualifT('Scan.themes.none'),
24
+ icon: /*#__PURE__*/React.createElement(QualificationIconStack, null)
25
+ }].concat(_toConsumableArray(themesList.map(function (theme) {
26
+ return {
27
+ id: theme.id,
28
+ title: qualifT("Scan.themes.".concat(theme.label)),
29
+ icon: /*#__PURE__*/React.createElement(QualificationIconStack, {
30
+ theme: theme.label
31
+ }),
32
+ children: theme.items.map(function (item) {
33
+ return {
34
+ id: item.label,
35
+ item: item,
36
+ title: qualifT("Scan.items.".concat(item.label)),
37
+ icon: isQualificationNote(item) ? /*#__PURE__*/React.createElement(Icon, {
38
+ icon: FileTypeNoteIcon,
39
+ size: 64
40
+ }) : /*#__PURE__*/React.createElement(QualificationIconStack, {
41
+ qualification: item.label
42
+ })
43
+ };
44
+ })
45
+ };
46
+ })))
47
+ };
48
+ };
49
+
50
+ var QualificationModal = function QualificationModal(_ref) {
51
+ var _getQualification;
52
+
53
+ var file = _ref.file,
54
+ title = _ref.title,
55
+ onClose = _ref.onClose;
56
+ useExtendI18n(locales);
57
+ var client = useClient();
58
+
59
+ var _useI18n = useI18n(),
60
+ t = _useI18n.t,
61
+ lang = _useI18n.lang;
62
+
63
+ var qualificationLabel = (_getQualification = getQualification(file)) === null || _getQualification === void 0 ? void 0 : _getQualification.label;
64
+ var options = useMemo(function () {
65
+ return makeOptions(lang);
66
+ }, [lang]);
67
+
68
+ var isSelected = function isSelected(_ref2) {
69
+ var id = _ref2.id,
70
+ item = _ref2.item;
71
+ return qualificationLabel ? qualificationLabel === (item === null || item === void 0 ? void 0 : item.label) : id === 'none';
72
+ };
73
+
74
+ var handleClick = /*#__PURE__*/function () {
75
+ var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(_ref3) {
76
+ var id, item, fileCollection, removeQualification;
77
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
78
+ while (1) {
79
+ switch (_context.prev = _context.next) {
80
+ case 0:
81
+ id = _ref3.id, item = _ref3.item;
82
+ fileCollection = client.collection('io.cozy.files');
83
+ removeQualification = qualificationLabel && id === 'none';
84
+ /*
85
+ In the case where we remove the qualification it's necessary to define the attribute to `null` and not `undefined`, with `undefined` the stack does not return the attribute and today the Redux store is not updated for a missing attribute.
86
+ As a result, the UI is not updated and continues to display the qualification on the document, even though it has been deleted in CouchDB.
87
+ */
88
+
89
+ _context.next = 5;
90
+ return fileCollection.updateMetadataAttribute(file._id, {
91
+ qualification: removeQualification ? null : item
92
+ });
93
+
94
+ case 5:
95
+ onClose();
96
+
97
+ case 6:
98
+ case "end":
99
+ return _context.stop();
100
+ }
101
+ }
102
+ }, _callee);
103
+ }));
104
+
105
+ return function handleClick(_x) {
106
+ return _ref4.apply(this, arguments);
107
+ };
108
+ }();
109
+
110
+ return /*#__PURE__*/React.createElement(NestedSelectResponsive, {
111
+ title: title || t('QualificationModal.title'),
112
+ options: options,
113
+ noDivider: true,
114
+ document: file,
115
+ isSelected: isSelected,
116
+ onSelect: handleClick,
117
+ onClose: onClose
118
+ });
119
+ };
120
+
121
+ QualificationModal.propTypes = {
122
+ file: PropTypes.object,
123
+ title: PropTypes.string,
124
+ onClose: PropTypes.func
125
+ };
126
+ export default QualificationModal;
@@ -0,0 +1,14 @@
1
+ var en = {
2
+ QualificationModal: {
3
+ title: "Document type"
4
+ }
5
+ };
6
+ var fr = {
7
+ QualificationModal: {
8
+ title: "Type de document"
9
+ }
10
+ };
11
+ export var locales = {
12
+ en: en,
13
+ fr: fr
14
+ };
@@ -98,6 +98,8 @@ export { default as Thumbnail } from './Thumbnail';
98
98
  export { default as ButtonBase } from './ButtonBase';
99
99
  export { default as QualificationGrid } from './QualificationGrid';
100
100
  export { default as QualificationItem } from './QualificationItem';
101
+ export { default as QualificationIconStack } from './QualificationIconStack';
102
+ export { default as QualificationModal } from './QualificationModal';
101
103
  export { default as Timeline } from './Timeline';
102
104
  export { default as TimelineConnector } from './TimelineConnector';
103
105
  export { default as TimelineContent } from './TimelineContent';