slackapi / deno-slack-sdk

SDK for building Run on Slack apps using Deno
https://api.slack.com/automation
MIT License
166 stars 28 forks source link

[QUERY] Scheduled Trigger, which sends a message with a button, which triggers an OpenForm, only allows button to be pressed by one user? #363

Open jpaulgale opened 1 month ago

jpaulgale commented 1 month ago

Question

First step of workflow is SendMessage with button in an interactive block. After a user submits the two fields in the form, it is stored using a datastore.

Issue is that the button in the SendMessage (in the channel for all users to see) disappears after one user submits a form, leaving unhelpful messages in the place of the button like <@message interactor user_id> submitted or <@message interactor user_id> action is not available.

For my app to work as intended, I'd like for all users to be able to submit a form response many times as they'd like, as opposed to the message disappearing after just one user's successful submission.

It seemed as though https://github.com/seratch/slack-next-generation-platform-tutorials/tree/main/12_Button_Interactions was of some relevance, but I have not been able to successfully integrate some of @seratch 's concepts.

I know that I could do this by sending out the /shortcuts/ link, but I'd really prefer for UI reasons to have it be a clean, simple, and customized message.

Context

Weekly Kudos sends a message -- say, CallForSubmissions -- on Friday 10am, asking users in a channel to click a "Submit" button, which triggers an OpenForm. The form's completed submissions get sent to a slack datastore.

On Friday at 2pm, all kudos submitted since the last friday at 2pm are collated and sent out in that same channel, tagging each user that was recognized for their kudos-worthy act. Let's call that CollatedListofSubmittedKudosSinceLastWeek.

I have previously attempted to build this in the no-code workflow builder (which did allow for a persistent submit button) on the scheduled message, but the only way to store data using that system appeared to be via google sheets, which would return only one row instead of all rows submitted since last week. I even attempted to make a second table in the sheet which would collate all of the rows, but that wasn't even doing the trick.

Environment

   "deno-slack-sdk/": "https://deno.land/x/deno_slack_sdk@2.14.2/",
    "deno-slack-api/": "https://deno.land/x/deno_slack_api@2.8.0/"

deno 1.46.3 (stable, release, aarch64-apple-darwin)
v8 12.9.202.5-rusty
typescript 5.5.2

ProductName:        macOS
ProductVersion:     14.6.1
BuildVersion:       23G93
Darwin Kernel Version 23.6.0: Mon Jul 29 21:14:30 PDT 2024; root:xnu-10063.141.2~1/RELEASE_ARM64_T6030
zimeg commented 1 month ago

Hey @jpaulgale! :wave: This is a nice way to be using scheduled triggers and neat examples to reference! 👀

Update: I had missed notes from a recent release! With new workflows, message that have interactive buttons will default to multi-click!

Adding the following step with your own shortcut link will hopefully work, but let me know if it doesn't... You might have to remove and re-add the workflow from your manifest if nothing changes with the button 😳


SampleWorkflow.addStep(
  Schema.slack.functions.SendMessage,
  {
    channel_id: SampleWorkflow.inputs.channel_id,
    message: "greetings",
    interactive_blocks: [{
      type: "actions",
      elements: [
        {
          type: "button",
          url:
            "https://slack.com/shortcuts/Ft0123456789/485b0252927b166cd8a3b3c0bdb1b708",
          text: { type: "plain_text", text: "Submit" },
          style: "primary",
          value: "submit",
          action_id: "submit_button",
        },
      ],
    }],
  },
);

I think the CallForSubmissions workflow still might make sense as separate steps from a CollectSubmission workflow, but am curious to know if this is working for a new workflow or still removing the button after a click? 🙏

jpaulgale commented 1 month ago

Hi @zimeg -- thanks for your quick reply. The link you shared is to the no code workflow interface? Want to make sure I'm understanding correctly that it's not directly relevant to my deno slack app, but a new feature for the no code apps.

when adding this suggested code here in the first step

import { DefineWorkflow, Schema } from "deno-slack-sdk/mod.ts";
import { StoreKudosFunction } from "../functions/store_kudos.ts";

export const SubmitKudosWorkflow = DefineWorkflow({
  callback_id: "submit_kudos_workflow",
  title: "Submit Kudos",
  description: "Submit kudos for team members",
  input_parameters: {
    properties: {
      channel: {
        type: Schema.slack.types.channel_id,
      },
    },
    required: ["channel"],
  },
});

// Add a step to send a message with a button
const sendMessage = SubmitKudosWorkflow.addStep(
  Schema.slack.functions.SendMessage,
  {
    channel_id: SubmitKudosWorkflow.inputs.channel,
    message: "Submit kudos here, to recognize any of your teammates who went above and beyond this week :slightly_smiling_face:",
    interactive_blocks: [{
      type: "actions",
      elements: [
        {
          type: "button",
+         url: "https://slack.com/shortcuts/Ft07P32XV59R/631f7edf86081179a12af8a5938b4f29", // This is your actual shortcut URL
          text: { type: "plain_text", text: "Submit" },
+         style: "primary",
+         value: "Submit",
-         action_id: "submit_kudos_button",
+         action_id: "submit_button",
        },
      ],
    }],
  },
);

const kudoForm = SubmitKudosWorkflow.addStep(
  Schema.slack.functions.OpenForm,
  {
    title: "Submit Kudos",
    interactivity: sendMessage.outputs.interactivity,
    submit_label: "Submit",
    fields: {
      elements: [{
        name: "kudo_recipients",
        title: "Who deserves kudos?",
        type: Schema.types.array,
        items: {
          type: Schema.slack.types.user_id,
        },
      }, {
        name: "kudo_reason",
        title: "What did they do to deserve kudos?",
        type: Schema.types.string,
      }],
      required: ["kudo_recipients", "kudo_reason"],
    },
  },
);

SubmitKudosWorkflow.addStep(StoreKudosFunction, {
  kudo_recipients: kudoForm.outputs.fields.kudo_recipients,
  kudo_reason: kudoForm.outputs.fields.kudo_reason,
  submitted_by: kudoForm.outputs.interactivity.interactor.id,
});

export default SubmitKudosWorkflow;

after having run slack run and then removed (from manifest.json) and re-added the workflow import, as well as within the Workflows: [] parameter,

I am continuing to receive this error

🚫 The provided manifest file does not validate against schema. Consult the additional errors field to locate specific issues (invalid_manifest)
   Interactivity at step 2 needs to be mapped to an interactivity in step 1's output (invalid_interactivity_pointer)
   Source: /workflows/submit_kudos_workflow/steps/1

the trigger only has channel as an input, and does not have interactivity.

I've tried to do my homework and google to see other people's issues with this, but coming up short on an answer.

Does the message with the new shortcut url button, as you see it, conclude that workflow, and the clicking of the button is its own trigger, which begins the openmodal + then store results workflow?

zimeg commented 1 month ago

@jpaulgale Thanks for sharing what you tried once again, it's so helpful 🙏

You're correct to call out that link referencing no-code, but similar features should be available in coded workflows, and the concerns of compatibility make total sense. I think with some change we can mimic these behaviors though!

I dove into this a bit more and the url from interactive_blocks removes interactivity from the output of this step. I'll look into documenting this, but using workflow_buttons might be another solid alternative 👀

With that change, I believe a separate RequestKudosWorkflow might be required for posting the SubmitKudosWorkflow shortcut trigger. I'm unsure of other patterns right now, but found that I could recreate this example with this manifest and these triggers:

kudos

Does the message with the new shortcut url button, as you see it, conclude that workflow, and the clicking of the button is its own trigger, which begins the openmodal + then store results workflow?

I'm thinking of the original button as a "gate" to the workflow, where pressing it continues to the next step with interactivity needed for the OpenForm and following steps. This gets confusing with workflow_button, but I was finding this behavior with a plain button.

Let me know if the example I shared makes sense as a starting place for the repeated button clicks! More change are needed to store kudos, but I'm wondering if this covers the starting case alright. And a bit of nuance is scattered throughout, but this diff should highlight the most important changes 🚀