@@ -10,6 +10,8 @@ import { styled } from '@mui/material/styles';
1010import React from 'react' ;
1111import { QueryToolEventsContext } from '../QueryToolComponent' ;
1212import { QUERY_TOOL_EVENTS } from '../QueryToolConstants' ;
13+ import gettext from 'sources/gettext' ;
14+ import { PgMenu , PgMenuItem } from '../../../../../../static/js/components/Menu' ;
1315
1416const StyledDiv = styled ( 'div' ) ( ( { theme} ) => ( {
1517 whiteSpace : 'pre-wrap' ,
@@ -27,6 +29,8 @@ const StyledDiv = styled('div')(({theme}) => ({
2729export function Messages ( ) {
2830
2931 const [ messageText , setMessageText ] = React . useState ( '' ) ;
32+ const [ contextPos , setContextPos ] = React . useState ( null ) ;
33+ const containerRef = React . useRef ( null ) ;
3034 const eventBus = React . useContext ( QueryToolEventsContext ) ;
3135 React . useEffect ( ( ) => {
3236 eventBus . registerListener ( QUERY_TOOL_EVENTS . SET_MESSAGE , ( text , append = false ) => {
@@ -38,5 +42,45 @@ export function Messages() {
3842 } ) ;
3943 } ) ;
4044 } , [ ] ) ;
41- return < StyledDiv tabIndex = "0" > { messageText } </ StyledDiv > ;
45+
46+ const handleContextMenu = React . useCallback ( ( e ) => {
47+ e . preventDefault ( ) ;
48+ setContextPos ( { x : e . clientX , y : e . clientY } ) ;
49+ } , [ ] ) ;
50+
51+ const selectAll = React . useCallback ( ( ) => {
52+ if ( containerRef . current ) {
53+ const selection = window . getSelection ( ) ;
54+ const range = document . createRange ( ) ;
55+ range . selectNodeContents ( containerRef . current ) ;
56+ selection . removeAllRanges ( ) ;
57+ selection . addRange ( range ) ;
58+ }
59+ setContextPos ( null ) ;
60+ } , [ ] ) ;
61+
62+ const copyToClipboard = React . useCallback ( ( ) => {
63+ const selection = window . getSelection ( ) ;
64+ const text = selection . toString ( ) ;
65+ if ( text ) {
66+ navigator . clipboard . writeText ( text ) ;
67+ }
68+ setContextPos ( null ) ;
69+ } , [ ] ) ;
70+
71+ return < >
72+ < StyledDiv tabIndex = "0" ref = { containerRef } onContextMenu = { handleContextMenu } >
73+ { messageText }
74+ </ StyledDiv >
75+ < PgMenu
76+ anchorPoint = { contextPos ? { x : contextPos . x , y : contextPos . y } : undefined }
77+ open = { Boolean ( contextPos ) }
78+ onClose = { ( ) => setContextPos ( null ) }
79+ label = "messages-context"
80+ portal
81+ >
82+ < PgMenuItem onClick = { copyToClipboard } > { gettext ( 'Copy' ) } </ PgMenuItem >
83+ < PgMenuItem onClick = { selectAll } > { gettext ( 'Select All' ) } </ PgMenuItem >
84+ </ PgMenu >
85+ </ > ;
4286}
0 commit comments