cozy-viewer 2.9.0 → 3.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 +32 -0
- package/dist/Panel/Informations.js +155 -0
- package/dist/Panel/PanelContent.js +1 -4
- package/dist/Panel/getPanelBlocks.js +9 -12
- package/dist/Panel/helpers.d.ts +4 -0
- package/dist/Panel/helpers.js +65 -0
- package/dist/locales/index.js +20 -0
- package/package.json +5 -5
- package/src/Panel/Informations.jsx +140 -0
- package/src/Panel/PanelContent.jsx +1 -3
- package/src/Panel/getPanelBlocks.jsx +8 -7
- package/src/Panel/getPanelBlocks.spec.jsx +1 -1
- package/src/Panel/helpers.js +43 -0
- package/src/locales/en.json +10 -0
- package/src/locales/fr.json +10 -0
- package/dist/Panel/Certifications.js +0 -80
- package/src/Panel/Certifications.jsx +0 -63
- /package/dist/Panel/{Certifications.d.ts → Informations.d.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,38 @@
|
|
|
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
|
+
# [3.0.0](https://github.com/cozy/cozy-libs/compare/cozy-viewer@2.9.1...cozy-viewer@3.0.0) (2024-11-26)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* **Viewer:** Remove useless typography wrapper around PanelBlock ([d15c875](https://github.com/cozy/cozy-libs/commit/d15c875c13632dbd3b469bc6886ff85a53f43228))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
* **Viewer:** Add action menu on information block ([a696472](https://github.com/cozy/cozy-libs/commit/a6964729cb28dd6006aaaec108b5d91ae33be491))
|
|
17
|
+
* **Viewer:** Add Informations block ([8c54678](https://github.com/cozy/cozy-libs/commit/8c546784a63da98a47c993091f73d2dd0e50a7fa))
|
|
18
|
+
* **Viewer:** Move Certifications block inside Informations block ([c583e35](https://github.com/cozy/cozy-libs/commit/c583e3502d307f55920d99bd1674e2f7027b0f78))
|
|
19
|
+
* **Viewer:** Upgrade cozy-ui ([76f7d4f](https://github.com/cozy/cozy-libs/commit/76f7d4f15f9b975834a92d570ad6030206e00261))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
### BREAKING CHANGES
|
|
23
|
+
|
|
24
|
+
* **Viewer:** You must have `cozy-ui >= 113.4.0`
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
## [2.9.1](https://github.com/cozy/cozy-libs/compare/cozy-viewer@2.9.0...cozy-viewer@2.9.1) (2024-11-22)
|
|
31
|
+
|
|
32
|
+
**Note:** Version bump only for package cozy-viewer
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
6
38
|
# [2.9.0](https://github.com/cozy/cozy-libs/compare/cozy-viewer@2.8.0...cozy-viewer@2.9.0) (2024-11-22)
|
|
7
39
|
|
|
8
40
|
|
|
@@ -0,0 +1,155 @@
|
|
|
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 _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
11
|
+
|
|
12
|
+
var _has = _interopRequireDefault(require("lodash/has"));
|
|
13
|
+
|
|
14
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
15
|
+
|
|
16
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
17
|
+
|
|
18
|
+
var _ActionsMenu = _interopRequireDefault(require("cozy-ui/transpiled/react/ActionsMenu"));
|
|
19
|
+
|
|
20
|
+
var _Actions = require("cozy-ui/transpiled/react/ActionsMenu/Actions");
|
|
21
|
+
|
|
22
|
+
var _Icon = _interopRequireDefault(require("cozy-ui/transpiled/react/Icon"));
|
|
23
|
+
|
|
24
|
+
var _IconButton = _interopRequireDefault(require("cozy-ui/transpiled/react/IconButton"));
|
|
25
|
+
|
|
26
|
+
var _Calendar = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/Calendar"));
|
|
27
|
+
|
|
28
|
+
var _CarbonCopy = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/CarbonCopy"));
|
|
29
|
+
|
|
30
|
+
var _Dots = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/Dots"));
|
|
31
|
+
|
|
32
|
+
var _FileOutline = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/FileOutline"));
|
|
33
|
+
|
|
34
|
+
var _Folder = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/Folder"));
|
|
35
|
+
|
|
36
|
+
var _Safe = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/Safe"));
|
|
37
|
+
|
|
38
|
+
var _Server = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/Server"));
|
|
39
|
+
|
|
40
|
+
var _List = _interopRequireDefault(require("cozy-ui/transpiled/react/List"));
|
|
41
|
+
|
|
42
|
+
var _ListItem = _interopRequireDefault(require("cozy-ui/transpiled/react/ListItem"));
|
|
43
|
+
|
|
44
|
+
var _ListItemIcon = _interopRequireDefault(require("cozy-ui/transpiled/react/ListItemIcon"));
|
|
45
|
+
|
|
46
|
+
var _ListItemSecondaryAction = _interopRequireDefault(require("cozy-ui/transpiled/react/ListItemSecondaryAction"));
|
|
47
|
+
|
|
48
|
+
var _ListItemText = _interopRequireDefault(require("cozy-ui/transpiled/react/ListItemText"));
|
|
49
|
+
|
|
50
|
+
var _I18n = require("cozy-ui/transpiled/react/providers/I18n");
|
|
51
|
+
|
|
52
|
+
var _helpers = require("./helpers");
|
|
53
|
+
|
|
54
|
+
var _withViewerLocales = require("../hoc/withViewerLocales");
|
|
55
|
+
|
|
56
|
+
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); }
|
|
57
|
+
|
|
58
|
+
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; }
|
|
59
|
+
|
|
60
|
+
var Informations = function Informations(_ref) {
|
|
61
|
+
var file = _ref.file,
|
|
62
|
+
t = _ref.t;
|
|
63
|
+
|
|
64
|
+
var _useState = (0, _react.useState)(false),
|
|
65
|
+
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
66
|
+
showMenu = _useState2[0],
|
|
67
|
+
setShowMenu = _useState2[1];
|
|
68
|
+
|
|
69
|
+
var _useI18n = (0, _I18n.useI18n)(),
|
|
70
|
+
f = _useI18n.f,
|
|
71
|
+
lang = _useI18n.lang;
|
|
72
|
+
|
|
73
|
+
var format = (0, _helpers.makeFormat)(file);
|
|
74
|
+
var path = (0, _helpers.makePath)(file);
|
|
75
|
+
var size = (0, _helpers.makeSize)(file.size);
|
|
76
|
+
var creation = f(file.created_at, (0, _helpers.makeDate)(lang));
|
|
77
|
+
var modification = f(file.updated_at, (0, _helpers.makeDate)(lang));
|
|
78
|
+
var hasCarbonCopy = (0, _has.default)(file, 'metadata.carbonCopy');
|
|
79
|
+
var hasElectronicSafe = (0, _has.default)(file, 'metadata.electronicSafe');
|
|
80
|
+
var anchorRef = (0, _react.useRef)();
|
|
81
|
+
var actions = (0, _Actions.makeActions)([_Actions.viewInDrive]);
|
|
82
|
+
return /*#__PURE__*/_react.default.createElement(_List.default, null, /*#__PURE__*/_react.default.createElement(_ListItem.default, null, /*#__PURE__*/_react.default.createElement(_ListItemIcon.default, null, /*#__PURE__*/_react.default.createElement(_Icon.default, {
|
|
83
|
+
icon: _FileOutline.default
|
|
84
|
+
})), /*#__PURE__*/_react.default.createElement(_ListItemText.default, {
|
|
85
|
+
primary: t('Viewer.panel.informations.format.title', {
|
|
86
|
+
format: format
|
|
87
|
+
}),
|
|
88
|
+
secondary: t('Viewer.panel.informations.format.subtitle')
|
|
89
|
+
})), /*#__PURE__*/_react.default.createElement(_ListItem.default, null, /*#__PURE__*/_react.default.createElement(_ListItemIcon.default, null, /*#__PURE__*/_react.default.createElement(_Icon.default, {
|
|
90
|
+
icon: _Server.default
|
|
91
|
+
})), /*#__PURE__*/_react.default.createElement(_ListItemText.default, {
|
|
92
|
+
primary: size,
|
|
93
|
+
secondary: t('Viewer.panel.informations.size')
|
|
94
|
+
})), /*#__PURE__*/_react.default.createElement(_ListItem.default, null, /*#__PURE__*/_react.default.createElement(_ListItemIcon.default, null, /*#__PURE__*/_react.default.createElement(_Icon.default, {
|
|
95
|
+
icon: _Folder.default
|
|
96
|
+
})), /*#__PURE__*/_react.default.createElement(_ListItemText.default, {
|
|
97
|
+
primary: path,
|
|
98
|
+
secondary: t('Viewer.panel.informations.location')
|
|
99
|
+
}), /*#__PURE__*/_react.default.createElement(_ListItemSecondaryAction.default, null, /*#__PURE__*/_react.default.createElement(_IconButton.default, {
|
|
100
|
+
ref: anchorRef,
|
|
101
|
+
onClick: function onClick() {
|
|
102
|
+
return setShowMenu(function (v) {
|
|
103
|
+
return !v;
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}, /*#__PURE__*/_react.default.createElement(_Icon.default, {
|
|
107
|
+
icon: _Dots.default
|
|
108
|
+
})))), showMenu && /*#__PURE__*/_react.default.createElement(_ActionsMenu.default, {
|
|
109
|
+
ref: anchorRef,
|
|
110
|
+
open: true,
|
|
111
|
+
docs: [file],
|
|
112
|
+
actions: actions,
|
|
113
|
+
anchorOrigin: {
|
|
114
|
+
vertical: 'bottom',
|
|
115
|
+
horizontal: 'right'
|
|
116
|
+
},
|
|
117
|
+
autoClose: true,
|
|
118
|
+
onClose: function onClose() {
|
|
119
|
+
return setShowMenu(false);
|
|
120
|
+
}
|
|
121
|
+
}), /*#__PURE__*/_react.default.createElement(_ListItem.default, null, /*#__PURE__*/_react.default.createElement(_ListItemIcon.default, null, /*#__PURE__*/_react.default.createElement(_Icon.default, {
|
|
122
|
+
icon: _Calendar.default
|
|
123
|
+
})), /*#__PURE__*/_react.default.createElement(_ListItemText.default, {
|
|
124
|
+
primary: creation,
|
|
125
|
+
secondary: t('Viewer.panel.informations.creation')
|
|
126
|
+
})), /*#__PURE__*/_react.default.createElement(_ListItem.default, null, /*#__PURE__*/_react.default.createElement(_ListItemIcon.default, null, /*#__PURE__*/_react.default.createElement(_Icon.default, {
|
|
127
|
+
icon: _Calendar.default
|
|
128
|
+
})), /*#__PURE__*/_react.default.createElement(_ListItemText.default, {
|
|
129
|
+
primary: modification,
|
|
130
|
+
secondary: t('Viewer.panel.informations.modification')
|
|
131
|
+
})), hasCarbonCopy && /*#__PURE__*/_react.default.createElement(_ListItem.default, {
|
|
132
|
+
ellipsis: false
|
|
133
|
+
}, /*#__PURE__*/_react.default.createElement(_ListItemIcon.default, null, /*#__PURE__*/_react.default.createElement(_Icon.default, {
|
|
134
|
+
icon: _CarbonCopy.default
|
|
135
|
+
})), /*#__PURE__*/_react.default.createElement(_ListItemText.default, {
|
|
136
|
+
primary: t('Viewer.panel.certifications.carbonCopy.title'),
|
|
137
|
+
secondary: t('Viewer.panel.certifications.carbonCopy.caption')
|
|
138
|
+
})), hasElectronicSafe && /*#__PURE__*/_react.default.createElement(_ListItem.default, {
|
|
139
|
+
ellipsis: false
|
|
140
|
+
}, /*#__PURE__*/_react.default.createElement(_ListItemIcon.default, null, /*#__PURE__*/_react.default.createElement(_Icon.default, {
|
|
141
|
+
icon: _Safe.default
|
|
142
|
+
})), /*#__PURE__*/_react.default.createElement(_ListItemText.default, {
|
|
143
|
+
primary: t('Viewer.panel.certifications.electronicSafe.title'),
|
|
144
|
+
secondary: t('Viewer.panel.certifications.electronicSafe.caption')
|
|
145
|
+
})));
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
Informations.propTypes = {
|
|
149
|
+
file: _propTypes.default.object.isRequired,
|
|
150
|
+
t: _propTypes.default.func
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
var _default = (0, _withViewerLocales.withViewerLocales)(Informations);
|
|
154
|
+
|
|
155
|
+
exports.default = _default;
|
|
@@ -52,12 +52,9 @@ var PanelContent = function PanelContent(_ref) {
|
|
|
52
52
|
}),
|
|
53
53
|
elevation: 2,
|
|
54
54
|
square: true
|
|
55
|
-
}, /*#__PURE__*/_react.default.createElement(_Typography.default, {
|
|
56
|
-
variant: "h4",
|
|
57
|
-
className: "u-pv-1"
|
|
58
55
|
}, /*#__PURE__*/_react.default.createElement(PanelBlock, {
|
|
59
56
|
file: file
|
|
60
|
-
}))
|
|
57
|
+
}));
|
|
61
58
|
}));
|
|
62
59
|
};
|
|
63
60
|
|
|
@@ -7,18 +7,14 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
});
|
|
8
8
|
exports.getPanelBlocksSpecs = exports.default = void 0;
|
|
9
9
|
|
|
10
|
-
var
|
|
10
|
+
var _file = require("cozy-client/dist/models/file");
|
|
11
11
|
|
|
12
12
|
var _KonnectorBlock = _interopRequireDefault(require("cozy-harvest-lib/dist/components/KonnectorBlock"));
|
|
13
13
|
|
|
14
|
-
var
|
|
14
|
+
var _Informations = _interopRequireDefault(require("./Informations"));
|
|
15
15
|
|
|
16
16
|
var _Qualification = _interopRequireDefault(require("./Qualification"));
|
|
17
17
|
|
|
18
|
-
var _models$file = _cozyClient.models.file,
|
|
19
|
-
isFromKonnector = _models$file.isFromKonnector,
|
|
20
|
-
hasQualifications = _models$file.hasQualifications,
|
|
21
|
-
hasCertifications = _models$file.hasCertifications;
|
|
22
18
|
/**
|
|
23
19
|
* @typedef {Object} PanelBlockSpec
|
|
24
20
|
* @property {Function} condition - Function that returns true if the block should be displayed
|
|
@@ -34,23 +30,24 @@ var _models$file = _cozyClient.models.file,
|
|
|
34
30
|
* @param {boolean} isPublic - Whether the panel is displayed in public view
|
|
35
31
|
* @returns {PanelBlocksSpecs}
|
|
36
32
|
*/
|
|
37
|
-
|
|
38
33
|
var getPanelBlocksSpecs = function getPanelBlocksSpecs() {
|
|
39
34
|
var isPublic = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
40
35
|
return {
|
|
41
36
|
qualifications: {
|
|
42
|
-
condition: hasQualifications,
|
|
37
|
+
condition: _file.hasQualifications,
|
|
43
38
|
component: _Qualification.default
|
|
44
39
|
},
|
|
45
40
|
konnector: {
|
|
46
41
|
condition: function condition(file) {
|
|
47
|
-
return isFromKonnector(file) && !isPublic;
|
|
42
|
+
return (0, _file.isFromKonnector)(file) && !isPublic;
|
|
48
43
|
},
|
|
49
44
|
component: _KonnectorBlock.default
|
|
50
45
|
},
|
|
51
|
-
|
|
52
|
-
condition:
|
|
53
|
-
|
|
46
|
+
informations: {
|
|
47
|
+
condition: function condition() {
|
|
48
|
+
return true;
|
|
49
|
+
},
|
|
50
|
+
component: _Informations.default
|
|
54
51
|
}
|
|
55
52
|
};
|
|
56
53
|
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.makeSize = exports.makePath = exports.makeFormat = exports.makeDate = void 0;
|
|
7
|
+
|
|
8
|
+
var _file = require("cozy-client/dist/models/file");
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Returns file extension or class
|
|
12
|
+
* @param {import("cozy-client/types").IOCozyFile} file - io.cozy.file
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
15
|
+
var makeFormat = function makeFormat(file) {
|
|
16
|
+
var _splitFilename = (0, _file.splitFilename)(file),
|
|
17
|
+
extension = _splitFilename.extension;
|
|
18
|
+
|
|
19
|
+
return (extension.replace('.', '') || file.class).toUpperCase();
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Returns a formatted date
|
|
23
|
+
* @param {string} lang - language in ISO 639-1 format
|
|
24
|
+
* @returns {string}
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
exports.makeFormat = makeFormat;
|
|
29
|
+
|
|
30
|
+
var makeDate = function makeDate(lang) {
|
|
31
|
+
return lang === 'fr' ? 'DD MMM YYYY à HH:mm' : 'MMM DD YYYY at HH:mm';
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Returns a formatted size
|
|
35
|
+
* @param {number} bytes - file bytes
|
|
36
|
+
* @returns {string}
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
exports.makeDate = makeDate;
|
|
41
|
+
|
|
42
|
+
var makeSize = function makeSize(bytes) {
|
|
43
|
+
if (!+bytes) return '0';
|
|
44
|
+
var k = 1024;
|
|
45
|
+
var dm = 2;
|
|
46
|
+
var sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
47
|
+
var i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
48
|
+
return "".concat(parseFloat((bytes / Math.pow(k, i)).toFixed(dm)), " ").concat(sizes[i]);
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Returns file path
|
|
52
|
+
* @param {import("cozy-client/types").IOCozyFile} file - io.cozy.file
|
|
53
|
+
* @returns {string}
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
exports.makeSize = makeSize;
|
|
58
|
+
|
|
59
|
+
var makePath = function makePath(file) {
|
|
60
|
+
var _file$path;
|
|
61
|
+
|
|
62
|
+
return (_file$path = file.path) === null || _file$path === void 0 ? void 0 : _file$path.replace("/".concat(file.name), '');
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
exports.makePath = makePath;
|
package/dist/locales/index.js
CHANGED
|
@@ -30,6 +30,16 @@ var en = {
|
|
|
30
30
|
openWith: "Open with...",
|
|
31
31
|
openInOnlyOffice: "Open with Only Office",
|
|
32
32
|
panel: {
|
|
33
|
+
informations: {
|
|
34
|
+
format: {
|
|
35
|
+
title: "%{format} Document",
|
|
36
|
+
subtitle: "Format"
|
|
37
|
+
},
|
|
38
|
+
size: "Size",
|
|
39
|
+
location: "Location",
|
|
40
|
+
creation: "Creation",
|
|
41
|
+
modification: "Last modification"
|
|
42
|
+
},
|
|
33
43
|
certifications: {
|
|
34
44
|
carbonCopy: {
|
|
35
45
|
title: "Carbon Copy",
|
|
@@ -96,6 +106,16 @@ var fr = {
|
|
|
96
106
|
openWith: "Ouvrir avec...",
|
|
97
107
|
openInOnlyOffice: "Ouvrir avec Only Office",
|
|
98
108
|
panel: {
|
|
109
|
+
informations: {
|
|
110
|
+
format: {
|
|
111
|
+
title: "Document %{format}",
|
|
112
|
+
subtitle: "Format"
|
|
113
|
+
},
|
|
114
|
+
size: "Taille",
|
|
115
|
+
location: "Emplacement",
|
|
116
|
+
creation: "Cr\xE9ation",
|
|
117
|
+
modification: "Derni\xE8re modification"
|
|
118
|
+
},
|
|
99
119
|
certifications: {
|
|
100
120
|
carbonCopy: {
|
|
101
121
|
title: "Copie conforme",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-viewer",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.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.
|
|
30
|
+
"cozy-harvest-lib": "^30.7.1",
|
|
31
31
|
"cozy-intent": "^2.29.1",
|
|
32
32
|
"cozy-logger": "^1.16.1",
|
|
33
33
|
"cozy-sharing": "14.1.0",
|
|
34
|
-
"cozy-ui": "^
|
|
34
|
+
"cozy-ui": "^113.4.0",
|
|
35
35
|
"enzyme": "3.11.0",
|
|
36
36
|
"enzyme-adapter-react-16": "1.15.6",
|
|
37
37
|
"enzyme-to-json": "3.6.2",
|
|
@@ -56,9 +56,9 @@
|
|
|
56
56
|
"cozy-intent": ">=2.26.0",
|
|
57
57
|
"cozy-logger": ">=1.9.0",
|
|
58
58
|
"cozy-sharing": ">=14.1.0",
|
|
59
|
-
"cozy-ui": ">=
|
|
59
|
+
"cozy-ui": ">=113.4.0",
|
|
60
60
|
"react": ">=16.12.0",
|
|
61
61
|
"react-dom": ">=16.12.0"
|
|
62
62
|
},
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "0ae6b6541b6603b86f11c5471ca5c6777516340d"
|
|
64
64
|
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import has from 'lodash/has'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import React, { useRef, useState } from 'react'
|
|
4
|
+
|
|
5
|
+
import ActionsMenu from 'cozy-ui/transpiled/react/ActionsMenu'
|
|
6
|
+
import {
|
|
7
|
+
makeActions,
|
|
8
|
+
viewInDrive
|
|
9
|
+
} from 'cozy-ui/transpiled/react/ActionsMenu/Actions'
|
|
10
|
+
import Icon from 'cozy-ui/transpiled/react/Icon'
|
|
11
|
+
import IconButton from 'cozy-ui/transpiled/react/IconButton'
|
|
12
|
+
import CalendarIcon from 'cozy-ui/transpiled/react/Icons/Calendar'
|
|
13
|
+
import CarbonCopyIcon from 'cozy-ui/transpiled/react/Icons/CarbonCopy'
|
|
14
|
+
import DotsIcon from 'cozy-ui/transpiled/react/Icons/Dots'
|
|
15
|
+
import FileOutlineIcon from 'cozy-ui/transpiled/react/Icons/FileOutline'
|
|
16
|
+
import FolderIcon from 'cozy-ui/transpiled/react/Icons/Folder'
|
|
17
|
+
import SafeIcon from 'cozy-ui/transpiled/react/Icons/Safe'
|
|
18
|
+
import ServerIcon from 'cozy-ui/transpiled/react/Icons/Server'
|
|
19
|
+
import List from 'cozy-ui/transpiled/react/List'
|
|
20
|
+
import ListItem from 'cozy-ui/transpiled/react/ListItem'
|
|
21
|
+
import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
|
|
22
|
+
import ListItemSecondaryAction from 'cozy-ui/transpiled/react/ListItemSecondaryAction'
|
|
23
|
+
import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
|
|
24
|
+
import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
|
|
25
|
+
|
|
26
|
+
import { makeFormat, makeSize, makeDate, makePath } from './helpers'
|
|
27
|
+
import { withViewerLocales } from '../hoc/withViewerLocales'
|
|
28
|
+
|
|
29
|
+
const Informations = ({ file, t }) => {
|
|
30
|
+
const [showMenu, setShowMenu] = useState(false)
|
|
31
|
+
const { f, lang } = useI18n()
|
|
32
|
+
const format = makeFormat(file)
|
|
33
|
+
const path = makePath(file)
|
|
34
|
+
const size = makeSize(file.size)
|
|
35
|
+
const creation = f(file.created_at, makeDate(lang))
|
|
36
|
+
const modification = f(file.updated_at, makeDate(lang))
|
|
37
|
+
const hasCarbonCopy = has(file, 'metadata.carbonCopy')
|
|
38
|
+
const hasElectronicSafe = has(file, 'metadata.electronicSafe')
|
|
39
|
+
const anchorRef = useRef()
|
|
40
|
+
|
|
41
|
+
const actions = makeActions([viewInDrive])
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<List>
|
|
45
|
+
<ListItem>
|
|
46
|
+
<ListItemIcon>
|
|
47
|
+
<Icon icon={FileOutlineIcon} />
|
|
48
|
+
</ListItemIcon>
|
|
49
|
+
<ListItemText
|
|
50
|
+
primary={t('Viewer.panel.informations.format.title', { format })}
|
|
51
|
+
secondary={t('Viewer.panel.informations.format.subtitle')}
|
|
52
|
+
/>
|
|
53
|
+
</ListItem>
|
|
54
|
+
<ListItem>
|
|
55
|
+
<ListItemIcon>
|
|
56
|
+
<Icon icon={ServerIcon} />
|
|
57
|
+
</ListItemIcon>
|
|
58
|
+
<ListItemText
|
|
59
|
+
primary={size}
|
|
60
|
+
secondary={t('Viewer.panel.informations.size')}
|
|
61
|
+
/>
|
|
62
|
+
</ListItem>
|
|
63
|
+
<ListItem>
|
|
64
|
+
<ListItemIcon>
|
|
65
|
+
<Icon icon={FolderIcon} />
|
|
66
|
+
</ListItemIcon>
|
|
67
|
+
<ListItemText
|
|
68
|
+
primary={path}
|
|
69
|
+
secondary={t('Viewer.panel.informations.location')}
|
|
70
|
+
/>
|
|
71
|
+
<ListItemSecondaryAction>
|
|
72
|
+
<IconButton ref={anchorRef} onClick={() => setShowMenu(v => !v)}>
|
|
73
|
+
<Icon icon={DotsIcon} />
|
|
74
|
+
</IconButton>
|
|
75
|
+
</ListItemSecondaryAction>
|
|
76
|
+
</ListItem>
|
|
77
|
+
{showMenu && (
|
|
78
|
+
<ActionsMenu
|
|
79
|
+
ref={anchorRef}
|
|
80
|
+
open={true}
|
|
81
|
+
docs={[file]}
|
|
82
|
+
actions={actions}
|
|
83
|
+
anchorOrigin={{
|
|
84
|
+
vertical: 'bottom',
|
|
85
|
+
horizontal: 'right'
|
|
86
|
+
}}
|
|
87
|
+
autoClose
|
|
88
|
+
onClose={() => setShowMenu(false)}
|
|
89
|
+
/>
|
|
90
|
+
)}
|
|
91
|
+
<ListItem>
|
|
92
|
+
<ListItemIcon>
|
|
93
|
+
<Icon icon={CalendarIcon} />
|
|
94
|
+
</ListItemIcon>
|
|
95
|
+
<ListItemText
|
|
96
|
+
primary={creation}
|
|
97
|
+
secondary={t('Viewer.panel.informations.creation')}
|
|
98
|
+
/>
|
|
99
|
+
</ListItem>
|
|
100
|
+
<ListItem>
|
|
101
|
+
<ListItemIcon>
|
|
102
|
+
<Icon icon={CalendarIcon} />
|
|
103
|
+
</ListItemIcon>
|
|
104
|
+
<ListItemText
|
|
105
|
+
primary={modification}
|
|
106
|
+
secondary={t('Viewer.panel.informations.modification')}
|
|
107
|
+
/>
|
|
108
|
+
</ListItem>
|
|
109
|
+
{hasCarbonCopy && (
|
|
110
|
+
<ListItem ellipsis={false}>
|
|
111
|
+
<ListItemIcon>
|
|
112
|
+
<Icon icon={CarbonCopyIcon} />
|
|
113
|
+
</ListItemIcon>
|
|
114
|
+
<ListItemText
|
|
115
|
+
primary={t('Viewer.panel.certifications.carbonCopy.title')}
|
|
116
|
+
secondary={t('Viewer.panel.certifications.carbonCopy.caption')}
|
|
117
|
+
/>
|
|
118
|
+
</ListItem>
|
|
119
|
+
)}
|
|
120
|
+
{hasElectronicSafe && (
|
|
121
|
+
<ListItem ellipsis={false}>
|
|
122
|
+
<ListItemIcon>
|
|
123
|
+
<Icon icon={SafeIcon} />
|
|
124
|
+
</ListItemIcon>
|
|
125
|
+
<ListItemText
|
|
126
|
+
primary={t('Viewer.panel.certifications.electronicSafe.title')}
|
|
127
|
+
secondary={t('Viewer.panel.certifications.electronicSafe.caption')}
|
|
128
|
+
/>
|
|
129
|
+
</ListItem>
|
|
130
|
+
)}
|
|
131
|
+
</List>
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
Informations.propTypes = {
|
|
136
|
+
file: PropTypes.object.isRequired,
|
|
137
|
+
t: PropTypes.func
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export default withViewerLocales(Informations)
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
isFromKonnector,
|
|
3
|
+
hasQualifications
|
|
4
|
+
} from 'cozy-client/dist/models/file'
|
|
2
5
|
import KonnectorBlock from 'cozy-harvest-lib/dist/components/KonnectorBlock'
|
|
3
6
|
|
|
4
|
-
import
|
|
7
|
+
import Informations from './Informations'
|
|
5
8
|
import Qualification from './Qualification'
|
|
6
9
|
|
|
7
|
-
const { isFromKonnector, hasQualifications, hasCertifications } = models.file
|
|
8
|
-
|
|
9
10
|
/**
|
|
10
11
|
* @typedef {Object} PanelBlockSpec
|
|
11
12
|
* @property {Function} condition - Function that returns true if the block should be displayed
|
|
@@ -30,9 +31,9 @@ export const getPanelBlocksSpecs = (isPublic = false) => ({
|
|
|
30
31
|
condition: file => isFromKonnector(file) && !isPublic,
|
|
31
32
|
component: KonnectorBlock
|
|
32
33
|
},
|
|
33
|
-
|
|
34
|
-
condition:
|
|
35
|
-
component:
|
|
34
|
+
informations: {
|
|
35
|
+
condition: () => true,
|
|
36
|
+
component: Informations
|
|
36
37
|
}
|
|
37
38
|
})
|
|
38
39
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { splitFilename } from 'cozy-client/dist/models/file'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns file extension or class
|
|
5
|
+
* @param {import("cozy-client/types").IOCozyFile} file - io.cozy.file
|
|
6
|
+
* @returns {string}
|
|
7
|
+
*/
|
|
8
|
+
export const makeFormat = file => {
|
|
9
|
+
const { extension } = splitFilename(file)
|
|
10
|
+
return (extension.replace('.', '') || file.class).toUpperCase()
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Returns a formatted date
|
|
15
|
+
* @param {string} lang - language in ISO 639-1 format
|
|
16
|
+
* @returns {string}
|
|
17
|
+
*/
|
|
18
|
+
export const makeDate = lang =>
|
|
19
|
+
lang === 'fr' ? 'DD MMM YYYY à HH:mm' : 'MMM DD YYYY at HH:mm'
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Returns a formatted size
|
|
23
|
+
* @param {number} bytes - file bytes
|
|
24
|
+
* @returns {string}
|
|
25
|
+
*/
|
|
26
|
+
export const makeSize = bytes => {
|
|
27
|
+
if (!+bytes) return '0'
|
|
28
|
+
|
|
29
|
+
const k = 1024
|
|
30
|
+
const dm = 2
|
|
31
|
+
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
|
32
|
+
|
|
33
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k))
|
|
34
|
+
|
|
35
|
+
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Returns file path
|
|
40
|
+
* @param {import("cozy-client/types").IOCozyFile} file - io.cozy.file
|
|
41
|
+
* @returns {string}
|
|
42
|
+
*/
|
|
43
|
+
export const makePath = file => file.path?.replace(`/${file.name}`, '')
|
package/src/locales/en.json
CHANGED
|
@@ -24,6 +24,16 @@
|
|
|
24
24
|
"openWith": "Open with...",
|
|
25
25
|
"openInOnlyOffice": "Open with Only Office",
|
|
26
26
|
"panel": {
|
|
27
|
+
"informations": {
|
|
28
|
+
"format": {
|
|
29
|
+
"title": "%{format} Document",
|
|
30
|
+
"subtitle": "Format"
|
|
31
|
+
},
|
|
32
|
+
"size": "Size",
|
|
33
|
+
"location": "Location",
|
|
34
|
+
"creation": "Creation",
|
|
35
|
+
"modification": "Last modification"
|
|
36
|
+
},
|
|
27
37
|
"certifications": {
|
|
28
38
|
"carbonCopy": {
|
|
29
39
|
"title": "Carbon Copy",
|
package/src/locales/fr.json
CHANGED
|
@@ -24,6 +24,16 @@
|
|
|
24
24
|
"openWith": "Ouvrir avec...",
|
|
25
25
|
"openInOnlyOffice": "Ouvrir avec Only Office",
|
|
26
26
|
"panel": {
|
|
27
|
+
"informations": {
|
|
28
|
+
"format": {
|
|
29
|
+
"title": "Document %{format}",
|
|
30
|
+
"subtitle": "Format"
|
|
31
|
+
},
|
|
32
|
+
"size": "Taille",
|
|
33
|
+
"location": "Emplacement",
|
|
34
|
+
"creation": "Création",
|
|
35
|
+
"modification": "Dernière modification"
|
|
36
|
+
},
|
|
27
37
|
"certifications": {
|
|
28
38
|
"carbonCopy": {
|
|
29
39
|
"title": "Copie conforme",
|
|
@@ -1,80 +0,0 @@
|
|
|
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 _has = _interopRequireDefault(require("lodash/has"));
|
|
11
|
-
|
|
12
|
-
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
13
|
-
|
|
14
|
-
var _react = _interopRequireDefault(require("react"));
|
|
15
|
-
|
|
16
|
-
var _Icon = _interopRequireWildcard(require("cozy-ui/transpiled/react/Icon"));
|
|
17
|
-
|
|
18
|
-
var _CarbonCopy = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/CarbonCopy"));
|
|
19
|
-
|
|
20
|
-
var _Safe = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/Safe"));
|
|
21
|
-
|
|
22
|
-
var _Typography = _interopRequireDefault(require("cozy-ui/transpiled/react/Typography"));
|
|
23
|
-
|
|
24
|
-
var _Media = require("cozy-ui/transpiled/react/deprecated/Media");
|
|
25
|
-
|
|
26
|
-
var _withViewerLocales = require("../hoc/withViewerLocales");
|
|
27
|
-
|
|
28
|
-
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); }
|
|
29
|
-
|
|
30
|
-
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; }
|
|
31
|
-
|
|
32
|
-
var Certification = function Certification(_ref) {
|
|
33
|
-
var icon = _ref.icon,
|
|
34
|
-
title = _ref.title,
|
|
35
|
-
caption = _ref.caption;
|
|
36
|
-
return /*#__PURE__*/_react.default.createElement("div", {
|
|
37
|
-
className: "u-ph-2 u-pv-1"
|
|
38
|
-
}, /*#__PURE__*/_react.default.createElement(_Media.Media, {
|
|
39
|
-
className: "u-mb-half",
|
|
40
|
-
align: "top"
|
|
41
|
-
}, /*#__PURE__*/_react.default.createElement(_Media.Img, {
|
|
42
|
-
className: "u-mr-half"
|
|
43
|
-
}, /*#__PURE__*/_react.default.createElement(_Icon.default, {
|
|
44
|
-
icon: icon
|
|
45
|
-
})), /*#__PURE__*/_react.default.createElement(_Media.Bd, null, /*#__PURE__*/_react.default.createElement(_Typography.default, {
|
|
46
|
-
variant: "body1"
|
|
47
|
-
}, title))), /*#__PURE__*/_react.default.createElement(_Typography.default, {
|
|
48
|
-
variant: "caption"
|
|
49
|
-
}, caption));
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
Certification.propTypes = {
|
|
53
|
-
icon: _Icon.iconPropType.isRequired,
|
|
54
|
-
title: _propTypes.default.string.isRequired,
|
|
55
|
-
caption: _propTypes.default.string.isRequired
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
var Certifications = function Certifications(_ref2) {
|
|
59
|
-
var file = _ref2.file,
|
|
60
|
-
t = _ref2.t;
|
|
61
|
-
var hasCarbonCopy = (0, _has.default)(file, 'metadata.carbonCopy');
|
|
62
|
-
var hasElectronicSafe = (0, _has.default)(file, 'metadata.electronicSafe');
|
|
63
|
-
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, hasCarbonCopy && /*#__PURE__*/_react.default.createElement(Certification, {
|
|
64
|
-
icon: _CarbonCopy.default,
|
|
65
|
-
title: t('Viewer.panel.certifications.carbonCopy.title'),
|
|
66
|
-
caption: t('Viewer.panel.certifications.carbonCopy.caption')
|
|
67
|
-
}), hasElectronicSafe && /*#__PURE__*/_react.default.createElement(Certification, {
|
|
68
|
-
icon: _Safe.default,
|
|
69
|
-
title: t('Viewer.panel.certifications.electronicSafe.title'),
|
|
70
|
-
caption: t('Viewer.panel.certifications.electronicSafe.caption')
|
|
71
|
-
}));
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
Certifications.propTypes = {
|
|
75
|
-
file: _propTypes.default.object.isRequired
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
var _default = (0, _withViewerLocales.withViewerLocales)(Certifications);
|
|
79
|
-
|
|
80
|
-
exports.default = _default;
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import has from 'lodash/has'
|
|
2
|
-
import PropTypes from 'prop-types'
|
|
3
|
-
import React from 'react'
|
|
4
|
-
|
|
5
|
-
import Icon, { iconPropType } from 'cozy-ui/transpiled/react/Icon'
|
|
6
|
-
import CarbonCopyIcon from 'cozy-ui/transpiled/react/Icons/CarbonCopy'
|
|
7
|
-
import SafeIcon from 'cozy-ui/transpiled/react/Icons/Safe'
|
|
8
|
-
import Typography from 'cozy-ui/transpiled/react/Typography'
|
|
9
|
-
import { Media, Img, Bd } from 'cozy-ui/transpiled/react/deprecated/Media'
|
|
10
|
-
|
|
11
|
-
import { withViewerLocales } from '../hoc/withViewerLocales'
|
|
12
|
-
|
|
13
|
-
const Certification = ({ icon, title, caption }) => {
|
|
14
|
-
return (
|
|
15
|
-
<div className="u-ph-2 u-pv-1">
|
|
16
|
-
<Media className="u-mb-half" align="top">
|
|
17
|
-
<Img className="u-mr-half">
|
|
18
|
-
<Icon icon={icon} />
|
|
19
|
-
</Img>
|
|
20
|
-
<Bd>
|
|
21
|
-
<Typography variant="body1">{title}</Typography>
|
|
22
|
-
</Bd>
|
|
23
|
-
</Media>
|
|
24
|
-
<Typography variant="caption">{caption}</Typography>
|
|
25
|
-
</div>
|
|
26
|
-
)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
Certification.propTypes = {
|
|
30
|
-
icon: iconPropType.isRequired,
|
|
31
|
-
title: PropTypes.string.isRequired,
|
|
32
|
-
caption: PropTypes.string.isRequired
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const Certifications = ({ file, t }) => {
|
|
36
|
-
const hasCarbonCopy = has(file, 'metadata.carbonCopy')
|
|
37
|
-
const hasElectronicSafe = has(file, 'metadata.electronicSafe')
|
|
38
|
-
|
|
39
|
-
return (
|
|
40
|
-
<>
|
|
41
|
-
{hasCarbonCopy && (
|
|
42
|
-
<Certification
|
|
43
|
-
icon={CarbonCopyIcon}
|
|
44
|
-
title={t('Viewer.panel.certifications.carbonCopy.title')}
|
|
45
|
-
caption={t('Viewer.panel.certifications.carbonCopy.caption')}
|
|
46
|
-
/>
|
|
47
|
-
)}
|
|
48
|
-
{hasElectronicSafe && (
|
|
49
|
-
<Certification
|
|
50
|
-
icon={SafeIcon}
|
|
51
|
-
title={t('Viewer.panel.certifications.electronicSafe.title')}
|
|
52
|
-
caption={t('Viewer.panel.certifications.electronicSafe.caption')}
|
|
53
|
-
/>
|
|
54
|
-
)}
|
|
55
|
-
</>
|
|
56
|
-
)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
Certifications.propTypes = {
|
|
60
|
-
file: PropTypes.object.isRequired
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export default withViewerLocales(Certifications)
|
|
File without changes
|