@searpent/react-image-annotate 2.1.0 → 2.1.2
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/Annotator/exampleImages_bugdemo_15_1.js +80 -0
- package/Annotator/examplePhotos.js +4 -76
- package/Annotator/examplePhotos_repr.js +7052 -0
- package/Annotator/index.js +2 -94
- package/Annotator/index.story_bugdemo_15_1.js +882 -0
- package/Annotator/index.story_repr.js +1075 -0
- package/Annotator/reducers/general-reducer.js +5 -23
- package/Editor/editor.css +30 -0
- package/Editor/index.js +3 -7
- package/Editor/index_bugdemo_15_1.js +147 -0
- package/MainLayout/index.js +4 -2
- package/MainLayout/index_bugdemo_15_1.js +588 -0
- package/MetadataEditorSidebarBox/index_14_01_25.js +231 -0
- package/MetadataEditorSidebarBox/index_repr.js +271 -0
- package/package.json +2 -2
|
@@ -1240,7 +1240,7 @@ export default (function (state, action) {
|
|
|
1240
1240
|
value: value
|
|
1241
1241
|
});
|
|
1242
1242
|
} else {
|
|
1243
|
-
var _state$images$
|
|
1243
|
+
var _state$images$_imageI3, _state$images$_imageI4;
|
|
1244
1244
|
|
|
1245
1245
|
// update metadata of article
|
|
1246
1246
|
if (_groupId2) {
|
|
@@ -1266,42 +1266,24 @@ export default (function (state, action) {
|
|
|
1266
1266
|
return state;
|
|
1267
1267
|
}
|
|
1268
1268
|
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
// This ensures the saveableAction is added to the image being modified, not the currently selected one
|
|
1272
|
-
|
|
1273
|
-
if (state.images[_imageIndex]) {
|
|
1274
|
-
var _state$images$_imageI3;
|
|
1275
|
-
|
|
1276
|
-
var currentSaveableActions = ((_state$images$_imageI3 = state.images[_imageIndex]) === null || _state$images$_imageI3 === void 0 ? void 0 : _state$images$_imageI3.saveableActions) || [];
|
|
1277
|
-
state = setIn(state, ["images", _imageIndex, "saveableActions"], [].concat(_toConsumableArray(currentSaveableActions), ["UPDATE_METADATA"]));
|
|
1278
|
-
}
|
|
1279
|
-
|
|
1269
|
+
articleMetadata[toBeUpdatedMetadataIdx].value = value;
|
|
1270
|
+
state = addSaveableAction(state, "UPDATE_METADATA");
|
|
1280
1271
|
return setIn(state, ["images", _imageIndex, "regions", articleMetadataRegionIdx], _objectSpread({}, articleRegionToUpdate, {
|
|
1281
1272
|
text: JSON.stringify(articleMetadata)
|
|
1282
1273
|
}));
|
|
1283
1274
|
} // update metadata of image
|
|
1284
1275
|
|
|
1285
1276
|
|
|
1286
|
-
var _metadataIndex = (_state$images$
|
|
1277
|
+
var _metadataIndex = (_state$images$_imageI3 = state.images[_imageIndex]) === null || _state$images$_imageI3 === void 0 ? void 0 : (_state$images$_imageI4 = _state$images$_imageI3.metadata) === null || _state$images$_imageI4 === void 0 ? void 0 : _state$images$_imageI4.findIndex(function (mt) {
|
|
1287
1278
|
return mt.key === name;
|
|
1288
1279
|
});
|
|
1289
1280
|
|
|
1290
1281
|
if (_metadataIndex < 0) {
|
|
1291
1282
|
console.error("can't find photo metadata by key \"".concat(name, "\""));
|
|
1292
1283
|
return state;
|
|
1293
|
-
} // Add saveableAction to the correct image (using imageIndex from action, not selectedImage)
|
|
1294
|
-
// This ensures the saveableAction is added to the image being modified, not the currently selected one
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
if (state.images[_imageIndex]) {
|
|
1298
|
-
var _state$images$_imageI6;
|
|
1299
|
-
|
|
1300
|
-
var _currentSaveableActions = ((_state$images$_imageI6 = state.images[_imageIndex]) === null || _state$images$_imageI6 === void 0 ? void 0 : _state$images$_imageI6.saveableActions) || [];
|
|
1301
|
-
|
|
1302
|
-
state = setIn(state, ["images", _imageIndex, "saveableActions"], [].concat(_toConsumableArray(_currentSaveableActions), ["UPDATE_METADATA"]));
|
|
1303
1284
|
}
|
|
1304
1285
|
|
|
1286
|
+
state = addSaveableAction(state, "UPDATE_METADATA");
|
|
1305
1287
|
return setIn(state, ["images", _imageIndex, "metadata", _metadataIndex], {
|
|
1306
1288
|
key: name,
|
|
1307
1289
|
value: value
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
.editor-toggle-wrapper {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
align-items: flex-start;
|
|
5
|
+
gap: 0.5rem; /* space between Spellcheck and Edit mode rows */
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/* Smaller toggle size only for Editor switches */
|
|
9
|
+
.editor-switch.switch {
|
|
10
|
+
width: 44px;
|
|
11
|
+
height: 24px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.editor-switch .slider {
|
|
15
|
+
border-radius: 24px;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.editor-switch .slider:before {
|
|
19
|
+
height: 18px;
|
|
20
|
+
width: 18px;
|
|
21
|
+
left: 3px;
|
|
22
|
+
bottom: 3px;
|
|
23
|
+
border-radius: 50%;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.editor-switch input:checked + .slider:before {
|
|
27
|
+
transform: translateX(18px);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
package/Editor/index.js
CHANGED
|
@@ -71,12 +71,6 @@ function Editor(_ref) {
|
|
|
71
71
|
});
|
|
72
72
|
};
|
|
73
73
|
|
|
74
|
-
if (blocks.length < 1) {
|
|
75
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
76
|
-
className: "instructions"
|
|
77
|
-
}, /*#__PURE__*/React.createElement("h1", null, "Click article to display text."));
|
|
78
|
-
}
|
|
79
|
-
|
|
80
74
|
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
|
|
81
75
|
className: "show-metadata-wrapper editor-toggle-wrapper"
|
|
82
76
|
}, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", {
|
|
@@ -99,7 +93,9 @@ function Editor(_ref) {
|
|
|
99
93
|
onChange: toggleEditMode
|
|
100
94
|
}), /*#__PURE__*/React.createElement("span", {
|
|
101
95
|
className: "slider round"
|
|
102
|
-
})), /*#__PURE__*/React.createElement("label", null, "Edit mode"))),
|
|
96
|
+
})), /*#__PURE__*/React.createElement("label", null, "Edit mode"))), blocks.length < 1 ? /*#__PURE__*/React.createElement("div", {
|
|
97
|
+
className: "instructions"
|
|
98
|
+
}, /*#__PURE__*/React.createElement("h1", null, "Click article to display text.")) : !editMode ? /*#__PURE__*/React.createElement(ReadOnly, {
|
|
103
99
|
article: blocksToArticle(blocks)
|
|
104
100
|
}) : /*#__PURE__*/React.createElement(ReactEditorJS, {
|
|
105
101
|
defaultValue: {
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import _regeneratorRuntime from "@babel/runtime/regenerator";
|
|
2
|
+
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
|
|
3
|
+
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
4
|
+
import React, { useState } from 'react';
|
|
5
|
+
import { createReactEditorJS } from 'react-editor-js';
|
|
6
|
+
import blocksToArticle from '../utils/blocks-to-article';
|
|
7
|
+
import { EDITOR_JS_TOOLS } from './tools';
|
|
8
|
+
import ReadOnly from './readOnly';
|
|
9
|
+
import { isSpellcheckEnabled, setSpellcheckEnabled } from '../utils/spellcheck-nspell';
|
|
10
|
+
import './editor.css';
|
|
11
|
+
var ReactEditorJS = createReactEditorJS();
|
|
12
|
+
|
|
13
|
+
function Editor(_ref) {
|
|
14
|
+
var _ref$blocks = _ref.blocks,
|
|
15
|
+
blocks = _ref$blocks === void 0 ? [] : _ref$blocks,
|
|
16
|
+
onChange = _ref.onChange,
|
|
17
|
+
imageIndex = _ref.imageIndex,
|
|
18
|
+
selectedFrame = _ref.selectedFrame,
|
|
19
|
+
_ref$selectedGroupId = _ref.selectedGroupId,
|
|
20
|
+
selectedGroupId = _ref$selectedGroupId === void 0 ? null : _ref$selectedGroupId,
|
|
21
|
+
_ref$originalSelected = _ref.originalSelectedGroupId,
|
|
22
|
+
originalSelectedGroupId = _ref$originalSelected === void 0 ? null : _ref$originalSelected;
|
|
23
|
+
|
|
24
|
+
var _useState = useState(false),
|
|
25
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
26
|
+
editMode = _useState2[0],
|
|
27
|
+
setEditMode = _useState2[1];
|
|
28
|
+
|
|
29
|
+
var _useState3 = useState(isSpellcheckEnabled()),
|
|
30
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
31
|
+
autoSpellcheck = _useState4[0],
|
|
32
|
+
setAutoSpellcheck = _useState4[1];
|
|
33
|
+
|
|
34
|
+
var handleChange = /*#__PURE__*/function () {
|
|
35
|
+
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(instance) {
|
|
36
|
+
var data;
|
|
37
|
+
return _regeneratorRuntime.wrap(function _callee$(_context) {
|
|
38
|
+
while (1) {
|
|
39
|
+
switch (_context.prev = _context.next) {
|
|
40
|
+
case 0:
|
|
41
|
+
_context.next = 2;
|
|
42
|
+
return instance.saver.save();
|
|
43
|
+
|
|
44
|
+
case 2:
|
|
45
|
+
data = _context.sent;
|
|
46
|
+
onChange({
|
|
47
|
+
imageIndex: imageIndex,
|
|
48
|
+
data: data
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
case 4:
|
|
52
|
+
case "end":
|
|
53
|
+
return _context.stop();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}, _callee);
|
|
57
|
+
}));
|
|
58
|
+
|
|
59
|
+
return function handleChange(_x) {
|
|
60
|
+
return _ref2.apply(this, arguments);
|
|
61
|
+
};
|
|
62
|
+
}();
|
|
63
|
+
|
|
64
|
+
var toggleEditMode = function toggleEditMode() {
|
|
65
|
+
setEditMode(function (prev) {
|
|
66
|
+
return !prev;
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
var toggleAutoSpellcheck = function toggleAutoSpellcheck() {
|
|
71
|
+
setAutoSpellcheck(function (prev) {
|
|
72
|
+
var next = !prev;
|
|
73
|
+
setSpellcheckEnabled(next);
|
|
74
|
+
return next;
|
|
75
|
+
});
|
|
76
|
+
}; // BUG SIMULATION: Only activate with ?bug=true parameter (not just localhost)
|
|
77
|
+
// This allows Storybook to test both the fix and the bug simulation
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
var isBugMode = typeof window !== 'undefined' && (window.location.search.includes('bug=true') || window.location.search.includes('bug=on')); // In bug mode: selectedGroupId is null (simulating the bug), but originalSelectedGroupId has the actual selection
|
|
81
|
+
// Use originalSelectedGroupId for filtering in read-only mode to show correct article
|
|
82
|
+
// Use selectedGroupId (null) for edit mode to reproduce the bug
|
|
83
|
+
|
|
84
|
+
var groupIdForReadOnly = isBugMode && originalSelectedGroupId != null ? originalSelectedGroupId // Use original selection for read-only filtering
|
|
85
|
+
: selectedGroupId; // Otherwise use selectedGroupId
|
|
86
|
+
|
|
87
|
+
var groupIdForEdit = selectedGroupId; // Always use selectedGroupId for edit mode (null in bug mode = bug)
|
|
88
|
+
// Filter blocks for read-only mode
|
|
89
|
+
|
|
90
|
+
var blocksForReadOnly = groupIdForReadOnly === null ? isBugMode ? blocks : [] : // In bug mode show all blocks, otherwise show empty
|
|
91
|
+
blocks.filter(function (i) {
|
|
92
|
+
var _i$data;
|
|
93
|
+
|
|
94
|
+
return (i === null || i === void 0 ? void 0 : (_i$data = i.data) === null || _i$data === void 0 ? void 0 : _i$data.groupId) === groupIdForReadOnly;
|
|
95
|
+
}); // Filter by selected article
|
|
96
|
+
// Filter blocks for edit mode - this is where the bug manifests
|
|
97
|
+
|
|
98
|
+
var blocksForEdit = groupIdForEdit === null ? blocks.filter(function (i) {
|
|
99
|
+
var _i$data2;
|
|
100
|
+
|
|
101
|
+
return (i === null || i === void 0 ? void 0 : (_i$data2 = i.data) === null || _i$data2 === void 0 ? void 0 : _i$data2.groupId) === groupIdForEdit;
|
|
102
|
+
}) // BUG: Filter to empty array when selectedGroupId is null
|
|
103
|
+
: blocks.filter(function (i) {
|
|
104
|
+
var _i$data3;
|
|
105
|
+
|
|
106
|
+
return (i === null || i === void 0 ? void 0 : (_i$data3 = i.data) === null || _i$data3 === void 0 ? void 0 : _i$data3.groupId) === groupIdForEdit;
|
|
107
|
+
}); // Normal: filter by selected article
|
|
108
|
+
|
|
109
|
+
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
|
|
110
|
+
className: "show-metadata-wrapper editor-toggle-wrapper"
|
|
111
|
+
}, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", {
|
|
112
|
+
className: "switch mr-2 editor-switch"
|
|
113
|
+
}, /*#__PURE__*/React.createElement("input", {
|
|
114
|
+
id: "automatic-spellcheck",
|
|
115
|
+
type: "checkbox",
|
|
116
|
+
checked: autoSpellcheck,
|
|
117
|
+
onChange: toggleAutoSpellcheck
|
|
118
|
+
}), /*#__PURE__*/React.createElement("span", {
|
|
119
|
+
className: "slider round"
|
|
120
|
+
})), /*#__PURE__*/React.createElement("label", {
|
|
121
|
+
className: "mr-4"
|
|
122
|
+
}, "Spellcheck")), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", {
|
|
123
|
+
className: "switch mr-2 editor-switch"
|
|
124
|
+
}, /*#__PURE__*/React.createElement("input", {
|
|
125
|
+
id: "show-metadata",
|
|
126
|
+
type: "checkbox",
|
|
127
|
+
checked: editMode,
|
|
128
|
+
onChange: toggleEditMode
|
|
129
|
+
}), /*#__PURE__*/React.createElement("span", {
|
|
130
|
+
className: "slider round"
|
|
131
|
+
})), /*#__PURE__*/React.createElement("label", null, "Edit mode"))), blocksForReadOnly.length < 1 ? /*#__PURE__*/React.createElement("div", {
|
|
132
|
+
className: "instructions"
|
|
133
|
+
}, /*#__PURE__*/React.createElement("h1", null, "Click article to display text.")) : !editMode ? /*#__PURE__*/React.createElement(ReadOnly, {
|
|
134
|
+
article: blocksToArticle(blocksForReadOnly)
|
|
135
|
+
}) : /*#__PURE__*/React.createElement(ReactEditorJS, {
|
|
136
|
+
defaultValue: {
|
|
137
|
+
blocks: blocksForEdit
|
|
138
|
+
},
|
|
139
|
+
tools: EDITOR_JS_TOOLS,
|
|
140
|
+
onChange: handleChange,
|
|
141
|
+
onInitialize: function onInitialize() {},
|
|
142
|
+
enableReInitialize: true,
|
|
143
|
+
key: selectedFrame
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export default Editor;
|
package/MainLayout/index.js
CHANGED
|
@@ -278,8 +278,10 @@ export var MainLayout = function MainLayout(_ref5) {
|
|
|
278
278
|
var extractionEngineRegions = (((_state$images$state$s2 = state.images[state.selectedImage]) === null || _state$images$state$s2 === void 0 ? void 0 : _state$images$state$s2.regions) || []).filter(function (r) {
|
|
279
279
|
return r.cls !== 'metadata';
|
|
280
280
|
});
|
|
281
|
-
var editorBlocks = regionsToBlocks(extractionEngineRegions, clsColor);
|
|
282
|
-
|
|
281
|
+
var editorBlocks = regionsToBlocks(extractionEngineRegions, clsColor); // FIX: Show all blocks when selectedGroupId is null
|
|
282
|
+
// This fixes the bug where text disappears in edit mode when selectedGroupId is null but blocks have groupId
|
|
283
|
+
|
|
284
|
+
var blocks = selectedGroupId === null ? editorBlocks : editorBlocks.filter(function (i) {
|
|
283
285
|
var _i$data;
|
|
284
286
|
|
|
285
287
|
return (i === null || i === void 0 ? void 0 : (_i$data = i.data) === null || _i$data === void 0 ? void 0 : _i$data.groupId) === selectedGroupId;
|