box-annotations 5.2.1-beta.0 → 5.2.1-beta.11
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/dist/annotations.css +3 -4
- package/dist/annotations.js +1 -1
- package/dist/annotations.js.LICENSE.txt +3 -43
- package/i18n/en-US.js +4 -0
- package/i18n/en-US.properties +8 -0
- package/i18n/json/src/components/BoundingBoxHighlight/messages.json +1 -0
- package/i18n/json/src/components/Popups/messages.json +1 -1
- package/package.json +31 -15
- package/src/@types/events.ts +4 -0
- package/src/@types/global.ts +0 -9
- package/src/@types/model.ts +5 -0
- package/src/BoxAnnotations.ts +5 -2
- package/src/adapters/threadedAnnotationsAdapters.ts +155 -0
- package/src/api/types.ts +28 -1
- package/src/boundingBoxHighlight/BoundingBoxHighlightContainer.tsx +33 -0
- package/src/boundingBoxHighlight/BoundingBoxHighlightManager.tsx +19 -0
- package/src/boundingBoxHighlight/index.ts +1 -0
- package/src/common/BaseAnnotator.scss +2 -1
- package/src/common/BaseAnnotator.ts +129 -0
- package/src/common/DeselectListener.tsx +3 -1
- package/src/components/BoundingBoxHighlight/BoundingBoxHighlightList.scss +8 -0
- package/src/components/BoundingBoxHighlight/BoundingBoxHighlightList.tsx +67 -0
- package/src/components/BoundingBoxHighlight/BoundingBoxHighlightNav.scss +73 -0
- package/src/components/BoundingBoxHighlight/BoundingBoxHighlightNav.tsx +68 -0
- package/src/components/BoundingBoxHighlight/BoundingBoxHighlightRect.scss +22 -0
- package/src/components/BoundingBoxHighlight/BoundingBoxHighlightRect.tsx +77 -0
- package/src/components/BoundingBoxHighlight/index.ts +4 -0
- package/src/components/BoundingBoxHighlight/messages.ts +14 -0
- package/src/components/Popups/PopupReply.tsx +9 -11
- package/src/components/Popups/PopupV2.scss +28 -0
- package/src/components/Popups/PopupV2.tsx +322 -0
- package/src/components/Popups/messages.ts +10 -0
- package/src/document/DocumentAnnotator.ts +76 -8
- package/src/drawing/DrawingAnnotations.tsx +3 -0
- package/src/drawing/DrawingAnnotationsContainer.tsx +3 -0
- package/src/drawing/DrawingCreator.tsx +9 -16
- package/src/drawing/DrawingTarget.tsx +1 -0
- package/src/highlight/HighlightTarget.tsx +1 -0
- package/src/icons/ChevronLeft.tsx +24 -0
- package/src/icons/ChevronRight.tsx +24 -0
- package/src/image/ImageAnnotator.ts +48 -2
- package/src/media/MediaAnnotator.ts +1 -1
- package/src/popup/PopupContainer.tsx +14 -1
- package/src/popup/PopupLayer.tsx +68 -21
- package/src/popup/PopupManager.tsx +21 -3
- package/src/region/RegionAnnotation.tsx +1 -0
- package/src/region/RegionCreation.tsx +4 -7
- package/src/region/RegionCreationContainer.tsx +2 -2
- package/src/region/RegionCreator.tsx +9 -17
- package/src/store/annotations/actions.ts +78 -3
- package/src/store/annotations/reducer.ts +23 -1
- package/src/store/boundingBoxHighlights/actions.ts +6 -0
- package/src/store/boundingBoxHighlights/index.ts +4 -0
- package/src/store/boundingBoxHighlights/reducer.ts +33 -0
- package/src/store/boundingBoxHighlights/selectors.ts +12 -0
- package/src/store/boundingBoxHighlights/types.ts +13 -0
- package/src/store/createRootReducer.ts +2 -0
- package/src/store/eventing/boundingBoxHighlightNav.ts +13 -0
- package/src/store/eventing/middleware.ts +3 -0
- package/src/store/index.ts +1 -0
- package/src/store/options/actions.ts +2 -0
- package/src/store/options/reducer.ts +9 -2
- package/src/store/options/selectors.ts +4 -0
- package/src/store/options/types.ts +6 -0
- package/src/store/types.ts +2 -0
- package/src/utils/rotate.ts +43 -0
- package/src/utils/scroll.ts +8 -3
|
@@ -12,9 +12,9 @@ object-assign
|
|
|
12
12
|
|
|
13
13
|
/*!
|
|
14
14
|
* Box Annotations
|
|
15
|
-
*
|
|
15
|
+
*
|
|
16
16
|
* Copyright 2016-present Box, Inc. All Rights Reserved.
|
|
17
|
-
*
|
|
17
|
+
*
|
|
18
18
|
* This source code is licensed under the Box Software License Agreement found
|
|
19
19
|
* in the LICENSE file in the root directory of this source tree. Additional
|
|
20
20
|
* third party license disclosures can be found in the THIRD_PARTY_LICENSES
|
|
@@ -30,46 +30,6 @@ object-assign
|
|
|
30
30
|
* Licensed under MIT License
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
|
-
/**
|
|
34
|
-
* @license React
|
|
35
|
-
* react-dom.production.min.js
|
|
36
|
-
*
|
|
37
|
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
38
|
-
*
|
|
39
|
-
* This source code is licensed under the MIT license found in the
|
|
40
|
-
* LICENSE file in the root directory of this source tree.
|
|
41
|
-
*/
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* @license React
|
|
45
|
-
* react.production.min.js
|
|
46
|
-
*
|
|
47
|
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
48
|
-
*
|
|
49
|
-
* This source code is licensed under the MIT license found in the
|
|
50
|
-
* LICENSE file in the root directory of this source tree.
|
|
51
|
-
*/
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* @license React
|
|
55
|
-
* scheduler.production.min.js
|
|
56
|
-
*
|
|
57
|
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
58
|
-
*
|
|
59
|
-
* This source code is licensed under the MIT license found in the
|
|
60
|
-
* LICENSE file in the root directory of this source tree.
|
|
61
|
-
*/
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* @license React
|
|
65
|
-
* use-sync-external-store-with-selector.production.min.js
|
|
66
|
-
*
|
|
67
|
-
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
68
|
-
*
|
|
69
|
-
* This source code is licensed under the MIT license found in the
|
|
70
|
-
* LICENSE file in the root directory of this source tree.
|
|
71
|
-
*/
|
|
72
|
-
|
|
73
33
|
/** @license React v0.18.0
|
|
74
34
|
* scheduler.production.min.js
|
|
75
35
|
*
|
|
@@ -79,7 +39,7 @@ object-assign
|
|
|
79
39
|
* LICENSE file in the root directory of this source tree.
|
|
80
40
|
*/
|
|
81
41
|
|
|
82
|
-
/** @license React v16.
|
|
42
|
+
/** @license React v16.13.1
|
|
83
43
|
* react-is.production.min.js
|
|
84
44
|
*
|
|
85
45
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
package/i18n/en-US.js
CHANGED
|
@@ -4,8 +4,12 @@ export default {
|
|
|
4
4
|
"ba.annotationsLoadError": "We’re sorry, the annotations failed to load for this file.",
|
|
5
5
|
"ba.annotationsPost": "Post",
|
|
6
6
|
"ba.annotationsSave": "Save",
|
|
7
|
+
"ba.boundingBoxHighlight.viewNextReference": "View next reference",
|
|
8
|
+
"ba.boundingBoxHighlight.viewPrevReference": "View previous reference",
|
|
7
9
|
"ba.popup.reply.comment": "Comment",
|
|
8
10
|
"ba.popup.reply.field": "Type a comment",
|
|
11
|
+
"ba.popup.reply.mentionLoading": "Loading users...",
|
|
12
|
+
"ba.popup.reply.mentionSelector": "Mention a collaborator",
|
|
9
13
|
"ba.popups.cancel": "Cancel",
|
|
10
14
|
"ba.popups.drawing.addComment": "Add Comment",
|
|
11
15
|
"ba.popups.drawing.delete": "Delete",
|
package/i18n/en-US.properties
CHANGED
|
@@ -8,10 +8,18 @@ ba.annotationsLoadError = We’re sorry, the annotations failed to load for this
|
|
|
8
8
|
ba.annotationsPost = Post
|
|
9
9
|
# Label for the save button
|
|
10
10
|
ba.annotationsSave = Save
|
|
11
|
+
# Aria label for the button to view the next reference
|
|
12
|
+
ba.boundingBoxHighlight.viewNextReference = View next reference
|
|
13
|
+
# Aria label for the button to view the previous reference
|
|
14
|
+
ba.boundingBoxHighlight.viewPrevReference = View previous reference
|
|
11
15
|
# Aria label description for reply popup
|
|
12
16
|
ba.popup.reply.comment = Comment
|
|
13
17
|
# Aria label description for annotation comment field
|
|
14
18
|
ba.popup.reply.field = Type a comment
|
|
19
|
+
# Aria label for mention selector loading state
|
|
20
|
+
ba.popup.reply.mentionLoading = Loading users...
|
|
21
|
+
# Aria role description for mention user selector
|
|
22
|
+
ba.popup.reply.mentionSelector = Mention a collaborator
|
|
15
23
|
# Button label for cancelling the creation of a description, comment, or reply
|
|
16
24
|
ba.popups.cancel = Cancel
|
|
17
25
|
# Button label for adding a comment in the drawing toolbar
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
[{"id":"ba.boundingBoxHighlight.viewNextReference","description":"Aria label for the button to view the next reference","defaultMessage":"View next reference"},{"id":"ba.boundingBoxHighlight.viewPrevReference","description":"Aria label for the button to view the previous reference","defaultMessage":"View previous reference"}]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
[{"id":"ba.popup.reply.comment","description":"Aria label description for reply popup","defaultMessage":"Comment"},{"id":"ba.popup.reply.field","description":"Aria label description for annotation comment field","defaultMessage":"Type a comment"},{"id":"ba.popups.cancel","description":"Button label for cancelling the creation of a description, comment, or reply","defaultMessage":"Cancel"},{"id":"ba.popups.post","description":"Button label for creating a description, comment, or reply","defaultMessage":"Post"},{"id":"ba.popups.drawing.addComment","description":"Button label for adding a comment in the drawing toolbar","defaultMessage":"Add Comment"},{"id":"ba.popups.drawing.delete","description":"Button title for deleting a staged drawing","defaultMessage":"Delete"},{"id":"ba.popups.drawing.redo","description":"Button title for redoing a staged drawing","defaultMessage":"Redo"},{"id":"ba.popups.drawing.undo","description":"Button title for undoing a staged drawing","defaultMessage":"Undo"},{"id":"ba.popups.replyField.placeholder","description":"Placeholder for reply field editor","defaultMessage":"Type a comment..."},{"id":"ba.popups.popupHighlight.promoter","description":"Popup message for highlight promoter","defaultMessage":"Highlight and Comment"},{"id":"ba.popups.popupHighlight.restrictedPrompt","description":"Prompt message when selection crosses multiple pages","defaultMessage":"Comments restricted to single page"},{"id":"ba.popups.popupList.prompt","description":"Prompt message for empty popup list","defaultMessage":"Mention someone to notify them"},{"id":"ba.popups.popupCursor.regionPrompt","description":"Prompt message following cursor in region annotations mode","defaultMessage":"Draw a box to comment"}]
|
|
1
|
+
[{"id":"ba.popup.reply.comment","description":"Aria label description for reply popup","defaultMessage":"Comment"},{"id":"ba.popup.reply.mentionLoading","description":"Aria label for mention selector loading state","defaultMessage":"Loading users..."},{"id":"ba.popup.reply.mentionSelector","description":"Aria role description for mention user selector","defaultMessage":"Mention a collaborator"},{"id":"ba.popup.reply.field","description":"Aria label description for annotation comment field","defaultMessage":"Type a comment"},{"id":"ba.popups.cancel","description":"Button label for cancelling the creation of a description, comment, or reply","defaultMessage":"Cancel"},{"id":"ba.popups.post","description":"Button label for creating a description, comment, or reply","defaultMessage":"Post"},{"id":"ba.popups.drawing.addComment","description":"Button label for adding a comment in the drawing toolbar","defaultMessage":"Add Comment"},{"id":"ba.popups.drawing.delete","description":"Button title for deleting a staged drawing","defaultMessage":"Delete"},{"id":"ba.popups.drawing.redo","description":"Button title for redoing a staged drawing","defaultMessage":"Redo"},{"id":"ba.popups.drawing.undo","description":"Button title for undoing a staged drawing","defaultMessage":"Undo"},{"id":"ba.popups.replyField.placeholder","description":"Placeholder for reply field editor","defaultMessage":"Type a comment..."},{"id":"ba.popups.popupHighlight.promoter","description":"Popup message for highlight promoter","defaultMessage":"Highlight and Comment"},{"id":"ba.popups.popupHighlight.restrictedPrompt","description":"Prompt message when selection crosses multiple pages","defaultMessage":"Comments restricted to single page"},{"id":"ba.popups.popupList.prompt","description":"Prompt message for empty popup list","defaultMessage":"Mention someone to notify them"},{"id":"ba.popups.popupCursor.regionPrompt","description":"Prompt message following cursor in region annotations mode","defaultMessage":"Draw a box to comment"}]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "box-annotations",
|
|
3
|
-
"version": "5.2.1-beta.
|
|
3
|
+
"version": "5.2.1-beta.11",
|
|
4
4
|
"description": "Box Annotations",
|
|
5
5
|
"author": "Box (https://www.box.com/)",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -28,7 +28,13 @@
|
|
|
28
28
|
"@babel/preset-react": "^7.25.9",
|
|
29
29
|
"@babel/preset-typescript": "^7.25.9",
|
|
30
30
|
"@box/frontend": "^10.0.0",
|
|
31
|
+
"@box/blueprint-web": "^14.27.0",
|
|
32
|
+
"@box/blueprint-web-assets": "^4.116.6",
|
|
33
|
+
"@box/collaboration-popover": "^1.61.30",
|
|
31
34
|
"@box/languages": "^1.1.0",
|
|
35
|
+
"@box/readable-time": "^1.40.30",
|
|
36
|
+
"@box/threaded-annotations": "^1.86.0",
|
|
37
|
+
"@box/user-selector": "^1.75.30",
|
|
32
38
|
"@cfaester/enzyme-adapter-react-18": "^0.8.0",
|
|
33
39
|
"@commitlint/cli": "^8.3.5",
|
|
34
40
|
"@commitlint/config-conventional": "^8.2.0",
|
|
@@ -36,6 +42,9 @@
|
|
|
36
42
|
"@formatjs/intl-relativetimeformat": "^4.5.12",
|
|
37
43
|
"@popperjs/core": "^2.4.0",
|
|
38
44
|
"@reduxjs/toolkit": "^1.3.5",
|
|
45
|
+
"@testing-library/dom": "^10.4.1",
|
|
46
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
47
|
+
"@testing-library/react": "^16.3.2",
|
|
39
48
|
"@types/classnames": "^2.2.10",
|
|
40
49
|
"@types/draft-js": "^0.10.40",
|
|
41
50
|
"@types/enzyme": "^3.10.5",
|
|
@@ -47,11 +56,11 @@
|
|
|
47
56
|
"@types/uuid": "^8.3.0",
|
|
48
57
|
"@typescript-eslint/eslint-plugin": "^7.3.1",
|
|
49
58
|
"@typescript-eslint/parser": "^7.3.1",
|
|
50
|
-
"autoprefixer": "^
|
|
59
|
+
"autoprefixer": "^10.4.19",
|
|
51
60
|
"axios": "^0.24.0",
|
|
52
61
|
"babel-eslint": "^10.1.0",
|
|
53
62
|
"babel-jest": "^24.9.0",
|
|
54
|
-
"babel-loader": "^
|
|
63
|
+
"babel-loader": "^9.2.1",
|
|
55
64
|
"babel-plugin-istanbul": "^6.0.0",
|
|
56
65
|
"babel-plugin-react-intl": "^7.5.1",
|
|
57
66
|
"babel-plugin-transform-require-ignore": "^0.1.1",
|
|
@@ -59,9 +68,11 @@
|
|
|
59
68
|
"box-ui-elements": "^20.0.0",
|
|
60
69
|
"circular-dependency-plugin": "^5.2.0",
|
|
61
70
|
"classnames": "^2.2.5",
|
|
71
|
+
"clsx": "^2.1.1",
|
|
62
72
|
"conventional-github-releaser": "^3.1.3",
|
|
63
73
|
"core-js": "^3.38.1",
|
|
64
|
-
"css-loader": "^
|
|
74
|
+
"css-loader": "^7.1.2",
|
|
75
|
+
"css-minimizer-webpack-plugin": "^7.0.4",
|
|
65
76
|
"cypress": "^4.4.1",
|
|
66
77
|
"draft-js": "0.10.5",
|
|
67
78
|
"enzyme": "^3.11.0",
|
|
@@ -87,12 +98,10 @@
|
|
|
87
98
|
"jest-environment-jsdom-sixteen": "^1.0.3",
|
|
88
99
|
"lint-staged": "^9.5.0",
|
|
89
100
|
"lodash": "^4.17.15",
|
|
90
|
-
"mini-css-extract-plugin": "^
|
|
101
|
+
"mini-css-extract-plugin": "^2.10.1",
|
|
91
102
|
"npm-run-all": "^4.1.5",
|
|
92
|
-
"
|
|
93
|
-
"postcss-loader": "^3.0.0",
|
|
103
|
+
"postcss-loader": "^8.1.1",
|
|
94
104
|
"prettier": "^1.19.1",
|
|
95
|
-
"raw-loader": "^4.0.1",
|
|
96
105
|
"react": "18.3.1",
|
|
97
106
|
"react-dom": "18.3.1",
|
|
98
107
|
"react-intl": "6.4.2",
|
|
@@ -102,27 +111,34 @@
|
|
|
102
111
|
"redux": "^4.0.5",
|
|
103
112
|
"regenerator-runtime": "^0.13.9",
|
|
104
113
|
"sass": "^1.64.1",
|
|
105
|
-
"sass-loader": "^
|
|
114
|
+
"sass-loader": "^16.0.4",
|
|
106
115
|
"scroll-into-view-if-needed": "^2.2.24",
|
|
107
|
-
"style-loader": "^
|
|
116
|
+
"style-loader": "^4.0.0",
|
|
108
117
|
"stylelint": "^12.0.0",
|
|
109
118
|
"stylelint-config-rational-order": "^0.1.2",
|
|
110
119
|
"stylelint-config-standard": "^19.0.0",
|
|
111
120
|
"stylelint-order": "^3.1.1",
|
|
112
121
|
"tabbable": "^1.1.3",
|
|
113
|
-
"terser-webpack-plugin": "^4.2.3",
|
|
114
122
|
"typescript": "4.9.5",
|
|
115
123
|
"uuid": "^8.3.1",
|
|
116
124
|
"wait-on": "^4.0.2",
|
|
117
|
-
"webpack": "^
|
|
118
|
-
"webpack-cli": "^
|
|
119
|
-
"webpack-dev-server": "^
|
|
125
|
+
"webpack": "^5.105.4",
|
|
126
|
+
"webpack-cli": "^5.1.4",
|
|
127
|
+
"webpack-dev-server": "^5.2.3",
|
|
120
128
|
"worker-farm": "^1.7.0"
|
|
121
129
|
},
|
|
130
|
+
"peerDependencies": {
|
|
131
|
+
"@box/blueprint-web": "^14.27.0",
|
|
132
|
+
"@box/blueprint-web-assets": "^4.116.6",
|
|
133
|
+
"@box/collaboration-popover": "^1.61.30",
|
|
134
|
+
"@box/readable-time": "^1.40.30",
|
|
135
|
+
"@box/threaded-annotations": "^1.86.0",
|
|
136
|
+
"@box/user-selector": "^1.75.30"
|
|
137
|
+
},
|
|
122
138
|
"scripts": {
|
|
123
139
|
"build": "yarn setup && yarn build:prod:dist",
|
|
124
140
|
"build:i18n": "props2es",
|
|
125
|
-
"build:dev:dist": "LANGUAGE=en-US BABEL_ENV=dev NODE_ENV=dev webpack --config scripts/webpack.config.js --mode development --progress
|
|
141
|
+
"build:dev:dist": "LANGUAGE=en-US BABEL_ENV=dev NODE_ENV=dev webpack --config scripts/webpack.config.js --mode development --progress",
|
|
126
142
|
"build:prod:dist": "LANGUAGE=en-US BABEL_ENV=production NODE_ENV=production webpack --config scripts/webpack.config.js --mode production",
|
|
127
143
|
"clean": "rm -rf dist reports/* i18n/json i18n/*.js",
|
|
128
144
|
"cy:open": "yarn cy:wait; yarn cypress open",
|
package/src/@types/events.ts
CHANGED
|
@@ -9,7 +9,11 @@ enum Event {
|
|
|
9
9
|
ANNOTATIONS_INITIALIZED = 'annotations_initialized',
|
|
10
10
|
ANNOTATIONS_MODE_CHANGE = 'annotations_mode_change',
|
|
11
11
|
COLOR_SET = 'annotations_color_set',
|
|
12
|
+
BOUNDING_BOX_HIGHLIGHTS_SET = 'bounding_box_highlights_set',
|
|
13
|
+
BOUNDING_BOX_HIGHLIGHT_NAVIGATE = 'bounding_box_highlight_navigate',
|
|
14
|
+
BOUNDING_BOX_HIGHLIGHT_SELECT = 'bounding_box_highlight_select',
|
|
12
15
|
VISIBLE_SET = 'annotations_visible_set',
|
|
16
|
+
VIEW_MODE_SET = 'view_mode_set',
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
// Existing legacy events, don't rename
|
package/src/@types/global.ts
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-namespace */
|
|
2
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3
|
-
declare namespace NodeJS {
|
|
4
|
-
interface Global {
|
|
5
|
-
window: any;
|
|
6
|
-
BoxAnnotations: any;
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
|
|
10
1
|
declare module 'box-annotations-locale-data';
|
|
11
2
|
declare module 'box-elements-messages';
|
|
12
3
|
declare module 'box-ui-elements/es/*'; // TODO: Figure out why types don't register properly
|
package/src/@types/model.ts
CHANGED
|
@@ -12,6 +12,11 @@ export interface Annotation {
|
|
|
12
12
|
modified_by: User;
|
|
13
13
|
permissions: Permissions;
|
|
14
14
|
replies?: Array<Reply>;
|
|
15
|
+
resolution?: {
|
|
16
|
+
resolved_at: string;
|
|
17
|
+
resolved_by: User;
|
|
18
|
+
} | null;
|
|
19
|
+
status?: 'open' | 'resolved';
|
|
15
20
|
target: Target;
|
|
16
21
|
type: 'annotation';
|
|
17
22
|
}
|
package/src/BoxAnnotations.ts
CHANGED
|
@@ -19,7 +19,8 @@ type AnnotationsOptions = {
|
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
export type Features = {
|
|
22
|
-
|
|
22
|
+
isThreadedAnnotation?: boolean;
|
|
23
|
+
[key: string]: boolean | undefined;
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
type PreviewOptions = {
|
|
@@ -42,6 +43,8 @@ type ViewerOption = {
|
|
|
42
43
|
|
|
43
44
|
type ViewerOptions = Record<string, ViewerOption>;
|
|
44
45
|
|
|
46
|
+
type GlobalWithBoxAnnotations = typeof globalThis & { BoxAnnotations: typeof BoxAnnotations };
|
|
47
|
+
|
|
45
48
|
/**
|
|
46
49
|
* NAME: The name of the annotator.
|
|
47
50
|
* CONSTRUCTOR: Constructor for the annotator.
|
|
@@ -144,5 +147,5 @@ class BoxAnnotations {
|
|
|
144
147
|
}
|
|
145
148
|
}
|
|
146
149
|
|
|
147
|
-
|
|
150
|
+
(globalThis as GlobalWithBoxAnnotations).BoxAnnotations = BoxAnnotations;
|
|
148
151
|
export default BoxAnnotations;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type { DocumentNodeV2, MentionNodeV2, ParagraphNodeV2, TextMessageTypeV2, TextNodeV2 } from '@box/threaded-annotations';
|
|
2
|
+
|
|
3
|
+
import type { Annotation, Collaborator, Reply, UserMini } from '../@types';
|
|
4
|
+
|
|
5
|
+
const MENTION_REGEX = /@\[(\d+):([^\]]+)\]/g;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Parses a plain-text line into paragraph content nodes.
|
|
9
|
+
* Recognizes @[userId:userName] mention markup and converts to MentionNode / TextNode.
|
|
10
|
+
*/
|
|
11
|
+
const parseLine = (line: string): (MentionNodeV2 | TextNodeV2)[] => {
|
|
12
|
+
const nodes: (MentionNodeV2 | TextNodeV2)[] = [];
|
|
13
|
+
let lastIndex = 0;
|
|
14
|
+
|
|
15
|
+
// Reset regex state since it's global
|
|
16
|
+
MENTION_REGEX.lastIndex = 0;
|
|
17
|
+
|
|
18
|
+
let match = MENTION_REGEX.exec(line);
|
|
19
|
+
while (match !== null) {
|
|
20
|
+
const [fullMatch, userId, userName] = match;
|
|
21
|
+
const { index } = match;
|
|
22
|
+
|
|
23
|
+
if (index > lastIndex) {
|
|
24
|
+
nodes.push({ type: 'text', text: line.slice(lastIndex, index) });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
nodes.push({
|
|
28
|
+
type: 'mention',
|
|
29
|
+
attrs: {
|
|
30
|
+
authorId: '',
|
|
31
|
+
mentionId: userId,
|
|
32
|
+
mentionedUserId: userId,
|
|
33
|
+
mentionedUserName: userName,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
lastIndex = index + fullMatch.length;
|
|
38
|
+
match = MENTION_REGEX.exec(line);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (lastIndex < line.length) {
|
|
42
|
+
nodes.push({ type: 'text', text: line.slice(lastIndex) });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return nodes;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Deserializes plain text with @[userId:userName] mention markup into a TipTap DocumentNode.
|
|
50
|
+
* This is the reverse of serializeMentionMarkup from @box/threaded-annotations.
|
|
51
|
+
*
|
|
52
|
+
* Newlines are treated as paragraph breaks.
|
|
53
|
+
*/
|
|
54
|
+
export const deserializeMentionMarkup = (text: string): DocumentNodeV2 => {
|
|
55
|
+
if (!text) {
|
|
56
|
+
return { type: 'doc', content: [] };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const lines = text.split('\n');
|
|
60
|
+
const content: ParagraphNodeV2[] = lines.map(line => {
|
|
61
|
+
const nodes = parseLine(line);
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
type: 'paragraph',
|
|
65
|
+
...(nodes.length > 0 ? { content: nodes } : {}),
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return { type: 'doc', content };
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Converts a box-annotations Reply to a threaded-annotations TextMessageType.
|
|
74
|
+
*/
|
|
75
|
+
export const replyToTextMessage = (reply: Reply): TextMessageTypeV2 => ({
|
|
76
|
+
author: {
|
|
77
|
+
email: reply.created_by?.login ?? '',
|
|
78
|
+
id: parseInt(reply.created_by?.id ?? '0', 10),
|
|
79
|
+
name: reply.created_by?.name ?? '',
|
|
80
|
+
},
|
|
81
|
+
createdAt: new Date(reply.created_at).getTime(),
|
|
82
|
+
id: reply.id,
|
|
83
|
+
message: deserializeMentionMarkup(reply.message),
|
|
84
|
+
permissions: {
|
|
85
|
+
canDelete: false,
|
|
86
|
+
canEdit: false,
|
|
87
|
+
canReply: true,
|
|
88
|
+
canResolve: false,
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Converts an Annotation's description (root message) to a TextMessageType.
|
|
94
|
+
* The root message gets resolve permission from the annotation's permissions.
|
|
95
|
+
* Falls back to annotation-level fields when the description object is sparse
|
|
96
|
+
* (the list endpoint returns description with only { message }).
|
|
97
|
+
*/
|
|
98
|
+
const descriptionToTextMessage = (
|
|
99
|
+
annotation: Annotation,
|
|
100
|
+
reply: Reply,
|
|
101
|
+
): TextMessageTypeV2 => ({
|
|
102
|
+
author: {
|
|
103
|
+
email: (reply.created_by ?? annotation.created_by)?.login ?? '',
|
|
104
|
+
id: parseInt((reply.created_by ?? annotation.created_by)?.id ?? '0', 10),
|
|
105
|
+
name: (reply.created_by ?? annotation.created_by)?.name ?? '',
|
|
106
|
+
},
|
|
107
|
+
createdAt: new Date(reply.created_at ?? annotation.created_at).getTime(),
|
|
108
|
+
id: reply.id ?? annotation.id,
|
|
109
|
+
message: deserializeMentionMarkup(reply.message),
|
|
110
|
+
permissions: {
|
|
111
|
+
canDelete: annotation.permissions?.can_delete ?? false,
|
|
112
|
+
canEdit: annotation.permissions?.can_edit ?? false,
|
|
113
|
+
canReply: true,
|
|
114
|
+
canResolve: annotation.permissions?.can_resolve ?? false,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Maps a full Annotation (description + replies) to an array of TextMessageType
|
|
120
|
+
* suitable for ThreadedAnnotationsV2.
|
|
121
|
+
*/
|
|
122
|
+
export const annotationToMessages = (annotation: Annotation): TextMessageTypeV2[] => {
|
|
123
|
+
const messages: TextMessageTypeV2[] = [];
|
|
124
|
+
|
|
125
|
+
if (annotation.description) {
|
|
126
|
+
messages.push(descriptionToTextMessage(annotation, annotation.description));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (annotation.replies) {
|
|
130
|
+
annotation.replies.forEach(reply => {
|
|
131
|
+
messages.push(replyToTextMessage(reply));
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return messages;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Converts a box-annotations Collaborator to a @box/user-selector UserContactType.
|
|
140
|
+
*/
|
|
141
|
+
export const collaboratorToUserContact = (collaborator: Collaborator): {
|
|
142
|
+
email: string;
|
|
143
|
+
id: number;
|
|
144
|
+
name: string;
|
|
145
|
+
value: string;
|
|
146
|
+
} => {
|
|
147
|
+
const item = collaborator.item as UserMini | undefined;
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
email: item?.email ?? item?.login ?? '',
|
|
151
|
+
id: parseInt(item?.id ?? collaborator.id, 10),
|
|
152
|
+
name: item?.name ?? collaborator.name,
|
|
153
|
+
value: collaborator.id,
|
|
154
|
+
};
|
|
155
|
+
};
|
package/src/api/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Annotation, Collaborator, NewAnnotation, Permissions, Token } from '../@types';
|
|
1
|
+
import { Annotation, Collaborator, NewAnnotation, Permissions, Reply, Token } from '../@types';
|
|
2
2
|
|
|
3
3
|
export type APICollection<R> = {
|
|
4
4
|
entries: R[];
|
|
@@ -33,6 +33,23 @@ export interface AnnotationsAPI {
|
|
|
33
33
|
errorCallback: (error: APIError) => void,
|
|
34
34
|
): Promise<void>;
|
|
35
35
|
|
|
36
|
+
createAnnotationReply(
|
|
37
|
+
fileId: string | null,
|
|
38
|
+
annotationId: string,
|
|
39
|
+
permissions: Permissions,
|
|
40
|
+
message: string,
|
|
41
|
+
successCallback: (result: Reply) => void,
|
|
42
|
+
errorCallback: (error: APIError) => void,
|
|
43
|
+
): Promise<void>;
|
|
44
|
+
|
|
45
|
+
deleteAnnotation(
|
|
46
|
+
fileId: string | null,
|
|
47
|
+
annotationId: string,
|
|
48
|
+
permissions: Permissions,
|
|
49
|
+
successCallback: () => void,
|
|
50
|
+
errorCallback: (error: APIError) => void,
|
|
51
|
+
): Promise<void>;
|
|
52
|
+
|
|
36
53
|
getAnnotations(
|
|
37
54
|
fileId: string | null,
|
|
38
55
|
fileVersionId: string | null,
|
|
@@ -41,6 +58,16 @@ export interface AnnotationsAPI {
|
|
|
41
58
|
errorCallback: (error: APIError) => void,
|
|
42
59
|
limit?: number,
|
|
43
60
|
shouldFetchAll?: boolean,
|
|
61
|
+
shouldFetchReplies?: boolean,
|
|
62
|
+
): Promise<void>;
|
|
63
|
+
|
|
64
|
+
updateAnnotation(
|
|
65
|
+
fileId: string | null,
|
|
66
|
+
annotationId: string,
|
|
67
|
+
permissions: Permissions,
|
|
68
|
+
payload: { message?: string; status?: string },
|
|
69
|
+
successCallback: (result: Annotation) => void,
|
|
70
|
+
errorCallback: (error: APIError) => void,
|
|
44
71
|
): Promise<void>;
|
|
45
72
|
|
|
46
73
|
destroy(): void;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { connect } from 'react-redux';
|
|
2
|
+
import { BoundingBoxHighlightList } from '../components/BoundingBoxHighlight';
|
|
3
|
+
import withProviders from '../common/withProviders';
|
|
4
|
+
import {
|
|
5
|
+
AppState,
|
|
6
|
+
BoundingBox,
|
|
7
|
+
getBoundingBoxHighlights,
|
|
8
|
+
getBoundingBoxHighlightsForPage,
|
|
9
|
+
getSelectedBoundingBoxHighlightId,
|
|
10
|
+
navigateBoundingBoxHighlightAction,
|
|
11
|
+
setSelectedBoundingBoxHighlightAction,
|
|
12
|
+
} from '../store';
|
|
13
|
+
|
|
14
|
+
export type Props = {
|
|
15
|
+
location: number;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const mapStateToProps = (state: AppState, { location }: Props): {
|
|
19
|
+
allBoundingBoxes: BoundingBox[];
|
|
20
|
+
boundingBoxes: BoundingBox[];
|
|
21
|
+
selectedId: string | null;
|
|
22
|
+
} => ({
|
|
23
|
+
allBoundingBoxes: getBoundingBoxHighlights(state),
|
|
24
|
+
boundingBoxes: getBoundingBoxHighlightsForPage(state, location),
|
|
25
|
+
selectedId: getSelectedBoundingBoxHighlightId(state),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const mapDispatchToProps = {
|
|
29
|
+
onNavigate: navigateBoundingBoxHighlightAction,
|
|
30
|
+
onSelect: setSelectedBoundingBoxHighlightAction,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default connect(mapStateToProps, mapDispatchToProps)(withProviders(BoundingBoxHighlightList));
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as ReactDOM from 'react-dom/client';
|
|
3
|
+
import BaseManager, { Props } from '../common/BaseManager';
|
|
4
|
+
import BoundingBoxHighlightContainer from './BoundingBoxHighlightContainer';
|
|
5
|
+
|
|
6
|
+
export default class BoundingBoxHighlightManager extends BaseManager {
|
|
7
|
+
decorate(): void {
|
|
8
|
+
this.reactEl.classList.add('ba-Layer--boundingBoxHighlight');
|
|
9
|
+
this.reactEl.dataset.testid = 'ba-Layer--boundingBoxHighlight';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
render(props: Props): void {
|
|
13
|
+
if (!this.root) {
|
|
14
|
+
this.root = ReactDOM.createRoot(this.reactEl);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
this.root.render(<BoundingBoxHighlightContainer location={this.location} {...props} />);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as BoundingBoxHighlightManager } from './BoundingBoxHighlightManager';
|