diff --git a/whiteboard/WhiteboardApp.ts b/whiteboard/WhiteboardApp.ts index f63094b2a6..b9c38f6854 100644 --- a/whiteboard/WhiteboardApp.ts +++ b/whiteboard/WhiteboardApp.ts @@ -116,6 +116,8 @@ export class WhiteboardApp extends App implements IUIKitInteractionHandler { \`/whiteboard delete \` - Delete a whiteboard \`/whiteboard help\` - Display helper message \`/whiteboard list\` - List all the board names in the room + \`/whiteboard delete \` - Delete a board + \`/whiteboard search \` - Search a board You can use \`Create Whiteboard\` Action Button to create a new whiteboard as well \n Refer https://github.com/RocketChat/Apps.Whiteboard documentation for more details 🚀`, persistence @@ -252,14 +254,13 @@ export class UpdateBoardEndpoint extends ApiEndpoint { const boardId = request.content.boardId; const boardData = request.content.boardData; const cover = request.content.cover; - const title = request.content.title; - + const savedBoardata = await getBoardRecord( read.getPersistenceReader(), boardId - ); - console.log("savedBoardata", savedBoardata) - const { messageId, privateMessageId, status, boardOwner } = savedBoardata; + ); + const { messageId, privateMessageId, status, boardOwner } = savedBoardata; + const title = request.content.title ? request.content.title : savedBoardata.title; const user = (await read.getMessageReader().getSenderUser(messageId))!; const room = await read.getMessageReader().getRoom(messageId); const AppSender = (await read.getUserReader().getAppUser()) as IUser; @@ -366,4 +367,4 @@ export class DeleteBoardEndpoint extends ApiEndpoint { }, }); } -} +} \ No newline at end of file diff --git a/whiteboard/blocks/UtilityBlock.ts b/whiteboard/blocks/UtilityBlock.ts index 6db1a31267..9cd37e8d75 100644 --- a/whiteboard/blocks/UtilityBlock.ts +++ b/whiteboard/blocks/UtilityBlock.ts @@ -117,7 +117,34 @@ export async function buildHeaderBlockAfterPermission( return block; } -// Header block when whiteboard is deleted +// Header block to take user back to the board + +export async function goToBoardBlock( + boardURL: string, + appId: string, + boardname?: string +): Promise> { + const block: Block[] = []; + const goToBoardButton = getButton( + `Go to the ${boardname} board`, + UtilityEnum.GOTO_BOARD_BLOCK_ID, + UtilityEnum.GOTO_BOARD_BUTTON_ACTION_ID, + appId, + "GOTO", + ButtonStyle.PRIMARY, + boardURL + ); + + let markdownBlock: SectionBlock; + markdownBlock = getMarkdownBlock(`*${boardname}* board`); + + const actionBlock = getActionsBlock(UtilityEnum.PREVIEW_BLOCK_ID, [ + goToBoardButton, + ]); + block.push(markdownBlock); + block.push(actionBlock); + return block; +} // export async function deletionHeaderBlock( // username: string, // boardname: string diff --git a/whiteboard/enum/uitlityEnum.ts b/whiteboard/enum/uitlityEnum.ts index 5dda7ffae8..e61f180b18 100644 --- a/whiteboard/enum/uitlityEnum.ts +++ b/whiteboard/enum/uitlityEnum.ts @@ -41,6 +41,8 @@ export enum UtilityEnum { DELETE_BLOCK_ID = "delete-block-id", NAME_ALREADY_EXISTS = "Name already exists. Try different name", + GOTO_BOARD_BLOCK_ID = "goto-board-block-id", + GOTO_BOARD_BUTTON_ACTION_ID = "goto-board-button-action-id", EDIT = "Edit", EDIT_DESC = "Do you want to edit this whiteboard?", EDIT_MODAL_ID = "edit-modal-id", diff --git a/whiteboard/lib/commandUtility.ts b/whiteboard/lib/commandUtility.ts index bf5833ad3f..bc272acabe 100644 --- a/whiteboard/lib/commandUtility.ts +++ b/whiteboard/lib/commandUtility.ts @@ -10,17 +10,16 @@ import { import { ExecutorProps } from "../definitions/ExecutorProps"; import { WhiteboardApp } from "../WhiteboardApp"; import { - handleListCommand, + handleBoardSearch, + handleList, helperMessage, sendMessage, sendMessageWithAttachment, } from "./messages"; -import { buildHeaderBlock, buildHeaderBlockAfterPermission, deletionHeaderBlock } from "../blocks/UtilityBlock"; +import { buildHeaderBlock, deletionHeaderBlock, goToBoardBlock } from "../blocks/UtilityBlock"; import { WhiteboardSlashCommandContext } from "../commands/WhiteboardCommand"; import { - deleteBoards, getBoardName, - getMessageIdByRoomName, storeBoardRecord, } from "../persistence/boardInteraction"; import { randomId } from "./utilts"; @@ -31,6 +30,7 @@ import { getMessageIdByBoardName, deleteBoardByMessageId, } from "../persistence/boardInteraction"; + import { IMessage } from "@rocket.chat/apps-engine/definition/messages"; //CommandUtility is used to handle the commands @@ -118,7 +118,7 @@ export class CommandUtility implements ExecutorProps { if (room) { const randomBoardId = randomId(); const boardURL = `${boardEndpoint.computedPath}?id=${randomBoardId}`; - + console.log("boardURL ", boardURL) // The variable "untitledName" stores "Untitled" if the name is not specified const untitledName = await getBoardName( read.getPersistenceReader(), @@ -211,10 +211,78 @@ export class CommandUtility implements ExecutorProps { const appSender: IUser = (await this.read .getUserReader() .getAppUser()) as IUser; - await handleListCommand(this.read, this.modify, this.room, appSender); + await handleList(this.read, this.modify, this.room, appSender); } - // handleListCommand is used to handle the /whiteboard delete command + // handleBoardSearchCommand is used to handle the /whiteboard search {boardname} command + + private async handleBoardSearchCommand( + name: string, + { + app, + context, + read, + }: WhiteboardSlashCommandContext + ) { + try { + + const appUser = (await read.getUserReader().getAppUser())!; + const boardData = await handleBoardSearch( + this.read, + this.room, + name + ); + + const sender = context.getSender()!; + const room = context.getRoom(); + let roomType = "channel" + if(room.type === "c"){ + roomType = "channel" + } + else if(room.type === "p"){ + roomType = "group" + } + else if(room.type === "d"){ + roomType = "direct" + } + + + const appId = app.getID(); + const boardURL = `/${roomType}/${room.slugifiedName}?msg=${boardData?.messageId}` + + + if (room && boardData?.id) { + + const goToBoard = await goToBoardBlock( + boardURL, + appId, + name + ) + + const attachments = [ + { + collapsed: true, + color: "#00000000", + imageUrl: boardData.cover !== "" ? boardData.cover : defaultPreview, + }, + ]; + + await sendMessageWithAttachment( + this.modify, + room, + appUser, + `Whiteboard created by @${sender.username}`, + attachments, + goToBoard + ); + } + } catch (err) { + console.error(err); + } + } + + + // deleteBoardCommand is used to handle the /whiteboard delete command private async deleteBoardCommand() { const appId = this.app.getID(); @@ -371,6 +439,9 @@ export class CommandUtility implements ExecutorProps { case "list": await this.handleListCommand(); break; + case "search": + await this.handleBoardSearchCommand(this.command.slice(1).join(' '), context); + break; case "delete": await this.deleteBoardCommand(); break; @@ -393,4 +464,4 @@ export class CommandUtility implements ExecutorProps { break; } } -} +} \ No newline at end of file diff --git a/whiteboard/lib/messages.ts b/whiteboard/lib/messages.ts index cd957f92a0..81d39a1790 100644 --- a/whiteboard/lib/messages.ts +++ b/whiteboard/lib/messages.ts @@ -9,6 +9,7 @@ import { NotificationsController } from "./notifications"; import { Block } from "@rocket.chat/ui-kit"; import { IMessageAttachment } from "@rocket.chat/apps-engine/definition/messages"; import { AppEnum } from "../enum/App"; +import { getMessagebyMessageID } from "../persistence/boardInteraction"; import { getBoardRecordByMessageId, getBoardRecordByRoomId, @@ -179,6 +180,10 @@ export async function helperMessage( appUser: IUser ) { const text = `*Whiteboard App Commands* + \`/whiteboard help\` - Display helper message + \`/whiteboard list\` - List all the whiteboard names in the room + \`/whiteboard delete \` - Delete a board + \`/whiteboard search \` - Search a board \`/whiteboard new \` - Create a new whiteboard \`/whiteboard delete \` - Delete a whiteboard \`/whiteboard help\` - Display helper message @@ -199,7 +204,7 @@ export async function helperMessage( } // function to handle /whiteboard list command -export async function handleListCommand( +export async function handleList( read: IRead, modify: IModify, room: IRoom, @@ -224,6 +229,8 @@ export async function handleListCommand( boardDataCheck ? boardDataCheck.title : "Error here messages.ts" ); } + + console.log("boardData checking list" , boardData) const text = `*All existing boards are*: ${boardDataArray.join("\n")} @@ -356,3 +363,28 @@ export async function addUsertoBoardOwner( return undefined } } + +// Function to search for a board + +export async function handleBoardSearch( + read: IRead, + room: IRoom, + boardName: string +) { + try { + const boardData = await getBoardRecordByRoomId(read.getPersistenceReader(), room.id); + + const foundBoard = boardData.find(board => board.title === boardName); + + if (foundBoard) { + const messageInfo = await getMessagebyMessageID(read.getPersistenceReader(), foundBoard.messageId); + + return { id: foundBoard.id, cover: messageInfo[0].cover, messageId: messageInfo[0].messageId }; + } + + return undefined; + } catch (error) { + console.log('Error in handleBoardSearch:', error); + throw error; + } +} \ No newline at end of file diff --git a/whiteboard/persistence/boardInteraction.ts b/whiteboard/persistence/boardInteraction.ts index 9eadf9563c..0a848ccb74 100644 --- a/whiteboard/persistence/boardInteraction.ts +++ b/whiteboard/persistence/boardInteraction.ts @@ -77,6 +77,21 @@ export const storeBoardRecord = async ( return recordId }; +// query all records with the messageID +export const getMessagebyMessageID = async ( + persistenceRead: IPersistenceRead, + messageId: string +): Promise => { + const association = new RocketChatAssociationRecord( + RocketChatAssociationModel.MESSAGE, + `${messageId}#MessageId` + ); + const result = (await persistenceRead.readByAssociation( + association + )) as Array; + return result; +}; + // query all records within the "scope" - room export const getBoardRecordByRoomId = async ( persistenceRead: IPersistenceRead,