box-annotations 5.3.0 → 5.3.1-beta.1
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 +1 -1
- package/dist/annotations.js +1 -1
- package/dist/annotations.js.LICENSE.txt +0 -9
- package/i18n/bn-IN.js +24 -17
- package/i18n/da-DK.js +24 -17
- package/i18n/de-DE.js +24 -17
- package/i18n/en-AU.js +4 -17
- package/i18n/en-CA.js +2 -18
- package/i18n/en-GB.js +4 -17
- package/i18n/en-US.js +4 -24
- package/i18n/en-x-pseudo.js +6 -0
- package/i18n/es-419.js +24 -17
- package/i18n/es-ES.js +24 -17
- package/i18n/fi-FI.js +24 -17
- package/i18n/fr-CA.js +24 -17
- package/i18n/fr-FR.js +24 -17
- package/i18n/hi-IN.js +24 -17
- package/i18n/it-IT.js +24 -17
- package/i18n/ja-JP.js +2 -18
- package/i18n/ko-KR.js +24 -17
- package/i18n/nb-NO.js +24 -17
- package/i18n/nl-NL.js +24 -17
- package/i18n/pl-PL.js +24 -17
- package/i18n/pt-BR.js +24 -17
- package/i18n/ru-RU.js +24 -17
- package/i18n/sv-SE.js +24 -17
- package/i18n/tr-TR.js +24 -17
- package/i18n/zh-CN.js +24 -17
- package/i18n/zh-TW.js +24 -17
- package/package.json +29 -28
- package/src/BoxAnnotations.ts +1 -1
- package/src/adapters/threadedAnnotationsAdapters.ts +10 -2
- package/src/boundingBoxHighlight/BoundingBoxHighlightContainer.tsx +4 -1
- package/src/common/BaseAnnotator.scss +1 -1
- package/src/common/BaseAnnotator.ts +9 -0
- package/src/common/DeselectListener.tsx +1 -1
- package/src/common/EventEmitter.ts +11 -3
- package/src/components/BoundingBoxHighlight/BoundingBoxHighlightNav.scss +3 -3
- package/src/components/BoundingBoxHighlight/BoundingBoxHighlightRect.scss +11 -6
- package/src/components/Popups/PopupBase.scss +2 -2
- package/src/components/Popups/PopupDrawingToolbar.scss +4 -4
- package/src/components/Popups/PopupList.scss +1 -1
- package/src/components/Popups/PopupV2.scss +2 -2
- package/src/components/Popups/PopupV2.tsx +62 -44
- package/src/components/ReplyForm/ReplyForm.tsx +1 -8
- package/src/constants.ts +2 -3
- package/src/document/DocumentAnnotator.ts +54 -14
- package/src/document/docUtil.ts +12 -2
- package/src/drawing/DrawingAnnotations.tsx +24 -24
- package/src/drawing/DrawingCursor.ts +2 -1
- package/src/drawing/DrawingManager.tsx +9 -1
- package/src/highlight/HighlightAnnotations.tsx +23 -22
- package/src/highlight/HighlightCreator.scss +9 -2
- package/src/media/MediaAnnotator.ts +38 -16
- package/src/popup/PopupLayer.tsx +1 -0
- package/src/region/RegionAnnotations.tsx +2 -3
- package/src/region/RegionCreation.tsx +8 -4
- package/src/region/RegionCreationContainer.tsx +3 -0
- package/src/region/RegionCreationManager.tsx +8 -1
- package/src/region/RegionCreator.scss +9 -3
- package/src/region/RegionManager.tsx +8 -1
- package/src/region/RegionRect.scss +17 -9
- package/src/store/annotations/actions.ts +88 -104
- package/src/store/annotations/reducer.ts +6 -4
- package/src/store/creator/selectors.ts +6 -6
- package/src/store/eventing/create.ts +4 -2
- package/src/store/eventing/delete.ts +4 -5
- package/src/store/eventing/middleware.ts +13 -11
- package/src/store/eventing/replyCreate.ts +6 -10
- package/src/store/eventing/replyDelete.ts +5 -9
- package/src/store/eventing/replyUpdate.ts +6 -10
- package/src/store/eventing/update.ts +5 -6
- package/src/store/highlight/actions.ts +43 -41
- package/src/test-utils/videoAnnotations.tsx +11 -11
- package/src/utils/useVideoTiming.ts +9 -13
- package/i18n/bn-IN.properties +0 -32
- package/i18n/da-DK.properties +0 -32
- package/i18n/de-DE.properties +0 -32
- package/i18n/en-AU.properties +0 -32
- package/i18n/en-CA.properties +0 -32
- package/i18n/en-GB.properties +0 -32
- package/i18n/en-US.properties +0 -44
- package/i18n/en-x-pseudo.properties +0 -32
- package/i18n/es-419.properties +0 -32
- package/i18n/es-ES.properties +0 -32
- package/i18n/fi-FI.properties +0 -32
- package/i18n/fr-CA.properties +0 -32
- package/i18n/fr-FR.properties +0 -32
- package/i18n/hi-IN.properties +0 -32
- package/i18n/it-IT.properties +0 -32
- package/i18n/ja-JP.properties +0 -32
- package/i18n/json/src/components/BoundingBoxHighlight/messages.json +0 -1
- package/i18n/json/src/components/Popups/messages.json +0 -1
- package/i18n/json/src/messages.json +0 -1
- package/i18n/ko-KR.properties +0 -32
- package/i18n/nb-NO.properties +0 -32
- package/i18n/nl-NL.properties +0 -32
- package/i18n/pl-PL.properties +0 -32
- package/i18n/pt-BR.properties +0 -32
- package/i18n/ru-RU.properties +0 -32
- package/i18n/sv-SE.properties +0 -32
- package/i18n/tr-TR.properties +0 -32
- package/i18n/zh-CN.properties +0 -32
- package/i18n/zh-TW.properties +0 -32
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
$ba-RegionRect-color: $bdl-yellorange;
|
|
4
4
|
$ba-RegionRect-bgColor--default: rgba($ba-RegionRect-color, 0); // Default color uses zero alpha value for transition
|
|
5
|
-
$ba-RegionRect-bgColor--hover: rgba($ba-RegionRect-color, .1);
|
|
5
|
+
$ba-RegionRect-bgColor--hover: rgba($ba-RegionRect-color, 0.1);
|
|
6
6
|
$ba-RegionRect-bgColor--active: rgba($ba-RegionRect-color, 0);
|
|
7
7
|
$ba-RegionRect-transitionDelay: 25ms;
|
|
8
8
|
$ba-RegionRect-transitionDuration: 200ms;
|
|
@@ -21,29 +21,37 @@ $ba-RegionRect-transitionDuration: 200ms;
|
|
|
21
21
|
|
|
22
22
|
&::after {
|
|
23
23
|
position: absolute;
|
|
24
|
-
|
|
25
|
-
right: $border-size-outer;
|
|
26
|
-
bottom: $border-size-outer;
|
|
27
|
-
left: $border-size-outer;
|
|
24
|
+
inset: $border-size-outer;
|
|
28
25
|
display: block;
|
|
29
26
|
background-color: $ba-RegionRect-bgColor--default;
|
|
30
27
|
border-radius: $border-radius;
|
|
31
|
-
box-shadow:
|
|
32
|
-
|
|
28
|
+
box-shadow:
|
|
29
|
+
0 0 0 $border-size-inner rgba($white, 1),
|
|
30
|
+
0 0 0 $border-size-outer rgba($ba-RegionRect-color, 0.6),
|
|
31
|
+
0 0 0 0 rgb(0 0 0 / 0%);
|
|
32
|
+
transition:
|
|
33
|
+
background-color $ba-RegionRect-transitionDuration ease,
|
|
34
|
+
box-shadow $ba-RegionRect-transitionDuration ease;
|
|
33
35
|
content: '';
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
&:hover {
|
|
37
39
|
&::after {
|
|
38
40
|
background-color: $ba-RegionRect-bgColor--hover;
|
|
39
|
-
box-shadow:
|
|
41
|
+
box-shadow:
|
|
42
|
+
0 0 0 $border-size-inner rgba($white, 1),
|
|
43
|
+
0 0 0 $border-size-outer rgba($ba-RegionRect-color, 1),
|
|
44
|
+
0 8px 16px 0 rgb(0 0 0 / 10%);
|
|
40
45
|
}
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
&.is-active {
|
|
44
49
|
&::after {
|
|
45
50
|
background-color: $ba-RegionRect-bgColor--active;
|
|
46
|
-
box-shadow:
|
|
51
|
+
box-shadow:
|
|
52
|
+
0 0 0 $border-size-inner rgba($ba-RegionRect-color, 1),
|
|
53
|
+
0 0 0 $border-size-outer rgba($ba-RegionRect-color, 1),
|
|
54
|
+
0 8px 52px 0 rgb(0 0 0 / 20%);
|
|
47
55
|
transition-delay: $ba-RegionRect-transitionDelay;
|
|
48
56
|
}
|
|
49
57
|
}
|
|
@@ -53,27 +53,24 @@ export const createReplyAction = createAsyncThunk<
|
|
|
53
53
|
{ annotationId: string; reply: Reply },
|
|
54
54
|
{ annotationId: string; message: string },
|
|
55
55
|
AppThunkAPI
|
|
56
|
-
>(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const annotation = getAnnotation(state, annotationId);
|
|
64
|
-
const permissions = { ...filePermissions, ...annotation?.permissions };
|
|
56
|
+
>('CREATE_REPLY', async ({ annotationId, message }, { extra, getState, signal }) => {
|
|
57
|
+
const client = extra.api.getAnnotationsAPI();
|
|
58
|
+
const state = getState();
|
|
59
|
+
const fileId = getFileId(state);
|
|
60
|
+
const filePermissions = getPermissions(state);
|
|
61
|
+
const annotation = getAnnotation(state, annotationId);
|
|
62
|
+
const permissions = { ...filePermissions, ...annotation?.permissions };
|
|
65
63
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
signal.addEventListener('abort', () => {
|
|
65
|
+
client.destroy();
|
|
66
|
+
});
|
|
69
67
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
const reply = await new Promise<Reply>((resolve, reject) => {
|
|
69
|
+
client.createAnnotationReply(fileId, annotationId, permissions, message, resolve, reject);
|
|
70
|
+
});
|
|
73
71
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
);
|
|
72
|
+
return { annotationId, reply };
|
|
73
|
+
});
|
|
77
74
|
|
|
78
75
|
export const deleteAnnotationAction = createAsyncThunk<string, string, AppThunkAPI>(
|
|
79
76
|
'DELETE_ANNOTATION',
|
|
@@ -101,97 +98,88 @@ export const updateAnnotationAction = createAsyncThunk<
|
|
|
101
98
|
Annotation,
|
|
102
99
|
{ annotationId: string; payload: { message?: string; status?: string } },
|
|
103
100
|
AppThunkAPI
|
|
104
|
-
>(
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
});
|
|
121
|
-
},
|
|
122
|
-
);
|
|
101
|
+
>('UPDATE_ANNOTATION', async ({ annotationId, payload }, { extra, getState, signal }) => {
|
|
102
|
+
const client = extra.api.getAnnotationsAPI();
|
|
103
|
+
const state = getState();
|
|
104
|
+
const fileId = getFileId(state);
|
|
105
|
+
const filePermissions = getPermissions(state);
|
|
106
|
+
const existingAnnotation = getAnnotation(state, annotationId);
|
|
107
|
+
const permissions = { ...filePermissions, ...existingAnnotation?.permissions };
|
|
108
|
+
|
|
109
|
+
signal.addEventListener('abort', () => {
|
|
110
|
+
client.destroy();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return new Promise<Annotation>((resolve, reject) => {
|
|
114
|
+
client.updateAnnotation(fileId, annotationId, permissions, payload, resolve, reject);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
123
117
|
|
|
124
118
|
export const updateReplyAction = createAsyncThunk<
|
|
125
119
|
{ annotationId: string; reply: Reply },
|
|
126
120
|
{ annotationId: string; replyId: string; payload: { message?: string; status?: string } },
|
|
127
121
|
AppThunkAPI
|
|
128
|
-
>(
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
122
|
+
>('UPDATE_REPLY', async ({ annotationId, replyId, payload }, { extra, getState, signal }) => {
|
|
123
|
+
const client = extra.api.getThreadedCommentsAPI();
|
|
124
|
+
const state = getState();
|
|
125
|
+
const fileId = getFileId(state);
|
|
126
|
+
const annotation = getAnnotation(state, annotationId);
|
|
127
|
+
const reply = annotation?.replies?.find(r => r.id === replyId);
|
|
128
|
+
|
|
129
|
+
if (!reply) {
|
|
130
|
+
throw new Error(`updateReplyAction: reply ${replyId} not found on annotation ${annotationId}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
signal.addEventListener('abort', () => {
|
|
134
|
+
client.destroy();
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const updated = await new Promise<Reply>((resolve, reject) => {
|
|
138
|
+
client.updateComment({
|
|
139
|
+
commentId: replyId,
|
|
140
|
+
errorCallback: reject,
|
|
141
|
+
fileId,
|
|
142
|
+
message: payload.message,
|
|
143
|
+
permissions: reply.permissions ?? {},
|
|
144
|
+
status: payload.status,
|
|
145
|
+
successCallback: resolve,
|
|
143
146
|
});
|
|
147
|
+
});
|
|
144
148
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
commentId: replyId,
|
|
148
|
-
errorCallback: reject,
|
|
149
|
-
fileId,
|
|
150
|
-
message: payload.message,
|
|
151
|
-
permissions: reply.permissions ?? {},
|
|
152
|
-
status: payload.status,
|
|
153
|
-
successCallback: resolve,
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
return { annotationId, reply: updated };
|
|
158
|
-
},
|
|
159
|
-
);
|
|
149
|
+
return { annotationId, reply: updated };
|
|
150
|
+
});
|
|
160
151
|
|
|
161
152
|
export const deleteReplyAction = createAsyncThunk<
|
|
162
153
|
{ annotationId: string; replyId: string },
|
|
163
154
|
{ annotationId: string; replyId: string },
|
|
164
155
|
AppThunkAPI
|
|
165
|
-
>(
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
permissions: reply.permissions ?? {},
|
|
188
|
-
successCallback: resolve,
|
|
189
|
-
});
|
|
156
|
+
>('DELETE_REPLY', async ({ annotationId, replyId }, { extra, getState, signal }) => {
|
|
157
|
+
const client = extra.api.getThreadedCommentsAPI();
|
|
158
|
+
const state = getState();
|
|
159
|
+
const fileId = getFileId(state);
|
|
160
|
+
const annotation = getAnnotation(state, annotationId);
|
|
161
|
+
const reply = annotation?.replies?.find(r => r.id === replyId);
|
|
162
|
+
|
|
163
|
+
if (!reply) {
|
|
164
|
+
throw new Error(`deleteReplyAction: reply ${replyId} not found on annotation ${annotationId}`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
signal.addEventListener('abort', () => {
|
|
168
|
+
client.destroy();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
await new Promise<void>((resolve, reject) => {
|
|
172
|
+
client.deleteComment({
|
|
173
|
+
commentId: replyId,
|
|
174
|
+
errorCallback: reject,
|
|
175
|
+
fileId,
|
|
176
|
+
permissions: reply.permissions ?? {},
|
|
177
|
+
successCallback: resolve,
|
|
190
178
|
});
|
|
179
|
+
});
|
|
191
180
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
);
|
|
181
|
+
return { annotationId, replyId };
|
|
182
|
+
});
|
|
195
183
|
|
|
196
184
|
export type SidebarAnnotationUpdatePayload = Partial<Annotation> & { id: string };
|
|
197
185
|
export type SidebarReplyMutationPayload = { annotationId: string; reply: Reply };
|
|
@@ -200,16 +188,12 @@ export type SidebarReplyDeletePayload = { annotationId: string; replyId: string
|
|
|
200
188
|
export const applySidebarAnnotationUpdateAction = createAction<SidebarAnnotationUpdatePayload>(
|
|
201
189
|
'APPLY_SIDEBAR_ANNOTATION_UPDATE',
|
|
202
190
|
);
|
|
203
|
-
export const applySidebarReplyCreateAction = createAction<SidebarReplyMutationPayload>(
|
|
204
|
-
|
|
205
|
-
);
|
|
206
|
-
export const applySidebarReplyDeleteAction = createAction<SidebarReplyDeletePayload>(
|
|
207
|
-
'APPLY_SIDEBAR_REPLY_DELETE',
|
|
208
|
-
);
|
|
209
|
-
export const applySidebarReplyUpdateAction = createAction<SidebarReplyMutationPayload>(
|
|
210
|
-
'APPLY_SIDEBAR_REPLY_UPDATE',
|
|
211
|
-
);
|
|
191
|
+
export const applySidebarReplyCreateAction = createAction<SidebarReplyMutationPayload>('APPLY_SIDEBAR_REPLY_CREATE');
|
|
192
|
+
export const applySidebarReplyDeleteAction = createAction<SidebarReplyDeletePayload>('APPLY_SIDEBAR_REPLY_DELETE');
|
|
193
|
+
export const applySidebarReplyUpdateAction = createAction<SidebarReplyMutationPayload>('APPLY_SIDEBAR_REPLY_UPDATE');
|
|
212
194
|
|
|
213
195
|
export const removeAnnotationAction = createAction<string>('REMOVE_ANNOTATION');
|
|
214
196
|
export const setActiveAnnotationIdAction = createAction<string | null>('SET_ACTIVE_ANNOTATION_ID');
|
|
197
|
+
// Clears activeId without emitting ACTIVE_CHANGE.
|
|
198
|
+
export const clearActiveAnnotationIdAction = createAction('CLEAR_ACTIVE_ANNOTATION_ID');
|
|
215
199
|
export const setIsInitialized = createAction('SET_IS_INITIALIZED');
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
applySidebarReplyCreateAction,
|
|
7
7
|
applySidebarReplyDeleteAction,
|
|
8
8
|
applySidebarReplyUpdateAction,
|
|
9
|
+
clearActiveAnnotationIdAction,
|
|
9
10
|
createAnnotationAction,
|
|
10
11
|
createReplyAction,
|
|
11
12
|
deleteAnnotationAction,
|
|
@@ -22,6 +23,7 @@ import { setViewModeAction } from '../options/actions';
|
|
|
22
23
|
const activeAnnotationId = createReducer<AnnotationsState['activeId']>(null, builder =>
|
|
23
24
|
builder
|
|
24
25
|
/* Preview will set the active ID with a an event which will trigger the url change */
|
|
26
|
+
.addCase(clearActiveAnnotationIdAction, () => null)
|
|
25
27
|
.addCase(createAnnotationAction.fulfilled, () => null)
|
|
26
28
|
.addCase(deleteAnnotationAction.fulfilled, (state, { payload: id }) => (state === id ? null : state))
|
|
27
29
|
.addCase(removeAnnotationAction, (state, { payload: id }) => (state === id ? null : state))
|
|
@@ -37,7 +39,9 @@ const annotationsAllIds = createReducer<AnnotationsState['allIds']>([], builder
|
|
|
37
39
|
.addCase(createAnnotationAction.fulfilled, (state, { payload: { id } }) => {
|
|
38
40
|
state.push(id);
|
|
39
41
|
})
|
|
40
|
-
.addCase(deleteAnnotationAction.fulfilled, (state, { payload: id }) =>
|
|
42
|
+
.addCase(deleteAnnotationAction.fulfilled, (state, { payload: id }) =>
|
|
43
|
+
state.filter(annotationId => annotationId !== id),
|
|
44
|
+
)
|
|
41
45
|
.addCase(removeAnnotationAction, (state, { payload: id }) => state.filter(annotationId => annotationId !== id))
|
|
42
46
|
.addCase(fetchAnnotationsAction.fulfilled, (state, { payload }) => {
|
|
43
47
|
payload.entries.forEach(({ id }) => state.indexOf(id) === -1 && state.push(id));
|
|
@@ -67,9 +71,7 @@ const annotationsById = createReducer<AnnotationsState['byId']>({}, builder =>
|
|
|
67
71
|
.addCase(updateReplyAction.fulfilled, (state, { payload: { annotationId, reply } }) => {
|
|
68
72
|
const annotation = state[annotationId];
|
|
69
73
|
if (annotation && annotation.replies) {
|
|
70
|
-
annotation.replies = annotation.replies.map(existing =>
|
|
71
|
-
existing.id === reply.id ? reply : existing,
|
|
72
|
-
);
|
|
74
|
+
annotation.replies = annotation.replies.map(existing => (existing.id === reply.id ? reply : existing));
|
|
73
75
|
}
|
|
74
76
|
})
|
|
75
77
|
.addCase(deleteReplyAction.fulfilled, (state, { payload: { annotationId, replyId } }) => {
|
|
@@ -11,13 +11,13 @@ export const getCreatorStaged = (state: State): CreatorItem | null => state.crea
|
|
|
11
11
|
export const getCreatorStagedForLocation = (state: State, location: number): CreatorItem | null => {
|
|
12
12
|
const staged = getCreatorStaged(state);
|
|
13
13
|
// The location is typically a page and this selector was originally meant to only return the staged annotation
|
|
14
|
-
// (those that have been drawn but not saved) that belong to the page specified by the location. For documents,
|
|
15
|
-
// the annotator creates new sets of managers(highlights, drawings, regions) for each page with the current
|
|
16
|
-
// page number being the location e.g. page 4 of 10. This selector prevents a staged annotation from staying on
|
|
17
|
-
// the screen when a user navigates to a different page. By default, the location value for managers is 1 which is
|
|
14
|
+
// (those that have been drawn but not saved) that belong to the page specified by the location. For documents,
|
|
15
|
+
// the annotator creates new sets of managers(highlights, drawings, regions) for each page with the current
|
|
16
|
+
// page number being the location e.g. page 4 of 10. This selector prevents a staged annotation from staying on
|
|
17
|
+
// the screen when a user navigates to a different page. By default, the location value for managers is 1 which is
|
|
18
18
|
// why this selector works for images. Video annotations will not work this way because they reference a timestamp, not a page,
|
|
19
|
-
// and the drawing canvas is the video player which has no pages. In this case, we just need to get the staged annotation and do the
|
|
20
|
-
// locaton check for MEDIA_LOCATION_INDEX. The MEDIA_LOCATION_INDEX is a special value, set in the manager, that is used to indicate that
|
|
19
|
+
// and the drawing canvas is the video player which has no pages. In this case, we just need to get the staged annotation and do the
|
|
20
|
+
// locaton check for MEDIA_LOCATION_INDEX. The MEDIA_LOCATION_INDEX is a special value, set in the manager, that is used to indicate that
|
|
21
21
|
// the this is actually a staged video annotation with a timestamp as its location.
|
|
22
22
|
if (location === MEDIA_LOCATION_INDEX) {
|
|
23
23
|
return staged;
|
|
@@ -15,8 +15,10 @@ const emitCreateEvent = (action: AsyncAction<NewAnnotation, Annotation>, status:
|
|
|
15
15
|
});
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
const createHandler =
|
|
19
|
-
|
|
18
|
+
const createHandler =
|
|
19
|
+
(status: Status) =>
|
|
20
|
+
(prevState: AppState, nextState: AppState, action: AsyncAction): void =>
|
|
21
|
+
emitCreateEvent(action as AsyncAction<NewAnnotation, Annotation>, status);
|
|
20
22
|
|
|
21
23
|
const handleCreateErrorEvents = createHandler(Status.ERROR);
|
|
22
24
|
const handleCreatePendingEvents = createHandler(Status.PENDING);
|
|
@@ -14,11 +14,10 @@ const emitDeleteEvent = (action: AsyncAction<string, string>, status: Status): v
|
|
|
14
14
|
});
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
const deleteHandler =
|
|
18
|
-
|
|
19
|
-
_next: AppState,
|
|
20
|
-
|
|
21
|
-
): void => emitDeleteEvent(action as AsyncAction<string, string>, status);
|
|
17
|
+
const deleteHandler =
|
|
18
|
+
(status: Status) =>
|
|
19
|
+
(_prev: AppState, _next: AppState, action: AsyncAction): void =>
|
|
20
|
+
emitDeleteEvent(action as AsyncAction<string, string>, status);
|
|
22
21
|
|
|
23
22
|
const handleDeleteErrorEvents = deleteHandler(Status.ERROR);
|
|
24
23
|
const handleDeletePendingEvents = deleteHandler(Status.PENDING);
|
|
@@ -71,19 +71,21 @@ export const eventHandlers: EventHandlerMap = {
|
|
|
71
71
|
};
|
|
72
72
|
|
|
73
73
|
function getEventingMiddleware(handlers: EventHandlerMap = eventHandlers): Middleware {
|
|
74
|
-
return (store: MiddlewareAPI) =>
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
74
|
+
return (store: MiddlewareAPI) =>
|
|
75
|
+
(next: Dispatch) =>
|
|
76
|
+
(action: Action): Action => {
|
|
77
|
+
const { type } = action;
|
|
78
|
+
// Retrieve the prevState as well as the nextState after the action has modified the state in order
|
|
79
|
+
// to pass all that information to the event handler
|
|
80
|
+
const prevState = store.getState();
|
|
81
|
+
const result = next(action);
|
|
82
|
+
const nextState = store.getState();
|
|
81
83
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
+
const handler = handlers[type] || noop;
|
|
85
|
+
handler(prevState, nextState, action);
|
|
84
86
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
return result;
|
|
88
|
+
};
|
|
87
89
|
}
|
|
88
90
|
|
|
89
91
|
export default getEventingMiddleware;
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import eventManager from '../../common/EventManager';
|
|
2
|
-
import { Reply
|
|
2
|
+
import { Reply, Event } from '../../@types';
|
|
3
3
|
import { AppState } from '../types';
|
|
4
4
|
import { AsyncAction, Status } from './types';
|
|
5
5
|
|
|
6
6
|
type ReplyCreateArg = { annotationId: string; message: string };
|
|
7
7
|
type ReplyCreatePayload = { annotationId: string; reply: Reply };
|
|
8
8
|
|
|
9
|
-
const emitReplyCreateEvent = (
|
|
10
|
-
action: AsyncAction<ReplyCreateArg, ReplyCreatePayload>,
|
|
11
|
-
status: Status,
|
|
12
|
-
): void => {
|
|
9
|
+
const emitReplyCreateEvent = (action: AsyncAction<ReplyCreateArg, ReplyCreatePayload>, status: Status): void => {
|
|
13
10
|
const { error, meta: { arg, requestId } = {}, payload } = action;
|
|
14
11
|
if (status === Status.SUCCESS && !payload?.reply) return;
|
|
15
12
|
const annotationId = payload?.annotationId ?? arg?.annotationId;
|
|
@@ -21,11 +18,10 @@ const emitReplyCreateEvent = (
|
|
|
21
18
|
});
|
|
22
19
|
};
|
|
23
20
|
|
|
24
|
-
const replyCreateHandler =
|
|
25
|
-
|
|
26
|
-
_next: AppState,
|
|
27
|
-
|
|
28
|
-
): void => emitReplyCreateEvent(action as AsyncAction<ReplyCreateArg, ReplyCreatePayload>, status);
|
|
21
|
+
const replyCreateHandler =
|
|
22
|
+
(status: Status) =>
|
|
23
|
+
(_prev: AppState, _next: AppState, action: AsyncAction): void =>
|
|
24
|
+
emitReplyCreateEvent(action as AsyncAction<ReplyCreateArg, ReplyCreatePayload>, status);
|
|
29
25
|
|
|
30
26
|
const handleReplyCreateErrorEvents = replyCreateHandler(Status.ERROR);
|
|
31
27
|
const handleReplyCreatePendingEvents = replyCreateHandler(Status.PENDING);
|
|
@@ -6,10 +6,7 @@ import { Event } from '../../@types';
|
|
|
6
6
|
type ReplyDeleteArg = { annotationId: string; replyId: string };
|
|
7
7
|
type ReplyDeletePayload = { annotationId: string; replyId: string };
|
|
8
8
|
|
|
9
|
-
const emitReplyDeleteEvent = (
|
|
10
|
-
action: AsyncAction<ReplyDeleteArg, ReplyDeletePayload>,
|
|
11
|
-
status: Status,
|
|
12
|
-
): void => {
|
|
9
|
+
const emitReplyDeleteEvent = (action: AsyncAction<ReplyDeleteArg, ReplyDeletePayload>, status: Status): void => {
|
|
13
10
|
const { error, meta: { arg, requestId } = {}, payload } = action;
|
|
14
11
|
if (status === Status.SUCCESS && !payload) return;
|
|
15
12
|
const annotationId = payload?.annotationId ?? arg?.annotationId;
|
|
@@ -22,11 +19,10 @@ const emitReplyDeleteEvent = (
|
|
|
22
19
|
});
|
|
23
20
|
};
|
|
24
21
|
|
|
25
|
-
const replyDeleteHandler =
|
|
26
|
-
|
|
27
|
-
_next: AppState,
|
|
28
|
-
|
|
29
|
-
): void => emitReplyDeleteEvent(action as AsyncAction<ReplyDeleteArg, ReplyDeletePayload>, status);
|
|
22
|
+
const replyDeleteHandler =
|
|
23
|
+
(status: Status) =>
|
|
24
|
+
(_prev: AppState, _next: AppState, action: AsyncAction): void =>
|
|
25
|
+
emitReplyDeleteEvent(action as AsyncAction<ReplyDeleteArg, ReplyDeletePayload>, status);
|
|
30
26
|
|
|
31
27
|
const handleReplyDeleteErrorEvents = replyDeleteHandler(Status.ERROR);
|
|
32
28
|
const handleReplyDeletePendingEvents = replyDeleteHandler(Status.PENDING);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import eventManager from '../../common/EventManager';
|
|
2
|
-
import { Reply
|
|
2
|
+
import { Reply, Event } from '../../@types';
|
|
3
3
|
import { AppState } from '../types';
|
|
4
4
|
import { AsyncAction, Status } from './types';
|
|
5
5
|
|
|
@@ -10,10 +10,7 @@ type ReplyUpdateArg = {
|
|
|
10
10
|
};
|
|
11
11
|
type ReplyUpdatePayload = { annotationId: string; reply: Reply };
|
|
12
12
|
|
|
13
|
-
const emitReplyUpdateEvent = (
|
|
14
|
-
action: AsyncAction<ReplyUpdateArg, ReplyUpdatePayload>,
|
|
15
|
-
status: Status,
|
|
16
|
-
): void => {
|
|
13
|
+
const emitReplyUpdateEvent = (action: AsyncAction<ReplyUpdateArg, ReplyUpdatePayload>, status: Status): void => {
|
|
17
14
|
const { error, meta: { arg, requestId } = {}, payload } = action;
|
|
18
15
|
if (status === Status.SUCCESS && !payload?.reply) return;
|
|
19
16
|
const annotationId = payload?.annotationId ?? arg?.annotationId;
|
|
@@ -26,11 +23,10 @@ const emitReplyUpdateEvent = (
|
|
|
26
23
|
});
|
|
27
24
|
};
|
|
28
25
|
|
|
29
|
-
const replyUpdateHandler =
|
|
30
|
-
|
|
31
|
-
_next: AppState,
|
|
32
|
-
|
|
33
|
-
): void => emitReplyUpdateEvent(action as AsyncAction<ReplyUpdateArg, ReplyUpdatePayload>, status);
|
|
26
|
+
const replyUpdateHandler =
|
|
27
|
+
(status: Status) =>
|
|
28
|
+
(_prev: AppState, _next: AppState, action: AsyncAction): void =>
|
|
29
|
+
emitReplyUpdateEvent(action as AsyncAction<ReplyUpdateArg, ReplyUpdatePayload>, status);
|
|
34
30
|
|
|
35
31
|
const handleReplyUpdateErrorEvents = replyUpdateHandler(Status.ERROR);
|
|
36
32
|
const handleReplyUpdatePendingEvents = replyUpdateHandler(Status.PENDING);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import eventManager from '../../common/EventManager';
|
|
2
|
-
import { Annotation
|
|
2
|
+
import { Annotation, Event } from '../../@types';
|
|
3
3
|
import { AppState } from '../types';
|
|
4
4
|
import { AsyncAction, Status } from './types';
|
|
5
5
|
|
|
@@ -16,11 +16,10 @@ const emitUpdateEvent = (action: AsyncAction<UpdateArg, Annotation>, status: Sta
|
|
|
16
16
|
});
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
const updateHandler =
|
|
20
|
-
|
|
21
|
-
_next: AppState,
|
|
22
|
-
|
|
23
|
-
): void => emitUpdateEvent(action as AsyncAction<UpdateArg, Annotation>, status);
|
|
19
|
+
const updateHandler =
|
|
20
|
+
(status: Status) =>
|
|
21
|
+
(_prev: AppState, _next: AppState, action: AsyncAction): void =>
|
|
22
|
+
emitUpdateEvent(action as AsyncAction<UpdateArg, Annotation>, status);
|
|
24
23
|
|
|
25
24
|
const handleUpdateErrorEvents = updateHandler(Status.ERROR);
|
|
26
25
|
const handleUpdatePendingEvents = updateHandler(Status.PENDING);
|
|
@@ -77,59 +77,61 @@ export const getShape = ({ height, left, top, width }: DOMRect): Shape => ({
|
|
|
77
77
|
y: top,
|
|
78
78
|
});
|
|
79
79
|
|
|
80
|
-
export const setSelectionAction = createAction(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const { containerEl, containerRect, hasError, location, range, rotation } = arg;
|
|
80
|
+
export const setSelectionAction = createAction('SET_SELECTION', (arg: SelectionArg | null): Payload => {
|
|
81
|
+
if (!arg) {
|
|
82
|
+
return {
|
|
83
|
+
payload: null,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
90
86
|
|
|
91
|
-
|
|
92
|
-
// getClientRects on IE/Edge might return 0 rects
|
|
93
|
-
if (!rects.length) {
|
|
94
|
-
rects = getClientRects(range);
|
|
95
|
-
}
|
|
87
|
+
const { containerEl, containerRect, hasError, location, range, rotation } = arg;
|
|
96
88
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const [lx1, ly1] = getElementLocalPosition(shape.x, shape.y, containerEl, rotation);
|
|
103
|
-
const [lx2, ly2] = getElementLocalPosition(shape.x + shape.width, shape.y + shape.height, containerEl, rotation);
|
|
104
|
-
return {
|
|
105
|
-
x: Math.min(lx1, lx2),
|
|
106
|
-
y: Math.min(ly1, ly2),
|
|
107
|
-
width: Math.abs(lx2 - lx1),
|
|
108
|
-
height: Math.abs(ly2 - ly1),
|
|
109
|
-
};
|
|
110
|
-
});
|
|
89
|
+
let rects = Array.from(range.getClientRects());
|
|
90
|
+
// getClientRects on IE/Edge might return 0 rects
|
|
91
|
+
if (!rects.length) {
|
|
92
|
+
rects = getClientRects(range);
|
|
93
|
+
}
|
|
111
94
|
|
|
95
|
+
const screenShapes = rects.map(getShape);
|
|
96
|
+
|
|
97
|
+
if (rotation && containerEl) {
|
|
98
|
+
// Convert screen rects to element-local coordinates
|
|
99
|
+
const localRects = screenShapes.map(shape => {
|
|
100
|
+
const [lx1, ly1] = getElementLocalPosition(shape.x, shape.y, containerEl, rotation);
|
|
101
|
+
const [lx2, ly2] = getElementLocalPosition(
|
|
102
|
+
shape.x + shape.width,
|
|
103
|
+
shape.y + shape.height,
|
|
104
|
+
containerEl,
|
|
105
|
+
rotation,
|
|
106
|
+
);
|
|
112
107
|
return {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
popupRect: getBoundingRect(screenShapes),
|
|
118
|
-
rects: combineRects(localRects),
|
|
119
|
-
},
|
|
108
|
+
x: Math.min(lx1, lx2),
|
|
109
|
+
y: Math.min(ly1, ly2),
|
|
110
|
+
width: Math.abs(lx2 - lx1),
|
|
111
|
+
height: Math.abs(ly2 - ly1),
|
|
120
112
|
};
|
|
121
|
-
}
|
|
113
|
+
});
|
|
122
114
|
|
|
123
115
|
return {
|
|
124
116
|
payload: {
|
|
125
|
-
containerRect:
|
|
117
|
+
containerRect: { x: 0, y: 0, width: containerEl.offsetWidth, height: containerEl.offsetHeight },
|
|
126
118
|
hasError,
|
|
127
119
|
location,
|
|
128
|
-
|
|
120
|
+
popupRect: getBoundingRect(screenShapes),
|
|
121
|
+
rects: combineRects(localRects),
|
|
129
122
|
},
|
|
130
123
|
};
|
|
131
|
-
}
|
|
132
|
-
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
payload: {
|
|
128
|
+
containerRect: getShape(containerRect),
|
|
129
|
+
hasError,
|
|
130
|
+
location,
|
|
131
|
+
rects: combineRects(screenShapes),
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
});
|
|
133
135
|
|
|
134
136
|
export const setIsPromotingAction = createAction<boolean>('SET_IS_PROMOTING');
|
|
135
137
|
export const setIsSelectingAction = createAction<boolean>('SET_IS_SELECTING');
|