cozy-viewer 3.0.1 → 5.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
@@ -3,6 +3,39 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [5.0.0](https://github.com/cozy/cozy-libs/compare/cozy-viewer@4.0.0...cozy-viewer@5.0.0) (2024-11-27)
7
+
8
+
9
+ ### Features
10
+
11
+ * **Viewer:** Add summary block ([ceebd77](https://github.com/cozy/cozy-libs/commit/ceebd77ba11c5033368fa891810abd0e8c5b391d))
12
+ * **Viewer:** Upgrade cozy-ui ([1c9c1ba](https://github.com/cozy/cozy-libs/commit/1c9c1ba7314daa07967a02c4de6eb574d9908e48))
13
+
14
+
15
+ ### BREAKING CHANGES
16
+
17
+ * **Viewer:** You must have `cozy-ui >= 113.7.0`
18
+
19
+
20
+
21
+
22
+
23
+ # [4.0.0](https://github.com/cozy/cozy-libs/compare/cozy-viewer@3.0.1...cozy-viewer@4.0.0) (2024-11-27)
24
+
25
+
26
+ ### Features
27
+
28
+ * **Viewer:** Upgrade cozy-harvest-lib ([c8c3457](https://github.com/cozy/cozy-libs/commit/c8c345788586a70b177fd0735c01a8342d027a44))
29
+
30
+
31
+ ### BREAKING CHANGES
32
+
33
+ * **Viewer:** You must have `cozy-harvest-lib >= 30.8.0`
34
+
35
+
36
+
37
+
38
+
6
39
  ## [3.0.1](https://github.com/cozy/cozy-libs/compare/cozy-viewer@3.0.0...cozy-viewer@3.0.1) (2024-11-27)
7
40
 
8
41
  **Note:** Version bump only for package cozy-viewer
@@ -6,7 +6,7 @@ declare function QualificationListItemText({ primary, secondary, disabled }: {
6
6
  }): JSX.Element;
7
7
  declare namespace QualificationListItemText {
8
8
  namespace propTypes {
9
- const primary: PropTypes.Validator<string>;
9
+ const primary: PropTypes.Requireable<string>;
10
10
  const secondary: PropTypes.Validator<string | number | boolean | {} | PropTypes.ReactElementLike | PropTypes.ReactNodeArray>;
11
11
  }
12
12
  }
@@ -35,7 +35,7 @@ var QualificationListItemText = function QualificationListItemText(_ref) {
35
35
  };
36
36
 
37
37
  QualificationListItemText.propTypes = {
38
- primary: _propTypes.default.string.isRequired,
38
+ primary: _propTypes.default.string,
39
39
  secondary: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.node]).isRequired
40
40
  };
41
41
  var _default = QualificationListItemText;
@@ -0,0 +1,2 @@
1
+ declare var _default: any;
2
+ export default _default;
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+
10
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
+
12
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
13
+
14
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
15
+
16
+ var _propTypes = _interopRequireDefault(require("prop-types"));
17
+
18
+ var _react = _interopRequireWildcard(require("react"));
19
+
20
+ var _ActionsMenu = _interopRequireDefault(require("cozy-ui/transpiled/react/ActionsMenu"));
21
+
22
+ var _Actions = require("cozy-ui/transpiled/react/ActionsMenu/Actions");
23
+
24
+ var _ActionsMenuMobileHeader = _interopRequireDefault(require("cozy-ui/transpiled/react/ActionsMenu/ActionsMenuMobileHeader"));
25
+
26
+ var _Icon = _interopRequireDefault(require("cozy-ui/transpiled/react/Icon"));
27
+
28
+ var _IconButton = _interopRequireDefault(require("cozy-ui/transpiled/react/IconButton"));
29
+
30
+ var _Dots = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/Dots"));
31
+
32
+ var _Right = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/Right"));
33
+
34
+ var _Text = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/Text"));
35
+
36
+ var _List = _interopRequireDefault(require("cozy-ui/transpiled/react/List"));
37
+
38
+ var _ListItem = _interopRequireDefault(require("cozy-ui/transpiled/react/ListItem"));
39
+
40
+ var _ListItemIcon = _interopRequireDefault(require("cozy-ui/transpiled/react/ListItemIcon"));
41
+
42
+ var _ListItemSecondaryAction = _interopRequireDefault(require("cozy-ui/transpiled/react/ListItemSecondaryAction"));
43
+
44
+ var _ListItemText = _interopRequireDefault(require("cozy-ui/transpiled/react/ListItemText"));
45
+
46
+ var _Alert = require("cozy-ui/transpiled/react/providers/Alert");
47
+
48
+ var _QualificationListItemText = _interopRequireDefault(require("./QualificationListItemText"));
49
+
50
+ var _SummaryDialog = _interopRequireDefault(require("./SummaryDialog"));
51
+
52
+ var _withViewerLocales = require("../hoc/withViewerLocales");
53
+
54
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
55
+
56
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
57
+
58
+ var Summary = function Summary(_ref) {
59
+ var file = _ref.file,
60
+ t = _ref.t;
61
+
62
+ var _useState = (0, _react.useState)(false),
63
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
64
+ showModal = _useState2[0],
65
+ setShowModal = _useState2[1];
66
+
67
+ var _useState3 = (0, _react.useState)(false),
68
+ _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
69
+ showMenu = _useState4[0],
70
+ setShowMenu = _useState4[1];
71
+
72
+ var anchorRef = (0, _react.useRef)();
73
+
74
+ var _useAlert = (0, _Alert.useAlert)(),
75
+ showAlert = _useAlert.showAlert;
76
+
77
+ var label = t('Viewer.panel.summary');
78
+ var value = file.metadata.description;
79
+ var actions = (0, _Actions.makeActions)([_Actions.copyToClipboard, _Actions.editAttribute]);
80
+
81
+ var handleClick = /*#__PURE__*/function () {
82
+ var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
83
+ return _regenerator.default.wrap(function _callee$(_context) {
84
+ while (1) {
85
+ switch (_context.prev = _context.next) {
86
+ case 0:
87
+ if (!value) {
88
+ _context.next = 5;
89
+ break;
90
+ }
91
+
92
+ _context.next = 3;
93
+ return (0, _Actions.copyToClipboard)().action(undefined, {
94
+ showAlert: showAlert,
95
+ copyValue: value
96
+ });
97
+
98
+ case 3:
99
+ _context.next = 6;
100
+ break;
101
+
102
+ case 5:
103
+ setShowModal(true);
104
+
105
+ case 6:
106
+ case "end":
107
+ return _context.stop();
108
+ }
109
+ }
110
+ }, _callee);
111
+ }));
112
+
113
+ return function handleClick() {
114
+ return _ref2.apply(this, arguments);
115
+ };
116
+ }();
117
+
118
+ return /*#__PURE__*/_react.default.createElement(_List.default, null, /*#__PURE__*/_react.default.createElement(_ListItem.default, {
119
+ button: true,
120
+ onClick: handleClick
121
+ }, /*#__PURE__*/_react.default.createElement(_ListItemIcon.default, null, /*#__PURE__*/_react.default.createElement(_Icon.default, {
122
+ icon: _Text.default
123
+ })), /*#__PURE__*/_react.default.createElement(_QualificationListItemText.default, {
124
+ primary: value && label,
125
+ secondary: value || label,
126
+ disabled: !value
127
+ }), value ? /*#__PURE__*/_react.default.createElement(_ListItemSecondaryAction.default, null, /*#__PURE__*/_react.default.createElement(_IconButton.default, {
128
+ ref: anchorRef,
129
+ onClick: function onClick() {
130
+ return setShowMenu(function (v) {
131
+ return !v;
132
+ });
133
+ }
134
+ }, /*#__PURE__*/_react.default.createElement(_Icon.default, {
135
+ icon: _Dots.default
136
+ }))) : /*#__PURE__*/_react.default.createElement(_ListItemIcon.default, null, /*#__PURE__*/_react.default.createElement(_Icon.default, {
137
+ icon: _Right.default
138
+ }))), showModal && /*#__PURE__*/_react.default.createElement(_SummaryDialog.default, {
139
+ file: file,
140
+ onClose: function onClose() {
141
+ return setShowModal(false);
142
+ }
143
+ }), showMenu && /*#__PURE__*/_react.default.createElement(_ActionsMenu.default, {
144
+ ref: anchorRef,
145
+ open: true,
146
+ docs: [file],
147
+ actions: actions,
148
+ anchorOrigin: {
149
+ vertical: 'bottom',
150
+ horizontal: 'right'
151
+ },
152
+ autoClose: true,
153
+ componentsProps: {
154
+ actionsItems: {
155
+ actionOptions: {
156
+ showAlert: showAlert,
157
+ copyValue: value,
158
+ editAttributeCallback: function editAttributeCallback() {
159
+ return setShowModal(true);
160
+ }
161
+ }
162
+ }
163
+ },
164
+ onClose: function onClose() {
165
+ return setShowMenu(false);
166
+ }
167
+ }, /*#__PURE__*/_react.default.createElement(_ActionsMenuMobileHeader.default, null, /*#__PURE__*/_react.default.createElement(_ListItemText.default, {
168
+ primary: label,
169
+ primaryTypographyProps: {
170
+ align: 'center',
171
+ variant: 'h6'
172
+ }
173
+ }))));
174
+ };
175
+
176
+ Summary.propTypes = {
177
+ file: _propTypes.default.object.isRequired,
178
+ t: _propTypes.default.func
179
+ };
180
+
181
+ var _default = (0, _withViewerLocales.withViewerLocales)(Summary);
182
+
183
+ exports.default = _default;
@@ -0,0 +1,2 @@
1
+ declare var _default: any;
2
+ export default _default;
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+
10
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
11
+
12
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
13
+
14
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
15
+
16
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
17
+
18
+ var _propTypes = _interopRequireDefault(require("prop-types"));
19
+
20
+ var _react = _interopRequireWildcard(require("react"));
21
+
22
+ var _cozyClient = require("cozy-client");
23
+
24
+ var _Buttons = _interopRequireDefault(require("cozy-ui/transpiled/react/Buttons"));
25
+
26
+ var _CozyDialogs = require("cozy-ui/transpiled/react/CozyDialogs");
27
+
28
+ var _TextField = _interopRequireDefault(require("cozy-ui/transpiled/react/TextField"));
29
+
30
+ var _withViewerLocales = require("../hoc/withViewerLocales");
31
+
32
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
33
+
34
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
35
+
36
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
37
+
38
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
39
+
40
+ var SummaryDialog = function SummaryDialog(_ref) {
41
+ var file = _ref.file,
42
+ t = _ref.t,
43
+ onClose = _ref.onClose;
44
+
45
+ var _useState = (0, _react.useState)(file.metadata.description),
46
+ _useState2 = (0, _slicedToArray2.default)(_useState, 2),
47
+ value = _useState2[0],
48
+ setValue = _useState2[1];
49
+
50
+ var _useState3 = (0, _react.useState)(false),
51
+ _useState4 = (0, _slicedToArray2.default)(_useState3, 2),
52
+ busy = _useState4[0],
53
+ setBusy = _useState4[1];
54
+
55
+ var client = (0, _cozyClient.useClient)();
56
+
57
+ var handleSubmit = /*#__PURE__*/function () {
58
+ var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
59
+ return _regenerator.default.wrap(function _callee$(_context) {
60
+ while (1) {
61
+ switch (_context.prev = _context.next) {
62
+ case 0:
63
+ setBusy(true);
64
+ _context.next = 3;
65
+ return client.collection('io.cozy.files').updateMetadataAttribute(file._id, _objectSpread(_objectSpread({}, file.metadata), {}, {
66
+ description: value
67
+ }));
68
+
69
+ case 3:
70
+ onClose();
71
+
72
+ case 4:
73
+ case "end":
74
+ return _context.stop();
75
+ }
76
+ }
77
+ }, _callee);
78
+ }));
79
+
80
+ return function handleSubmit() {
81
+ return _ref2.apply(this, arguments);
82
+ };
83
+ }();
84
+
85
+ return /*#__PURE__*/_react.default.createElement(_CozyDialogs.ConfirmDialog, {
86
+ open: true,
87
+ title: t('Viewer.panel.summary'),
88
+ content: /*#__PURE__*/_react.default.createElement(_TextField.default, {
89
+ multiline: true,
90
+ value: value,
91
+ rows: 4,
92
+ autoFocus: true,
93
+ fullWidth: true,
94
+ required: true,
95
+ variant: "outlined",
96
+ onChange: function onChange(ev) {
97
+ return setValue(ev.target.value);
98
+ }
99
+ }),
100
+ actions: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_Buttons.default, {
101
+ className: "u-miw-4",
102
+ variant: "secondary",
103
+ label: t('Viewer.cancel'),
104
+ onClick: onClose
105
+ }), /*#__PURE__*/_react.default.createElement(_Buttons.default, {
106
+ className: "u-miw-4",
107
+ label: t('Viewer.ok'),
108
+ busy: busy,
109
+ onClick: handleSubmit
110
+ })),
111
+ onClose: onClose
112
+ });
113
+ };
114
+
115
+ SummaryDialog.propTypes = {
116
+ file: _propTypes.default.object.isRequired,
117
+ t: _propTypes.default.func,
118
+ onClose: _propTypes.default.func
119
+ };
120
+
121
+ var _default = (0, _withViewerLocales.withViewerLocales)(SummaryDialog);
122
+
123
+ exports.default = _default;
@@ -15,6 +15,8 @@ var _Informations = _interopRequireDefault(require("./Informations"));
15
15
 
16
16
  var _Qualification = _interopRequireDefault(require("./Qualification"));
17
17
 
18
+ var _Summary = _interopRequireDefault(require("./Summary"));
19
+
18
20
  /**
19
21
  * @typedef {Object} PanelBlockSpec
20
22
  * @property {Function} condition - Function that returns true if the block should be displayed
@@ -33,6 +35,12 @@ var _Qualification = _interopRequireDefault(require("./Qualification"));
33
35
  var getPanelBlocksSpecs = function getPanelBlocksSpecs() {
34
36
  var isPublic = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
35
37
  return {
38
+ summary: {
39
+ condition: function condition() {
40
+ return true;
41
+ },
42
+ component: _Summary.default
43
+ },
36
44
  qualifications: {
37
45
  condition: _file.hasQualifications,
38
46
  component: _Qualification.default
@@ -14,6 +14,8 @@ var en = {
14
14
  preparing: "Preparing your files\u2026"
15
15
  },
16
16
  close: "close",
17
+ cancel: "Cancel",
18
+ ok: "Ok",
17
19
  download: "Download",
18
20
  complete: "Complete the document",
19
21
  noImage: "No image",
@@ -30,6 +32,7 @@ var en = {
30
32
  openWith: "Open with...",
31
33
  openInOnlyOffice: "Open with Only Office",
32
34
  panel: {
35
+ summary: "Summary",
33
36
  informations: {
34
37
  format: {
35
38
  title: "%{format} Document",
@@ -90,6 +93,8 @@ var fr = {
90
93
  preparing: "Preparation de vos fichiers\u2026"
91
94
  },
92
95
  close: "Fermer",
96
+ cancel: "Annuler",
97
+ ok: "Ok",
93
98
  download: "T\xE9l\xE9charger",
94
99
  complete: "Compl\xE9ter le document",
95
100
  noImage: "Aucune image",
@@ -106,6 +111,7 @@ var fr = {
106
111
  openWith: "Ouvrir avec...",
107
112
  openInOnlyOffice: "Ouvrir avec Only Office",
108
113
  panel: {
114
+ summary: "R\xE9sum\xE9",
109
115
  informations: {
110
116
  format: {
111
117
  title: "Document %{format}",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-viewer",
3
- "version": "3.0.1",
3
+ "version": "5.0.0",
4
4
  "description": "Cozy-Viewer provides a component to show files in a viewer.",
5
5
  "main": "dist/index.js",
6
6
  "license": "MIT",
@@ -27,11 +27,11 @@
27
27
  "babel-preset-cozy-app": "^2.8.1",
28
28
  "cozy-client": "50.0.0",
29
29
  "cozy-device-helper": "2.0.0",
30
- "cozy-harvest-lib": "^30.8.0",
30
+ "cozy-harvest-lib": "^30.8.2",
31
31
  "cozy-intent": "^2.29.1",
32
32
  "cozy-logger": "^1.16.1",
33
33
  "cozy-sharing": "14.1.0",
34
- "cozy-ui": "^113.4.0",
34
+ "cozy-ui": "^113.7.0",
35
35
  "enzyme": "3.11.0",
36
36
  "enzyme-adapter-react-16": "1.15.6",
37
37
  "enzyme-to-json": "3.6.2",
@@ -52,13 +52,13 @@
52
52
  "peerDependencies": {
53
53
  "cozy-client": ">=50.0.0",
54
54
  "cozy-device-helper": ">=2.0.0",
55
- "cozy-harvest-lib": ">=30.2.0",
55
+ "cozy-harvest-lib": ">=30.8.0",
56
56
  "cozy-intent": ">=2.26.0",
57
57
  "cozy-logger": ">=1.9.0",
58
58
  "cozy-sharing": ">=14.1.0",
59
- "cozy-ui": ">=113.4.0",
59
+ "cozy-ui": ">=113.7.0",
60
60
  "react": ">=16.12.0",
61
61
  "react-dom": ">=16.12.0"
62
62
  },
63
- "gitHead": "38b8eacca88975853144d089f51c939b4ec2fe43"
63
+ "gitHead": "65fc17fd76d5cbf63e3fa5c9b9c874edf5a6639c"
64
64
  }
@@ -23,7 +23,7 @@ const QualificationListItemText = ({ primary, secondary, disabled }) => {
23
23
  }
24
24
 
25
25
  QualificationListItemText.propTypes = {
26
- primary: PropTypes.string.isRequired,
26
+ primary: PropTypes.string,
27
27
  secondary: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired
28
28
  }
29
29
 
@@ -0,0 +1,110 @@
1
+ import PropTypes from 'prop-types'
2
+ import React, { useState, useRef } from 'react'
3
+
4
+ import ActionsMenu from 'cozy-ui/transpiled/react/ActionsMenu'
5
+ import {
6
+ makeActions,
7
+ editAttribute,
8
+ copyToClipboard
9
+ } from 'cozy-ui/transpiled/react/ActionsMenu/Actions'
10
+ import ActionsMenuMobileHeader from 'cozy-ui/transpiled/react/ActionsMenu/ActionsMenuMobileHeader'
11
+ import Icon from 'cozy-ui/transpiled/react/Icon'
12
+ import IconButton from 'cozy-ui/transpiled/react/IconButton'
13
+ import DotsIcon from 'cozy-ui/transpiled/react/Icons/Dots'
14
+ import RightIcon from 'cozy-ui/transpiled/react/Icons/Right'
15
+ import TextIcon from 'cozy-ui/transpiled/react/Icons/Text'
16
+ import List from 'cozy-ui/transpiled/react/List'
17
+ import ListItem from 'cozy-ui/transpiled/react/ListItem'
18
+ import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
19
+ import ListItemSecondaryAction from 'cozy-ui/transpiled/react/ListItemSecondaryAction'
20
+ import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
21
+ import { useAlert } from 'cozy-ui/transpiled/react/providers/Alert'
22
+
23
+ import QualificationListItemText from './QualificationListItemText'
24
+ import SummaryDialog from './SummaryDialog'
25
+ import { withViewerLocales } from '../hoc/withViewerLocales'
26
+
27
+ const Summary = ({ file, t }) => {
28
+ const [showModal, setShowModal] = useState(false)
29
+ const [showMenu, setShowMenu] = useState(false)
30
+ const anchorRef = useRef()
31
+ const { showAlert } = useAlert()
32
+
33
+ const label = t('Viewer.panel.summary')
34
+ const value = file.metadata.description
35
+ const actions = makeActions([copyToClipboard, editAttribute])
36
+
37
+ const handleClick = async () => {
38
+ if (value) {
39
+ await copyToClipboard().action(undefined, { showAlert, copyValue: value })
40
+ } else {
41
+ setShowModal(true)
42
+ }
43
+ }
44
+
45
+ return (
46
+ <List>
47
+ <ListItem button onClick={handleClick}>
48
+ <ListItemIcon>
49
+ <Icon icon={TextIcon} />
50
+ </ListItemIcon>
51
+ <QualificationListItemText
52
+ primary={value && label}
53
+ secondary={value || label}
54
+ disabled={!value}
55
+ />
56
+ {value ? (
57
+ <ListItemSecondaryAction>
58
+ <IconButton ref={anchorRef} onClick={() => setShowMenu(v => !v)}>
59
+ <Icon icon={DotsIcon} />
60
+ </IconButton>
61
+ </ListItemSecondaryAction>
62
+ ) : (
63
+ <ListItemIcon>
64
+ <Icon icon={RightIcon} />
65
+ </ListItemIcon>
66
+ )}
67
+ </ListItem>
68
+ {showModal && (
69
+ <SummaryDialog file={file} onClose={() => setShowModal(false)} />
70
+ )}
71
+ {showMenu && (
72
+ <ActionsMenu
73
+ ref={anchorRef}
74
+ open={true}
75
+ docs={[file]}
76
+ actions={actions}
77
+ anchorOrigin={{
78
+ vertical: 'bottom',
79
+ horizontal: 'right'
80
+ }}
81
+ autoClose
82
+ componentsProps={{
83
+ actionsItems: {
84
+ actionOptions: {
85
+ showAlert,
86
+ copyValue: value,
87
+ editAttributeCallback: () => setShowModal(true)
88
+ }
89
+ }
90
+ }}
91
+ onClose={() => setShowMenu(false)}
92
+ >
93
+ <ActionsMenuMobileHeader>
94
+ <ListItemText
95
+ primary={label}
96
+ primaryTypographyProps={{ align: 'center', variant: 'h6' }}
97
+ />
98
+ </ActionsMenuMobileHeader>
99
+ </ActionsMenu>
100
+ )}
101
+ </List>
102
+ )
103
+ }
104
+
105
+ Summary.propTypes = {
106
+ file: PropTypes.object.isRequired,
107
+ t: PropTypes.func
108
+ }
109
+
110
+ export default withViewerLocales(Summary)
@@ -0,0 +1,68 @@
1
+ import PropTypes from 'prop-types'
2
+ import React, { useState } from 'react'
3
+
4
+ import { useClient } from 'cozy-client'
5
+ import Button from 'cozy-ui/transpiled/react/Buttons'
6
+ import { ConfirmDialog } from 'cozy-ui/transpiled/react/CozyDialogs'
7
+ import TextField from 'cozy-ui/transpiled/react/TextField'
8
+
9
+ import { withViewerLocales } from '../hoc/withViewerLocales'
10
+
11
+ const SummaryDialog = ({ file, t, onClose }) => {
12
+ const [value, setValue] = useState(file.metadata.description)
13
+ const [busy, setBusy] = useState(false)
14
+ const client = useClient()
15
+
16
+ const handleSubmit = async () => {
17
+ setBusy(true)
18
+ await client.collection('io.cozy.files').updateMetadataAttribute(file._id, {
19
+ ...file.metadata,
20
+ description: value
21
+ })
22
+ onClose()
23
+ }
24
+
25
+ return (
26
+ <ConfirmDialog
27
+ open
28
+ title={t('Viewer.panel.summary')}
29
+ content={
30
+ <TextField
31
+ multiline
32
+ value={value}
33
+ rows={4}
34
+ autoFocus
35
+ fullWidth
36
+ required
37
+ variant="outlined"
38
+ onChange={ev => setValue(ev.target.value)}
39
+ />
40
+ }
41
+ actions={
42
+ <>
43
+ <Button
44
+ className="u-miw-4"
45
+ variant="secondary"
46
+ label={t('Viewer.cancel')}
47
+ onClick={onClose}
48
+ />
49
+ <Button
50
+ className="u-miw-4"
51
+ label={t('Viewer.ok')}
52
+ busy={busy}
53
+ onClick={handleSubmit}
54
+ />
55
+ </>
56
+ }
57
+ onClose={onClose}
58
+ />
59
+ )
60
+ }
61
+
62
+ SummaryDialog.propTypes = {
63
+ file: PropTypes.object.isRequired,
64
+ t: PropTypes.func,
65
+ onClose: PropTypes.func
66
+ }
67
+
68
+ export default withViewerLocales(SummaryDialog)
@@ -6,6 +6,7 @@ import KonnectorBlock from 'cozy-harvest-lib/dist/components/KonnectorBlock'
6
6
 
7
7
  import Informations from './Informations'
8
8
  import Qualification from './Qualification'
9
+ import Summary from './Summary'
9
10
 
10
11
  /**
11
12
  * @typedef {Object} PanelBlockSpec
@@ -23,6 +24,10 @@ import Qualification from './Qualification'
23
24
  * @returns {PanelBlocksSpecs}
24
25
  */
25
26
  export const getPanelBlocksSpecs = (isPublic = false) => ({
27
+ summary: {
28
+ condition: () => true,
29
+ component: Summary
30
+ },
26
31
  qualifications: {
27
32
  condition: hasQualifications,
28
33
  component: Qualification
@@ -62,6 +62,10 @@ describe('getPanelBlocks', () => {
62
62
  describe('getPanelBlocksSpecs', () => {
63
63
  it('should return the specs of the blocks to display in the panel', () => {
64
64
  expect(getPanelBlocksSpecs()).toEqual({
65
+ summary: {
66
+ condition: expect.any(Function),
67
+ component: expect.anything()
68
+ },
65
69
  qualifications: {
66
70
  condition: expect.any(Function),
67
71
  component: expect.anything()
@@ -8,6 +8,8 @@
8
8
  "preparing": "Preparing your files…"
9
9
  },
10
10
  "close": "close",
11
+ "cancel": "Cancel",
12
+ "ok": "Ok",
11
13
  "download": "Download",
12
14
  "complete": "Complete the document",
13
15
  "noImage": "No image",
@@ -24,6 +26,7 @@
24
26
  "openWith": "Open with...",
25
27
  "openInOnlyOffice": "Open with Only Office",
26
28
  "panel": {
29
+ "summary": "Summary",
27
30
  "informations": {
28
31
  "format": {
29
32
  "title": "%{format} Document",
@@ -8,6 +8,8 @@
8
8
  "preparing": "Preparation de vos fichiers…"
9
9
  },
10
10
  "close": "Fermer",
11
+ "cancel": "Annuler",
12
+ "ok": "Ok",
11
13
  "download": "Télécharger",
12
14
  "complete": "Compléter le document",
13
15
  "noImage": "Aucune image",
@@ -24,6 +26,7 @@
24
26
  "openWith": "Ouvrir avec...",
25
27
  "openInOnlyOffice": "Ouvrir avec Only Office",
26
28
  "panel": {
29
+ "summary": "Résumé",
27
30
  "informations": {
28
31
  "format": {
29
32
  "title": "Document %{format}",