box-annotations 5.3.1-beta.1 → 5.3.1-beta.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/i18n/ja-JP.js CHANGED
@@ -1,2 +1,25 @@
1
1
  // THIS IS A GENERATED FILE. DO NOT EDIT MANUALLY OR YOUR CHANGES WILL BE OVERWRITTEN
2
- export default {};
2
+ export default {
3
+ "ba.annotationsClose": "閉じる",
4
+ "ba.annotationsCreateError": "注釈を作成できませんでした。",
5
+ "ba.annotationsLoadError": "このファイルの注釈を読み込めませんでした。",
6
+ "ba.annotationsPost": "投稿",
7
+ "ba.annotationsSave": "保存",
8
+ "ba.boundingBoxHighlight.viewNextReference": "次の参照を表示",
9
+ "ba.boundingBoxHighlight.viewPrevReference": "前の参照を表示",
10
+ "ba.popup.reply.comment": "コメント",
11
+ "ba.popup.reply.field": "コメントを入力する",
12
+ "ba.popup.reply.mentionLoading": "ユーザーを読み込み中…",
13
+ "ba.popup.reply.mentionSelector": "コラボレータにコメントする",
14
+ "ba.popups.cancel": "キャンセル",
15
+ "ba.popups.drawing.addComment": "コメントを追加",
16
+ "ba.popups.drawing.delete": "削除",
17
+ "ba.popups.drawing.redo": "やり直す",
18
+ "ba.popups.drawing.undo": "元に戻す",
19
+ "ba.popups.popupCursor.regionPrompt": "四角を描いてコメントする",
20
+ "ba.popups.popupHighlight.promoter": "ハイライトとコメント",
21
+ "ba.popups.popupHighlight.restrictedPrompt": "コメントは1つのページに制限されています",
22
+ "ba.popups.popupList.prompt": "ユーザーにメンションして知らせます",
23
+ "ba.popups.post": "投稿",
24
+ "ba.popups.replyField.placeholder": "コメントを入力…"
25
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "box-annotations",
3
- "version": "5.3.1-beta.1",
3
+ "version": "5.3.1-beta.2",
4
4
  "description": "Box Annotations",
5
5
  "author": "Box (https://www.box.com/)",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -40,7 +40,7 @@
40
40
  "@box/item-icon": "^3.2.0",
41
41
  "@box/languages": "^1.1.0",
42
42
  "@box/readable-time": "^2.1.32",
43
- "@box/threaded-annotations": "^4.11.14",
43
+ "@box/threaded-annotations": "^4.14.0",
44
44
  "@box/types": "^2.1.8",
45
45
  "@box/user-selector": "^2.1.35",
46
46
  "@cfaester/enzyme-adapter-react-18": "^0.8.0",
@@ -71,7 +71,7 @@
71
71
  "babel-loader": "^9.2.1",
72
72
  "babel-plugin-istanbul": "^6.0.0",
73
73
  "babel-plugin-transform-require-ignore": "^0.1.1",
74
- "box-ui-elements": "^20.0.0",
74
+ "box-ui-elements": "^28.0.0-beta.2",
75
75
  "circular-dependency-plugin": "^5.2.0",
76
76
  "classnames": "^2.2.5",
77
77
  "clsx": "^2.1.1",
@@ -142,7 +142,7 @@
142
142
  "@box/combobox-with-api": "^1.42.22",
143
143
  "@box/item-icon": "^3.2.0",
144
144
  "@box/readable-time": "^2.1.32",
145
- "@box/threaded-annotations": "^4.11.14",
145
+ "@box/threaded-annotations": "^4.14.0",
146
146
  "@box/types": "^2.1.8",
147
147
  "@box/user-selector": "^2.1.35",
148
148
  "axios": "^0.33.0"
package/src/api/types.ts CHANGED
@@ -31,6 +31,7 @@ export interface AnnotationsAPI {
31
31
  permissions: Permissions,
32
32
  successCallback: (result: Annotation) => void,
33
33
  errorCallback: (error: APIError) => void,
34
+ shouldEnableRichText?: boolean,
34
35
  ): Promise<void>;
35
36
 
36
37
  createAnnotationReply(
@@ -40,6 +41,7 @@ export interface AnnotationsAPI {
40
41
  message: string,
41
42
  successCallback: (result: Reply) => void,
42
43
  errorCallback: (error: APIError) => void,
44
+ shouldEnableRichText?: boolean,
43
45
  ): Promise<void>;
44
46
 
45
47
  deleteAnnotation(
@@ -59,6 +61,7 @@ export interface AnnotationsAPI {
59
61
  limit?: number,
60
62
  shouldFetchAll?: boolean,
61
63
  shouldFetchReplies?: boolean,
64
+ shouldEnableRichText?: boolean,
62
65
  ): Promise<void>;
63
66
 
64
67
  updateAnnotation(
@@ -68,6 +71,7 @@ export interface AnnotationsAPI {
68
71
  payload: { message?: string; status?: string },
69
72
  successCallback: (result: Annotation) => void,
70
73
  errorCallback: (error: APIError) => void,
74
+ shouldEnableRichText?: boolean,
71
75
  ): Promise<void>;
72
76
 
73
77
  destroy(): void;
@@ -88,6 +92,7 @@ export interface ThreadedCommentsAPI {
88
92
  fileId: string | null;
89
93
  message?: string;
90
94
  permissions: ReplyPermissions;
95
+ shouldEnableRichText?: boolean;
91
96
  status?: string;
92
97
  successCallback: (reply: Reply) => void;
93
98
  }): void;
@@ -1,4 +1,4 @@
1
- import createMentionSelectorState from 'box-ui-elements/es/components/form-elements/draft-js-mention-selector/createMentionSelectorState';
1
+ import createMentionTimestampSelectorState from 'box-ui-elements/es/components/form-elements/draft-js-mention-selector/createMentionTimestampSelectorState';
2
2
  import { getFormattedCommentText } from 'box-ui-elements/es/components/form-elements/draft-js-mention-selector/utils';
3
3
  import { EditorState, SelectionState } from 'draft-js';
4
4
  import { FormikBag, withFormik } from 'formik';
@@ -30,13 +30,16 @@ export const mapStateToProps = (state: AppState): PropsFromState => ({
30
30
  export const mapPropsToErrors = (): FormErrors => ({ editorState: 'initial' });
31
31
 
32
32
  export const mapPropsToValues = ({ cursorPosition: prevCursorPosition, value = '' }: Props): FormValues => {
33
- const mentionState = withMentionDecorator(createMentionSelectorState(value));
34
- const cursorPosition = value ? prevCursorPosition : 0;
33
+ const mentionState = withMentionDecorator(createMentionTimestampSelectorState(value));
34
+ const selection = mentionState.getSelection();
35
+ const blockLength = mentionState.getCurrentContent().getBlockForKey(selection.getAnchorKey()).getLength();
36
+ // The saved message is trimmed, so the saved cursor can sit past the end of the rebuilt text
37
+ const cursorPosition = value ? Math.min(prevCursorPosition, blockLength) : 0;
35
38
 
36
39
  return {
37
40
  editorState: EditorState.forceSelection(
38
41
  mentionState,
39
- mentionState.getSelection().merge({
42
+ selection.merge({
40
43
  anchorOffset: cursorPosition,
41
44
  focusOffset: cursorPosition,
42
45
  hasFocus: true,
@@ -3,7 +3,7 @@ import { Annotation, NewAnnotation, Reply } from '../../@types';
3
3
  import { APICollection } from '../../api';
4
4
  import { AppThunkAPI } from '../types';
5
5
  import { getAnnotation } from './selectors';
6
- import { getFileId, getFileVersionId, getPermissions, isFeatureEnabled } from '../options';
6
+ import { getFileId, getFileVersionId, getIsRichTextEnabled, getPermissions, isFeatureEnabled } from '../options';
7
7
 
8
8
  export const createAnnotationAction = createAsyncThunk<Annotation, NewAnnotation, AppThunkAPI>(
9
9
  'CREATE_ANNOTATION',
@@ -14,13 +14,22 @@ export const createAnnotationAction = createAsyncThunk<Annotation, NewAnnotation
14
14
  const fileId = getFileId(state);
15
15
  const fileVersionId = getFileVersionId(state);
16
16
  const permissions = getPermissions(state);
17
+ const shouldEnableRichText = getIsRichTextEnabled(state);
17
18
 
18
19
  signal.addEventListener('abort', () => {
19
20
  client.destroy();
20
21
  });
21
22
 
22
23
  return new Promise<Annotation>((resolve, reject) => {
23
- client.createAnnotation(fileId, fileVersionId, newAnnotation, permissions, resolve, reject);
24
+ client.createAnnotation(
25
+ fileId,
26
+ fileVersionId,
27
+ newAnnotation,
28
+ permissions,
29
+ resolve,
30
+ reject,
31
+ shouldEnableRichText,
32
+ );
24
33
  });
25
34
  },
26
35
  );
@@ -40,11 +49,22 @@ export const fetchAnnotationsAction = createAsyncThunk<APICollection<Annotation>
40
49
  client.destroy();
41
50
  });
42
51
 
43
- const shouldFetchReplies = isFeatureEnabled({ options: getState().options }, 'isThreadedAnnotation');
52
+ const shouldFetchReplies = isFeatureEnabled(state, 'isThreadedAnnotation');
53
+ const shouldEnableRichText = getIsRichTextEnabled(state);
44
54
 
45
55
  // Wrap the client request in a promise to allow it to be returned and cancelled
46
56
  return new Promise<APICollection<Annotation>>((resolve, reject) => {
47
- client.getAnnotations(fileId, fileVersionId, permissions, resolve, reject, 1000, false, shouldFetchReplies);
57
+ client.getAnnotations(
58
+ fileId,
59
+ fileVersionId,
60
+ permissions,
61
+ resolve,
62
+ reject,
63
+ 1000,
64
+ false,
65
+ shouldFetchReplies,
66
+ shouldEnableRichText,
67
+ );
48
68
  });
49
69
  },
50
70
  );
@@ -60,13 +80,14 @@ export const createReplyAction = createAsyncThunk<
60
80
  const filePermissions = getPermissions(state);
61
81
  const annotation = getAnnotation(state, annotationId);
62
82
  const permissions = { ...filePermissions, ...annotation?.permissions };
83
+ const shouldEnableRichText = getIsRichTextEnabled(state);
63
84
 
64
85
  signal.addEventListener('abort', () => {
65
86
  client.destroy();
66
87
  });
67
88
 
68
89
  const reply = await new Promise<Reply>((resolve, reject) => {
69
- client.createAnnotationReply(fileId, annotationId, permissions, message, resolve, reject);
90
+ client.createAnnotationReply(fileId, annotationId, permissions, message, resolve, reject, shouldEnableRichText);
70
91
  });
71
92
 
72
93
  return { annotationId, reply };
@@ -105,13 +126,14 @@ export const updateAnnotationAction = createAsyncThunk<
105
126
  const filePermissions = getPermissions(state);
106
127
  const existingAnnotation = getAnnotation(state, annotationId);
107
128
  const permissions = { ...filePermissions, ...existingAnnotation?.permissions };
129
+ const shouldEnableRichText = getIsRichTextEnabled(state);
108
130
 
109
131
  signal.addEventListener('abort', () => {
110
132
  client.destroy();
111
133
  });
112
134
 
113
135
  return new Promise<Annotation>((resolve, reject) => {
114
- client.updateAnnotation(fileId, annotationId, permissions, payload, resolve, reject);
136
+ client.updateAnnotation(fileId, annotationId, permissions, payload, resolve, reject, shouldEnableRichText);
115
137
  });
116
138
  });
117
139
 
@@ -125,6 +147,7 @@ export const updateReplyAction = createAsyncThunk<
125
147
  const fileId = getFileId(state);
126
148
  const annotation = getAnnotation(state, annotationId);
127
149
  const reply = annotation?.replies?.find(r => r.id === replyId);
150
+ const shouldEnableRichText = getIsRichTextEnabled(state);
128
151
 
129
152
  if (!reply) {
130
153
  throw new Error(`updateReplyAction: reply ${replyId} not found on annotation ${annotationId}`);
@@ -141,6 +164,7 @@ export const updateReplyAction = createAsyncThunk<
141
164
  fileId,
142
165
  message: payload.message,
143
166
  permissions: reply.permissions ?? {},
167
+ shouldEnableRichText,
144
168
  status: payload.status,
145
169
  successCallback: resolve,
146
170
  });
@@ -18,3 +18,8 @@ export const getScale = (state: State): number => state.options.scale;
18
18
  export const getToken = (state: State): Token => state.options.token;
19
19
  export const isFeatureEnabled = (state: State, featurename: string): boolean =>
20
20
  getProp(getFeatures(state), featurename, false);
21
+
22
+ // Rich text is only rendered and authored in the threaded popup (PopupV2). The legacy popup editor
23
+ // is plain text, so the flag only applies when threaded annotations are on.
24
+ export const getIsRichTextEnabled = (state: State): boolean =>
25
+ isFeatureEnabled(state, 'isThreadedAnnotation') && isFeatureEnabled(state, 'isRichTextEnabled');