cozy-ui 113.8.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/jest.config.js +1 -2
  3. package/package.json +6 -12
  4. package/react/AppSections/components/AppsSection.spec.jsx +10 -19
  5. package/react/AppSections/index.spec.jsx +98 -77
  6. package/react/ContactsList/ContactRow.spec.js +28 -53
  7. package/react/DateMonthPicker/index.spec.jsx +17 -45
  8. package/react/Field/index.spec.js +28 -5
  9. package/react/Figure/Figure.spec.jsx +9 -4
  10. package/react/Figure/__snapshots__/Figure.spec.jsx.snap +289 -225
  11. package/react/FileInput/index.jsx +1 -0
  12. package/react/FileInput/index.spec.jsx +16 -38
  13. package/react/Paywall/Paywall.spec.jsx +3 -5
  14. package/react/Popup/index.spec.jsx +90 -41
  15. package/react/QualificationIconStack/Readme.md +4 -1
  16. package/react/QualificationIconStack/index.jsx +28 -7
  17. package/react/QualificationModal/Readme.md +28 -0
  18. package/react/QualificationModal/index.jsx +94 -0
  19. package/react/QualificationModal/locales/en.json +5 -0
  20. package/react/QualificationModal/locales/fr.json +5 -0
  21. package/react/QualificationModal/locales/index.jsx +7 -0
  22. package/react/deprecated/ViewStack/example.jsx +1 -1
  23. package/react/hooks/useClientErrors.spec.jsx +16 -24
  24. package/react/index.js +2 -0
  25. package/react/providers/I18n/index.spec.jsx +13 -5
  26. package/react/providers/I18n/withLocales.spec.jsx +4 -4
  27. package/transpiled/react/FileInput/index.js +2 -1
  28. package/transpiled/react/QualificationIconStack/index.js +26 -6
  29. package/transpiled/react/QualificationModal/index.js +126 -0
  30. package/transpiled/react/QualificationModal/locales/index.js +14 -0
  31. package/transpiled/react/deprecated/ViewStack/example.js +1 -1
  32. package/transpiled/react/index.js +2 -0
  33. package/react/AppSections/__snapshots__/index.spec.jsx.snap +0 -1843
  34. package/react/AppSections/components/__snapshots__/AppsSection.spec.jsx.snap +0 -41
  35. package/react/ContactsList/__snapshots__/ContactRow.spec.js.snap +0 -69
  36. package/react/FileInput/__snapshots__/index.spec.jsx.snap +0 -86
  37. package/react/Input/__snapshots__/index.spec.jsx.snap +0 -11
  38. package/react/Input/index.spec.jsx +0 -12
  39. package/react/__snapshots__/examples.spec.jsx.snap +0 -3720
  40. package/react/deprecated/ActionMenu/__snapshots__/index.spec.jsx.snap +0 -157
  41. package/react/deprecated/ActionMenu/index.spec.jsx +0 -115
  42. package/react/deprecated/Alerter/__snapshots__/alerter.spec.js.snap +0 -88
  43. package/react/deprecated/Alerter/alerter.spec.js +0 -78
  44. package/react/deprecated/InfosCarrousel/index.spec.jsx +0 -71
  45. package/react/deprecated/Modal/index.spec.jsx +0 -70
  46. package/react/deprecated/ViewStack/index.spec.jsx +0 -64
  47. package/react/examples.spec.jsx +0 -67
@@ -1,4 +1,4 @@
1
- import { render, fireEvent } from '@testing-library/react'
1
+ import { render, fireEvent, screen } from '@testing-library/react'
2
2
  import PropTypes from 'prop-types'
3
3
  import React, { useState } from 'react'
4
4
 
@@ -34,23 +34,31 @@ I18nHelloWorldOldAPI.contextTypes = {
34
34
 
35
35
  describe('new context api', () => {
36
36
  it('should provide t and f and lang through useI18n hook', () => {
37
- const root = mount(
37
+ render(
38
38
  <I18n lang="en" dictRequire={() => locales}>
39
39
  <I18nHelloWorldHook />
40
40
  </I18n>
41
41
  )
42
- expect(root.html()).toBe('<div>Hello World !<br>6 Jan<br>en</div>')
42
+ expect(
43
+ screen.getByText('Hello World !', { exact: false })
44
+ ).toBeInTheDocument()
45
+ expect(screen.getByText('6 Jan', { exact: false })).toBeInTheDocument()
46
+ expect(screen.getByText('en', { exact: false })).toBeInTheDocument()
43
47
  })
44
48
  })
45
49
 
46
50
  describe('old context api', () => {
47
51
  it('should provide t and f and lang through old context API', () => {
48
- const root = mount(
52
+ render(
49
53
  <I18n lang="en" dictRequire={() => locales}>
50
54
  <I18nHelloWorldOldAPI />
51
55
  </I18n>
52
56
  )
53
- expect(root.html()).toBe('<div>Hello World !<br>6 Jan<br>en</div>')
57
+ expect(
58
+ screen.getByText('Hello World !', { exact: false })
59
+ ).toBeInTheDocument()
60
+ expect(screen.getByText('6 Jan', { exact: false })).toBeInTheDocument()
61
+ expect(screen.getByText('en', { exact: false })).toBeInTheDocument()
54
62
  })
55
63
  })
56
64
 
@@ -1,3 +1,4 @@
1
+ import { render, screen } from '@testing-library/react'
1
2
  import React from 'react'
2
3
 
3
4
  import { I18n } from '.'
@@ -29,9 +30,8 @@ class MockComponent extends React.Component {
29
30
  }
30
31
 
31
32
  describe('with locales', () => {
32
- let root
33
33
  const setup = ({ lang, Component }) => {
34
- root = mount(
34
+ render(
35
35
  <I18n lang={lang} dictRequire={localeCode => globalLocales[localeCode]}>
36
36
  <Component />
37
37
  </I18n>
@@ -42,9 +42,9 @@ describe('with locales', () => {
42
42
  describe(description, () => {
43
43
  it('should provide t with correct locale strings', () => {
44
44
  setup({ lang: 'en', Component })
45
- expect(root.text()).toBe('Hello local world !')
45
+ expect(screen.getByText('Hello local world !')).toBeInTheDocument()
46
46
  setup({ lang: 'fr', Component })
47
- expect(root.text()).toBe('Bonjour le monde local !')
47
+ expect(screen.getByText('Bonjour le monde local !')).toBeInTheDocument()
48
48
  })
49
49
  })
50
50
  }
@@ -47,7 +47,8 @@ var FileInput = function FileInput(_ref) {
47
47
  } else {
48
48
  _onChange(Array.from(e.target.files)[0]);
49
49
  }
50
- }
50
+ },
51
+ "data-testid": "file-input"
51
52
  }, inputProps)));
52
53
  };
53
54
 
@@ -1,6 +1,6 @@
1
1
  import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
2
2
  import _extends from "@babel/runtime/helpers/extends";
3
- var _excluded = ["qualification"];
3
+ var _excluded = ["theme", "qualification"];
4
4
  import PropTypes from 'prop-types';
5
5
  import React from 'react';
6
6
  import { getIconByLabel } from 'cozy-client/dist/models/document/qualification';
@@ -11,7 +11,9 @@ import BankCheckIcon from "cozy-ui/transpiled/react/Icons/BankCheck";
11
11
  import BenefitIcon from "cozy-ui/transpiled/react/Icons/Benefit";
12
12
  import BillIcon from "cozy-ui/transpiled/react/Icons/Bill";
13
13
  import CarIcon from "cozy-ui/transpiled/react/Icons/Car";
14
+ import ChessIcon from "cozy-ui/transpiled/react/Icons/Chess";
14
15
  import ChildIcon from "cozy-ui/transpiled/react/Icons/Child";
16
+ import DotsIcon from "cozy-ui/transpiled/react/Icons/Dots";
15
17
  import EmailIcon from "cozy-ui/transpiled/react/Icons/Email";
16
18
  import EuroIcon from "cozy-ui/transpiled/react/Icons/Euro";
17
19
  import ExchangeIcon from "cozy-ui/transpiled/react/Icons/Exchange";
@@ -49,13 +51,15 @@ function FileDuotoneWhite(props) {
49
51
  })));
50
52
  }
51
53
 
52
- var qualificationIcon = {
54
+ var IconByLabel = {
53
55
  'bank-check': BankCheckIcon,
54
56
  bank: BankIcon,
55
57
  benefit: BenefitIcon,
56
58
  bill: BillIcon,
57
59
  car: CarIcon,
60
+ chess: ChessIcon,
58
61
  child: ChildIcon,
62
+ dots: DotsIcon,
59
63
  email: EmailIcon,
60
64
  euro: EuroIcon,
61
65
  exchange: ExchangeIcon,
@@ -81,12 +85,25 @@ var qualificationIcon = {
81
85
  water: WaterIcon,
82
86
  work: WorkIcon
83
87
  };
88
+ var themeIconByLabel = {
89
+ identity: 'people',
90
+ family: 'team',
91
+ work_study: 'work',
92
+ health: 'heart',
93
+ home: 'home',
94
+ transport: 'car',
95
+ activity: 'chess',
96
+ finance: 'bank',
97
+ invoice: 'bill',
98
+ others: 'dots'
99
+ };
84
100
 
85
101
  var QualificationIconStack = function QualificationIconStack(_ref) {
86
- var qualification = _ref.qualification,
102
+ var theme = _ref.theme,
103
+ qualification = _ref.qualification,
87
104
  props = _objectWithoutProperties(_ref, _excluded);
88
105
 
89
- var QualificationIcon = qualificationIcon[getIconByLabel(qualification)];
106
+ var ForegroundIcon = qualification ? IconByLabel[getIconByLabel(qualification)] : theme ? IconByLabel[themeIconByLabel[theme]] : null;
90
107
  return /*#__PURE__*/React.createElement(IconStack, _extends({}, props, {
91
108
  backgroundIcon: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Icon, {
92
109
  className: "u-pos-absolute",
@@ -98,7 +115,7 @@ var QualificationIconStack = function QualificationIconStack(_ref) {
98
115
  size: 32
99
116
  })),
100
117
  foregroundIcon: /*#__PURE__*/React.createElement(Icon, {
101
- icon: QualificationIcon,
118
+ icon: ForegroundIcon,
102
119
  color: "#E049BF",
103
120
  size: 16
104
121
  })
@@ -107,6 +124,9 @@ var QualificationIconStack = function QualificationIconStack(_ref) {
107
124
 
108
125
  QualificationIconStack.propTypes = {
109
126
  /** The name of the qualification (isp\_invoice, family\_record\_book, etc.) */
110
- qualification: PropTypes.string.isRequired
127
+ qualification: PropTypes.string,
128
+
129
+ /** The name of the qualification theme (indentity, family, etc.) */
130
+ theme: PropTypes.string
111
131
  };
112
132
  export default QualificationIconStack;
@@ -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
+ };
@@ -34,7 +34,7 @@ var Slide = function Slide(_ref2) {
34
34
  return stackPop();
35
35
 
36
36
  case 2:
37
- // No alerts during enzyme tests
37
+ // No alerts during tests
38
38
  if (number === 2 && !global.mount) {
39
39
  alert('You went back to the first slide');
40
40
  }
@@ -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';