Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add in Hello World example across docs #1608

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
47 changes: 30 additions & 17 deletions docs/_future/app_manifests.md
Expand Up @@ -9,7 +9,7 @@ permalink: /future/app-manifests
# App manifests <span class="label-beta">BETA</span>

<div class="section-content">
An app's manifest is where you can configure its name and scopes, declare the functions your app will use, and more.
An app's manifest is where you can configure its name and scopes, declare the functions your app will use, and more.
</div>

---
Expand All @@ -18,40 +18,53 @@ An app's manifest is where you can configure its name and scopes, declare the fu

Locate the file named `manifest.js` within your application. This will likely be in your project's root directory or a `manifest` folder.

Inside the manifest file, you will find an `module.exports = Manifest({})` block that defines the app's configuration:
Inside the manifest file, you will find an `module.exports = Manifest({})` block that defines the app's configuration. For the [Hello World application](https://github.com/slack-samples/bolt-js-starter-template/tree/future) in the Bolt for JavaScript Starter Template, it will look something like this:

```javascript
// manifest/manifest.js
const { Manifest } = require('@slack/bolt');
const { TimeOffWorkflow } = require('./workflows/approval');
const { SampleWorkflow } = require('./workflow/sample-workflow');

/**
* The app manifest contains the app's configuration. This
* file defines attributes like app name and description.
* https://api.slack.com/future/manifest
*/
module.exports = Manifest({
runOnSlack: false,
// This is the internal name for your app.
// It can contain spaces (e.g., "My App")
name: 'take-your-time',
displayName: 'Take Your Time',
// A description of your app that will help users decide whether to use it.
description: 'Request and take time off.',
longDescription: 'Take your time off by using this application to request and take time off from your manager. Launch the workflow, put in your manager, requested PTO start and end date, and receive updates on your PTO request!',
botScopes: ['chat:write'],
tokenManagementEnabled: true,
name: 'Bolt Template App TEST',
displayName: 'Bolt Template App TEST',
description: 'A starter app template built with Bolt JS',
botScopes: ['channels:history', 'chat:write', 'commands', 'chat:write.public'],
eventSubscriptions: { bot_events: ['app_home_opened', 'message.channels'] },
socketModeEnabled: true,
// A list of all workflows your app will use.
workflows: [TimeOffWorkflow],
workflows: [SampleWorkflow],
features: {
appHome: {
homeTabEnabled: true,
messagesTabEnabled: true,
messagesTabEnabled: false,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting... can you have messagesTabEnabled false but readOnlyEnabled as true?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahh, yes it seems so! this is the current configuration for our manifest in the future branch of the starter template!

messagesTabReadOnlyEnabled: true,
},
botUser: {
always_online: false,
},
shortcuts: [{
name: 'Run sample shortcut',
type: 'global',
callback_id: 'sample_shortcut_id',
description: 'Runs a sample shortcut',
}],
slashCommands: [{
command: '/sample-command',
description: 'Runs a sample command',
should_escape: false,
}],
},
settings: {
interactivity: {
is_enabled: true,
},
},
tokenRotationEnabled: false,
});
```
---
Expand Down Expand Up @@ -84,4 +97,4 @@ You will come back to the Manifest every time you create a new workflow, since a

### Next steps {#next-steps}

Now that you're acquainted with the Manifest, you can now dive into the world of [built-in functions](/bolt-js/future/built-in-functions) and [custom functions](/bolt-js/future/custom-functions)!
Now that you're acquainted with the Manifest, you can dive into the world of [built-in functions](/bolt-js/future/built-in-functions) and [custom functions](/bolt-js/future/custom-functions)!
15 changes: 7 additions & 8 deletions docs/_future/built_in_functions.md
Expand Up @@ -23,20 +23,19 @@ Built-in functions need to be imported from the standard library built into the

Built-in functions define their own inputs and outputs, as detailed for each built-in below.

Here's an example of a Workflow that creates a new Slack channel using the `CreateChannel` built-in function:
Here's an example of a Workflow that sends a message using the `SendMessage` built-in function:

```javascript
const { DefineWorkflow, Schema } = require('@slack/bolt');

...

const createChannelStep = myWorkflow.addStep(
Schema.slack.functions.CreateChannel,
{
channel_name: myWorkflow.inputs.channel_name,
is_private: false,
},
);
SampleWorkflow.addStep(Schema.slack.functions.SendMessage, {
channel_id: inputForm.outputs.fields.channel,
message: greetingFunctionStep.outputs.greeting,
});

module.exports = { SampleWorkflow };
```

Read the full documentation for [Workflows](/bolt-js/future/workflows) to learn how to build out Workflows.
Expand Down
36 changes: 21 additions & 15 deletions docs/_future/custom_functions.md
Expand Up @@ -21,7 +21,7 @@ To create a function, we need to do the following:
### Defining a function {#define}
Functions are defined in your app via the `DefineFunction` method, which is part of the SDK that gets included with every newly created project. These function definitions are stored under the `manifest/functions/` directory.

Let's go ahead and create a new function definition file under `manifest/functions` directory. Name it something related to what the function does. In our [Bolt for JavaScript Starter Template](https://github.com/slack-samples/bolt-js-starter-template/blob/future/manifest/function/sample-function.js), we name the file `sample-function.js`. Let's take a peek at it:
Let's go ahead and create a new function definition file under `manifest/functions` directory. Name it something related to what the function does. In our [Bolt for JavaScript Starter Template](https://github.com/slack-samples/bolt-js-starter-template/blob/future/manifest/functions/sample-function.js), we name the file `sample-function.js`. Let's take a peek at it:
```js
const { DefineFunction, Schema } = require('@slack/bolt');

Expand All @@ -35,17 +35,22 @@ const SampleFunctionDefinition = DefineFunction({
type: Schema.slack.types.user_id,
description: 'Send greeting to this recipient',
},
channel: {
type: Schema.slack.types.channel_id,
description: 'Channel to send message to',
},
message: {
type: Schema.types.string,
description: 'Message to the recipient',
},
},
required: ['message'],
},
output_parameters: {
properties: {
greeting: {
type: Schema.types.string,
description: 'Greeting for the recipient',
},
},
required: ['greeting'],
},
});

module.exports = { SampleFunctionDefinition };
Expand All @@ -69,7 +74,7 @@ The value for properties in `input_parameters` and `output_parameters` needs to
* `type`: The type of the input parameter. This can be a [Built-in type](https://api.slack.com/future/types) or a [Custom type](https://api.slack.com/future/types/custom) that you define.
* `description`: A string description of the parameter.

If you want to set a property as required, list its name in its respective input or output properties `required` property.
If you want to set a property as required, list its name in its respective input or output properties as a `required` property.

For example, if you have an input parameter named `customer_id` that you want to be required, you can do so like this:

Expand Down Expand Up @@ -102,7 +107,7 @@ Once your function is defined in its own file in `manifest/functions`, the next
Implement functions in just a few steps:

#### 1. Create the function definition file in the `manifest/functions` directory
If you haven't done so already, create a file for your function definition to live in and name it something that makes sense for your function. In the [Bolt for JavaScript Starter Template](https://github.com/slack-samples/bolt-js-starter-template/blob/future/manifest/function/sample-function.js), we named this file `sample-function.js`
If you haven't done so already, create a file for your function definition to live in and name it something that makes sense for your function. In the [Bolt for JavaScript Starter Template](https://github.com/slack-samples/bolt-js-starter-template/blob/future/manifest/functions/sample-function.js), we named this file `sample-function.js`


#### 2. Add function listener and handler(s)
Expand All @@ -119,16 +124,13 @@ const { SlackFunction } = require('@slack/bolt');
const { SampleFunctionDefinition } = require('../../manifest/functions/sample-function');

// Here is the work we want to do!
const helloWorld = async ({ event, client, complete }) => {
const { recipient, channel, message } = event.inputs;
const helloWorld = async ({ event, complete }) => {
const { recipient, message } = event.inputs;
const salutations = ['Hello', 'Hi', 'Howdy', 'Hola', 'Salut'];
const salutation = salutations[Math.floor(Math.random() * salutations.length)];
try {
await client.chat.postMessage({
channel,
text: `${salutation}, <@${recipient}>! :wave: Someone sent the following greeting: \n\n>${message}`,
});
complete();
const greeting = `${salutation}, <@${recipient}>! :wave: Someone sent the following greeting: \n\n>${message}`;
complete({ outputs: { greeting } });
} catch (err) {
// Complete function with an error
await complete({ error: `There was an issue: ${err}` });
Expand All @@ -141,7 +143,7 @@ const helloWorldFunc = new SlackFunction(SampleFunctionDefinition.id, helloWorld

module.exports = { helloWorldFunc };
```
The `hello-world.js` file declares a function handler, `helloWorld`, that takes in inputs from the `event`, which is the payload received when your function is being executed. It executes logic within the handler to send a message with a random greeting to the specified recipient in the desired channel. Then, a new `SlackFunction` instance is declared that actually links the `helloWorld` handler to `SampleFunctionDefinition` through the function's ID:
The `hello-world.js` file declares a function handler, `helloWorld`, that takes in inputs from the `event`, which is the payload received when your function is being executed. It executes logic within the handler to return a message with a random greeting. This message is the function's output. In addition to the function handler, a new `SlackFunction` instance is declared that actually links the `helloWorld` handler to `SampleFunctionDefinition` through the function's ID:
```js
// Let's create a new Slack Function with helloWorld as its handler
const helloWorldFunc = new SlackFunction(SampleFunctionDefinition.id, helloWorld);
Expand Down Expand Up @@ -171,3 +173,7 @@ module.exports.registerListeners = (app) => {
```
#### 3. Add the function as a step in your workflow
To actually call the defined function, `SampleFunctionDefinition`, don't forget to add your function to a workflow! When you're finished defining and implementing your functions, the next step is to add them to [Workflows](/bolt-js/future/workflows). Once added as a step in a Workflow, your Function will run when that Workflow is invoked by a [Trigger](/bolt-js/future/triggers).

---
### Next steps
You've learned about built-in and custom functions - now it's time to jump into [Workflows](/bolt-js/future/workflows) and learn about how they work with Functions. 🎉
4 changes: 2 additions & 2 deletions docs/_future/getting_started_future.md
Expand Up @@ -130,13 +130,13 @@ Once the app is successfully run, you'll see output in your Terminal to indicate

With your app running, access your workspace and paste the URL from the Trigger you created in the previous step into a message in a public channel.

> 💡 To make the trigger URL more widely accessible, we recommend saving the Trigger as a channel bookmark for easy access.
> 💡 App Triggers are automatically saved as a channel bookmark under "Workflows" for easy access.

Send the message and click the "Run" button that appears. A modal will appear prompting you to enter information to greet someone in your Slack workspace. Fill out the requested information.

![Hello World modal](../assets/hello-world-modal.png "Hello World modal")

Then, submit the form. In the specified channel submitted in the form, you should receive a message from the app tagging the submitted user. The message will also contain a randomly generated greeting and the message you wrote in the form..
Then, submit the form. In the specified channel submitted in the form, you should receive a message from the app tagging the submitted user. The message will also contain a randomly generated greeting and the message you wrote in the form.

The full app flow can be seen here:
![Hello World app](../assets/hello-world-demo.gif "Hello World app")
Expand Down
2 changes: 1 addition & 1 deletion docs/_future/request_time_off_tutorial.md
Expand Up @@ -96,7 +96,7 @@ Once the app is successfully run, you'll see output in your Terminal to indicate

With your app running, access your workspace and paste the URL from the Trigger you created in the previous step into a message in a public channel.

> 💡 To make the trigger URL more widely accessible, we recommend saving the Trigger as a channel bookmark for easy access.
> 💡 App Triggers are automatically saved as a channel bookmark under "Workflows" for easy access.

Send the message and click the "Run" button that appears. A modal will appear prompting you to enter information to request time off. To test your app properly, we recommend entering your own Slack username in the "Manager" field.

Expand Down
6 changes: 4 additions & 2 deletions docs/_future/triggers.md
Expand Up @@ -39,6 +39,8 @@ Triggers created with the CLI are designed using Trigger Files. The Trigger File

The specifics of the Trigger File's structure will depend on what [type of Trigger](#types) you want to use.

The Hello World app from the Bolt for JavaScript starter template uses a Link Trigger, which is one of several [Trigger types](#types). You can view its Trigger File [here](https://github.com/slack-samples/bolt-js-starter-template/blob/future/triggers/hello-world-trigger.json).

**2. Run the** `trigger create` **command**

Use the `trigger create` command to create your desired Trigger by pointing to a Trigger File.
Expand Down Expand Up @@ -75,7 +77,7 @@ const triggerResponse = await client.workflows.triggers.create({

The response will have a property called `ok`. If `true`, then the Trigger was created, and the `trigger` property will be populated.

Your response will include a `trigger.id`; be sure to store it! You use that to `update` or `delete` the Trigger if need be.
Your response will include a `trigger.id`; be sure to store it! You will use that to `update` or `delete` the Trigger if need be.

#### Development and production Triggers

Expand Down Expand Up @@ -128,4 +130,4 @@ To learn more about this, visit the guide [here](https://api.slack.com/future/tr

And that's the end of our triumphant trek learning about Triggers!

If you want to see Triggers in action with their pals, the Function and the Workflow, check out our sample [Request Time Off](https://github.com/slack-samples/bolt-js-request-time-off) app within our GitHub repository.
If you want to see Triggers in action with their pals, the Function and the Workflow, check out our sample [Hello World](https://github.com/slack-samples/bolt-js-starter-template/tree/future) app. For a more complex example, you can take a look at our [Request Time Off](https://github.com/slack-samples/bolt-js-request-time-off) app and its end-to-end [tutorial](/bolt-js/future/request-time-off-tutorial).