@wordpress/editor 14.31.1-next.f56bd8138.0 → 14.32.0
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/CHANGELOG.md +2 -0
- package/build/components/collab-sidebar/add-comment.js +10 -4
- package/build/components/collab-sidebar/add-comment.js.map +1 -1
- package/build/components/collab-sidebar/comment-author-info.js +39 -11
- package/build/components/collab-sidebar/comment-author-info.js.map +1 -1
- package/build/components/collab-sidebar/comment-form.js +23 -19
- package/build/components/collab-sidebar/comment-form.js.map +1 -1
- package/build/components/collab-sidebar/comment-indicator-toolbar.js +7 -4
- package/build/components/collab-sidebar/comment-indicator-toolbar.js.map +1 -1
- package/build/components/collab-sidebar/comments.js +220 -169
- package/build/components/collab-sidebar/comments.js.map +1 -1
- package/build/components/collab-sidebar/hooks.js +96 -0
- package/build/components/collab-sidebar/hooks.js.map +1 -0
- package/build/components/collab-sidebar/index.js +79 -169
- package/build/components/collab-sidebar/index.js.map +1 -1
- package/build/components/collab-sidebar/utils.js +72 -25
- package/build/components/collab-sidebar/utils.js.map +1 -1
- package/build/components/header/index.js +5 -1
- package/build/components/header/index.js.map +1 -1
- package/build/components/provider/use-block-editor-settings.js +1 -1
- package/build/components/provider/use-block-editor-settings.js.map +1 -1
- package/build/dataviews/store/private-actions.js +1 -1
- package/build/dataviews/store/private-actions.js.map +1 -1
- package/build/store/actions.js +63 -2
- package/build/store/actions.js.map +1 -1
- package/build-module/components/collab-sidebar/add-comment.js +11 -5
- package/build-module/components/collab-sidebar/add-comment.js.map +1 -1
- package/build-module/components/collab-sidebar/comment-author-info.js +42 -14
- package/build-module/components/collab-sidebar/comment-author-info.js.map +1 -1
- package/build-module/components/collab-sidebar/comment-form.js +26 -22
- package/build-module/components/collab-sidebar/comment-form.js.map +1 -1
- package/build-module/components/collab-sidebar/comment-indicator-toolbar.js +8 -5
- package/build-module/components/collab-sidebar/comment-indicator-toolbar.js.map +1 -1
- package/build-module/components/collab-sidebar/comments.js +223 -172
- package/build-module/components/collab-sidebar/comments.js.map +1 -1
- package/build-module/components/collab-sidebar/hooks.js +89 -0
- package/build-module/components/collab-sidebar/hooks.js.map +1 -0
- package/build-module/components/collab-sidebar/index.js +82 -172
- package/build-module/components/collab-sidebar/index.js.map +1 -1
- package/build-module/components/collab-sidebar/utils.js +70 -24
- package/build-module/components/collab-sidebar/utils.js.map +1 -1
- package/build-module/components/header/index.js +5 -1
- package/build-module/components/header/index.js.map +1 -1
- package/build-module/components/provider/use-block-editor-settings.js +1 -1
- package/build-module/components/provider/use-block-editor-settings.js.map +1 -1
- package/build-module/dataviews/store/private-actions.js +2 -2
- package/build-module/dataviews/store/private-actions.js.map +1 -1
- package/build-module/store/actions.js +63 -2
- package/build-module/store/actions.js.map +1 -1
- package/build-style/style-rtl.css +60 -19
- package/build-style/style.css +60 -19
- package/build-types/components/collab-sidebar/add-comment.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/comment-author-info.d.ts +3 -1
- package/build-types/components/collab-sidebar/comment-author-info.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/comment-form.d.ts +3 -5
- package/build-types/components/collab-sidebar/comment-form.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/comment-indicator-toolbar.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/comments.d.ts +1 -7
- package/build-types/components/collab-sidebar/comments.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/hooks.d.ts +6 -0
- package/build-types/components/collab-sidebar/hooks.d.ts.map +1 -0
- package/build-types/components/collab-sidebar/index.d.ts.map +1 -1
- package/build-types/components/collab-sidebar/utils.d.ts +11 -6
- package/build-types/components/collab-sidebar/utils.d.ts.map +1 -1
- package/build-types/components/header/index.d.ts.map +1 -1
- package/build-types/components/provider/use-block-editor-settings.d.ts.map +1 -1
- package/build-types/dataviews/store/private-actions.d.ts.map +1 -1
- package/build-types/store/actions.d.ts.map +1 -1
- package/package.json +37 -37
- package/src/components/collab-sidebar/add-comment.js +9 -4
- package/src/components/collab-sidebar/comment-author-info.js +51 -28
- package/src/components/collab-sidebar/comment-form.js +25 -24
- package/src/components/collab-sidebar/comment-indicator-toolbar.js +16 -5
- package/src/components/collab-sidebar/comments.js +271 -210
- package/src/components/collab-sidebar/hooks.js +95 -0
- package/src/components/collab-sidebar/index.js +107 -218
- package/src/components/collab-sidebar/style.scss +34 -20
- package/src/components/collab-sidebar/utils.js +73 -30
- package/src/components/header/index.js +6 -3
- package/src/components/provider/use-block-editor-settings.js +1 -0
- package/src/dataviews/store/private-actions.ts +6 -0
- package/src/store/actions.js +93 -2
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -6,18 +6,22 @@ import clsx from 'clsx';
|
|
|
6
6
|
/**
|
|
7
7
|
* WordPress dependencies
|
|
8
8
|
*/
|
|
9
|
-
import { useState, RawHTML,
|
|
9
|
+
import { useState, RawHTML, useRef } from '@wordpress/element';
|
|
10
10
|
import {
|
|
11
|
+
__experimentalText as Text,
|
|
11
12
|
__experimentalHStack as HStack,
|
|
12
13
|
__experimentalVStack as VStack,
|
|
13
14
|
__experimentalConfirmDialog as ConfirmDialog,
|
|
14
15
|
Button,
|
|
15
|
-
|
|
16
|
+
FlexItem,
|
|
17
|
+
privateApis as componentsPrivateApis,
|
|
16
18
|
} from '@wordpress/components';
|
|
19
|
+
import { useDebounce } from '@wordpress/compose';
|
|
17
20
|
|
|
18
21
|
import { published, moreVertical } from '@wordpress/icons';
|
|
19
22
|
import { __, _x, sprintf, _n } from '@wordpress/i18n';
|
|
20
23
|
import { useSelect, useDispatch } from '@wordpress/data';
|
|
24
|
+
import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
|
|
21
25
|
import {
|
|
22
26
|
store as blockEditorStore,
|
|
23
27
|
privateApis as blockEditorPrivateApis,
|
|
@@ -29,30 +33,10 @@ import {
|
|
|
29
33
|
import { unlock } from '../../lock-unlock';
|
|
30
34
|
import CommentAuthorInfo from './comment-author-info';
|
|
31
35
|
import CommentForm from './comment-form';
|
|
36
|
+
import { getCommentExcerpt } from './utils';
|
|
32
37
|
|
|
33
38
|
const { useBlockElement } = unlock( blockEditorPrivateApis );
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Finds the first block that has the specified comment ID.
|
|
37
|
-
*
|
|
38
|
-
* @param {string} commentId - The comment ID to search for.
|
|
39
|
-
* @param {Array} blockList - The list of blocks to search through.
|
|
40
|
-
* @return {string|null} The client ID of the found block, or null if not found.
|
|
41
|
-
*/
|
|
42
|
-
const findBlockByCommentId = ( commentId, blockList ) => {
|
|
43
|
-
for ( const block of blockList ) {
|
|
44
|
-
if ( block.attributes?.blockCommentId === commentId ) {
|
|
45
|
-
return block.clientId;
|
|
46
|
-
}
|
|
47
|
-
if ( block.innerBlocks ) {
|
|
48
|
-
const found = findBlockByCommentId( commentId, block.innerBlocks );
|
|
49
|
-
if ( found ) {
|
|
50
|
-
return found;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return null;
|
|
55
|
-
};
|
|
39
|
+
const { Menu } = unlock( componentsPrivateApis );
|
|
56
40
|
|
|
57
41
|
/**
|
|
58
42
|
* Renders the Comments component.
|
|
@@ -62,9 +46,6 @@ const findBlockByCommentId = ( commentId, blockList ) => {
|
|
|
62
46
|
* @param {Function} props.onEditComment - The function to handle comment editing.
|
|
63
47
|
* @param {Function} props.onAddReply - The function to add a reply to a comment.
|
|
64
48
|
* @param {Function} props.onCommentDelete - The function to delete a comment.
|
|
65
|
-
* @param {Function} props.onCommentResolve - The function to mark a comment as resolved.
|
|
66
|
-
* @param {Function} props.onCommentReopen - The function to reopen a resolved comment.
|
|
67
|
-
* @param {boolean} props.showCommentBoard - Whether to show the comment board.
|
|
68
49
|
* @param {Function} props.setShowCommentBoard - The function to set the comment board visibility.
|
|
69
50
|
* @return {React.ReactNode} The rendered Comments component.
|
|
70
51
|
*/
|
|
@@ -73,81 +54,47 @@ export function Comments( {
|
|
|
73
54
|
onEditComment,
|
|
74
55
|
onAddReply,
|
|
75
56
|
onCommentDelete,
|
|
76
|
-
onCommentResolve,
|
|
77
|
-
onCommentReopen,
|
|
78
|
-
showCommentBoard,
|
|
79
57
|
setShowCommentBoard,
|
|
80
58
|
} ) {
|
|
81
|
-
const
|
|
82
|
-
const { getBlockAttributes, getSelectedBlockClientId
|
|
59
|
+
const blockCommentId = useSelect( ( select ) => {
|
|
60
|
+
const { getBlockAttributes, getSelectedBlockClientId } =
|
|
83
61
|
select( blockEditorStore );
|
|
84
|
-
const
|
|
85
|
-
return
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
: null,
|
|
89
|
-
blocks: getBlocks(),
|
|
90
|
-
};
|
|
62
|
+
const clientId = getSelectedBlockClientId();
|
|
63
|
+
return clientId
|
|
64
|
+
? getBlockAttributes( clientId )?.metadata?.commentId
|
|
65
|
+
: null;
|
|
91
66
|
}, [] );
|
|
67
|
+
const [ selectedThread = blockCommentId, setSelectedThread ] = useState();
|
|
92
68
|
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}, [ blockCommentId, focusThread, blocks, setFocusThread ] );
|
|
69
|
+
const hasThreads = Array.isArray( threads ) && threads.length > 0;
|
|
70
|
+
if ( ! hasThreads ) {
|
|
71
|
+
return (
|
|
72
|
+
<VStack
|
|
73
|
+
alignment="left"
|
|
74
|
+
className="editor-collab-sidebar-panel__thread"
|
|
75
|
+
justify="flex-start"
|
|
76
|
+
spacing="2"
|
|
77
|
+
>
|
|
78
|
+
{
|
|
79
|
+
// translators: message displayed when there are no comments available
|
|
80
|
+
__( 'No comments available' )
|
|
81
|
+
}
|
|
82
|
+
</VStack>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
110
85
|
|
|
111
|
-
return (
|
|
112
|
-
|
|
113
|
-
{
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
// translators: message displayed when there are no comments available
|
|
124
|
-
__( 'No comments available' )
|
|
125
|
-
}
|
|
126
|
-
</VStack>
|
|
127
|
-
)
|
|
128
|
-
}
|
|
129
|
-
{ Array.isArray( threads ) &&
|
|
130
|
-
threads.length > 0 &&
|
|
131
|
-
threads.map( ( thread ) => (
|
|
132
|
-
<Thread
|
|
133
|
-
key={ thread.id }
|
|
134
|
-
thread={ thread }
|
|
135
|
-
onAddReply={ onAddReply }
|
|
136
|
-
onCommentDelete={ onCommentDelete }
|
|
137
|
-
onCommentResolve={ onCommentResolve }
|
|
138
|
-
onCommentReopen={ onCommentReopen }
|
|
139
|
-
onEditComment={ onEditComment }
|
|
140
|
-
isFocused={ focusThread === thread.id }
|
|
141
|
-
clearThreadFocus={ clearThreadFocus }
|
|
142
|
-
setFocusThread={ setFocusThread }
|
|
143
|
-
blockCommentId={ blockCommentId }
|
|
144
|
-
blocks={ blocks }
|
|
145
|
-
flashBlock={ flashBlock }
|
|
146
|
-
setShowCommentBoard={ setShowCommentBoard }
|
|
147
|
-
/>
|
|
148
|
-
) ) }
|
|
149
|
-
</>
|
|
150
|
-
);
|
|
86
|
+
return threads.map( ( thread ) => (
|
|
87
|
+
<Thread
|
|
88
|
+
key={ thread.id }
|
|
89
|
+
thread={ thread }
|
|
90
|
+
onAddReply={ onAddReply }
|
|
91
|
+
onCommentDelete={ onCommentDelete }
|
|
92
|
+
onEditComment={ onEditComment }
|
|
93
|
+
isSelected={ selectedThread === thread.id }
|
|
94
|
+
setSelectedThread={ setSelectedThread }
|
|
95
|
+
setShowCommentBoard={ setShowCommentBoard }
|
|
96
|
+
/>
|
|
97
|
+
) );
|
|
151
98
|
}
|
|
152
99
|
|
|
153
100
|
function Thread( {
|
|
@@ -155,98 +102,181 @@ function Thread( {
|
|
|
155
102
|
onEditComment,
|
|
156
103
|
onAddReply,
|
|
157
104
|
onCommentDelete,
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
isFocused,
|
|
161
|
-
clearThreadFocus,
|
|
162
|
-
setFocusThread,
|
|
163
|
-
blocks,
|
|
164
|
-
flashBlock,
|
|
105
|
+
isSelected,
|
|
106
|
+
setSelectedThread,
|
|
165
107
|
setShowCommentBoard,
|
|
166
108
|
} ) {
|
|
167
|
-
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
109
|
+
const threadRef = useRef( null );
|
|
110
|
+
const { toggleBlockHighlight } = useDispatch( blockEditorStore );
|
|
111
|
+
const relatedBlockElement = useBlockElement( thread.blockClientId );
|
|
112
|
+
const debouncedToggleBlockHighlight = useDebounce(
|
|
113
|
+
toggleBlockHighlight,
|
|
114
|
+
50
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
const onMouseEnter = () => {
|
|
118
|
+
debouncedToggleBlockHighlight( thread.blockClientId, true );
|
|
119
|
+
};
|
|
174
120
|
|
|
175
|
-
const
|
|
121
|
+
const onMouseLeave = () => {
|
|
122
|
+
debouncedToggleBlockHighlight( thread.blockClientId, false );
|
|
123
|
+
};
|
|
176
124
|
|
|
177
|
-
const handleCommentSelect = (
|
|
125
|
+
const handleCommentSelect = ( { id, blockClientId } ) => {
|
|
178
126
|
setShowCommentBoard( false );
|
|
179
|
-
|
|
180
|
-
if (
|
|
127
|
+
setSelectedThread( id );
|
|
128
|
+
if ( blockClientId && relatedBlockElement ) {
|
|
181
129
|
relatedBlockElement.scrollIntoView( {
|
|
182
130
|
behavior: 'instant',
|
|
183
131
|
block: 'center',
|
|
184
132
|
} );
|
|
185
|
-
flashBlock( relatedBlock );
|
|
186
133
|
}
|
|
187
134
|
};
|
|
188
135
|
|
|
136
|
+
const focusThread = () => {
|
|
137
|
+
threadRef.current?.focus();
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
const unselectThread = () => {
|
|
141
|
+
setSelectedThread( null );
|
|
142
|
+
setShowCommentBoard( false );
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const replies = thread?.reply;
|
|
146
|
+
const lastReply = !! replies.length
|
|
147
|
+
? replies[ replies.length - 1 ]
|
|
148
|
+
: undefined;
|
|
149
|
+
const restReplies = !! replies.length ? replies.slice( 0, -1 ) : [];
|
|
150
|
+
|
|
151
|
+
const commentExcerpt = getCommentExcerpt(
|
|
152
|
+
stripHTML( thread.content.rendered ),
|
|
153
|
+
10
|
|
154
|
+
);
|
|
155
|
+
const ariaLabel = relatedBlockElement
|
|
156
|
+
? sprintf(
|
|
157
|
+
// translators: %s: comment excerpt
|
|
158
|
+
__( 'Comment: %s' ),
|
|
159
|
+
commentExcerpt
|
|
160
|
+
)
|
|
161
|
+
: sprintf(
|
|
162
|
+
// translators: %s: comment excerpt
|
|
163
|
+
__( 'Original block deleted. Comment: %s' ),
|
|
164
|
+
commentExcerpt
|
|
165
|
+
);
|
|
166
|
+
|
|
189
167
|
return (
|
|
168
|
+
// Disable reason: role="listitem" does in fact support aria-expanded.
|
|
169
|
+
// eslint-disable-next-line jsx-a11y/role-supports-aria-props
|
|
190
170
|
<VStack
|
|
191
171
|
className={ clsx( 'editor-collab-sidebar-panel__thread', {
|
|
192
|
-
'
|
|
172
|
+
'is-selected': isSelected,
|
|
193
173
|
} ) }
|
|
194
|
-
id={ thread.id }
|
|
195
|
-
spacing="
|
|
196
|
-
onClick={ () => handleCommentSelect( thread
|
|
174
|
+
id={ `thread-${ thread.id }` }
|
|
175
|
+
spacing="2"
|
|
176
|
+
onClick={ () => handleCommentSelect( thread ) }
|
|
177
|
+
onMouseEnter={ onMouseEnter }
|
|
178
|
+
onMouseLeave={ onMouseLeave }
|
|
179
|
+
onFocus={ onMouseEnter }
|
|
180
|
+
onBlur={ onMouseLeave }
|
|
181
|
+
onKeyDown={ ( event ) => {
|
|
182
|
+
// Expand or Collapse thread.
|
|
183
|
+
if (
|
|
184
|
+
event.key === 'Enter' &&
|
|
185
|
+
event.currentTarget === event.target
|
|
186
|
+
) {
|
|
187
|
+
if ( isSelected ) {
|
|
188
|
+
unselectThread();
|
|
189
|
+
} else {
|
|
190
|
+
handleCommentSelect( thread );
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// Collapse thread and focus the thread.
|
|
194
|
+
if ( event.key === 'Escape' ) {
|
|
195
|
+
unselectThread();
|
|
196
|
+
focusThread();
|
|
197
|
+
}
|
|
198
|
+
} }
|
|
199
|
+
tabIndex={ 0 }
|
|
200
|
+
role="listitem"
|
|
201
|
+
ref={ threadRef }
|
|
202
|
+
aria-label={ ariaLabel }
|
|
203
|
+
aria-expanded={ isSelected }
|
|
197
204
|
>
|
|
205
|
+
{ ! relatedBlockElement && (
|
|
206
|
+
<Text as="p" weight={ 500 } variant="muted">
|
|
207
|
+
{ __( 'Original block deleted.' ) }
|
|
208
|
+
</Text>
|
|
209
|
+
) }
|
|
198
210
|
<CommentBoard
|
|
199
211
|
thread={ thread }
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
212
|
+
onEdit={ ( params = {} ) => {
|
|
213
|
+
const { status } = params;
|
|
214
|
+
onEditComment( params );
|
|
215
|
+
if ( status === 'approved' ) {
|
|
216
|
+
unselectThread();
|
|
217
|
+
focusThread();
|
|
218
|
+
}
|
|
219
|
+
} }
|
|
203
220
|
onDelete={ onCommentDelete }
|
|
204
221
|
status={ thread.status }
|
|
205
222
|
/>
|
|
206
|
-
{
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
{
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
thread
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
223
|
+
{ isSelected &&
|
|
224
|
+
replies.map( ( reply ) => (
|
|
225
|
+
<VStack
|
|
226
|
+
key={ reply.id }
|
|
227
|
+
className="editor-collab-sidebar-panel__child-thread"
|
|
228
|
+
id={ reply.id }
|
|
229
|
+
spacing="2"
|
|
230
|
+
>
|
|
231
|
+
<CommentBoard
|
|
232
|
+
thread={ reply }
|
|
233
|
+
onEdit={
|
|
234
|
+
'approved' !== thread.status
|
|
235
|
+
? onEditComment
|
|
236
|
+
: undefined
|
|
237
|
+
}
|
|
238
|
+
onDelete={
|
|
239
|
+
'approved' !== thread.status
|
|
240
|
+
? onCommentDelete
|
|
241
|
+
: undefined
|
|
242
|
+
}
|
|
243
|
+
/>
|
|
244
|
+
</VStack>
|
|
245
|
+
) ) }
|
|
246
|
+
{ ! isSelected && restReplies.length > 0 && (
|
|
247
|
+
<HStack className="editor-collab-sidebar-panel__more-reply-separator">
|
|
248
|
+
<Button
|
|
249
|
+
size="compact"
|
|
250
|
+
variant="tertiary"
|
|
251
|
+
className="editor-collab-sidebar-panel__more-reply-button"
|
|
252
|
+
onClick={ () => setSelectedThread( thread.id ) }
|
|
253
|
+
>
|
|
254
|
+
{ sprintf(
|
|
255
|
+
// translators: %s: number of replies.
|
|
256
|
+
_n(
|
|
257
|
+
'%s more reply',
|
|
258
|
+
'%s more replies',
|
|
259
|
+
restReplies.length
|
|
260
|
+
),
|
|
261
|
+
restReplies.length
|
|
262
|
+
) }
|
|
263
|
+
</Button>
|
|
264
|
+
</HStack>
|
|
248
265
|
) }
|
|
249
|
-
{
|
|
266
|
+
{ ! isSelected && lastReply && (
|
|
267
|
+
<CommentBoard
|
|
268
|
+
thread={ lastReply }
|
|
269
|
+
onEdit={
|
|
270
|
+
'approved' !== thread.status ? onEditComment : undefined
|
|
271
|
+
}
|
|
272
|
+
onDelete={
|
|
273
|
+
'approved' !== thread.status
|
|
274
|
+
? onCommentDelete
|
|
275
|
+
: undefined
|
|
276
|
+
}
|
|
277
|
+
/>
|
|
278
|
+
) }
|
|
279
|
+
{ isSelected && (
|
|
250
280
|
<VStack
|
|
251
281
|
className="editor-collab-sidebar-panel__child-thread"
|
|
252
282
|
spacing="2"
|
|
@@ -254,36 +284,37 @@ function Thread( {
|
|
|
254
284
|
<HStack alignment="left" spacing="3" justify="flex-start">
|
|
255
285
|
<CommentAuthorInfo />
|
|
256
286
|
</HStack>
|
|
257
|
-
<VStack
|
|
258
|
-
spacing="3"
|
|
259
|
-
className="editor-collab-sidebar-panel__comment-field"
|
|
260
|
-
>
|
|
287
|
+
<VStack spacing="2">
|
|
261
288
|
<CommentForm
|
|
262
289
|
onSubmit={ ( inputComment ) => {
|
|
263
290
|
if ( 'approved' === thread.status ) {
|
|
264
|
-
|
|
291
|
+
onEditComment( {
|
|
292
|
+
id: thread.id,
|
|
293
|
+
status: 'hold',
|
|
294
|
+
} );
|
|
265
295
|
}
|
|
266
|
-
onAddReply(
|
|
296
|
+
onAddReply( {
|
|
297
|
+
content: inputComment,
|
|
298
|
+
parent: thread.id,
|
|
299
|
+
} );
|
|
267
300
|
} }
|
|
268
301
|
onCancel={ ( event ) => {
|
|
302
|
+
threadRef.current?.focus();
|
|
269
303
|
event.stopPropagation(); // Prevent the parent onClick from being triggered
|
|
270
|
-
|
|
304
|
+
unselectThread();
|
|
271
305
|
} }
|
|
272
|
-
placeholderText={
|
|
273
|
-
'approved' === thread.status &&
|
|
274
|
-
__(
|
|
275
|
-
'Adding a comment will re-open this discussion….'
|
|
276
|
-
)
|
|
277
|
-
}
|
|
278
306
|
submitButtonText={
|
|
279
307
|
'approved' === thread.status
|
|
280
|
-
?
|
|
281
|
-
|
|
282
|
-
'Reopen comment and add reply'
|
|
283
|
-
)
|
|
284
|
-
: _x( 'Reply', 'Add reply comment' )
|
|
308
|
+
? __( 'Reopen & Reply' )
|
|
309
|
+
: __( 'Reply' )
|
|
285
310
|
}
|
|
286
311
|
rows={ 'approved' === thread.status ? 2 : 4 }
|
|
312
|
+
labelText={ sprintf(
|
|
313
|
+
// translators: %1$s: comment identifier, %2$s: author name
|
|
314
|
+
__( 'Reply to Comment %1$s by %2$s' ),
|
|
315
|
+
thread.id,
|
|
316
|
+
thread?.author_name || 'Unknown'
|
|
317
|
+
) }
|
|
287
318
|
/>
|
|
288
319
|
</VStack>
|
|
289
320
|
</VStack>
|
|
@@ -292,19 +323,12 @@ function Thread( {
|
|
|
292
323
|
);
|
|
293
324
|
}
|
|
294
325
|
|
|
295
|
-
const CommentBoard = ( {
|
|
296
|
-
thread,
|
|
297
|
-
onResolve,
|
|
298
|
-
onReopen,
|
|
299
|
-
onEdit,
|
|
300
|
-
onDelete,
|
|
301
|
-
status,
|
|
302
|
-
} ) => {
|
|
326
|
+
const CommentBoard = ( { thread, onEdit, onDelete, status } ) => {
|
|
303
327
|
const [ actionState, setActionState ] = useState( false );
|
|
304
328
|
const [ showConfirmDialog, setShowConfirmDialog ] = useState( false );
|
|
305
329
|
|
|
306
330
|
const handleConfirmDelete = () => {
|
|
307
|
-
onDelete( thread
|
|
331
|
+
onDelete( thread );
|
|
308
332
|
setActionState( false );
|
|
309
333
|
setShowConfirmDialog( false );
|
|
310
334
|
};
|
|
@@ -317,27 +341,31 @@ const CommentBoard = ( {
|
|
|
317
341
|
const actions = [
|
|
318
342
|
onEdit &&
|
|
319
343
|
status !== 'approved' && {
|
|
344
|
+
id: 'edit',
|
|
320
345
|
title: _x( 'Edit', 'Edit comment' ),
|
|
321
346
|
onClick: () => {
|
|
322
347
|
setActionState( 'edit' );
|
|
323
348
|
},
|
|
324
349
|
},
|
|
325
350
|
onDelete && {
|
|
351
|
+
id: 'delete',
|
|
326
352
|
title: _x( 'Delete', 'Delete comment' ),
|
|
327
353
|
onClick: () => {
|
|
328
354
|
setActionState( 'delete' );
|
|
329
355
|
setShowConfirmDialog( true );
|
|
330
356
|
},
|
|
331
357
|
},
|
|
332
|
-
|
|
358
|
+
onEdit &&
|
|
333
359
|
status === 'approved' && {
|
|
360
|
+
id: 'reopen',
|
|
334
361
|
title: _x( 'Reopen', 'Reopen comment' ),
|
|
335
362
|
onClick: () => {
|
|
336
|
-
|
|
363
|
+
onEdit( { id: thread.id, status: 'hold' } );
|
|
337
364
|
},
|
|
338
365
|
},
|
|
339
366
|
];
|
|
340
367
|
|
|
368
|
+
const canResolve = thread?.parent === 0;
|
|
341
369
|
const moreActions = actions.filter( ( item ) => item?.onClick );
|
|
342
370
|
|
|
343
371
|
return (
|
|
@@ -347,10 +375,17 @@ const CommentBoard = ( {
|
|
|
347
375
|
avatar={ thread?.author_avatar_urls?.[ 48 ] }
|
|
348
376
|
name={ thread?.author_name }
|
|
349
377
|
date={ thread?.date }
|
|
378
|
+
userId={ thread?.author }
|
|
350
379
|
/>
|
|
351
|
-
<
|
|
352
|
-
|
|
353
|
-
|
|
380
|
+
<FlexItem
|
|
381
|
+
className="editor-collab-sidebar-panel__comment-status"
|
|
382
|
+
onClick={ ( event ) => {
|
|
383
|
+
// Prevent the thread from being selected.
|
|
384
|
+
event.stopPropagation();
|
|
385
|
+
} }
|
|
386
|
+
>
|
|
387
|
+
<HStack spacing="0">
|
|
388
|
+
{ canResolve && (
|
|
354
389
|
<Button
|
|
355
390
|
label={ _x(
|
|
356
391
|
'Resolve',
|
|
@@ -361,33 +396,59 @@ const CommentBoard = ( {
|
|
|
361
396
|
disabled={ status === 'approved' }
|
|
362
397
|
accessibleWhenDisabled={ status === 'approved' }
|
|
363
398
|
onClick={ () => {
|
|
364
|
-
|
|
399
|
+
onEdit( {
|
|
400
|
+
id: thread.id,
|
|
401
|
+
status: 'approved',
|
|
402
|
+
} );
|
|
365
403
|
} }
|
|
366
404
|
/>
|
|
367
405
|
) }
|
|
368
|
-
|
|
369
|
-
<
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
406
|
+
<Menu placement="bottom-end">
|
|
407
|
+
<Menu.TriggerButton
|
|
408
|
+
render={
|
|
409
|
+
<Button
|
|
410
|
+
size="small"
|
|
411
|
+
icon={ moreVertical }
|
|
412
|
+
label={ __( 'Actions' ) }
|
|
413
|
+
disabled={ ! moreActions.length }
|
|
414
|
+
accessibleWhenDisabled
|
|
415
|
+
/>
|
|
416
|
+
}
|
|
377
417
|
/>
|
|
378
|
-
|
|
418
|
+
<Menu.Popover>
|
|
419
|
+
{ moreActions.map( ( action ) => (
|
|
420
|
+
<Menu.Item
|
|
421
|
+
key={ action.id }
|
|
422
|
+
onClick={ () => action.onClick() }
|
|
423
|
+
>
|
|
424
|
+
<Menu.ItemLabel>
|
|
425
|
+
{ action.title }
|
|
426
|
+
</Menu.ItemLabel>
|
|
427
|
+
</Menu.Item>
|
|
428
|
+
) ) }
|
|
429
|
+
</Menu.Popover>
|
|
430
|
+
</Menu>
|
|
379
431
|
</HStack>
|
|
380
|
-
</
|
|
432
|
+
</FlexItem>
|
|
381
433
|
</HStack>
|
|
382
434
|
{ 'edit' === actionState ? (
|
|
383
435
|
<CommentForm
|
|
384
436
|
onSubmit={ ( value ) => {
|
|
385
|
-
onEdit(
|
|
437
|
+
onEdit( {
|
|
438
|
+
id: thread.id,
|
|
439
|
+
content: value,
|
|
440
|
+
} );
|
|
386
441
|
setActionState( false );
|
|
387
442
|
} }
|
|
388
443
|
onCancel={ () => handleCancel() }
|
|
389
444
|
thread={ thread }
|
|
390
445
|
submitButtonText={ _x( 'Update', 'verb' ) }
|
|
446
|
+
labelText={ sprintf(
|
|
447
|
+
// translators: %1$s: comment identifier, %2$s: author name.
|
|
448
|
+
__( 'Edit Comment %1$s by %2$s' ),
|
|
449
|
+
thread.id,
|
|
450
|
+
thread?.author_name || 'Unknown'
|
|
451
|
+
) }
|
|
391
452
|
/>
|
|
392
453
|
) : (
|
|
393
454
|
<RawHTML className="editor-collab-sidebar-panel__user-comment">
|