cozy-ui 98.1.1 → 98.2.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,10 @@
1
+ # [98.2.0](https://github.com/cozy/cozy-ui/compare/v98.1.1...v98.2.0) (2023-12-07)
2
+
3
+
4
+ ### Features
5
+
6
+ * **ActionsMenu:** Add print action ([82d918d](https://github.com/cozy/cozy-ui/commit/82d918d))
7
+
1
8
  ## [98.1.1](https://github.com/cozy/cozy-ui/compare/v98.1.0...v98.1.1) (2023-12-06)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-ui",
3
- "version": "98.1.1",
3
+ "version": "98.2.0",
4
4
  "description": "Cozy apps UI SDK",
5
5
  "main": "./index.js",
6
6
  "bin": {
@@ -61,3 +61,23 @@ export const getOnlyNeededActions = (actions, file) => {
61
61
  })
62
62
  )
63
63
  }
64
+
65
+ /**
66
+ * Make a base64 string from a File object
67
+ * @param {File} file - File object
68
+ * @returns {Promise<string | null>} base64 string
69
+ */
70
+ export const makeBase64FromFile = async file => {
71
+ const reader = new FileReader()
72
+ reader.readAsDataURL(file)
73
+
74
+ return new Promise((resolve, reject) => {
75
+ reader.onload = () => {
76
+ const base64 = reader.result
77
+ resolve(base64)
78
+ }
79
+ reader.onerror = err => {
80
+ reject(err)
81
+ }
82
+ })
83
+ }
@@ -1,4 +1,4 @@
1
- import { makeActions } from './helpers'
1
+ import { makeActions, makeBase64FromFile } from './helpers'
2
2
 
3
3
  describe('makeActions', () => {
4
4
  it('should have empty actions array', () => {
@@ -60,3 +60,21 @@ describe('makeActions', () => {
60
60
  expect(actions).toStrictEqual([{ mockConstructor: { propA: 0, propB: 1 } }])
61
61
  })
62
62
  })
63
+
64
+ describe('makeBase64FromFile', () => {
65
+ it('returns a base64 string for a given file', async () => {
66
+ const file = new File(['test'], 'test.txt', { type: 'text/plain' })
67
+ const base64String = await makeBase64FromFile(file)
68
+
69
+ expect(base64String).toMatch(
70
+ /^data:text\/plain;base64,[a-zA-Z0-9+/]+={0,2}$/
71
+ )
72
+ })
73
+
74
+ it('rejects with an error if the file cannot be read', async () => {
75
+ const file = new File(['test'], 'test.txt', { type: 'text/plain' })
76
+ const invalidFile = { ...file, size: -1 }
77
+
78
+ await expect(makeBase64FromFile(invalidFile)).rejects.toThrow()
79
+ })
80
+ })
@@ -4,4 +4,5 @@ export { modify } from './modify'
4
4
  export { smsTo } from './smsTo'
5
5
  export { call } from './call'
6
6
  export { emailTo } from './emailTo'
7
+ export { print } from './print'
7
8
  export { viewInContacts } from './viewInContacts'
@@ -0,0 +1,67 @@
1
+ import React, { forwardRef } from 'react'
2
+
3
+ import logger from 'cozy-logger'
4
+ import { useWebviewIntent } from 'cozy-intent'
5
+ import { fetchBlobFileById } from 'cozy-client/dist/models/file'
6
+
7
+ import { makeBase64FromFile } from './helpers'
8
+ import PrinterIcon from '../../Icons/Printer'
9
+ import withActionsLocales from './locales/withActionsLocales'
10
+ import ActionsMenuItem from '../ActionsMenuItem'
11
+ import ListItemIcon from '../../ListItemIcon'
12
+ import Icon from '../../Icon'
13
+ import ListItemText from '../../ListItemText'
14
+ import { useI18n } from '../../providers/I18n'
15
+
16
+ export const print = () => {
17
+ return {
18
+ name: 'print',
19
+ action: async (doc, { client, webviewIntent }) => {
20
+ if (webviewIntent) {
21
+ try {
22
+ const blob = await fetchBlobFileById(client, doc._id)
23
+ const base64 = await makeBase64FromFile(blob)
24
+
25
+ return webviewIntent.call('print', base64)
26
+ } catch (error) {
27
+ logger.error(
28
+ `Error trying to print document with Flagship App: ${JSON.stringify(
29
+ error
30
+ )}`
31
+ )
32
+ }
33
+ }
34
+
35
+ try {
36
+ const downloadURL = await client
37
+ .collection('io.cozy.files')
38
+ .getDownloadLinkById(doc._id, doc.name)
39
+
40
+ window.open(downloadURL, '_blank')
41
+ } catch (error) {
42
+ logger.error(`Error trying to print document: ${JSON.stringify(error)}`)
43
+ }
44
+ },
45
+ Component: withActionsLocales(
46
+ forwardRef(({ onClick, ...props }, ref) => {
47
+ const { t } = useI18n()
48
+ const webviewIntent = useWebviewIntent()
49
+
50
+ return (
51
+ <ActionsMenuItem
52
+ {...props}
53
+ ref={ref}
54
+ onClick={() => {
55
+ onClick({ webviewIntent })
56
+ }}
57
+ >
58
+ <ListItemIcon>
59
+ <Icon icon={PrinterIcon} />
60
+ </ListItemIcon>
61
+ <ListItemText primary={t('print')} />
62
+ </ActionsMenuItem>
63
+ )
64
+ })
65
+ )
66
+ }
67
+ }
@@ -52,7 +52,7 @@ import Icon from 'cozy-ui/transpiled/react/Icon'
52
52
  import FileTypeText from 'cozy-ui/transpiled/react/Icons/FileTypeText'
53
53
  import FileIcon from 'cozy-ui/transpiled/react/Icons/File'
54
54
 
55
- import { makeActions, modify, emailTo, viewInContacts, divider, smsTo, call } from 'cozy-ui/transpiled/react/ActionsMenu/Actions'
55
+ import { makeActions, modify, emailTo, print, viewInContacts, divider, smsTo, call } from 'cozy-ui/transpiled/react/ActionsMenu/Actions'
56
56
 
57
57
  initialState = { showMenu: isTesting() }
58
58
 
@@ -87,7 +87,7 @@ const customAction = () => ({
87
87
  })
88
88
  })
89
89
 
90
- const actions = makeActions([ modify, viewInContacts, divider, call, smsTo, emailTo, divider, customAction ])
90
+ const actions = makeActions([ modify, viewInContacts, divider, call, smsTo, emailTo, print, divider, customAction ])
91
91
 
92
92
  ;
93
93
 
@@ -3,5 +3,6 @@
3
3
  "modify": "Modify",
4
4
  "emailTo": "Send an email",
5
5
  "smsTo": "Send a message",
6
+ "print": "Print",
6
7
  "call": "Call"
7
8
  }
@@ -3,5 +3,6 @@
3
3
  "modify": "Modifier",
4
4
  "emailTo": "Envoyer un e-mail",
5
5
  "smsTo": "Envoyer un message",
6
+ "print": "Imprimer",
6
7
  "call": "Appeler"
7
8
  }
@@ -1,4 +1,6 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
1
2
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
2
4
 
3
5
  /**
4
6
  * Make array of actions for ActionsItems component
@@ -48,4 +50,42 @@ export var getOnlyNeededActions = function getOnlyNeededActions(actions, file) {
48
50
  .filter(function (cleanedAction, idx, cleanedActions) {
49
51
  return !(getActionName(cleanedAction) === 'hr' && idx === cleanedActions.length - 1);
50
52
  });
51
- };
53
+ };
54
+ /**
55
+ * Make a base64 string from a File object
56
+ * @param {File} file - File object
57
+ * @returns {Promise<string | null>} base64 string
58
+ */
59
+
60
+ export var makeBase64FromFile = /*#__PURE__*/function () {
61
+ var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(file) {
62
+ var reader;
63
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
64
+ while (1) {
65
+ switch (_context.prev = _context.next) {
66
+ case 0:
67
+ reader = new FileReader();
68
+ reader.readAsDataURL(file);
69
+ return _context.abrupt("return", new Promise(function (resolve, reject) {
70
+ reader.onload = function () {
71
+ var base64 = reader.result;
72
+ resolve(base64);
73
+ };
74
+
75
+ reader.onerror = function (err) {
76
+ reject(err);
77
+ };
78
+ }));
79
+
80
+ case 3:
81
+ case "end":
82
+ return _context.stop();
83
+ }
84
+ }
85
+ }, _callee);
86
+ }));
87
+
88
+ return function makeBase64FromFile(_x) {
89
+ return _ref2.apply(this, arguments);
90
+ };
91
+ }();
@@ -4,4 +4,5 @@ export { modify } from './modify';
4
4
  export { smsTo } from './smsTo';
5
5
  export { call } from './call';
6
6
  export { emailTo } from './emailTo';
7
+ export { print } from './print';
7
8
  export { viewInContacts } from './viewInContacts';
@@ -4,6 +4,7 @@ var en = {
4
4
  modify: "Modify",
5
5
  emailTo: "Send an email",
6
6
  smsTo: "Send a message",
7
+ print: "Print",
7
8
  call: "Call"
8
9
  };
9
10
  var fr = {
@@ -11,6 +12,7 @@ var fr = {
11
12
  modify: "Modifier",
12
13
  emailTo: "Envoyer un e-mail",
13
14
  smsTo: "Envoyer un message",
15
+ print: "Imprimer",
14
16
  call: "Appeler"
15
17
  };
16
18
  export var locales = {
@@ -0,0 +1,105 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
3
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
4
+ var _excluded = ["onClick"];
5
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
6
+ import React, { forwardRef } from 'react';
7
+ import logger from 'cozy-logger';
8
+ import { useWebviewIntent } from 'cozy-intent';
9
+ import { fetchBlobFileById } from 'cozy-client/dist/models/file';
10
+ import { makeBase64FromFile } from "cozy-ui/transpiled/react/ActionsMenu/Actions/helpers";
11
+ import PrinterIcon from "cozy-ui/transpiled/react/Icons/Printer";
12
+ import withActionsLocales from "cozy-ui/transpiled/react/ActionsMenu/Actions/locales/withActionsLocales";
13
+ import ActionsMenuItem from "cozy-ui/transpiled/react/ActionsMenu/ActionsMenuItem";
14
+ import ListItemIcon from "cozy-ui/transpiled/react/ListItemIcon";
15
+ import Icon from "cozy-ui/transpiled/react/Icon";
16
+ import ListItemText from "cozy-ui/transpiled/react/ListItemText";
17
+ import { useI18n } from "cozy-ui/transpiled/react/providers/I18n";
18
+ export var print = function print() {
19
+ return {
20
+ name: 'print',
21
+ action: function () {
22
+ var _action = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(doc, _ref) {
23
+ var client, webviewIntent, blob, base64, downloadURL;
24
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
25
+ while (1) {
26
+ switch (_context.prev = _context.next) {
27
+ case 0:
28
+ client = _ref.client, webviewIntent = _ref.webviewIntent;
29
+
30
+ if (!webviewIntent) {
31
+ _context.next = 15;
32
+ break;
33
+ }
34
+
35
+ _context.prev = 2;
36
+ _context.next = 5;
37
+ return fetchBlobFileById(client, doc._id);
38
+
39
+ case 5:
40
+ blob = _context.sent;
41
+ _context.next = 8;
42
+ return makeBase64FromFile(blob);
43
+
44
+ case 8:
45
+ base64 = _context.sent;
46
+ return _context.abrupt("return", webviewIntent.call('print', base64));
47
+
48
+ case 12:
49
+ _context.prev = 12;
50
+ _context.t0 = _context["catch"](2);
51
+ logger.error("Error trying to print document with Flagship App: ".concat(JSON.stringify(_context.t0)));
52
+
53
+ case 15:
54
+ _context.prev = 15;
55
+ _context.next = 18;
56
+ return client.collection('io.cozy.files').getDownloadLinkById(doc._id, doc.name);
57
+
58
+ case 18:
59
+ downloadURL = _context.sent;
60
+ window.open(downloadURL, '_blank');
61
+ _context.next = 25;
62
+ break;
63
+
64
+ case 22:
65
+ _context.prev = 22;
66
+ _context.t1 = _context["catch"](15);
67
+ logger.error("Error trying to print document: ".concat(JSON.stringify(_context.t1)));
68
+
69
+ case 25:
70
+ case "end":
71
+ return _context.stop();
72
+ }
73
+ }
74
+ }, _callee, null, [[2, 12], [15, 22]]);
75
+ }));
76
+
77
+ function action(_x, _x2) {
78
+ return _action.apply(this, arguments);
79
+ }
80
+
81
+ return action;
82
+ }(),
83
+ Component: withActionsLocales( /*#__PURE__*/forwardRef(function (_ref2, ref) {
84
+ var _onClick = _ref2.onClick,
85
+ props = _objectWithoutProperties(_ref2, _excluded);
86
+
87
+ var _useI18n = useI18n(),
88
+ t = _useI18n.t;
89
+
90
+ var webviewIntent = useWebviewIntent();
91
+ return /*#__PURE__*/React.createElement(ActionsMenuItem, _extends({}, props, {
92
+ ref: ref,
93
+ onClick: function onClick() {
94
+ _onClick({
95
+ webviewIntent: webviewIntent
96
+ });
97
+ }
98
+ }), /*#__PURE__*/React.createElement(ListItemIcon, null, /*#__PURE__*/React.createElement(Icon, {
99
+ icon: PrinterIcon
100
+ })), /*#__PURE__*/React.createElement(ListItemText, {
101
+ primary: t('print')
102
+ }));
103
+ }))
104
+ };
105
+ };
@@ -4,6 +4,7 @@ var en = {
4
4
  modify: "Modify",
5
5
  emailTo: "Send an email",
6
6
  smsTo: "Send a message",
7
+ print: "Print",
7
8
  call: "Call"
8
9
  };
9
10
  var fr = {
@@ -11,6 +12,7 @@ var fr = {
11
12
  modify: "Modifier",
12
13
  emailTo: "Envoyer un e-mail",
13
14
  smsTo: "Envoyer un message",
15
+ print: "Imprimer",
14
16
  call: "Appeler"
15
17
  };
16
18
  export var locales = {