This is an automated email from the ASF dual-hosted git repository.

brusdev pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/activemq-artemis-console.git


The following commit(s) were added to refs/heads/main by this push:
     new dd02a7a  ARTEMIS-5131 - Add a button to copy messages
dd02a7a is described below

commit dd02a7a4815eca92695d6b3834d2dfd7ed76f235
Author: Andy Taylor <[email protected]>
AuthorDate: Fri Nov 15 18:31:07 2024 +0000

    ARTEMIS-5131 - Add a button to copy messages
    
    This will be disabled if the management method does not exist
---
 .../artemis-extension/artemis/artemis-service.ts   | 20 ++++++
 .../artemis/messages/MessagesTable.tsx             | 76 +++++++++++++++++++++-
 2 files changed, 94 insertions(+), 2 deletions(-)

diff --git 
a/artemis-console-extension/artemis-extension/src/artemis-extension/artemis/artemis-service.ts
 
b/artemis-console-extension/artemis-extension/src/artemis-extension/artemis/artemis-service.ts
index 20db62b..b97ce7f 100644
--- 
a/artemis-console-extension/artemis-extension/src/artemis-extension/artemis/artemis-service.ts
+++ 
b/artemis-console-extension/artemis-extension/src/artemis-extension/artemis/artemis-service.ts
@@ -116,6 +116,7 @@ const SEND_MESSAGE_SIG = 
"sendMessage(java.util.Map,int,java.lang.String,boolean
 const DELETE_ADDRESS_SIG = "deleteAddress(java.lang.String)";
 const DELETE_MESSAGE_SIG = "removeMessage(long)";
 const MOVE_MESSAGE_SIG = "moveMessage(long,java.lang.String)";
+const COPY_MESSAGE_SIG = "copyMessage(long,java.lang.String)";
 const CREATE_QUEUE_SIG = "createQueue(java.lang.String,boolean)"
 const CREATE_ADDRESS_SIG = "createAddress(java.lang.String,java.lang.String)"
 const COUNT_MESSAGES_SIG = "countMessages()";
@@ -302,6 +303,11 @@ class ArtemisService {
         return jolokiaService.execute(mbean, MOVE_MESSAGE_SIG, [id, 
targetQueue])
     }
 
+    async copyMessage(id: number, targetQueue: string,  address: string, 
routingType: string, queue: string) {
+        const mbean = createQueueObjectName(await this.getBrokerObjectName(), 
address, routingType, queue);
+        return jolokiaService.execute(mbean, COPY_MESSAGE_SIG, [id, 
targetQueue])
+    }
+
 
     async createQueue(queueConfiguration: string) {
         return await jolokiaService.execute(await this.getBrokerObjectName(), 
CREATE_QUEUE_SIG, [queueConfiguration, false]).then().catch() as string;
@@ -589,6 +595,20 @@ class ArtemisService {
     checkCanBrowseQueue = (queueMBean: MBeanNode ): boolean => {
         return (this.DEBUG_PRIVS && queueMBean?.hasInvokeRights(BROWSE_SIG)) 
?? false;
     }
+
+    doesCopyMessageMethodExist = (broker: MBeanNode | undefined, queue: 
string): boolean => {
+        return this.doesMethodExist(broker, queue, COPY_MESSAGE_SIG);
+    }
+
+    doesMethodExist = (broker: MBeanNode | undefined, queue: string, method: 
string): boolean => {
+        if(broker) {
+            var queueMBean = broker.parent?.find(node => { 
+                return node.propertyList?.get('subcomponent') === 'queues' && 
node.name === queue 
+            })
+            return queueMBean?queueMBean.hasOperations(method): false;
+        }
+        return false;
+    }
 }
 
 export const artemisService = new ArtemisService()
\ No newline at end of file
diff --git 
a/artemis-console-extension/artemis-extension/src/artemis-extension/artemis/messages/MessagesTable.tsx
 
b/artemis-console-extension/artemis-extension/src/artemis-extension/artemis/messages/MessagesTable.tsx
index 7863e05..24b1c49 100644
--- 
a/artemis-console-extension/artemis-extension/src/artemis-extension/artemis/messages/MessagesTable.tsx
+++ 
b/artemis-console-extension/artemis-extension/src/artemis-extension/artemis/messages/MessagesTable.tsx
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import React, { useEffect, useState } from 'react'
+import React, { useContext, useEffect, useState } from 'react'
 import { Column } from '../table/ArtemisTable';
 import { artemisService } from '../artemis-service';
 import { Toolbar, ToolbarContent, ToolbarItem, Text, SearchInput, Button, 
PaginationVariant, Pagination, DataList, DataListCell, DataListCheck, 
DataListItem, DataListItemCells, DataListItemRow, Modal, TextContent, Icon, 
ModalVariant } from '@patternfly/react-core';
@@ -26,6 +26,8 @@ import { eventService } from '@hawtio/react';
 import { QueueSelectInput } from './QueueSelect';
 import { SendMessage } from './SendMessage';
 import { Message } from './MessageView';
+import { ArtemisContext } from '../context';
+import { log } from '../globals';
 
 export type MessageProps = {
   address: string,
@@ -70,9 +72,12 @@ export const MessagesTable: 
React.FunctionComponent<MessageProps> = props => {
   const [selectedTargetQueue, setSelectedTargetQueue] = useState<string>('');
   const [showDeleteMessagesModal, setShowDeleteMessagesModal] = 
useState(false);
   const [showMoveMessagesModal, setShowMoveMessagesModal] = useState(false);
+  const [showCopyMessagesModal, setShowCopyMessagesModal] = useState(false);
   const [showResendModal, setShowResendModal] = useState(false);
   const [ resendMessage, setResendMessage] = useState<Message | undefined>();
 
+  const { brokerNode } = useContext(ArtemisContext);
+
   useEffect(() => {
     const listData = async () => {
       var data = await listMessages();
@@ -176,6 +181,13 @@ export const MessagesTable: 
React.FunctionComponent<MessageProps> = props => {
     return selectedMessages.includes(id);
   }
 
+  const doesCopyMessagemethodExist = 
artemisService.doesMethodExist(brokerNode, props.queue, "copyMessage");
+
+  if(!doesCopyMessagemethodExist) {
+    log.warn("Copy button method not available in this version of Artemis");
+    
+  }
+
   const selectAllMessages = (isSelecting: boolean) => {
     if(isSelecting) {
         var updatedSelectedMessages: number[] = rows.map((row: any, index) => {
@@ -247,6 +259,35 @@ export const MessagesTable: 
React.FunctionComponent<MessageProps> = props => {
     setSelectedMessages([]);
   }
 
+  const handleCopyMessages = () => {
+
+    const isRejected = <T,>(p: PromiseSettledResult<T>): p is 
PromiseRejectedResult => p.status === 'rejected';
+    var results: Promise<unknown>[] = [];
+    for (let i = 0; i < selectedMessages.length; i++) {
+      var promise: Promise<unknown> = 
artemisService.copyMessage(selectedMessages[i], selectedTargetQueue, 
props.address, props.routingType, props.queue);
+      results.push(promise);
+    };
+    Promise.allSettled(results)
+      .then((results) => {
+        const rejectedReasons = results.filter(isRejected).map(p => p.reason);
+
+        if (rejectedReasons.length > 0) {
+          eventService.notify({
+            type: 'warning',
+            message: "not all messages copied: errors " + 
rejectedReasons.toString(),
+          })
+        } else {
+          eventService.notify({
+            type: 'success',
+            message: "Messages Successfully Copied [" + selectedMessages + "]",
+          })
+        }
+      });
+
+    setShowCopyMessagesModal(false);
+    setSelectedMessages([]);
+  }
+
   return (
     <React.Fragment>
       <Toolbar id="toolbar">
@@ -272,7 +313,10 @@ export const MessagesTable: 
React.FunctionComponent<MessageProps> = props => {
             <Button onClick={() => 
setShowMoveMessagesModal(true)}>Move</Button>
           </ToolbarItem>
           <ToolbarItem>
-            <Button variant='link' onClick={handleColumnsModalToggle}>Manage 
Columns</Button>
+            <Button onClick={() => setShowCopyMessagesModal(true)} 
isDisabled={!doesCopyMessagemethodExist} >Copy</Button>
+          </ToolbarItem>
+          <ToolbarItem>
+            <Button variant='link' onClick={handleColumnsModalToggle} >Manage 
Columns</Button>
           </ToolbarItem>
         </ToolbarContent>
       </Toolbar>
@@ -395,6 +439,34 @@ export const MessagesTable: 
React.FunctionComponent<MessageProps> = props => {
           <QueueSelectInput selectQueue={setSelectedTargetQueue}/>
         </TextContent>
       </Modal>
+      <Modal
+        aria-label='copy-message-modal'
+        variant={ModalVariant.medium}
+        isOpen={showCopyMessagesModal}
+        actions={[
+          <Button key="cancel" variant="secondary" onClick={() => 
setShowCopyMessagesModal(false)}>
+            Cancel
+          </Button>,
+          <Button key="copy" variant="primary" onClick={handleCopyMessages}>
+            Confirm
+          </Button>
+        ]}>
+        <TextContent>
+          <Text component="h2">
+            Confirm Copy Message(s)
+          </Text>
+          <Text component="p">
+            <Icon isInline status='warning'>
+              <ExclamationCircleIcon />
+            </Icon>
+            You are about to copy messages {selectedMessages.toString()}
+          </Text>
+          <Text component="p">
+            This operation cannot be undone so please be careful.
+          </Text>
+          <QueueSelectInput selectQueue={setSelectedTargetQueue}/>
+        </TextContent>
+      </Modal>
       <Modal
         title="Resend Message"
         isOpen={showResendModal}


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information, visit: https://activemq.apache.org/contact


Reply via email to