RocketChat / Rocket.Chat

The communications platform that puts data protection first.
https://rocket.chat/
Other
40.61k stars 10.61k forks source link

ui-kit there is no way to access the contents of the InputBlock #33888

Open Welets opened 1 week ago

Welets commented 1 week ago

It looks like I found a bug, and an understatement in the wiki, I don’t even know anymore. The gist: I'm trying to pass the value of a text input block entered by the user. I need it in exactly that window. Since this is the data for forming the request. However, it seems there is simply no such way. And why is there a text input in the ui kit in this case? The code I'm using:

app.ts

`import {
    IAppAccessors,
    IConfigurationExtend,
    IHttp,
    ILogger,
    IModify,
    IPersistence,
    IRead,
} from "@rocket.chat/apps-engine/definition/accessors";
import { App } from "@rocket.chat/apps-engine/definition/App";
import { IAppInfo } from "@rocket.chat/apps-engine/definition/metadata";
import {
    IUIKitResponse,
    UIKitLivechatBlockInteractionContext,
    UIKitBlockInteractionContext,
} from "@rocket.chat/apps-engine/definition/uikit";
import { MemeAsImageAttachment } from "./lib/MemeAsImageAttachment";

import { MemeCommand } from "./commands/meme";
import {
    IMessage,
    IPostMessageSent,
} from "@rocket.chat/apps-engine/definition/messages";
import { initiatorMessage } from "./lib/initiatorMessage";

export class testApp extends App implements IPostMessageSent {
    private appInfo: IAppInfo;

    constructor(info: IAppInfo, logger: ILogger, accessors: IAppAccessors) {
        super(info, logger, accessors);
        this.appInfo = info; // Сохраняем информацию о приложении
    }

public async executeBlockActionHandler(
    context: UIKitBlockInteractionContext,
    read: IRead,
    http: IHttp,
    persistence: IPersistence,
    modify: IModify
) {
    const data = context.getInteractionData();
    const { actionId } = data;

    try {
        const { room } = context.getInteractionData();

        if (!room) {
            console.error("Room is undefined");
            return { success: false };
        }

        const issueId = data.value; // Получаем issueId из data.value
        let responseText = "";
        let comment: string | undefined; // Объявляем comment как string | undefined

        // Обработка для commentAction
        if (actionId === "commentAction") {
            comment = data.value; // Получаем комментарий из data.value
            console.log(`Обработка комментария: ${comment}`);
        }

        if (data.value === "complete") {
            responseText = "Готово";
        } else {
            const apiKey = "api"; // Замените на созданный ключ для бота
            const url = `http://url3000/issues/${issueId}.json`;

            await http.put(url, {
                headers: {
                    "Content-Type": "application/json",
                    "X-Redmine-API-Key": apiKey,
                },
                data: {
                    issue: {
                        status_id: 8,
                        notes: comment ?? "Нет комментария" // Используем оператор нулевого слияния
                    },
                },
            });
        }

        return {
            success: true,
        };
    } catch (err) {
        console.error(err);
        return {
            success: false,
        };
    }
}

    public async executePostMessageSent(
        message: IMessage,
        read: IRead,
        http: IHttp,
        persistence: IPersistence,
        modify: IModify
    ): Promise<void> {
        // Проверяем, что сообщение не из LiveChat и не от самого бота
        if (message.room.type === "l" || message.sender.id === this.appInfo.id) {
            return;
        }

        // Проверяем наличие вложений и их содержимое
        if (!message.attachments || message.attachments.length === 0) {
            return; // Если нет вложений, выходим из функции
        }

        // Ищем вложение со статусом
        for (const attachment of message.attachments) {
            console.log(`Текущее вложение: ${JSON.stringify(attachment)}`);

            if (attachment.fields && Array.isArray(attachment.fields)) {
                for (const field of attachment.fields) {
                    if (field.title === "Статус") {
                        const statusValue = field.value; // Извлекаем значение статуса

                        const statusMessage = `Найден статус: ${statusValue}`;
                        console.log(statusMessage); // Логируем статус

                        if (statusValue === "✎ Approve" || statusValue === "⚡ Art approve") {
                            const regex = /(.+?) - (.+?) #(\d+): (ep\d+_seq\d+_sh\d+)/;

                            if (message.text && regex.test(message.text)) {
                                const match = message.text.match(regex);

                                if (match) {
                                    const project = match[1];
                                    const tracker = match[2].split('|')[1];
                                    const issueNumber = match[3];
                                    const issueData = match[4];

                                    const newText = `Сменить статус на: ${issueNumber}: ${issueData} (Проект: ${project}, Трекер: ${tracker})`;
                                    const data = {
                                        room: message.room,
                                        sender: message.sender,
                                        tracker,
                                        issueNumber,
                                        issueData,
                                        messageText: newText,
                                    };
                                    await initiatorMessage({ data, read, persistence, modify, http });
                                    return;
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    protected async extendConfiguration(
        configuration: IConfigurationExtend
    ): Promise<void> {
        await configuration.slashCommands.provideSlashCommand(
            new MemeCommand(this)
        );
    }
}
**initiatorMessage.ts**
`import {
    IHttp,
    IModify,
    IPersistence,
    IRead,
} from "@rocket.chat/apps-engine/definition/accessors";
import { ButtonStyle } from "@rocket.chat/apps-engine/definition/uikit";

export async function initiatorMessage({
    data,
    read,
    persistence,
    modify,
    http,
}: {
    data;
    read: IRead;
    persistence: IPersistence;
    modify: IModify;
    http: IHttp;
}) {
    const builder = await modify.getCreator().startMessage().setRoom(data.room);

    const block = modify.getCreator().getBlockBuilder();

    // Извлекаем данные из messageText
    const { tracker, issueNumber, issueData, comment } = data;

    // Формируем новый текст для блока
    const newText = `${tracker} #${issueNumber}: ${issueData} - сменить статус на 👇`;

    block.addSectionBlock({
        text: block.newPlainTextObject(newText),
    });

    block.addActionsBlock({
        blockId: "subreddits",
        elements: [
            block.newButtonElement({
                actionId: "complete",
                text: block.newPlainTextObject("Complete"),
                value: "complete",
                style: ButtonStyle.PRIMARY,
            }),
            block.newButtonElement({
                actionId: "memeSelect",
                text: block.newPlainTextObject("Fix it"),
                value: issueNumber,
                style: ButtonStyle.PRIMARY,
            }),
            block.newButtonElement({
                actionId: "test_but",
                text: block.newPlainTextObject("test comment"),
                value: issueNumber,
                style: ButtonStyle.PRIMARY,
            }),
        ],
    });

    // Добавляем поле для ввода комментария
    block.addInputBlock({
        blockId: "commentInput",
        element: block.newPlainTextInputElement({
            actionId: "commentAction",
            placeholder: block.newPlainTextObject("Поле для комментария"),
        }),
        label: block.newPlainTextObject("Поле для комментария"),
    });

    builder.setBlocks(block);

    // Отправляем сообщение с кнопками и полем ввода в общий чат
    await modify.getCreator().finish(builder);
}

there must be some way to pass the commentInput text value to my request

            await http.put(url, {
                headers: {
                    "Content-Type": "application/json",
                    "X-Redmine-API-Key": apiKey,
                },
                data: {
                    issue: {
                        status_id: 8,
                        notes: comment ?? "No comment" // Use the null merge operator
                    },
                },
            });
        }

Yes, I already know about the support. However, I cannot call the absence of the method anything other than a bug! Therefore, if I haven’t found such a method, then just write it to me in response, simply correcting my code or pointing out the fundamental problems with it and why I could not use the method. Which might work in other conditions. Thank you

Steps to reproduce:

Expected behavior:

Actual behavior:

Server Setup Information:

Client Setup Information

Additional context

Relevant logs:

reetp commented 2 days ago

Yes, I already know about the support.

Excellent. Please use it.

https://open.rocket.chat/channel/support

or your existing thread here:

https://forums.rocket.chat/t/text-input-block-ui-kit/20856

simply correcting my code

No one is going to sit and write code for you for free.

However, I cannot call the absence of the method anything other than a bug!

Nope. Assuming this isn't an XY problem, and it isn't just a support issue, then if it works generally but doesn't do what you want it to do, at best it's called a feature request and there is a repo for that.

However this has the hallmarks of a support request. Please use the appropriate channels for that.