@searpent/react-image-annotate 2.0.74 → 2.0.76

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 (224) hide show
  1. package/.babelrc +6 -0
  2. package/.env +1 -0
  3. package/.flowconfig +2 -0
  4. package/.github/workflows/release-on-master.yml +32 -0
  5. package/.github/workflows/test.yml +16 -0
  6. package/.prettierrc +3 -0
  7. package/.releaserc.js +18 -0
  8. package/.storybook/addons.js +2 -0
  9. package/.storybook/config.js +16 -0
  10. package/LICENSE +21 -0
  11. package/package.json +1 -1
  12. package/public/favicon.ico +0 -0
  13. package/public/index.html +38 -0
  14. package/src/Annotator/bike-pic.png +0 -0
  15. package/src/Annotator/bike-pic2.png +0 -0
  16. package/src/Annotator/dab-keyframes.story.json +1 -0
  17. package/src/Annotator/exampleImages.js +48 -0
  18. package/src/Annotator/examplePhotos.js +7603 -0
  19. package/src/Annotator/index.js +380 -0
  20. package/src/Annotator/index.story.js +877 -0
  21. package/src/Annotator/poses.story.js +150 -0
  22. package/src/Annotator/reducers/combine-reducers.js +7 -0
  23. package/src/Annotator/reducers/convert-expanding-line-to-polygon.js +53 -0
  24. package/{Annotator → src/Annotator}/reducers/fix-twisted.js +5 -3
  25. package/src/Annotator/reducers/general-reducer.js +1228 -0
  26. package/src/Annotator/reducers/get-active-image.js +21 -0
  27. package/src/Annotator/reducers/get-implied-video-regions.js +115 -0
  28. package/src/Annotator/reducers/history-handler.js +60 -0
  29. package/src/Annotator/reducers/image-reducer.js +23 -0
  30. package/src/Annotator/reducers/video-reducer.js +85 -0
  31. package/src/Annotator/video.story.js +51 -0
  32. package/src/ClassSelectionMenu/index.js +112 -0
  33. package/src/Crosshairs/index.js +64 -0
  34. package/src/DebugSidebarBox/index.js +36 -0
  35. package/src/DemoSite/Editor.js +235 -0
  36. package/src/DemoSite/ErrorBoundaryDialog.js +34 -0
  37. package/src/DemoSite/index.js +41 -0
  38. package/src/DemoSite/index.story.js +10 -0
  39. package/src/DemoSite/simple-segmentation-example.json +572 -0
  40. package/{Editor → src/Editor}/annotation-plugin/annotation.css +2 -0
  41. package/src/Editor/annotation-plugin/annotation.js +536 -0
  42. package/src/Editor/index.js +50 -0
  43. package/src/Editor/readOnly.js +21 -0
  44. package/{Editor → src/Editor}/tools.js +3 -2
  45. package/src/Errorer/index.js +13 -0
  46. package/src/FullImageSegmentationAnnotator/hard1.story.jpg +0 -0
  47. package/src/FullImageSegmentationAnnotator/hard2.story.jpg +0 -0
  48. package/src/FullImageSegmentationAnnotator/hard3.story.jpg +0 -0
  49. package/src/FullImageSegmentationAnnotator/index.js +7 -0
  50. package/src/FullImageSegmentationAnnotator/index.story.js +177 -0
  51. package/src/FullImageSegmentationAnnotator/orange.story.png +0 -0
  52. package/src/GroupSelectorSidebarBox/index.js +48 -0
  53. package/src/GroupsEditorSidebarBox/index.js +108 -0
  54. package/src/HelpSidebarBox/index.js +43 -0
  55. package/src/HighlightBox/index.js +143 -0
  56. package/src/HistorySidebarBox/index.js +78 -0
  57. package/src/ImageCanvas/dancing-man.story.jpg +0 -0
  58. package/src/ImageCanvas/index.js +515 -0
  59. package/src/ImageCanvas/index.story.js +314 -0
  60. package/src/ImageCanvas/mouse_mask.story.png +0 -0
  61. package/src/ImageCanvas/region-tools.js +171 -0
  62. package/src/ImageCanvas/seves_desk.story.jpg +0 -0
  63. package/{ImageCanvas → src/ImageCanvas}/styles.js +8 -12
  64. package/src/ImageCanvas/use-mouse.js +168 -0
  65. package/src/ImageCanvas/use-project-box.js +23 -0
  66. package/src/ImageCanvas/use-wasd-mode.js +50 -0
  67. package/src/ImageMask/index.js +127 -0
  68. package/src/ImageMask/load-image.js +32 -0
  69. package/src/ImageSelectorSidebarBox/index.js +54 -0
  70. package/src/KeyframeTimeline/get-time-string.js +25 -0
  71. package/src/KeyframeTimeline/index.js +223 -0
  72. package/src/KeyframesSelectorSidebarBox/index.js +93 -0
  73. package/src/LandingPage/content.md +57 -0
  74. package/src/LandingPage/github-markdown.css +964 -0
  75. package/src/LandingPage/index.js +147 -0
  76. package/src/Locker/index.js +13 -0
  77. package/src/MainLayout/RightSidebarItemsWrapper.js +21 -0
  78. package/src/MainLayout/icon-dictionary.js +79 -0
  79. package/src/MainLayout/index.js +564 -0
  80. package/src/MainLayout/index.story.js +240 -0
  81. package/{MainLayout → src/MainLayout}/styles.js +7 -6
  82. package/src/MainLayout/types.js +171 -0
  83. package/src/MainLayout/use-implied-video-regions.js +17 -0
  84. package/src/MetadataEditorSidebarBox/index.js +160 -0
  85. package/src/PageSelector/index.js +159 -0
  86. package/src/PointDistances/index.js +90 -0
  87. package/src/PreventScrollToParents/index.js +48 -0
  88. package/src/PreventScrollToParents/index.story.js +23 -0
  89. package/src/RegionLabel/index.js +236 -0
  90. package/{RegionLabel → src/RegionLabel}/styles.js +15 -12
  91. package/src/RegionSelectAndTransformBoxes/index.js +236 -0
  92. package/src/RegionSelectorSidebarBox/index.js +220 -0
  93. package/{RegionSelectorSidebarBox → src/RegionSelectorSidebarBox}/styles.js +14 -13
  94. package/src/RegionShapes/index.js +254 -0
  95. package/src/RegionTags/index.js +136 -0
  96. package/src/SettingsDialog/index.js +58 -0
  97. package/src/SettingsProvider/index.js +57 -0
  98. package/src/Shortcuts/ShortcutField.js +44 -0
  99. package/src/Shortcuts/index.js +129 -0
  100. package/src/ShortcutsManager/index.js +162 -0
  101. package/src/Sidebar/index.js +117 -0
  102. package/src/SidebarBoxContainer/index.js +93 -0
  103. package/src/SmallToolButton/index.js +57 -0
  104. package/src/TagsSidebarBox/index.js +93 -0
  105. package/src/TaskDescriptionSidebarBox/index.js +43 -0
  106. package/src/Theme/index.js +36 -0
  107. package/src/VideoOrImageCanvasBackground/index.js +170 -0
  108. package/src/colors.js +32 -0
  109. package/src/hooks/use-colors.js +75 -0
  110. package/src/hooks/use-event-callback.js +11 -0
  111. package/src/hooks/use-exclude-pattern.js +27 -0
  112. package/src/hooks/use-load-image.js +21 -0
  113. package/src/hooks/use-window-size.js +46 -0
  114. package/{hooks → src/hooks}/xpattern.js +1 -1
  115. package/src/hooks/xpattern.png +0 -0
  116. package/src/index.js +18 -0
  117. package/src/lib.js +7 -0
  118. package/src/screenshot.png +0 -0
  119. package/src/site.css +5 -0
  120. package/src/stories.js +2 -0
  121. package/src/utils/blocks-to-article.js +61 -0
  122. package/{utils → src/utils}/blocks-to-article.test.js +8 -5
  123. package/{utils → src/utils}/default-locked-until.js +1 -2
  124. package/{utils → src/utils}/filter-only-unique.js +1 -1
  125. package/src/utils/get-from-local-storage.js +7 -0
  126. package/src/utils/get-hotkey-help-text.js +11 -0
  127. package/src/utils/get-landmarks-with-transform.js +23 -0
  128. package/src/utils/photosToImages.js +67 -0
  129. package/src/utils/regions-groups.js +19 -0
  130. package/src/utils/regions-to-blocks.js +16 -0
  131. package/src/utils/saveable-actions-enum.js +5 -0
  132. package/src/utils/set-in-local-storage.js +6 -0
  133. package/src/utils/sleep.js +3 -0
  134. package/src/utils/uuid-to-hash.js +5 -0
  135. package/Annotator/exampleImages.js +0 -41
  136. package/Annotator/examplePhotos.js +0 -6980
  137. package/Annotator/index.js +0 -417
  138. package/Annotator/reducers/combine-reducers.js +0 -14
  139. package/Annotator/reducers/convert-expanding-line-to-polygon.js +0 -73
  140. package/Annotator/reducers/general-reducer.js +0 -1430
  141. package/Annotator/reducers/get-active-image.js +0 -27
  142. package/Annotator/reducers/get-implied-video-regions.js +0 -180
  143. package/Annotator/reducers/history-handler.js +0 -38
  144. package/Annotator/reducers/image-reducer.js +0 -20
  145. package/Annotator/reducers/video-reducer.js +0 -88
  146. package/ClassSelectionMenu/index.js +0 -140
  147. package/Crosshairs/index.js +0 -53
  148. package/DebugSidebarBox/index.js +0 -20
  149. package/DemoSite/Editor.js +0 -194
  150. package/DemoSite/ErrorBoundaryDialog.js +0 -64
  151. package/DemoSite/index.js +0 -40
  152. package/Editor/annotation-plugin/annotation.js +0 -642
  153. package/Editor/index.js +0 -93
  154. package/Editor/readOnly.js +0 -68
  155. package/Errorer/index.js +0 -11
  156. package/FullImageSegmentationAnnotator/index.js +0 -7
  157. package/GroupSelectorSidebarBox/index.js +0 -63
  158. package/GroupsEditorSidebarBox/index.js +0 -138
  159. package/HelpSidebarBox/index.js +0 -58
  160. package/HighlightBox/index.js +0 -102
  161. package/HistorySidebarBox/index.js +0 -71
  162. package/ImageCanvas/index.js +0 -441
  163. package/ImageCanvas/region-tools.js +0 -165
  164. package/ImageCanvas/use-mouse.js +0 -180
  165. package/ImageCanvas/use-project-box.js +0 -27
  166. package/ImageCanvas/use-wasd-mode.js +0 -62
  167. package/ImageMask/index.js +0 -133
  168. package/ImageMask/load-image.js +0 -25
  169. package/ImageSelectorSidebarBox/index.js +0 -60
  170. package/KeyframeTimeline/get-time-string.js +0 -27
  171. package/KeyframeTimeline/index.js +0 -233
  172. package/KeyframesSelectorSidebarBox/index.js +0 -93
  173. package/LandingPage/index.js +0 -159
  174. package/Locker/index.js +0 -11
  175. package/MainLayout/RightSidebarItemsWrapper.js +0 -19
  176. package/MainLayout/icon-dictionary.js +0 -104
  177. package/MainLayout/index.js +0 -526
  178. package/MainLayout/types.js +0 -0
  179. package/MainLayout/use-implied-video-regions.js +0 -13
  180. package/MetadataEditorSidebarBox/index.js +0 -231
  181. package/PageSelector/index.js +0 -180
  182. package/PointDistances/index.js +0 -73
  183. package/PreventScrollToParents/index.js +0 -51
  184. package/RegionLabel/index.js +0 -232
  185. package/RegionSelectAndTransformBoxes/index.js +0 -169
  186. package/RegionSelectorSidebarBox/index.js +0 -254
  187. package/RegionShapes/index.js +0 -294
  188. package/RegionTags/index.js +0 -144
  189. package/SettingsDialog/index.js +0 -52
  190. package/SettingsProvider/index.js +0 -60
  191. package/Shortcuts/ShortcutField.js +0 -46
  192. package/Shortcuts/index.js +0 -133
  193. package/ShortcutsManager/index.js +0 -155
  194. package/Sidebar/index.js +0 -69
  195. package/SidebarBoxContainer/index.js +0 -93
  196. package/SmallToolButton/index.js +0 -42
  197. package/TagsSidebarBox/index.js +0 -105
  198. package/TaskDescriptionSidebarBox/index.js +0 -58
  199. package/Theme/index.js +0 -30
  200. package/VideoOrImageCanvasBackground/index.js +0 -151
  201. package/colors.js +0 -14
  202. package/hooks/use-colors.js +0 -94
  203. package/hooks/use-event-callback.js +0 -10
  204. package/hooks/use-exclude-pattern.js +0 -24
  205. package/hooks/use-load-image.js +0 -26
  206. package/hooks/use-window-size.js +0 -46
  207. package/index.js +0 -3
  208. package/lib.js +0 -3
  209. package/stories.js +0 -5
  210. package/utils/blocks-to-article.js +0 -60
  211. package/utils/get-from-local-storage.js +0 -7
  212. package/utils/get-hotkey-help-text.js +0 -9
  213. package/utils/get-landmarks-with-transform.js +0 -40
  214. package/utils/photosToImages.js +0 -85
  215. package/utils/regions-groups.js +0 -28
  216. package/utils/regions-to-blocks.js +0 -18
  217. package/utils/saveable-actions-enum.js +0 -3
  218. package/utils/set-in-local-storage.js +0 -3
  219. package/utils/sleep.js +0 -7
  220. package/utils/uuid-to-hash.js +0 -5
  221. /package/{Errorer → src/Errorer}/errorer.css +0 -0
  222. /package/{Locker → src/Locker}/locker.css +0 -0
  223. /package/{PageSelector → src/PageSelector}/page-selector.css +0 -0
  224. /package/{utils → src/utils}/next-group-id.js +0 -0
@@ -0,0 +1,240 @@
1
+ // @flow
2
+
3
+ import React from "react"
4
+
5
+ import { storiesOf } from "@storybook/react"
6
+ import { action } from "@storybook/addon-actions"
7
+ import { testRegions } from "../ImageCanvas/index.story"
8
+
9
+ import exampleImage from "../ImageCanvas/seves_desk.story.jpg"
10
+ import moment from "moment"
11
+
12
+ import MainLayout from "./"
13
+
14
+ storiesOf("MainLayout", module)
15
+ .add("Basic", () => (
16
+ <MainLayout
17
+ state={{
18
+ showTags: true,
19
+ selectedImage: exampleImage,
20
+ selectedTool: "select",
21
+ taskDescription: "## Example Task Description\n\nPlease work hard.",
22
+ labelImages: true,
23
+ imageClsList: ["alpha image", "beta image", "charlie image"],
24
+ imageTagList: ["tag1", "tag2", "tag3"],
25
+ regionClsList: ["alpha region", "beta region", "charlie region"],
26
+ regionTagList: ["tag1", "tag2", "tag3"],
27
+ images: [
28
+ {
29
+ src: exampleImage,
30
+ name: "Seve's Desk",
31
+ regions: testRegions,
32
+ },
33
+ {
34
+ src: "https://loremflickr.com/100/100/cars?lock=1",
35
+ name: "Frame 0036",
36
+ },
37
+ {
38
+ src: "https://loremflickr.com/100/100/cars?lock=2",
39
+ name: "Frame 0037",
40
+ },
41
+ {
42
+ src: "https://loremflickr.com/100/100/cars?lock=3",
43
+ name: "Frame 0038",
44
+ },
45
+ ],
46
+ mode: null,
47
+ enabledTools: ["create-point", "create-polygon", "modify-allowed-area"],
48
+ history: [{ name: "Reset Stuff", state: null, time: moment() }],
49
+ }}
50
+ dispatch={(a) => action(a.type)(a)}
51
+ />
52
+ ))
53
+ .add("Completing a Polygon", () => (
54
+ <MainLayout
55
+ state={{
56
+ showTags: false,
57
+ selectedImage: exampleImage,
58
+ selectedTool: "create-polygon",
59
+ taskDescription: "",
60
+ mode: {
61
+ mode: "DRAW_POLYGON",
62
+ regionId: "p1",
63
+ },
64
+ images: [
65
+ {
66
+ src: exampleImage,
67
+ name: "Seve's Desk",
68
+ regions: [
69
+ {
70
+ type: "polygon",
71
+ points: [
72
+ [0.25, 0.25],
73
+ [0.25, 0.5],
74
+ [0.5, 0.5],
75
+ ],
76
+ highlighted: true,
77
+ open: true,
78
+ color: "#00f",
79
+ id: "p1",
80
+ },
81
+ ],
82
+ },
83
+ ],
84
+ enabledTools: [],
85
+ history: [],
86
+ }}
87
+ dispatch={(a) => action(a.type)(a)}
88
+ />
89
+ ))
90
+ .add("Region Overlap Clicking", () => (
91
+ <MainLayout
92
+ state={{
93
+ showTags: false,
94
+ selectedImage: exampleImage,
95
+ selectedTool: "create-box",
96
+ taskDescription: "",
97
+ showTags: true,
98
+ mode: {
99
+ mode: "DRAW_POLYGON",
100
+ regionId: "p1",
101
+ },
102
+ images: [
103
+ {
104
+ src: exampleImage,
105
+ name: "Seve's Desk",
106
+ regions: [
107
+ {
108
+ type: "box",
109
+ cls: "Pants",
110
+ x: 0.25,
111
+ y: 0.25,
112
+ w: 0.5,
113
+ h: 0.5,
114
+ color: "#00f",
115
+ id: "p1",
116
+ },
117
+ {
118
+ type: "box",
119
+ cls: "Shirt",
120
+ x: 0.8,
121
+ y: 0.25,
122
+ w: 0.1,
123
+ h: 0.1,
124
+ highlighted: true,
125
+ color: "#00f",
126
+ id: "p1",
127
+ },
128
+ ],
129
+ },
130
+ ],
131
+ clsList: [],
132
+ tagList: [],
133
+ enabledTools: [],
134
+ history: [],
135
+ }}
136
+ dispatch={(a) => !a.type.includes("MOUSE_MOVE") && action(a.type)(a)}
137
+ />
138
+ ))
139
+ .add("Point Distances", () => (
140
+ <MainLayout
141
+ state={{
142
+ showTags: false,
143
+ showPointDistances: true,
144
+ selectedImage: exampleImage,
145
+ selectedTool: "create-point",
146
+ taskDescription: "",
147
+ showTags: true,
148
+ mode: null,
149
+ images: [
150
+ {
151
+ src: exampleImage,
152
+ name: "Point Distance Check",
153
+ regions: [
154
+ {
155
+ type: "point",
156
+ cls: "P",
157
+ x: 0.25,
158
+ y: 0.25,
159
+ color: "#f00",
160
+ id: "p1",
161
+ },
162
+ {
163
+ type: "point",
164
+ cls: "P",
165
+ x: 0.5,
166
+ y: 0.25,
167
+ color: "#0f0",
168
+ id: "p2",
169
+ },
170
+ {
171
+ type: "point",
172
+ cls: "P",
173
+ x: 0.5,
174
+ y: 0.5,
175
+ color: "#00f",
176
+ id: "p3",
177
+ },
178
+ ],
179
+ },
180
+ ],
181
+ clsList: [],
182
+ tagList: [],
183
+ enabledTools: [],
184
+ history: [],
185
+ }}
186
+ dispatch={(a) => !a.type.includes("MOUSE_MOVE") && action(a.type)(a)}
187
+ />
188
+ ))
189
+ .add("Point distances real units", () => (
190
+ <MainLayout
191
+ state={{
192
+ showTags: false,
193
+ showPointDistances: true,
194
+ pointDistancePrecision: 2,
195
+ selectedImage: exampleImage,
196
+ selectedTool: "create-point",
197
+ taskDescription: "",
198
+ showTags: true,
199
+ mode: null,
200
+ images: [
201
+ {
202
+ src: exampleImage,
203
+ name: "Point Distance Check",
204
+ realSize: { w: 200, h: 1000, unitName: "cm" },
205
+ regions: [
206
+ {
207
+ type: "point",
208
+ cls: "P",
209
+ x: 0.25,
210
+ y: 0.25,
211
+ color: "#f00",
212
+ id: "p1",
213
+ },
214
+ {
215
+ type: "point",
216
+ cls: "P",
217
+ x: 0.5,
218
+ y: 0.25,
219
+ color: "#0f0",
220
+ id: "p2",
221
+ },
222
+ {
223
+ type: "point",
224
+ cls: "P",
225
+ x: 0.5,
226
+ y: 0.5,
227
+ color: "#00f",
228
+ id: "p3",
229
+ },
230
+ ],
231
+ },
232
+ ],
233
+ clsList: [],
234
+ tagList: [],
235
+ enabledTools: [],
236
+ history: [],
237
+ }}
238
+ dispatch={(a) => !a.type.includes("MOUSE_MOVE") && action(a.type)(a)}
239
+ />
240
+ ))
@@ -1,4 +1,5 @@
1
- import { grey } from "@mui/material/colors";
1
+ import { grey } from "@mui/material/colors"
2
+
2
3
  export default {
3
4
  container: {
4
5
  display: "flex",
@@ -14,12 +15,12 @@ export default {
14
15
  left: 0,
15
16
  right: 0,
16
17
  top: 0,
17
- bottom: 0
18
- }
18
+ bottom: 0,
19
+ },
19
20
  },
20
21
  headerTitle: {
21
22
  fontWeight: "bold",
22
23
  color: grey[700],
23
- paddingLeft: 16
24
- }
25
- };
24
+ paddingLeft: 16,
25
+ },
26
+ }
@@ -0,0 +1,171 @@
1
+ // @flow
2
+
3
+ import type {
4
+ Region,
5
+ Polygon,
6
+ Box,
7
+ Point,
8
+ KeypointsDefinition,
9
+ Keypoints,
10
+ KeypointDefinition,
11
+ } from "../ImageCanvas/region-tools.js"
12
+
13
+ import type { Node } from "react"
14
+
15
+ export type ToolEnum =
16
+ | "select"
17
+ | "pan"
18
+ | "zoom"
19
+ | "create-point"
20
+ | "create-box"
21
+ | "create-polygon"
22
+ | "create-pixel"
23
+ | "create-expanding-line"
24
+ | "create-keypoints"
25
+
26
+ export type Metadata = {
27
+ key: string,
28
+ value: string
29
+ }
30
+
31
+ export type MetadataConfig = {
32
+ key: string,
33
+ level: string,
34
+ options: Array<string>
35
+ }
36
+
37
+ export type Image = {
38
+ src: string,
39
+ thumbnailSrc?: string,
40
+ name: string,
41
+ regions?: Array<Region>,
42
+ pixelSize?: { w: number, h: number },
43
+ realSize?: { w: number, h: number, unitName: string },
44
+ frameTime?: number,
45
+ metadata?: Array<Metadata>,
46
+ lockedUntil?: string,
47
+ }
48
+
49
+ export type Mode =
50
+ | null
51
+ | {| mode: "DRAW_POLYGON", regionId: string |}
52
+ | {| mode: "MOVE_POLYGON_POINT", regionId: string, pointIndex: number |}
53
+ | {|
54
+ mode: "RESIZE_BOX",
55
+ editLabelEditorAfter ?: boolean,
56
+ regionId: string,
57
+ freedom: [number, number],
58
+ original: { x: number, y: number, w: number, h: number },
59
+ isNew ?: boolean,
60
+ |}
61
+ | {| mode: "MOVE_REGION" |}
62
+ | {| mode: "MOVE_KEYPOINT", regionId: string, keypointId: string |}
63
+ | {|
64
+ mode: "RESIZE_KEYPOINTS",
65
+ landmarks: {
66
+ [string]: KeypointDefinition,
67
+ },
68
+ centerX: number,
69
+ centerY: number,
70
+ regionId: string,
71
+ isNew: boolean,
72
+ |}
73
+
74
+ export type MainLayoutStateBase = {|
75
+ annotationType: "video" | "image",
76
+ mouseDownAt ?: ? { x: number, y: number },
77
+ fullScreen ?: boolean,
78
+ settingsOpen ?: boolean,
79
+ minRegionSize ?: number,
80
+ showTags: boolean,
81
+ showMask: boolean,
82
+ showPointDistances ?: boolean,
83
+ pointDistancePrecision ?: number,
84
+ selectedTool: ToolEnum,
85
+ selectedCls ?: string,
86
+ mode: Mode,
87
+ taskDescription: string,
88
+ allowedArea ?: { x: number, y: number, w: number, h: number },
89
+ regionClsList ?: Array < string >,
90
+ regionTagList ?: Array < string >,
91
+ imageClsList ?: Array < string >,
92
+ imageTagList ?: Array < string >,
93
+ enabledTools: Array < string >,
94
+ history: Array < { time: Date, state: MainLayoutState, name: string } >,
95
+ keypointDefinitions: KeypointsDefinition,
96
+ |}
97
+
98
+ export type MainLayoutImageAnnotationState = {|
99
+ ...MainLayoutStateBase,
100
+ annotationType: "image",
101
+
102
+ selectedImage ?: string,
103
+ images: Array < Image >,
104
+ labelImages ?: boolean,
105
+
106
+ // If the selectedImage corresponds to a frame of a video
107
+ selectedImageFrameTime ?: number,
108
+ |}
109
+
110
+ export type MainLayoutVideoAnnotationState = {|
111
+ ...MainLayoutStateBase,
112
+ annotationType: "video",
113
+
114
+ videoSrc: string,
115
+ currentVideoTime: number,
116
+ videoName ?: string,
117
+ videoPlaying: boolean,
118
+ videoDuration ?: number,
119
+ keyframes: {
120
+ [time: number]: {|
121
+ time: number,
122
+ regions: Array < Region >,
123
+ |},
124
+ },
125
+ pixelSize ?: { w: number, h: number },
126
+ realSize ?: { w: number, h: number, unitName: string },
127
+ |}
128
+
129
+ export type MainLayoutState =
130
+ | MainLayoutImageAnnotationState
131
+ | MainLayoutVideoAnnotationState
132
+
133
+ export type Action =
134
+ | {| type: "@@INIT" |}
135
+ | {| type: "SELECT_IMAGE", image: Image, imageIndex: number |}
136
+ | {|
137
+ type: "IMAGE_OR_VIDEO_LOADED",
138
+ metadata: {
139
+ naturalWidth: number,
140
+ naturalHeight: number,
141
+ duration ?: number,
142
+ },
143
+ |}
144
+ | {| type: "CHANGE_REGION", region: Region |}
145
+ | {| type: "RESTORE_HISTORY" |}
146
+ | {| type: "CLOSE_POLYGON", polygon: Polygon |}
147
+ | {| type: "SELECT_REGION", region: Region |}
148
+ | {| type: "BEGIN_MOVE_POINT", point: Point |}
149
+ | {| type: "BEGIN_BOX_TRANSFORM", box: Box, directions: [number, number] |}
150
+ | {| type: "BEGIN_MOVE_POLYGON_POINT", polygon: Polygon, pointIndex: number |}
151
+ | {| type: "BEGIN_MOVE_KEYPOINT", region: Keypoints, keypointId: string |}
152
+ | {|
153
+ type: "ADD_POLYGON_POINT",
154
+ polygon: Polygon,
155
+ point: { x: number, y: number },
156
+ pointIndex: number,
157
+ |}
158
+ | {| type: "MOUSE_MOVE", x: number, y: number |}
159
+ | {| type: "MOUSE_DOWN", x: number, y: number |}
160
+ | {| type: "MOUSE_UP", x: number, y: number |}
161
+ | {| type: "CHANGE_REGION", region: Region |}
162
+ | {| type: "OPEN_REGION_EDITOR", region: Region |}
163
+ | {| type: "CLOSE_REGION_EDITOR", region: Region |}
164
+ | {| type: "DELETE_REGION", region: Region |}
165
+ | {| type: "DELETE_SELECTED_REGION" |}
166
+ | {| type: "HEADER_BUTTON_CLICKED", buttonName: string |}
167
+ | {| type: "SELECT_TOOL", selectedTool: ToolEnum |}
168
+ | {| type: "CANCEL" |}
169
+ | {| type: "SELECT_CLASSIFICATION", cls: string |}
170
+ | {| type: "UPDATE_REGIONS", imageId: string, regions: Array < Region > |}
171
+ | {| type: "IMAGES_CHANGED", updatedAt: Date |}
@@ -0,0 +1,17 @@
1
+ // @flow
2
+
3
+ import { useMemo } from "react"
4
+ import type { MainLayoutVideoAnnotationState } from "../Annotator/types"
5
+ import getImpliedVideoRegions from "../Annotator/reducers/get-implied-video-regions.js"
6
+
7
+ const emptyArr = []
8
+
9
+ export default (state: MainLayoutVideoAnnotationState) => {
10
+ if (state.annotationType !== "video") return emptyArr
11
+ const { keyframes, currentVideoTime = 0 } = state
12
+ // TODO memoize
13
+ return useMemo(
14
+ () => getImpliedVideoRegions(keyframes, currentVideoTime),
15
+ [keyframes, currentVideoTime]
16
+ )
17
+ }
@@ -0,0 +1,160 @@
1
+ // @flow
2
+
3
+ import React, { memo } from "react"
4
+ import SidebarBoxContainer from "../SidebarBoxContainer"
5
+ import DescriptionIcon from "@mui/icons-material/Description"
6
+ import { styled } from "@mui/material/styles"
7
+ import { createTheme, ThemeProvider } from "@mui/material/styles"
8
+ import { grey } from "@mui/material/colors"
9
+
10
+ type MetadataItemProps = {
11
+ name: string,
12
+ value: string,
13
+ imageIndex: number,
14
+ metadataId?: string,
15
+ onChange: ({ name: string, value: String, imageIndex: number }) => void
16
+ }
17
+
18
+ const MetadataItemDiv = styled("div")(({ theme }) => ({
19
+ display: "flex",
20
+ flexDirection: "row",
21
+ marginBottom: ".5em",
22
+ "& > label": {
23
+ fontSize: "1rem",
24
+ marginBottom: ".5em",
25
+ textTransform: "capitalize",
26
+ wordWrap: "break-word",
27
+ },
28
+ label: {
29
+ width: "50%",
30
+ },
31
+ select: {
32
+ width: "100%",
33
+ },
34
+ }))
35
+
36
+ const MetadataItem = ({ name, value, metadataId, imageIndex, groupId, onChange, metadataConfig = {} }: MetadataItemProps) => {
37
+ const handleChange = e => {
38
+ e.preventDefault()
39
+ const { name, value } = e.target
40
+ onChange({
41
+ name,
42
+ value,
43
+ imageIndex,
44
+ groupId,
45
+ metadataId
46
+ })
47
+ }
48
+
49
+ return (
50
+ <MetadataItemDiv>
51
+ <label for={name}>{name}</label>
52
+ <div style={{
53
+ width: "50%",
54
+ }}>
55
+ {
56
+ metadataConfig?.selectable !== true && (
57
+ <>
58
+ <input type="text" value={value} name={name} onChange={handleChange} id={name} list={`${name}-list`} style={{ width: "100%" }} />
59
+ <datalist id={`${name}-list`}>
60
+ {
61
+ metadataConfig?.options?.map(opt => {
62
+ if (opt.value && opt.label) {
63
+ return <option key={opt.value} value={opt.value}>{opt.label}</option>
64
+ }
65
+ return <option key={opt} value={opt}></option>
66
+ })
67
+ }
68
+ </datalist>
69
+ </>
70
+ )
71
+ }
72
+ {
73
+ metadataConfig?.selectable === true && (
74
+ <select name={name} id={name} onChange={handleChange} style={{ width: '100%' }}>
75
+ {
76
+ metadataConfig?.options?.map(opt => {
77
+ if (opt.value && opt.label) {
78
+ return <option key={opt.value} value={opt.value} selected={opt.value === value}>{opt.label}</option>
79
+ }
80
+ return <option key={opt} value={opt}></option>
81
+ })
82
+ }
83
+ </select>
84
+ )
85
+ }
86
+
87
+ </div>
88
+ </MetadataItemDiv>
89
+ )
90
+ }
91
+
92
+ const MetadataList = ({ title, metadata, imageIndex, onMetadataChange, metadataConfigs = [], groupId }) => (
93
+ <div>
94
+ <h2>{title}</h2>
95
+ {
96
+ metadata && metadata.map(({ key, value, metadataId }) => (
97
+ <MetadataItem name={key} value={value} imageIndex={imageIndex} metadataId={metadataId} groupId={groupId} onChange={onMetadataChange} metadataConfig={metadataConfigs.find(i => i.key === key)} />
98
+ ))
99
+ }
100
+ </div>
101
+ )
102
+
103
+ const theme = createTheme()
104
+ const DivContainer = styled("div")(({ theme }) => ({
105
+ paddingLeft: 16,
106
+ paddingRight: 16,
107
+ fontSize: 12,
108
+ "& h1": { fontSize: 18 },
109
+ "& h2": { fontSize: 14 },
110
+ "& h3": { fontSize: 12 },
111
+ "& h4": { fontSize: 12 },
112
+ "& h5": { fontSize: 12 },
113
+ "& h6": { fontSize: 12 },
114
+ "& p": { fontSize: 12 },
115
+ "& a": {},
116
+ "& img": { width: "100%" },
117
+ }))
118
+
119
+ export const MetadataEditorSidebarBox = ({ state, onMetadataChange }) => {
120
+ const metadataConfigs = state.metadataConfigs || [];
121
+ const selectedPhotoMetadata = state?.images[state.selectedImage]?.metadata;
122
+ let selectedGroupId = state?.images[state.selectedImage]?.regions?.find(r => r.highlighted === true)?.groupId;
123
+ let articleMetadata = []; // example: [{key: "previousArticleId", value "123-123-123-123-123"}]
124
+
125
+ if (selectedGroupId !== undefined) {
126
+ const articleMetadataRegion = state?.images[state.selectedImage].regions.find(r => r.cls === 'metadata' && `${r.groupId}` === selectedGroupId)
127
+ if (articleMetadataRegion) {
128
+ const metadata = JSON.parse(articleMetadataRegion.text)
129
+ articleMetadata = metadata
130
+ }
131
+ }
132
+
133
+ return (
134
+ <ThemeProvider theme={theme}>
135
+ <SidebarBoxContainer
136
+ title="Metadata"
137
+ icon={<DescriptionIcon style={{ color: grey[700] }} />}
138
+ expandedByDefault={true}
139
+ >
140
+ <DivContainer style={{
141
+ height: "600px",
142
+ }}>
143
+ {
144
+ articleMetadata.length > 0 && (
145
+ <MetadataList title="Article" metadata={articleMetadata} imageIndex={state.selectedImage} groupId={selectedGroupId} onMetadataChange={onMetadataChange} metadataConfigs={metadataConfigs.filter(mfc => mfc.level === 'photo_metadata-engine')} />
146
+ )
147
+ }
148
+ {
149
+ selectedPhotoMetadata && (
150
+ <MetadataList title="Page" metadata={selectedPhotoMetadata} imageIndex={state.selectedImage} onMetadataChange={onMetadataChange} metadataConfigs={metadataConfigs.filter(mfc => mfc.level === 'photo')} />
151
+ )
152
+ }
153
+ <MetadataList title="Issue" metadata={state.albumMetadata} onMetadataChange={onMetadataChange} id="metadata-album" metadataConfigs={metadataConfigs.filter(mfc => mfc.level === 'album')} />
154
+ </DivContainer>
155
+ </SidebarBoxContainer>
156
+ </ThemeProvider>
157
+ )
158
+ }
159
+
160
+ export default memo(MetadataEditorSidebarBox)