{"id":23543701,"url":"https://github.com/TrueSparrowSystems/slackmin","last_synced_at":"2025-08-29T03:32:04.403Z","repository":{"id":37824721,"uuid":"492696216","full_name":"TrueSparrowSystems/slackmin","owner":"TrueSparrowSystems","description":"Slack Superpowers for Business Ops","archived":false,"fork":false,"pushed_at":"2024-03-01T17:44:45.000Z","size":311,"stargazers_count":51,"open_issues_count":2,"forks_count":6,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-08-19T15:25:44.936Z","etag":null,"topics":["admin","slack"],"latest_commit_sha":null,"homepage":"https://plgworks.com/slackmin","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TrueSparrowSystems.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-05-16T05:32:58.000Z","updated_at":"2025-02-17T04:24:45.000Z","dependencies_parsed_at":"2025-04-12T12:00:42.719Z","dependency_job_id":null,"html_url":"https://github.com/TrueSparrowSystems/slackmin","commit_stats":null,"previous_names":["plg-works/slackmin"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/TrueSparrowSystems/slackmin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TrueSparrowSystems%2Fslackmin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TrueSparrowSystems%2Fslackmin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TrueSparrowSystems%2Fslackmin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TrueSparrowSystems%2Fslackmin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TrueSparrowSystems","download_url":"https://codeload.github.com/TrueSparrowSystems/slackmin/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TrueSparrowSystems%2Fslackmin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272619383,"owners_count":24965415,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-29T02:00:10.610Z","response_time":87,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["admin","slack"],"created_at":"2024-12-26T07:11:03.816Z","updated_at":"2025-08-29T03:32:03.946Z","avatar_url":"https://github.com/TrueSparrowSystems.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Group 11088](https://user-images.githubusercontent.com/7627517/179924973-20755a21-db85-428c-9f25-a0b693d0ab87.png)\n\n![npm version](https://img.shields.io/npm/v/@truesparrow/slackmin.svg?style=flat)\n\nSlackmin allows you to easily integrate slack [slash (/) commands](https://api.slack.com/interactivity/slash-commands), [interactive components](https://api.slack.com/interactivity/components), message formatting \u0026 custom modals in your Node.js application. You can build and setup custom tailored tools for your daily ops like different analytics reports, content management interfaces, customer support modules and much more. Also send alerts and notifications over Slack for your team to take actions on critical events in your application.\n\n## Business Benefits\n- Use **Slack’s Web, Desktop and Mobile apps** to manage your Content, Orders, Reports, Customers and much more.\n- **Focus** on your Product instead of building custom solutions for your admin needs. Use Slack to manage everything and save valuable time.\n- **Spend Less $** on Admin Tools. Use the tool you already have, use Slack!\n- Use public and private channels in Slack to **manage access** to certain types of data and features. Additionally, you can whitelist slack users for specific functionalities.\n- Leverage the robust **Search** features in Slack so your team has easy access to historical data.\n- Users can setup their own push **notifications** in Slack to get alerts about the data they need most.\n- **Logs for actions** taken by your admins like updated product details, Customer queries, Payment notifications and much more are easily searchable and accessible.\n\n## Developer Benefits\n- Slackmin is **open source**. Developers can use (as it is) or modify Slackmin for their custom needs, for free!\n- Slack has built a **secure platform**. Slackmin uses this secure infrastructure instead of you building your own security layers.\n- Slackmin provides **Message and Modal wrappers** that help in easy formatting \u0026 sending messages, sending system alerts and [creating modals](https://slack.dev/bolt-js/concepts#creating-modals). No need to create complex data structures for message and modal layout.\n- Slackmin's multiple slack app support helps in overcoming the 25 slash commands limitation per slack app. You can also create multiple applications for better access control.\n- The [block actions payload](https://api.slack.com/reference/interaction-payloads/block-actions) and [view submission payload](https://api.slack.com/reference/interaction-payloads/views#view_submission) are validated and parsed into a key-value pair of parameters.\n\nAdditionally, Slackmin provides following **built-in security** features as middlewares:\n- **Sanitize unwanted HTML tags** from parameters obtained in the request body, query and headers. [HTML sanitization](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html#html-sanitization) is recommended by Open Web Application Security Project (OWASP)\n- **Signature / signed secret verification** is provided as a middleware ready to be plugged in and used for all the requests coming from slack. This [guide](https://api.slack.com/authentication/verifying-requests-from-slack) gives a detailed description of signature verification.\n- **Slack app id** is validated against whitelisted app ids.\n- **Slack channel** validation is done to only allow requests from whitelisted slack channels.\n- **User authentication** helps in validating whether the slack user has the correct privileges or not.\n- Slack app’s **workspace domain** validation is also exposed as a middleware.\n\n## Demo\n\nAs a demo of Slackmin, let's take an example use case: Customer Support Team receives a complaint on broken product. They want to check on the user’s order history and issue refund.\n\nThe customer support executive gets the order details using a slash command. Then the executive clicks on the \"User Order History\" button to get a sheet URL, which has all the past orders from that user. After checking the order history, executive clicks on the \"Issue Refund\" button to open the issue refund modal, provides the required information and clicks \"Submit\". Voila! Refund issued along with a log message in the channel, which brings in transparency.\n\nhttps://user-images.githubusercontent.com/7627517/181164530-ee5772ca-e477-4725-9f52-65c097940f8e.mp4\n\n## Prerequisites\n- [Node.js](https://nodejs.org/en/)\n- [NPM](https://www.npmjs.com/package/npm)\n\n## Slack app setup\nFirst things first, setup a slack app as mentioned in [this guide](https://api.slack.com/authentication/basics). Following are the major steps involved:\n\n- Create a slack app. Visit https://api.slack.com/apps.\n- Configure request URL for interactive components. Click [here](https://api.slack.com/interactivity/handling) for details.\n- Configure slash commands. For more details [click here](https://api.slack.com/interactivity/slash-commands).\n- Add scopes [chat:write](https://api.slack.com/scopes/chat:write) and [chat:write:public](https://api.slack.com/scopes/chat:write.public) to the bot token scopes. Know more about [Slack Scopes](https://api.slack.com/scopes).\n- Then [install](https://api.slack.com/authentication/basics#installing) the app to your workspace.\n\nKeep a note of your App ID and Signing Secret from the \"Basic Information\" section of your app. Also note the Bot User OAuth Token from the \"OAuth \u0026 Permissions\" section of your app. These details will be required later.\n\n## Install NPM\n\n```shell script\nnpm install @truesparrow/slackmin --save\n```\n\n## Initialize\nWhile using the package, create a singleton object of Slackmin and then use it across the application.\nExample snippet for the Slackmin singleton object is given below.\n\n```js\nconst Slackmin = require('@truesparrow/slackmin');\n\nconst appConfigs = [\n  {\n    id: '\u003cslack_app_id\u003e',\n    secret: '\u003cslack_signing_secret\u003e',\n    slack_bot_user_oauth_token: '\u003cslack_bot_user_oauth_token\u003e',\n    slack_domain: '\u003cyour_slack_domain\u003e'\n  }\n];\n\nconst whiteListedChannels = ['\u003cslack_channel_id\u003e', '\u003cslack_channel_id\u003e', '\u003cslack_channel_id\u003e'];\n\nconst whitelistedUsers = ['\u003cslack_member_id\u003e', '\u003cslack_member_id\u003e', '\u003cslack_member_id\u003e'];\n\nconst slackmin = new Slackmin(\n  appConfigs,\n  whiteListedChannels,\n  whitelistedUsers\n);\n\nmodule.exports = slackmin;\n```\n\n### Initialization Params\n**1. `appConfigs`** is an array of app config objects allowing Slackmin to support multiple apps. Each app config consists of id, secret, token and domain.\n\n- **id**: This is your slack app id.\n- **secret**: Your app's signing secret. It is required for signature verification.\n- **slack_bot_user_oauth_token**: This is the Bot User OAuth Token.\n- **slack_domain**: This is your slack app's workspace domain. Apps can reside on different slack domains. \n\n\u003cbr\u003e\n\n**2. `whiteListedChannels`** is an array of whitelisted channel ids. Only whitelisted users are allowed to execute slash commands in the whitelisted channels. Pass `whiteListedChannels` as an empty array to skip this validation.\n\n\u003cbr\u003e\n\n**3. `whitelistedUsers`** is an array of whitelisted slack member ids. Only whitelisted users are allowed to execute slash commands in the whitelisted channels. Pass `whitelistedUsers` as an empty array to skip this validation.\n\n## Middlewares\n\nSlackmin middlewares are used with slash commands as well as with interactive routes. These middlewares format and preprocess the Slack payload and sanitize unwanted HTML tags from parameters obtained in the request body, query and headers. Slackmin has a built-in security layer for request verification, app id validation, channel id validation and slack member id validation.\n\n### Interactive Component Middlewares\n```js\nconst express = require('express');\nconst slackmin = require('path-to-your-slackmin-singletone-provider');\nconst router = express.Router();\n\n// common middlewares\n// This set of middlewares can be used with slash commands as well as with interactive routes.\nrouter.use(\n  slackmin.commonMiddlewares\n);\n\n//  interactive-endpoint middlewares\n// This set of middlewares can be used with interactive routes.\nrouter.use(\n  slackmin.interactiveEndpointMiddlewares\n);\n\n// Example interactive endpoint\nrouter.post(\n  '/interactive-endpoint',\n  async function(req, res, next) {\n     // your business logic\n    // req.decodedParams contains sanitized parameters and must be used to read data for further business logic.\n   console.log(req.decodedParams);  }\n);\n```\n\n### Slash Command Middlewares\n```js\nconst express = require('express');\nconst slackmin = require('path-to-your-slackmin-singletone-provider');\nconst router = express.Router();\n\n// common middlewares\n// This set of middlewares can be used with slash commands as well as with interactive routes.\nrouter.use(\n  slackmin.commonMiddlewares\n);\n\n// slash ('/') command middlewares\n// This set of middlewares can be used with Slash commands.\nrouter.use(\n  slackmin.slashCommandMiddlewares\n);\n\n// Write all routes specific to slash commands below.\n// Example slash command endpoint\nrouter.post(\n  '/slash-command',\n  async function(req, res, next) {\n     // your business logic\n    // req.decodedParams contains sanitized parameters and must be used to read data for further business logic.\n   console.log(req.decodedParams);\n  }\n);\n```\n**Important Note**: `req.decodedParams` contains sanitized parameters and must be used to read data for further business logic.\n\n## Validators\n\nValidators are functions which expose the middleware functionality which can be used in non express Node js frameworks like Koa, Fastify, etc.\n\n**Methods**\n\n- `common` - function accessed as `slackmin.validators.common`\n    - Parameters: requestBody, requestQuery, requestHeaders, requestMethod\n    - Description: This method can be used for implementing common middleware for slash command and interactive-endpoint routes.\n- `interactive` - function accessed as `slackmin.validators.interactive`\n    - Parameters: requestParams, requestBody, requestHeaders, decodedParams, internalDecodedParams\n    - Description: This method can be used for implementing interactive endpoint middleware for interactive-endpoint route.\n- `slashCommands` - function accessed as `slackmin.validators.slashCommands`\n    - Parameters: requestBody, requestRawBody, requestHeaders, decodedParams\n    - Description: This method can be used for implementing slash command middleware for slash command route.\n\nRefer validators methods usage examples [here](https://github.com/TrueSparrowSystems/slackmin/tree/master/examples/koa)\n\n## Interactive Components\n\nSlack provides a range of visual components (Block Kit) used to layout complex information. These blocks are represented as JSON objects. You can include up to 50 blocks in a message and 100 blocks in a modal.\nYou can find the Block Kit reference [here](https://api.slack.com/reference/block-kit/blocks).\n\n### Message Wrapper\n\nSlackmin Message wrapper provides simple methods to create and format complex message layouts thus simplifying the creation of [block elements](https://api.slack.com/reference/block-kit/block-elements).\n\n**Methods**\n\n- `addSection`\n  - Parameters: text (string)\n  - Description: Adds a [section](https://api.slack.com/reference/block-kit/blocks#section) block with the provided text. Supports [mrkdwn](https://api.slack.com/reference/surfaces/formatting).\n- `addSectionWithTextFields`\n  - Parameters: texts (array of strings)\n  - Description: Adds a [section](https://api.slack.com/reference/block-kit/blocks#section) block with two columns layout to display provided texts. Supports [mrkdwn](https://api.slack.com/reference/surfaces/formatting).\n- `addButton`\n  - Parameters: labelText (string), buttonText (string), value (string)\n  - Description: Adds a [section](https://api.slack.com/reference/block-kit/blocks#section) block to render a [button](https://api.slack.com/reference/block-kit/block-elements#button). \n  `labelText` is the section text, `buttonText` is the button label text and `value` is the button value. \n- `addButtonElements`\n  - Parameters: buttonDetails (array of objects with keys - buttonText, value, confirmText)\n  - Description: Adds an [action](https://api.slack.com/reference/block-kit/blocks#actions) block with multiple [button](https://api.slack.com/reference/block-kit/block-elements#button) elements.\n   Each button element comes with a confirmation popup. `buttonText` is the button label text, `value` is the button value and `confirmText` is the confirmation pop up message. If you don't want to have\n   a confirmation pop up, don't pass `confirmText`.\n- `addDivider`\n  - Parameters: null\n  - Description: Adds [divider](https://api.slack.com/reference/block-kit/blocks#divider) block.\n- `addCustomHeader`\n  - Parameters: text (string)\n  - Description: Adds a [divider](https://api.slack.com/reference/block-kit/blocks#divider) and a [section](https://api.slack.com/reference/block-kit/blocks#section) block with the provided text. Supports [mrkdwn](https://api.slack.com/reference/surfaces/formatting).\n- `sendUsingResponseUrl`\n  - Parameters: responseUrl (string), isTemporary (boolean)\n  - Description: Method for sending message using [response url](https://api.slack.com/interactivity/handling#message_responses). `responseUrl` is the response URL. `isTemporary` is true for [ephemeral message] (https://api.slack.com/messaging/managing#ephemeral), otherwise false.\n- `sendMessageToChannel`\n  - Parameters: postMessageParams (object with keys - channel, text), slackDomain (string) \n  - Description: Utilizes slack's [Web API method](https://api.slack.com/methods/chat.postMessage) `chat.postMessage` to send message to channel. `channel` is the channel id or your slack channel name. `text` is the message title text.\n  `slackDomain` is you slack app's workspace domain. `slackDomain` is optional parameter if not passed, then the first app's domain is taken.\n\n#### Example 1 - Sync Message / System Alert\nWhen responding to a slash command or any other interaction, we have 2 choices - synchronous response and asynchronous response. If the generation of the message body is simple, then the response can be sent synchronously. Following is an example of the same.\n\n```js\nconst text = 'TITLE TEXT';\n\nconst slackMessageParams = {};\nslackMessageParams.text = text;\nslackMessageParams.channel = 'CHANNEL ID OR CHANNEL NAME HERE';\n\nconst message = new slackmin.interactiveElements.Message();\nmessage.addDivider();\nmessage.addSection(`*${text}*`);\nmessage.addSection('Another section.');\n\nmessage.sendMessageToChannel(slackMessageParams);\n```\nOutput of above code is shown in the screenshot below.\n\n\u003cimg width=\"473\" alt=\"Sync Message / System Alert\" src=\"https://user-images.githubusercontent.com/7627517/171800304-5b3ddd5c-0deb-4a71-828d-a2259fe2e985.png\"\u003e\n\n#### Example 2 - Async Message\nThe following example explains how to send an asynchronous response using the [response URL](https://api.slack.com/interactivity/handling#message_responses), obtained from the initial slack interaction. These response URLs expire after 30 minutes.\n\n```js\nconst responseUrl = 'Response URL HERE';\nconst message = new slackmin.interactiveElements.Message();\n\nmessage.addCustomHeader('Message *title* `text` here.');\n\nconst texts = [\n  '2 Column Support.',\n  '`mrkdwn` is supported too.',\n  'Row 2, Column 1.',\n  'Row 2, Column 2.'\n ];\n\nmessage.addSectionWithTextFields(texts);\nconst actionButtons = [];\n\n// as a convention, we have value as a JSON string with keys action and hiddenParams.\n// action specifies the next method call to be performed for interactive endpoint i.e call to testModal1Open opens the test modal 1\n// hiddenParams in value are internal params that need to be forwarded\nconst testButton1 = {\n      buttonText: 'Test Button 1',\n      confirmText: 'Do you want to really click the test button 1?',\n      value:\n        \"{\\\"action\\\":\\\"testModal1Open\\\",\\\"hiddenParams\\\":{\\\"user_id\\\":\\\"123\\\"}}\"\n    };\n\nactionButtons.push(testButton1);\n\nconst testButton2 = {\n      buttonText: 'Test Button 2',\n      confirmText: 'Do you want to really click the test button 2?',\n      value:\n        \"{\\\"action\\\":\\\"testModal2Open\\\",\\\"hiddenParams\\\":{\\\"user_id\\\":\\\"123\\\"}}\"\n    };\n\nactionButtons.push(testButton2);\n\nmessage.addButtonElements(actionButtons);\nmessage.sendUsingResponseUrl(responseUrl);\n```\nOutput of above code is shown in the screenshot below. On clicking of the buttons a confirmation popup comes, as configured.\n\n\u003cimg width=\"636\" alt=\"Message wrapper async example\" src=\"https://user-images.githubusercontent.com/7627517/171792168-df189989-0790-4326-b54a-1ff79b0c6c1f.png\"\u003e\n\n### Modal Wrapper\nSlackmin Modal Wrapper simplifies the [block elements](https://api.slack.com/reference/block-kit/block-elements) by providing easy to use methods to create and format complex [modal](https://api.slack.com/surfaces/modals) layouts.\n\n**Methods**\n\n- `addSubmitAndCancel`\n  - Parameters: submitText (string), cancelText (string)\n  - Description: Add submit and cancel button to the modal. `submitText` is the submit button label text. `cancelText` is the cancel button label text.\n- `addPlainTextSection`\n  - Parameters: text (string)\n  - Description: Adds a [section](https://api.slack.com/reference/block-kit/blocks#section) block with the provided text.\n- `addMarkdownTextContext`\n  - Parameters: text (string)\n  - Description: Adds a [context](https://api.slack.com/reference/block-kit/blocks#context) block with the provided text. Supports [mrkdwn](https://api.slack.com/reference/surfaces/formatting).\n- `addDivider`\n  - Parameters: null\n  - Description: Adds [divider](https://api.slack.com/reference/block-kit/blocks#divider) block.\n- `addTextbox`\n  - Parameters: labelText (string), multiline (boolean), isOptional (boolean), initialText (string), placeHolderText (string)\n  - Description: Adds an [input](https://api.slack.com/reference/block-kit/blocks#input) block with an element type [plain-text](https://api.slack.com/reference/block-kit/block-elements#input).\n  `labelText` is the input block label text. `multiline` indicates whether the input will be a single line (false) or a larger textarea (true), defaults set to true.\n  `isOptional` is a boolean that indicates whether the input element may be empty when a user submits the modal, defaults to false. \n  `initialText` is the initial value, defaults to empty. `placeHolderText` is the placeholder or help text, defaults to 'Write Something'.\n- `addCheckBoxes`\n  - Parameters: labelText (string), options (Array of objects, each object with keys text, value), initialOptions (Array of objects, each object with keys text, value)\n  - Description: Adds an [input](https://api.slack.com/reference/block-kit/blocks#input) block with an element type [checkboxes](https://api.slack.com/reference/block-kit/block-elements#checkboxes). \n    `labelText` is the input block label text. `text` is the individual checkbox option label text. `value` is a unique string that specifies the value of the checkbox option.\n- `addRadioButtons`\n  - Parameters: labelText (string), optionsArray (Array of objects, each object with keys text, value), initialOption (object with keys text and value)\n  - Description: Adds an [input](https://api.slack.com/reference/block-kit/blocks#input) block with an element type [radio buttons](https://api.slack.com/reference/block-kit/block-elements#radio). \n   `labelText` is the input block label text. `text` is the radio button label text. `value` is a unique string value that will be passed to your app when any option is chosen. You can set `initial_option` in the element for selecting the radio button option by default.\n- `addParamsMeta`\n  - Parameters: paramsMeta (array of strings)\n  - Description: To specify parameter names for the subsequent [input](https://api.slack.com/reference/block-kit/blocks#input) block elements such as [plain-text](https://api.slack.com/reference/block-kit/block-elements#input),\n    [checkboxes](https://api.slack.com/reference/block-kit/block-elements#checkboxes) and [radio buttons](https://api.slack.com/reference/block-kit/block-elements#radio).\n    `paramsMeta` is sent in [private_metadata](https://api.slack.com/reference/surfaces/views) in modal submissions.\n- `addHiddenParamsMeta`\n  - Parameters: hiddenParamsMeta (object)\n  - Description: To pass on internal parameters on modal submit. `hiddenParamsMeta` contains hidden parameters which have to be passed to the next modal action.\n      `hiddenParamsMeta` is sent in [private_metadata](https://api.slack.com/reference/surfaces/views) in modal submissions.\n- `addAction`\n  - Parameters: actionName (string)\n  - Description: You can provide the next action method/route to be executed on modal submit. As all the interactive component interactions are sent to a single request URL, this `actionName` helps in deciding what needs to be done.\n  `actionName` is sent in [private_metadata](https://api.slack.com/reference/surfaces/views) in modal submissions.\n- `open`\n  - Parameters: triggerId (string)\n  - Description: Opens modal using the trigger id, which expires in 3 seconds. `triggerId` is obtained from [interaction payload](https://api.slack.com/interactivity/handling#payloads).\n\n#### Example\n\n```js\nconst triggerId = req.decodedParams.trigger_id; // Our middleware layer sets the trigger_id in req.decodedParams\nconst apiAppId = '\u003cslack_app_id\u003e'; // slack app id\nconst modal = new slackmin.interactiveElements.Modal(apiAppId, 'Give your vote');\n\n// These are the parameter names for the subsequent textboxes.\nconst paramsMeta = ['name', 'member_id', 'designation', 'projects'];\nmodal.addParamsMeta(paramsMeta);\n\nconst hiddenParamsMeta = {param1: \"value1\"};\nmodal.addHiddenParamsMeta(hiddenParamsMeta);\n\nmodal.addAction('submitForm');\n\nmodal.addMarkdownTextContext('`Hello` *World!*');\n\nmodal.addPlainTextSection('Hello World!');\n\nmodal.addDivider();\n\nmodal.addTextbox('Name', false);\nmodal.addTextbox('Member Id', false);\n\nmodal.addRadioButtons(\n 'Designation',\n  [\n    { text: 'Front End Developer', value: 'FE' },\n    { text: 'Back End Developer', value: 'BE' },\n    { text: 'Quality Assurance Engineer', value: 'QA' }\n  ],\n  { text: 'Front End Developer', value: 'FE' }\n);\n\nmodal.addCheckBoxes('Projects', [\n  { text: 'Fab', value: '1' },\n  { text: 'Moxie', value: '2'},\n  { text: 'Hem', value: '3' }\n]);\n\nmodal.addSubmitAndCancel();\n\nmodal.open(triggerId);\n```\nOutput of above code is shown in the screenshot below.\n\n\u003cimg width=\"575\" alt=\"Modal wrapper example\" src=\"https://user-images.githubusercontent.com/7627517/171832112-a87d979d-378a-44ea-b191-14c2306eb2db.png\"\u003e\n\n### Journey of Hidden Parameters\nIn this section, we will go through an example of our convention if handling hidden parameters. Hidden parameters have the contextual information needed for the CRUD operations like entity id, etc.\n\nFollowing are the different parts of our example:\n#### Part 1\nA slash command which sends a message with interactive buttons in it (refer Message Wrapper documentation to create message UI).\nThe hidden parameters (user_id in our example) must be present in the value of the button element as shown in the following snippet.\n\n```js\n// hiddenParams in value are internal params that need to be forwarded\nconst testButton1 = {\n      buttonText: 'Test Button 1',\n      confirmText: 'Do you want to really click the test button 1?',\n      value:\n        \"{\\\"action\\\":\\\"testModal1Open\\\",\\\"hiddenParams\\\":{\\\"user_id\\\":\\\"123\\\"}}\"\n    };\n\n// Refer to the snippet given in section \"Example 1 - Async Message\" for the complete idea.\nactionButtons.push(testButton1);\n```\n\n#### Part 2\nWhen the button in the message is clicked, a confirmation popup is shown. On confirmation, a POST API call comes from slack to the interactive request URL (which was setup in the \"Slack app setup\" section above).\nThe block submission payload which comes from slack is converted to api parameters and assigned to `req.decodedParams` by our Interactive Component Middlewares.\n\n#### Part 3\nA modal UI is created and opened using our Modal wrapper. Hidden parameters are forwarded to the modal view using `addHiddenParamsMeta` method of the Modal wrapper (refer documentation above).\n\n#### Part 4\nOn submission of the modal, the hidden parameters are obtained in the view submission payload, which is parsed and parameters are assigned to `req.decodedParams` by our Interactive Component Middlewares.\n\n## Examples\n\nWe have added code snippets for all demo slackmin commands available on https://truesparrow.com/slackmin\n\n**1**. Refer [Express code snippets](https://github.com/TrueSparrowSystems/slackmin/tree/master/examples/express) to integrate Slackmin with [Express](https://expressjs.com/)\u003cbr\u003e\n**2**. Refer [Fastify code snippets](https://github.com/TrueSparrowSystems/slackmin/tree/master/examples/fastify) to integrate Slackmin with [Fastify](https://www.fastify.io/docs/latest/)\u003cbr\u003e\n**3**. Refer [Koa code snippets](https://github.com/TrueSparrowSystems/slackmin/tree/master/examples/koa) to integrate Slackmin with [Koa](https://koajs.com/)\n\n## Contribution\nWe welcome more helping hands to make Slackmin better. Feel free to report issues, raise PRs for fixes \u0026 enhancements.\n\n\u003cp align=\"left\"\u003eBuilt with :heart: by \u003ca href=\"https://truesparrow.com/\" target=\"_blank\"\u003eTrue Sparrow\u003c/a\u003e\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTrueSparrowSystems%2Fslackmin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTrueSparrowSystems%2Fslackmin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTrueSparrowSystems%2Fslackmin/lists"}