mirador-annotation-editor-video 1.1.5 → 1.1.7

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 (92) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/__tests__/AnnotationCreation.test.js +62 -28
  3. package/__tests__/AnnotationExportDialog.test.js +18 -16
  4. package/__tests__/CanvasListItem.test.js +53 -19
  5. package/__tests__/LocalStorageAdapter.test.js +1 -1
  6. package/__tests__/miradorAnnotationPlugin.test.js +97 -70
  7. package/__tests__/style-mock.js +1 -0
  8. package/__tests__/test-utils.js +57 -0
  9. package/demo/src/index.js +9 -4
  10. package/demo/src/quillConfig.js +34 -0
  11. package/es/AnnotationExportDialog.js +17 -25
  12. package/es/CanvasListItem.js +8 -4
  13. package/es/IIIFUtils.js +35 -3
  14. package/es/SingleCanvasDialog.js +1 -4
  15. package/es/TextEditor.js +9 -19
  16. package/es/annotationForm/AnnotationForm.js +14 -41
  17. package/es/annotationForm/AnnotationFormBody.js +36 -27
  18. package/es/annotationForm/AnnotationFormHeader.js +3 -3
  19. package/es/annotationForm/AnnotationFormOverlay/AnnotationDrawing.js +3 -1
  20. package/es/annotationForm/AnnotationFormOverlay/AnnotationFormOverlay.js +1 -1
  21. package/es/annotationForm/AnnotationFormOverlay/AnnotationFormOverlayTool.js +3 -2
  22. package/es/annotationForm/AnnotationFormOverlay/AnnotationFormOverlayToolOptions.js +8 -6
  23. package/es/annotationForm/AnnotationFormOverlay/KonvaDrawing/KonvaUtils.js +17 -19
  24. package/es/annotationForm/AnnotationFormOverlay/KonvaDrawing/shapes/ColorPicker.js +16 -6
  25. package/es/annotationForm/AnnotationFormTemplateSelector.js +9 -9
  26. package/es/annotationForm/AnnotationFormUtils.js +3 -0
  27. package/es/annotationForm/Debug.js +1 -0
  28. package/es/annotationForm/DebugInformation.js +27 -0
  29. package/es/annotationForm/MultiTagsInput.js +4 -1
  30. package/es/annotationForm/MultipleBodyTemplate.js +7 -9
  31. package/es/annotationForm/TaggingTemplate.js +0 -1
  32. package/es/annotationForm/TargetFormSection.js +4 -3
  33. package/es/annotationForm/TargetSpatialInput.js +4 -3
  34. package/es/annotationForm/TextCommentInput.js +25 -12
  35. package/es/annotationForm/TextCommentTemplate.js +0 -1
  36. package/es/annotationForm/UnsupportedMedia.js +43 -0
  37. package/es/containers/miradorAnnotationPlugin.js +1 -50
  38. package/es/custom.css +0 -13
  39. package/es/index.js +5 -12
  40. package/es/locales/locales.js +3 -2
  41. package/es/locales/locales_en.js +1 -1
  42. package/es/playerReferences.js +2 -1
  43. package/es/plugins/annotationCreationCompanionWindow.js +5 -8
  44. package/es/plugins/annotationSaga.js +44 -0
  45. package/es/plugins/canvasAnnotationsPlugin.js +86 -61
  46. package/es/plugins/canvasAnnotationsPluginUtils.js +202 -0
  47. package/es/plugins/externalStorageAnnotationPlugin.js +6 -71
  48. package/es/plugins/miradorAnnotationPlugin.js +44 -6
  49. package/es/plugins/windowSideBarButtonsPlugin.js +8 -10
  50. package/jest.config.js +14 -3
  51. package/package.json +8 -3
  52. package/setupJest.js +1 -4
  53. package/src/AnnotationExportDialog.js +12 -24
  54. package/src/CanvasListItem.js +4 -3
  55. package/src/IIIFUtils.js +33 -5
  56. package/src/SingleCanvasDialog.js +0 -3
  57. package/src/TextEditor.js +8 -32
  58. package/src/annotationForm/AnnotationForm.js +8 -47
  59. package/src/annotationForm/AnnotationFormBody.js +62 -83
  60. package/src/annotationForm/AnnotationFormHeader.js +3 -3
  61. package/src/annotationForm/AnnotationFormOverlay/AnnotationDrawing.js +3 -9
  62. package/src/annotationForm/AnnotationFormOverlay/AnnotationFormOverlay.js +1 -1
  63. package/src/annotationForm/AnnotationFormOverlay/AnnotationFormOverlayTool.js +2 -1
  64. package/src/annotationForm/AnnotationFormOverlay/AnnotationFormOverlayToolOptions.js +10 -6
  65. package/src/annotationForm/AnnotationFormOverlay/KonvaDrawing/KonvaUtils.js +25 -20
  66. package/src/annotationForm/AnnotationFormOverlay/KonvaDrawing/shapes/ColorPicker.js +14 -12
  67. package/src/annotationForm/AnnotationFormTemplateSelector.js +5 -7
  68. package/src/annotationForm/AnnotationFormUtils.js +2 -0
  69. package/src/annotationForm/Debug.js +0 -0
  70. package/src/annotationForm/DebugInformation.js +59 -0
  71. package/src/annotationForm/MultiTagsInput.js +4 -1
  72. package/src/annotationForm/MultipleBodyTemplate.js +7 -8
  73. package/src/annotationForm/TaggingTemplate.js +0 -1
  74. package/src/annotationForm/TargetFormSection.js +2 -3
  75. package/src/annotationForm/TargetSpatialInput.js +3 -3
  76. package/src/annotationForm/TextCommentInput.js +28 -14
  77. package/src/annotationForm/TextCommentTemplate.js +0 -1
  78. package/src/annotationForm/UnsupportedMedia.js +31 -0
  79. package/src/containers/miradorAnnotationPlugin.js +0 -36
  80. package/src/custom.css +0 -13
  81. package/src/index.js +10 -15
  82. package/src/locales/locales.js +3 -1
  83. package/src/locales/locales_en.js +1 -1
  84. package/src/playerReferences.js +5 -2
  85. package/src/plugins/annotationCreationCompanionWindow.js +9 -23
  86. package/src/plugins/annotationSaga.js +50 -0
  87. package/src/plugins/canvasAnnotationsPlugin.js +122 -98
  88. package/src/plugins/canvasAnnotationsPluginUtils.js +199 -0
  89. package/src/plugins/externalStorageAnnotationPlugin.js +6 -79
  90. package/src/plugins/miradorAnnotationPlugin.js +32 -4
  91. package/src/plugins/windowSideBarButtonsPlugin.js +6 -8
  92. package/webpack.config.js +1 -0
@@ -14,9 +14,11 @@ var _MiradorMenuButton = require("mirador/dist/es/src/components/MiradorMenuButt
14
14
  var _canvases = require("mirador/dist/es/src/state/selectors/canvases");
15
15
  var _reactRedux = require("react-redux");
16
16
  var _material = require("@mui/material");
17
+ var _companionWindows = require("mirador/dist/es/src/state/selectors/companionWindows");
17
18
  var _SingleCanvasDialog = _interopRequireDefault(require("../SingleCanvasDialog"));
18
19
  var _AnnotationExportDialog = _interopRequireDefault(require("../AnnotationExportDialog"));
19
20
  var _LocalStorageAdapter = _interopRequireDefault(require("../annotationAdapter/LocalStorageAdapter"));
21
+ var _locales = _interopRequireDefault(require("../locales/locales"));
20
22
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
21
23
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
22
24
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
@@ -76,8 +78,7 @@ function MiradorAnnotation({
76
78
  }, /*#__PURE__*/_react.default.createElement(_AddBox.default, null))), singleCanvasDialogOpen && /*#__PURE__*/_react.default.createElement(_SingleCanvasDialog.default, {
77
79
  open: singleCanvasDialogOpen,
78
80
  handleClose: toggleSingleCanvasDialogOpen,
79
- switchToSingleCanvasView: switchToSingleCanvasView,
80
- t: t
81
+ switchToSingleCanvasView: switchToSingleCanvasView
81
82
  }), offerExportDialog && /*#__PURE__*/_react.default.createElement(_material.Tooltip, {
82
83
  title: t('export_local_annotation')
83
84
  }, /*#__PURE__*/_react.default.createElement(_MiradorMenuButton.MiradorMenuButton, {
@@ -88,8 +89,7 @@ function MiradorAnnotation({
88
89
  canvases: canvases,
89
90
  config: config,
90
91
  handleClose: toggleCanvasExportDialog,
91
- open: annotationExportDialogOpen,
92
- t: t
92
+ open: annotationExportDialogOpen
93
93
  }));
94
94
  }
95
95
  MiradorAnnotation.propTypes = {
@@ -104,11 +104,49 @@ MiradorAnnotation.propTypes = {
104
104
  exportLocalStorageAnnotations: _propTypes.default.bool
105
105
  })
106
106
  }).isRequired,
107
- createAnnotation: _propTypes.default.bool.isRequired,
108
107
  t: _propTypes.default.func.isRequired,
109
108
  TargetComponent: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.node]).isRequired,
110
109
  // eslint-disable-next-line react/forbid-prop-types
111
110
  targetProps: _propTypes.default.object.isRequired,
112
111
  windowViewType: _propTypes.default.string.isRequired
113
112
  };
114
- var _default = exports.default = MiradorAnnotation;
113
+
114
+ // TODO use selector in main componenent
115
+ /**
116
+ * this function map the state to the annotationPlugin's props
117
+ * */
118
+ function mapStateToProps(state, {
119
+ targetProps: {
120
+ windowId
121
+ }
122
+ }) {
123
+ // Annotation edit companion window ou annotation creation companion window is the same thing
124
+ const annotationCreationCompanionWindows = (0, _companionWindows.getCompanionWindowsForContent)(state, {
125
+ content: 'annotationCreation',
126
+ windowId
127
+ });
128
+ let annotationEditCompanionWindowIsOpened = true;
129
+ if (Object.keys(annotationCreationCompanionWindows).length !== 0) {
130
+ annotationEditCompanionWindowIsOpened = false;
131
+ }
132
+ return {
133
+ annotationEditCompanionWindowIsOpened,
134
+ canvases: (0, _canvases.getVisibleCanvases)(state, {
135
+ windowId
136
+ }),
137
+ config: state.config,
138
+ windowViewType: (0, _selectors.getWindowViewType)(state, {
139
+ windowId
140
+ })
141
+ };
142
+ }
143
+ const miradorAnnotationPlugin = {
144
+ component: MiradorAnnotation,
145
+ config: {
146
+ translations: _locales.default
147
+ },
148
+ mapStateToProps,
149
+ mode: 'wrap',
150
+ target: 'AnnotationSettings'
151
+ };
152
+ var _default = exports.default = miradorAnnotationPlugin;
@@ -12,29 +12,27 @@ function _extends() { return _extends = Object.assign ? Object.assign.bind() : f
12
12
  * A wrapper plugin that sets hasAnyAnnotations to true so that the annotation
13
13
  * companion window button is present
14
14
  */
15
- const WindowSideBarButtonWrapper = ({
16
- PluginComponents,
15
+ function WindowSideBarButtonWrapper({
16
+ PluginComponents = [],
17
17
  TargetComponent,
18
18
  targetProps
19
- }) => {
19
+ }) {
20
20
  // eslint-disable-next-line no-param-reassign
21
21
  targetProps.hasAnyAnnotations = true;
22
22
  return /*#__PURE__*/_react.default.createElement(TargetComponent, _extends({}, targetProps, {
23
23
  // eslint-disable-line react/jsx-props-no-spreading
24
24
  PluginComponents: PluginComponents
25
25
  }));
26
- };
26
+ }
27
27
  WindowSideBarButtonWrapper.propTypes = {
28
- PluginComponents: _propTypes.default.array,
28
+ PluginComponents: _propTypes.default.array.isRequired,
29
29
  // eslint-disable-line react/forbid-prop-types
30
30
  TargetComponent: _propTypes.default.oneOfType([_propTypes.default.func, _propTypes.default.node]).isRequired,
31
31
  targetProps: _propTypes.default.object.isRequired // eslint-disable-line react/forbid-prop-types
32
32
  };
33
- WindowSideBarButtonWrapper.defaultProps = {
34
- PluginComponents: []
35
- };
36
- var _default = exports.default = {
33
+ const windowSideBarButtonsPlugin = {
37
34
  component: WindowSideBarButtonWrapper,
38
35
  mode: 'wrap',
39
36
  target: 'WindowSideBarButtons'
40
- };
37
+ };
38
+ var _default = exports.default = windowSideBarButtonsPlugin;
package/jest.config.js CHANGED
@@ -7,11 +7,22 @@ module.exports = {
7
7
 
8
8
  // The directory where Jest should output its coverage files
9
9
  coverageDirectory: 'coverage',
10
+ moduleNameMapper: {
11
+ '\\.css$': '<rootDir>/__tests__/style-mock.js',
12
+ },
10
13
  setupFiles: [
11
- '<rootDir>/setupJest.js', 'jest-localstorage-mock', 'jest-canvas-mock',
14
+ 'jest-localstorage-mock', 'jest-canvas-mock',
15
+ ],
16
+ setupFilesAfterEnv: [
17
+ '<rootDir>/setupJest.js',
18
+ ],
19
+ testEnvironment: 'jsdom',
20
+ testPathIgnorePatterns: [
21
+ '<rootDir>/__tests__/test-utils.js',
22
+ '<rootDir>/__tests__/style-mock.js',
12
23
  ],
13
24
  // Ignore Mirador code from jest transforms
14
25
  transformIgnorePatterns: [
15
- '<rootDir>/node_modules/(?!(mirador|manifesto.js))',
26
+ '<rootDir>/node_modules/(?!(mirador|manifesto.js|react-dnd|dnd-core|@react-dnd|dnd-multi-backend|rdndmb-html5-to-touch|react-quill|react-konva-to-svg|jsoneditor-react))',
16
27
  ],
17
- };
28
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mirador-annotation-editor-video",
3
- "version": "1.1.5",
3
+ "version": "1.1.7",
4
4
  "description": "Mirador annotation editor video plugin in a React component. Mirador 4 (Alpha 2) compatible ",
5
5
  "main": "es/index.js",
6
6
  "module": "es/index.js",
@@ -37,7 +37,7 @@
37
37
  "draft-js-export-html": "^1.4.1",
38
38
  "draft-js-import-html": "^1.4.1",
39
39
  "html-loader": "^5.0.0",
40
- "i18next": "^24.2.0",
40
+ "i18next": "^25.4.1",
41
41
  "json-edit-react": "^1.22.2",
42
42
  "jsoneditor": "^9.10.5",
43
43
  "jsoneditor-react": "npm:jsoneditor-react18@0.5.0",
@@ -53,6 +53,8 @@
53
53
  "react-select": "^5.10.1",
54
54
  "react-sortablejs": "^6.1.4",
55
55
  "redux": "^5.0.1",
56
+ "redux-saga": "^1.3.0",
57
+ "redux-thunk": "^3.1.0",
56
58
  "sortablejs": "^1.15.2",
57
59
  "use-image": "^1.1.1",
58
60
  "webpack": "^5.91.0",
@@ -78,6 +80,9 @@
78
80
  "@mui/utils": "^5.13.1",
79
81
  "@mui/x-tree-view": "^6.17.0",
80
82
  "@pmmmwh/react-refresh-webpack-plugin": "^0.5.11",
83
+ "@testing-library/jest-dom": "^6",
84
+ "@testing-library/react": "^14",
85
+ "@testing-library/user-event": "^14",
81
86
  "canvas": "^2.6.1",
82
87
  "css-loader": "^6.10.0",
83
88
  "enzyme": "^3.11.0",
@@ -94,7 +99,7 @@
94
99
  "jest-canvas-mock": "^2.2.0",
95
100
  "jest-junit": "^15.0.0",
96
101
  "jest-localstorage-mock": "^2.4.2",
97
- "mirador": "npm:mirador-video@1.0.28",
102
+ "mirador": "npm:mirador-video@^1.0.30",
98
103
  "prop-types": "^15.7.2",
99
104
  "react": "^18.2.0",
100
105
  "react-dom": "^18.0",
package/setupJest.js CHANGED
@@ -1,4 +1 @@
1
- import Enzyme from 'enzyme'; // eslint-disable-line import/no-extraneous-dependencies
2
- import Adapter from 'enzyme-adapter-react-16'; // eslint-disable-line import/no-extraneous-dependencies
3
-
4
- Enzyme.configure({ adapter: new Adapter() });
1
+ import "@testing-library/jest-dom"
@@ -10,43 +10,34 @@ import MenuItem from '@mui/material/MenuItem';
10
10
  import Typography from '@mui/material/Typography';
11
11
  import PropTypes from 'prop-types';
12
12
  import { styled } from '@mui/system';
13
+ import { useTranslation } from 'react-i18next';
13
14
 
14
- /**
15
- * Styles for AnnotationExportDialog
16
- * @param theme
17
- * @returns {{listitem: {'&:focus': {backgroundColor}, '&:hover': {backgroundColor: *}}}}
18
- */
19
- const styles = (theme) => ({
20
- listitem: {
21
- '&:focus': {
22
- backgroundColor: theme.palette.action.focus,
23
- },
24
- '&:hover': {
25
- backgroundColor: theme.palette.action.hover,
26
- },
15
+ const StyledMenuItem = styled(MenuItem)(({ theme }) => ({
16
+ '&:focus': {
17
+ backgroundColor: theme.palette.action.focus,
18
+ },
19
+ '&:hover': {
20
+ backgroundColor: theme.palette.action.hover,
27
21
  },
28
- });
22
+ }));
29
23
 
30
24
  /**
31
25
  *
32
26
  * @param canvases
33
- * @param classes
34
27
  * @param config
35
28
  * @param handleClose
36
29
  * @param open
37
- * @param t
38
30
  * @returns {JSX.Element}
39
31
  * @constructor AnnotationExportDialog
40
32
  */
41
33
  function AnnotationExportDialog({
42
34
  canvases,
43
- classes,
44
35
  config,
45
36
  handleClose,
46
37
  open,
47
- t,
48
38
  }) {
49
39
  const [exportLinks, setExportLinks] = useState([]);
40
+ const { t } = useTranslation();
50
41
 
51
42
  useEffect(() => {
52
43
  if (!open) return;
@@ -115,9 +106,8 @@ function AnnotationExportDialog({
115
106
  ) : (
116
107
  <MenuList>
117
108
  {exportLinks.map((dl) => (
118
- <MenuItem
109
+ <StyledMenuItem
119
110
  button
120
- className={classes.listitem}
121
111
  component="a"
122
112
  key={dl.canvasId}
123
113
  aria-label={t('export_annotation_for')}
@@ -130,7 +120,7 @@ function AnnotationExportDialog({
130
120
  <ListItemText>
131
121
  {t('export_annotation_for')}
132
122
  </ListItemText>
133
- </MenuItem>
123
+ </StyledMenuItem>
134
124
  ))}
135
125
  </MenuList>
136
126
  )}
@@ -143,7 +133,6 @@ AnnotationExportDialog.propTypes = {
143
133
  canvases: PropTypes.arrayOf(
144
134
  PropTypes.shape({ id: PropTypes.string }),
145
135
  ).isRequired,
146
- classes: PropTypes.objectOf(PropTypes.string).isRequired,
147
136
  config: PropTypes.shape({
148
137
  annotation: PropTypes.shape({
149
138
  adapter: PropTypes.func,
@@ -151,7 +140,6 @@ AnnotationExportDialog.propTypes = {
151
140
  }).isRequired,
152
141
  handleClose: PropTypes.func.isRequired,
153
142
  open: PropTypes.bool.isRequired,
154
- t: PropTypes.func.isRequired,
155
143
  };
156
144
 
157
- export default styled(styles)(AnnotationExportDialog);
145
+ export default AnnotationExportDialog;
@@ -107,13 +107,15 @@ const CanvasListItem = forwardRef((props, ref) => {
107
107
  .includes(annotationid);
108
108
  };
109
109
 
110
- const { t } = context;
110
+ // eslint-disable-next-line react/prop-types
111
+ const { t, tReady, ...filteredProps } = props;
111
112
 
112
113
  return (
113
114
  <div
114
115
  onMouseEnter={() => setIsHovering(true)}
115
116
  onMouseLeave={() => setIsHovering(false)}
116
117
  className="mirador-annotation-list-item"
118
+ data-testid="mirador-annotation-list-item"
117
119
  ref={ref}
118
120
  >
119
121
  {(isHovering && editable()) && (
@@ -184,7 +186,7 @@ const CanvasListItem = forwardRef((props, ref) => {
184
186
  </div>
185
187
  )}
186
188
  {/* eslint-disable-next-line react/jsx-props-no-spreading */}
187
- <li {...props}>
189
+ <li {...filteredProps}>
188
190
  {props.children}
189
191
  </li>
190
192
  </div>
@@ -192,7 +194,6 @@ const CanvasListItem = forwardRef((props, ref) => {
192
194
  });
193
195
 
194
196
  CanvasListItem.propTypes = {
195
- annotationEditCompanionWindowIsOpened: PropTypes.bool.isRequired,
196
197
  annotationid: PropTypes.string.isRequired,
197
198
  children: PropTypes.oneOfType([
198
199
  PropTypes.func,
package/src/IIIFUtils.js CHANGED
@@ -70,10 +70,10 @@ export const convertAnnotationStateToBeSaved = async (
70
70
  if (annotationStateForSaving.maeData.templateType === TEMPLATE.MULTIPLE_BODY_TYPE) {
71
71
  annotationStateForSaving.body = [annotationState.maeData.textBody];
72
72
  annotationStateForSaving.body.push(...annotationState.maeData.tags.map((tag) => ({
73
+ id: tag.value,
73
74
  purpose: 'tagging',
74
75
  type: 'TextualBody',
75
76
  value: tag.value,
76
- id: tag.value,
77
77
  })));
78
78
  }
79
79
 
@@ -91,6 +91,7 @@ export const convertAnnotationStateToBeSaved = async (
91
91
  }
92
92
  }
93
93
 
94
+ // TODO Always relevant ?
94
95
  annotationStateForSaving.maeData.target.scale = playerReferences.getMediaTrueHeight()
95
96
  / playerReferences.getDisplayedMediaHeight() * playerReferences.getZoom();
96
97
 
@@ -135,6 +136,8 @@ export const getIIIFTargetFromMaeData = (
135
136
  case TEMPLATE.MANIFEST_TYPE:
136
137
  case TEMPLATE.MULTIPLE_BODY_TYPE:
137
138
  case TEMPLATE.TEXT_TYPE:
139
+ case TEMPLATE.MULTIPLE_BODY_TYPE:
140
+ // In some case the target can be simplified in a string
138
141
  // In some case the target can be simplified in a string
139
142
  if (isSimpleTarget(maeTarget.drawingState.shapes)) {
140
143
  return getIIIFTargetFromRectangleShape(
@@ -154,10 +157,35 @@ export const getIIIFTargetFromMaeData = (
154
157
  return getIIIFTargetFullCanvas(maeData, canvasId);
155
158
  };
156
159
 
157
- const isSimpleTarget = (shapes) => shapes.length === 1
158
- && shapes[0].type === SHAPES_TOOL.RECTANGLE
159
- && shapes[0].strokeColor === TARGET_TOOL_STATE.strokeColor
160
- && shapes[0].fillColor === TARGET_TOOL_STATE.fillColor;
160
+ /**
161
+ * Check if the target is a simple rectangle with the same color as the tool
162
+ * @param shapes
163
+ * @returns {boolean}
164
+ */
165
+ const isSimpleTarget = (shapes) => {
166
+ if (shapes.length !== 1) return false;
167
+ const shape = shapes[0];
168
+ return isRectangleShape(shape) && hasMatchingStrokeAndFillColors(shape);
169
+ };
170
+
171
+ /**
172
+ * Check if the shape is a rectangle
173
+ * @param shape
174
+ * @returns {boolean}
175
+ */
176
+ const isRectangleShape = (shape) => {
177
+ return shape.type === SHAPES_TOOL.RECTANGLE;
178
+ };
179
+
180
+ /**
181
+ * Check if the shape has the same stroke and fill colors as the TARGET_TOOL_STATE
182
+ * @param shape
183
+ * @returns {boolean}
184
+ */
185
+ const hasMatchingStrokeAndFillColors = (shape) => {
186
+ return shape.strokeColor === TARGET_TOOL_STATE.strokeColor
187
+ && shape.fillColor === TARGET_TOOL_STATE.fillColor;
188
+ };
161
189
 
162
190
  /**
163
191
  * Get the IIIF target from a Konva annotation (Drawing template)
@@ -8,8 +8,6 @@ import DialogTitle from '@mui/material/DialogTitle';
8
8
  import Typography from '@mui/material/Typography';
9
9
  import PropTypes from 'prop-types';
10
10
  import { Tooltip } from '@mui/material';
11
- import { withTranslation } from 'react-i18next';
12
- import i18n from 'i18next';
13
11
 
14
12
  /**
15
13
  * Dialog to enforce single view for annotation creation / editing
@@ -36,7 +34,6 @@ class SingleCanvasDialog extends Component {
36
34
  const {
37
35
  handleClose,
38
36
  open,
39
- t,
40
37
  } = this.props;
41
38
 
42
39
  return (
package/src/TextEditor.js CHANGED
@@ -3,6 +3,8 @@ import PropTypes from 'prop-types';
3
3
  import ReactQuill from 'react-quill';
4
4
  import 'react-quill/dist/quill.snow.css';
5
5
  import { styled } from '@mui/material/styles';
6
+ import { useSelector } from 'react-redux';
7
+ import { getConfig } from 'mirador/dist/es/src/state/selectors';
6
8
 
7
9
  const StyledReactQuill = styled(ReactQuill)(({ theme }) => ({
8
10
  '.ql-editor': {
@@ -15,6 +17,11 @@ function TextEditor({
15
17
  text,
16
18
  setText,
17
19
  }) {
20
+ const annotationConfig = useSelector((state) => getConfig(state)).annotation;
21
+ const {
22
+ formats,
23
+ modules,
24
+ } = annotationConfig.quillConfig;
18
25
  /**
19
26
  * Handle Change On ReactQuil Editor
20
27
  * @param html
@@ -22,41 +29,10 @@ function TextEditor({
22
29
  const handleChange = (html) => {
23
30
  setText(html);
24
31
  };
25
- const modules = {
26
- toolbar: [
27
- [{ header: [1, 2, false] }],
28
- ['bold', 'italic', 'underline', 'strike', 'blockquote'],
29
- [
30
- { list: 'ordered' },
31
- { list: 'bullet' },
32
- { indent: '-1' },
33
- { indent: '+1' },
34
- ],
35
- [{ color: [] }, { background: [] }],
36
- ['link', 'image'],
37
- ['clean'],
38
- ],
39
- };
40
-
41
- const formats = [
42
- 'header',
43
- 'bold',
44
- 'italic',
45
- 'underline',
46
- 'strike',
47
- 'blockquote',
48
- 'list',
49
- 'bullet',
50
- 'indent',
51
- 'link',
52
- 'image',
53
- 'color',
54
- 'background',
55
- ];
56
32
 
57
33
  // Data field is needed to set bounds for the editor and avoir tooltip overflow
58
34
  return (
59
- <div data-text-editor="name">
35
+ <div data-text-editor="name" data-testid="textEditor">
60
36
  <StyledReactQuill
61
37
  value={text}
62
38
  onChange={handleChange}
@@ -2,16 +2,14 @@ import React, { useEffect, useReducer, useState } from 'react';
2
2
  import CompanionWindow from 'mirador/dist/es/src/containers/CompanionWindow';
3
3
  import PropTypes from 'prop-types';
4
4
  import { Grid } from '@mui/material';
5
- import Typography from '@mui/material/Typography';
6
- import { withTranslation } from 'react-i18next';
7
- import i18n from 'i18next';
5
+ import { useTranslation } from 'react-i18next';
8
6
  import AnnotationFormTemplateSelector from './AnnotationFormTemplateSelector';
9
7
  import { getTemplateType, saveAnnotationInStorageAdapter, TEMPLATE } from './AnnotationFormUtils';
10
8
  import AnnotationFormHeader from './AnnotationFormHeader';
11
9
  import AnnotationFormBody from './AnnotationFormBody';
12
10
  import { convertAnnotationStateToBeSaved } from '../IIIFUtils';
13
- import '../118n';
14
11
  import '../custom.css';
12
+ import UnsupportedMedia from './UnsupportedMedia';
15
13
 
16
14
  /**
17
15
  * Component for submitting a form to create or edit an annotation.
@@ -25,15 +23,14 @@ function AnnotationForm(
25
23
  id,
26
24
  playerReferences,
27
25
  receiveAnnotation,
28
- t,
29
26
  windowId,
30
27
  },
31
28
  ) {
29
+ const { t } = useTranslation();
32
30
  const [templateType, setTemplateType] = useState(null);
33
31
  // eslint-disable-next-line no-underscore-dangle
34
32
  const [mediaType, setMediaType] = useState(playerReferences.getMediaType());
35
33
 
36
- const [containerWidth, setContainerWidth] = useState(0);
37
34
  const [retryCount, setRetryCount] = useState(0);
38
35
 
39
36
  const [, forceUpdate] = useReducer((x) => x + 1, 0);
@@ -52,8 +49,6 @@ function AnnotationForm(
52
49
  width: window.innerWidth,
53
50
  });
54
51
 
55
- const debugMode = config.debug === true;
56
-
57
52
  if (!templateType) {
58
53
  if (annotation.id) {
59
54
  if (annotation.maeData && annotation.maeData.templateType) {
@@ -66,26 +61,6 @@ function AnnotationForm(
66
61
  }
67
62
  }
68
63
 
69
- // Add translations from config to i18n
70
- useEffect(() => {
71
- if (i18n.isInitialized && config.translations) {
72
- Object.keys(config.translations)
73
- .forEach((language) => {
74
- i18n.addResourceBundle(
75
- language,
76
- 'translation',
77
- config.translations[language],
78
- true,
79
- true,
80
- );
81
- });
82
-
83
- if (config.language) {
84
- i18n.changeLanguage(config.language);
85
- }
86
- }
87
- }, [config.translations, config.language]);
88
-
89
64
  useEffect(() => {
90
65
  setTemplateType(null);
91
66
  setMediaType(playerReferences.getMediaType());
@@ -116,18 +91,7 @@ function AnnotationForm(
116
91
  }
117
92
  if (!playerReferences.isInitCorrectly) {
118
93
  return (
119
- <CompanionWindow title={t('media_not_supported')} windowId={windowId} id={id}>
120
- <Grid container padding={1} spacing={1}>
121
- <Grid item>
122
- <Typography>{t('media_not_supported')}</Typography>
123
- </Grid>
124
- <Grid item>
125
- <Typography>
126
- {t('detected_media_type', { mediaType })}
127
- </Typography>
128
- </Grid>
129
- </Grid>
130
- </CompanionWindow>
94
+ <UnsupportedMedia id={id} mediaType={mediaType} windowId={windowId} />
131
95
  );
132
96
  }
133
97
 
@@ -187,7 +151,6 @@ function AnnotationForm(
187
151
  <AnnotationFormTemplateSelector
188
152
  setCommentingType={setTemplateType}
189
153
  mediaType={mediaType}
190
- t={t}
191
154
  />
192
155
  )
193
156
  : (
@@ -204,11 +167,8 @@ function AnnotationForm(
204
167
  annotation={annotation}
205
168
  canvases={canvases}
206
169
  closeFormCompanionWindow={closeFormCompanionWindow}
207
- config={config}
208
- debugMode={debugMode}
209
170
  playerReferences={playerReferences}
210
171
  saveAnnotation={saveAnnotation}
211
- t={t}
212
172
  templateType={templateType}
213
173
  windowId={windowId}
214
174
  />
@@ -237,7 +197,9 @@ AnnotationForm.propTypes = {
237
197
  PropTypes.string,
238
198
  ]).isRequired,
239
199
  // eslint-disable-next-line react/forbid-prop-types
240
- canvases: PropTypes.object.isRequired,
200
+ canvases: PropTypes.arrayOf(
201
+ PropTypes.shape({ id: PropTypes.string }),
202
+ ).isRequired,
241
203
  closeCompanionWindow: PropTypes.func.isRequired,
242
204
  config: PropTypes.shape({
243
205
  annotation: PropTypes.shape({
@@ -255,8 +217,7 @@ AnnotationForm.propTypes = {
255
217
  // eslint-disable-next-line react/forbid-prop-types
256
218
  playerReferences: PropTypes.object.isRequired,
257
219
  receiveAnnotation: PropTypes.func.isRequired,
258
- t: PropTypes.func.isRequired,
259
220
  windowId: PropTypes.string.isRequired,
260
221
  };
261
222
 
262
- export default withTranslation()(AnnotationForm);
223
+ export default AnnotationForm;