mirador-annotation-editor-video 1.1.5 → 1.1.6
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 +11 -0
- package/__tests__/AnnotationCreation.test.js +62 -28
- package/__tests__/AnnotationExportDialog.test.js +18 -16
- package/__tests__/CanvasListItem.test.js +53 -19
- package/__tests__/LocalStorageAdapter.test.js +1 -1
- package/__tests__/miradorAnnotationPlugin.test.js +97 -70
- package/__tests__/style-mock.js +1 -0
- package/__tests__/test-utils.js +57 -0
- package/demo/src/index.js +9 -4
- package/demo/src/quillConfig.js +34 -0
- package/es/AnnotationExportDialog.js +17 -25
- package/es/CanvasListItem.js +8 -4
- package/es/IIIFUtils.js +35 -3
- package/es/SingleCanvasDialog.js +1 -4
- package/es/TextEditor.js +9 -19
- package/es/annotationForm/AnnotationForm.js +14 -41
- package/es/annotationForm/AnnotationFormBody.js +36 -27
- package/es/annotationForm/AnnotationFormHeader.js +3 -3
- package/es/annotationForm/AnnotationFormOverlay/AnnotationDrawing.js +3 -1
- package/es/annotationForm/AnnotationFormOverlay/AnnotationFormOverlay.js +1 -1
- package/es/annotationForm/AnnotationFormOverlay/AnnotationFormOverlayTool.js +3 -2
- package/es/annotationForm/AnnotationFormOverlay/AnnotationFormOverlayToolOptions.js +8 -6
- package/es/annotationForm/AnnotationFormOverlay/KonvaDrawing/KonvaUtils.js +6 -20
- package/es/annotationForm/AnnotationFormOverlay/KonvaDrawing/shapes/ColorPicker.js +16 -6
- package/es/annotationForm/AnnotationFormTemplateSelector.js +9 -9
- package/es/annotationForm/AnnotationFormUtils.js +3 -0
- package/es/annotationForm/Debug.js +1 -0
- package/es/annotationForm/DebugInformation.js +27 -0
- package/es/annotationForm/MultiTagsInput.js +4 -1
- package/es/annotationForm/MultipleBodyTemplate.js +7 -9
- package/es/annotationForm/TaggingTemplate.js +0 -1
- package/es/annotationForm/TargetFormSection.js +4 -3
- package/es/annotationForm/TargetSpatialInput.js +4 -3
- package/es/annotationForm/TextCommentInput.js +25 -12
- package/es/annotationForm/TextCommentTemplate.js +0 -1
- package/es/annotationForm/UnsupportedMedia.js +43 -0
- package/es/containers/miradorAnnotationPlugin.js +1 -50
- package/es/custom.css +0 -13
- package/es/index.js +5 -12
- package/es/locales/locales.js +3 -2
- package/es/locales/locales_en.js +1 -1
- package/es/playerReferences.js +2 -1
- package/es/plugins/annotationCreationCompanionWindow.js +5 -8
- package/es/plugins/annotationSaga.js +44 -0
- package/es/plugins/canvasAnnotationsPlugin.js +86 -61
- package/es/plugins/canvasAnnotationsPluginUtils.js +202 -0
- package/es/plugins/externalStorageAnnotationPlugin.js +6 -71
- package/es/plugins/miradorAnnotationPlugin.js +44 -6
- package/es/plugins/windowSideBarButtonsPlugin.js +8 -10
- package/jest.config.js +14 -3
- package/package.json +8 -3
- package/setupJest.js +1 -4
- package/src/AnnotationExportDialog.js +12 -24
- package/src/CanvasListItem.js +4 -3
- package/src/IIIFUtils.js +33 -5
- package/src/SingleCanvasDialog.js +0 -3
- package/src/TextEditor.js +8 -32
- package/src/annotationForm/AnnotationForm.js +8 -47
- package/src/annotationForm/AnnotationFormBody.js +62 -83
- package/src/annotationForm/AnnotationFormHeader.js +3 -3
- package/src/annotationForm/AnnotationFormOverlay/AnnotationDrawing.js +3 -9
- package/src/annotationForm/AnnotationFormOverlay/AnnotationFormOverlay.js +1 -1
- package/src/annotationForm/AnnotationFormOverlay/AnnotationFormOverlayTool.js +2 -1
- package/src/annotationForm/AnnotationFormOverlay/AnnotationFormOverlayToolOptions.js +10 -6
- package/src/annotationForm/AnnotationFormOverlay/KonvaDrawing/KonvaUtils.js +14 -20
- package/src/annotationForm/AnnotationFormOverlay/KonvaDrawing/shapes/ColorPicker.js +14 -12
- package/src/annotationForm/AnnotationFormTemplateSelector.js +5 -7
- package/src/annotationForm/AnnotationFormUtils.js +2 -0
- package/src/annotationForm/Debug.js +0 -0
- package/src/annotationForm/DebugInformation.js +59 -0
- package/src/annotationForm/MultiTagsInput.js +4 -1
- package/src/annotationForm/MultipleBodyTemplate.js +7 -8
- package/src/annotationForm/TaggingTemplate.js +0 -1
- package/src/annotationForm/TargetFormSection.js +2 -3
- package/src/annotationForm/TargetSpatialInput.js +3 -3
- package/src/annotationForm/TextCommentInput.js +28 -14
- package/src/annotationForm/TextCommentTemplate.js +0 -1
- package/src/annotationForm/UnsupportedMedia.js +31 -0
- package/src/containers/miradorAnnotationPlugin.js +0 -36
- package/src/custom.css +0 -13
- package/src/index.js +10 -15
- package/src/locales/locales.js +3 -1
- package/src/locales/locales_en.js +1 -1
- package/src/playerReferences.js +5 -2
- package/src/plugins/annotationCreationCompanionWindow.js +9 -23
- package/src/plugins/annotationSaga.js +50 -0
- package/src/plugins/canvasAnnotationsPlugin.js +122 -98
- package/src/plugins/canvasAnnotationsPluginUtils.js +199 -0
- package/src/plugins/externalStorageAnnotationPlugin.js +6 -79
- package/src/plugins/miradorAnnotationPlugin.js +32 -4
- package/src/plugins/windowSideBarButtonsPlugin.js +6 -8
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
'
|
|
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.
|
|
3
|
+
"version": "1.1.6",
|
|
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": "^
|
|
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
|
|
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
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
<
|
|
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
|
-
</
|
|
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
|
|
145
|
+
export default AnnotationExportDialog;
|
package/src/CanvasListItem.js
CHANGED
|
@@ -107,13 +107,15 @@ const CanvasListItem = forwardRef((props, ref) => {
|
|
|
107
107
|
.includes(annotationid);
|
|
108
108
|
};
|
|
109
109
|
|
|
110
|
-
|
|
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 {...
|
|
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
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
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
|
|
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
|
-
<
|
|
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.
|
|
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
|
|
223
|
+
export default AnnotationForm;
|