From 500675b8a4083ada926a8b9eb658b2cb874a0cfe Mon Sep 17 00:00:00 2001 From: alan lew Date: Thu, 1 Sep 2022 15:51:48 -0400 Subject: [PATCH 01/22] Update Apps Structure Manifest topic; Update styles to not break words in links of table cells; Fix trailing space when newtabref shortcode is rendered --- .../apps/structure/manifest/_index.md | 116 +++++++----------- site/layouts/shortcodes/newtabref.html | 2 +- site/static/css/styles.css | 4 + 3 files changed, 47 insertions(+), 75 deletions(-) diff --git a/site/content/integrate/apps/structure/manifest/_index.md b/site/content/integrate/apps/structure/manifest/_index.md index 2dc2e039cf..f664b3edc6 100644 --- a/site/content/integrate/apps/structure/manifest/_index.md +++ b/site/content/integrate/apps/structure/manifest/_index.md @@ -1,40 +1,44 @@ --- title: "Manifest" -heading: "App manifest" +heading: "Manifest" description: "App manifest spec" weight: 10 aliases: - /integrate/apps/api/manifest/ --- -All apps should define a manifest -([godoc](https://pkg.go.dev/github.com/mattermost/mattermost-plugin-apps/apps#Manifest)) -as a JSON file. The fields of the manifest are: - -| Name | Type | Description | -|:------------------------|:------------|:-----------------------------------------------------------------------------------------------------------------------------------------| -| `app_id`(*) | string | ID for your app. | -| `homepage_url`(*) | string | The app homepage. Used in the Marketplace and for OAuth purposes. | -| `version` | string | The version of your app. | -| `display_name` | string | The display name for your app. | -| `description` | string | The description for your app. Used in the Marketplace. Provide examples of key functionality the App provides in a short paragraph. | -| `icon` | string | The icon for your app. Used as the bot account icon and in the Marketplace. A relative path in the static assets folder of a .PNG image. | -| `requested_permissions` | Permissions | All the permissions needed by the app. | -| `requested_locations` | Locations | The list of top-level locations that the application intends to bind to. | -| `bindings` | Call | The call gets invoked to retrieve bindings. By default invoke `/bindings`. | -| `on_disable` | Call | The call gets invoked when the app is disabled after having been enabled. | -| `on_enable` | Call | The call gets invoked when the app is enabled after having been disabled. | -| `on_install` | Call | The call gets invoked when the app gets installed. | -| `on_uninstall` | Call | The call gets invoked when the app gets uninstalled, before the app is actually removed. | - -- (*) `app_id` and `homepage_url` must be provided and valid. -- `on_...` callbacks are not invoked unless explicitly provided in the manifest. -`bindings` defaults to `/bindings` with nothing expanded. -- In addition, an app must define at least one of the following deployment types, as a section -in its `manifest.json`: `"http"`, `"aws_lambda"`, `"kubeless"`, or -`"open_faas"`. - -An example manifest looks like this: +All Apps should define a manifest ({{}}) as a JSON file. +The fields of the manifest are: + +| Name | Type | Description | +|:---------------------------|:----------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------| +| `app_id`(*) | string | ID for your App. | +| `homepage_url`(*) | string | The App homepage. Used in the Marketplace and for OAuth purposes. | +| `version` | string | The version of your App, formatted as `v00.00.0000`. | +| `display_name` | string | The display name for your App. | +| `description` | string | The description for your App. Used in the Marketplace. Provide examples of key functionality the App provides in a short paragraph. | +| `icon` | string | The icon for your App. Must be a relative path to a PNG image in the static assets folder. Used as the bot account icon and in the Marketplace. | +| `requested_permissions` | [Permissions](#permissions) | List of permissions needed by the App. | +| `requested_locations` | [Locations](#locations) | The list of top-level locations that the application intends to bind to. | +| `bindings` | [Call]({{}}) | The call invoked to retrieve bindings. Default value: `/bindings` | +| `on_install` | [Call]({{}}) | The call invoked when the App is installed. | +| `on_uninstall` | [Call]({{}}) | The call invoked when the App is uninstalled, before the App is removed. | +| `on_version_changed` | [Call]({{}}) | The call invoked when the App needs to be upgraded or downgraded. | +| `get_oauth2_connect_url` | [Call]({{}}) | The call invoked with the App's "connect to 3rd party" link is clicked, to be redirected to the OAuth flow. | +| `on_oauth2_complete` | [Call]({{}}) | The call invoked when the OAuth flow has successfully completed. | +| `on_remote_webhook` | [Call]({{}}) | The call invoked when an HTTP webhook is received from a remote system. | +| `remote_webhook_auth_type` | string | Specifies how incoming webhook messages from remote systems should be authenticated by Mattermost. | +| `aws_lambda`(*) | [AWSLambda](#aws-lambda) | Metadata for an App that can be deployed to AWS Lambda and S3 services, and is accessed using the AWS APIs. | +| `open_faas`(*) | [OpenFAAS](#openfaas) | Metadata for an App that can be deployed to OpenFAAS. | +| `http`(*) | [HTTP](#http) | Metadata for an App that is already deployed externally and is accessed using HTTP. | + +{{}} +- The `app_id` and `homepage_url` values must be specified. +- A deployment method - `aws_lambda`, `open_faas`, or `http` - must be specified. +{{}} + +For example, a typical App manifest would look like the following: + ```json { "app_id": "hello-world", @@ -59,7 +63,7 @@ An example manifest looks like this: Apps need to request permissions from the admin who is installing them. After an app is installed and available to end users, each user in Mattermost will need to "authenticate" with your app. Using the `act_as_user` permission, your app will be performing an API call on each authenticated user's behalf. -Below are the permissions ([godoc](https://pkg.go.dev/github.com/mattermost/mattermost-plugin-apps/apps#Permission)) an app can currently ask for: +Below are the supported permissions ({{}}) an app can request: | Name | Description | |:-----------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------| @@ -72,18 +76,18 @@ Below are the permissions ([godoc](https://pkg.go.dev/github.com/mattermost/matt ### Locations -Locations ([godoc](https://pkg.go.dev/github.com/mattermost/mattermost-plugin-apps/apps#Location)) are spaces in the UI where an app can add interactions. Locations in the App framework are supported on the Mobile/Desktop/Webapp clients unless otherwise noted. This list of locations will grow over time as the App Framework expands. +Locations ({{}}) are spaces in the UI where an app can add interactions. Locations in the App framework are supported on the Mobile/Desktop/Webapp clients unless otherwise noted. This list of locations will grow over time as the App Framework expands. | Name | Description | -| :---------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +|:------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `/post_menu` | An item in a Mattermost post's dropdown menu (aka Message Action) where the user can leverage the message content as part of your App's action. A good example for using the post menu: someone reports a bug in a channel with some details, then using the "post-menu" button the message's content could be used to create a new "bug" object in a tracking system. | | `/channel_header` | Webapp: A button in the channel header, Mobile: An item in the channel menu. This is used for actions that take place at the channel level, for example a button for the user to set up a notification subscription for all new tickets in system XYZ to be posted to the current channel | | `/command` | A slash command accessed by typing `/` at the beginning of any new message in Mattermost. Slash commands are an easy way for power-users to perform actions in external systems via a "chat-command-line" that can interactively provide the users with hints and suggestions based on dynamic lookups. For example, a slash command `/ticketing --name "test Ticket" --priority high` can capture two fields and create a ticket in an external system. The options for "priority" field could be displayed to the user in a multi-select menu to reduce their need to type. | -| `/in_post` | A form that is embedded within a message in Mattermost. Used to interact with users without switching context to an Interactive Dialog. Great for confirming simple things - like "Did you complete your OKR review yet? (Yes/No)" options can be presented to the user and they can simply check off a box. | +| `/in_post` | A form that is embedded within a message in Mattermost. Used to interact with users without switching context to an Interactive Dialog. Great for confirming simple things - like "Did you complete your OKR review yet? (Yes/No)" options can be presented to the user and they can simply check off a box. | -### Deployment information +### Deployment methods -#### `http`: Apps accessible via HTTP +#### HTTP Provides configuration for accessing an app that is deployed exterally of Mattermost and is accessible via HTTP. @@ -102,7 +106,7 @@ Example: } ``` -#### `aws_lambda`: Apps deployable and accessible as AWS Lambda functions and S3 static assets +#### AWS Lambda Provides configuration for deploying an app (bundle) onto the AWS Lambda and S3 services and accessing it there. @@ -134,9 +138,9 @@ Example (some fields omitted): } ``` -#### `open_faas`: Apps deployable and accessible as OpenFaaS or faasd functions +#### OpenFaaS -Provides configuration for deploying an app (bundle) onto OpenFaaS and faasd platforms. +Provides configuration for deploying an app (bundle) onto OpenFaaS and `faasd` platforms. | Name | Type | Description | |:---------------|:------------------|:------------------| @@ -162,39 +166,3 @@ Example (some fields omitted): } } ``` - -#### `Kubeless`: Apps deployable and accessible as Kubeless - -Provides configuration for deploying an app (bundle) onto -[Kubeless](https://kubeless.io/docs/quick-start/) serverless platform on -Kubernetes. - -| Name | Type | Description | -|:---------------|:------------------|:------------------| -| `functions`(*) | Kubeless Function | List of functions | - -Each function contains the following fields: - -| Name | Description | -|:-------------|:--------------------------------------------------------------------| -| `path`(*) | (root) path of calls to be mapped to this function, e.g. `"/"` | -| `handler`(*) | the name of the language-specific function to invoke | -| `file`(*) | the name of the file to invoke | -| `runtime`(*) | Kubeless runtime to use | -| `deps_file` | Dependencies file for the function (`go.mod` or `requirements.txt`) | -| `timeout` | Function completion timeout in seconds, default none | -| `port` | IPV4 port to use in the function image, default 8080 | - -Example (some fields omitted): -```json -{ - "kubeless": { - "functions": [ - { - "path": "/", - "handler": "hello" - } - ] - } -} -``` diff --git a/site/layouts/shortcodes/newtabref.html b/site/layouts/shortcodes/newtabref.html index 3695c16c5a..96b581be4b 100644 --- a/site/layouts/shortcodes/newtabref.html +++ b/site/layouts/shortcodes/newtabref.html @@ -1 +1 @@ -{{ .Get "title" }} +{{ .Get "title" }}{{- "" -}} diff --git a/site/static/css/styles.css b/site/static/css/styles.css index 0375687735..402dea5d2e 100644 --- a/site/static/css/styles.css +++ b/site/static/css/styles.css @@ -3120,6 +3120,10 @@ td:first-child code { word-break: normal; } +td>a { + word-break: normal; +} + .container-fluid { max-width: 1140px; } From bd8a61f5f138487fabc6700841e08fa496ab066d Mon Sep 17 00:00:00 2001 From: alan lew Date: Thu, 8 Sep 2022 11:41:22 -0400 Subject: [PATCH 02/22] Update existing content in Apps Structure topic; Fix missing CSS styles for h4, h5, and h6 headings; Modify CSS to not break words used in links in a table cell --- .../integrate/apps/structure/_index.md | 52 ++----- .../apps/structure/bindings/_index.md | 2 - .../integrate/apps/structure/call/_index.md | 7 - .../apps/structure/manifest/_index.md | 138 +++++++++--------- site/static/css/styles.css | 14 +- 5 files changed, 97 insertions(+), 116 deletions(-) diff --git a/site/content/integrate/apps/structure/_index.md b/site/content/integrate/apps/structure/_index.md index 82f6683f14..b5ada0c11b 100644 --- a/site/content/integrate/apps/structure/_index.md +++ b/site/content/integrate/apps/structure/_index.md @@ -9,54 +9,28 @@ aliases: Apps consist of three kinds of assets: -- [manifest.json]({{< ref "manifest" >}}) file +1. A [manifest]({{< ref "manifest" >}}) file, which contains App details such as name, version, requested permissions, and deployment methods -- [Call]({{< ref "call" >}}) handlers, starting with `/bindings` (see - [Bindings]({{< ref "bindings" >}})) and `/on_install` (see - [Manifest]({{< ref "manifest" >}})). Call handlers are typically source files - in a programming language like JavaScript, Python, or Go. +2. [Call]({{< ref "call" >}}) handlers, which are functions that handle incoming requests from the Mattermost server -- Static assets, currently solely icon files +3. [Static assets]({{}}) (e.g. images) -## Interactivity: Bindings and forms +To interact with users an App must [bind]({{< ref "bindings" >}}) a call handler to a location in the Mattermost user interface. These locations may be slash commands, toolbar and menu items, or embedded in posts. -- To interact with users an App must [bind]({{< ref "bindings" >}}) a call to a - location in the Mattermost user interface. These locations may be - `/`-commands, toolbar and menu items, and embedded in posts. +A [Binding]({{< ref "bindings" >}}) may display a [Form]({{< ref "interactivity" >}}), or it may invoke a call that will return a form. Forms allow the user to input information with limited dynamic behavior, such as dynamically-populated pick lists, or form refreshes on field changes. -- A [binding]({{< ref "bindings" >}}) may display a [Form]({{< ref - "interactivity" >}}), or it may invoke a `Call` that will return a `Form`. - Forms allow to gather fields with limited dynamic behavior - (dynamically-populated selects, form refresh on field changes). A Form invokes - a `Call` when it is submitted. A `/`-command is just another way of filling - out a `Form` and submitting it. +## Functionality -## Use Mattermost APIs +In addition to the {{}}, the Apps framework provides additional functionality: -Apps can use all general [Mattermost REST API]({{< ref "mattermost-api" >}})s, -as well as special services that are provided to the apps. +- [KV Store]({{< ref "/integrate/apps/functionality/kv-store" >}}) - a simple key-value store for App-specific data. -See [Authenticating with Mattermost]({{< ref "app-to-mattermost" >}}) for how -to authenticate to all these services. +- [OAuth2 Store]({{< ref "mattermost-api#apps-api" >}}) - store, expand, and retrieve user and App OAuth2 configuration data. -App services: +- [Calling other Apps]({{< ref "mattermost-api#apps-api" >}}) - use the Call API to invoke other Apps (experimental). -- [KV Store]({{< ref "mattermost-api#apps-api" >}}) - store and retrive app-specific data. +- [Subscriptions]({{< ref "subscriptions" >}}) covers how to subscribe to notifications about Mattermost events. Examples of a subscription include having your App notified whenever a message is posted in a channel that mentions your @bot account. -- [OAuth2 Store]({{< ref "mattermost-api#apps-api" >}}) - store, expand, and retrieve user and - app OAuth2 configuration data. +- [External webhooks]({{< ref "/integrate/apps/functionality/external-webhooks" >}}) covers subscribing to webhooks from third-party systems. -- [Calling other Apps]({{< ref "mattermost-api#apps-api" >}}) - use the `Call` API to invoke - other apps (experimental). - -## Other - -- [Subscriptions]({{< ref "subscriptions" >}}) covers how to subscribe to - notifications abdout Mattermost events. Examples of a subscription include having your App notified whenever a message is posted in a channel that mentions your @bot account. - -- [External webhooks]({{< ref "/integrate/apps/functionality/external-webhooks" >}}) covers subscribing to - webhooks from third-party systems. - -- [Lifecycle]({{< ref "lifecycle" >}}) covers lifecycle callback API, i. e. - `on_install`. This is useful for calling your app when it is first installed, or the user is attempting to uninstall it and gives you a chance to initialize or clean up data (such as from the KV store) before uninstalling your app. - +See [Authenticating with Mattermost]({{< ref "/integrate/apps/authentication/app-to-mattermost" >}}) for how to authenticate to all these services. diff --git a/site/content/integrate/apps/structure/bindings/_index.md b/site/content/integrate/apps/structure/bindings/_index.md index 787d96c175..dbc5b29a14 100644 --- a/site/content/integrate/apps/structure/bindings/_index.md +++ b/site/content/integrate/apps/structure/bindings/_index.md @@ -17,8 +17,6 @@ Bindings ([godoc](https://pkg.go.dev/github.com/mattermost/mattermost-plugin-app **Note:** Bindings are fetched (and refreshed) on every channel switch. When the user moves to a different context (like opening a thread, or a post in a search view) new bindings may be fetched to provide the correct bindings for the thread/post context. Bindings are also fetched when an OAuth2 process is completed and when the application gets installed. -One example bindings response is the one from the [Hello World!](https://github.com/mattermost/mattermost-plugin-apps/blob/master/examples/go/hello-world/bindings.json) app. - The expected response should include the following: | Type | Function | Description | diff --git a/site/content/integrate/apps/structure/call/_index.md b/site/content/integrate/apps/structure/call/_index.md index 90dda422e8..943b2ea177 100644 --- a/site/content/integrate/apps/structure/call/_index.md +++ b/site/content/integrate/apps/structure/call/_index.md @@ -134,10 +134,3 @@ There are several types ([godoc](https://pkg.go.dev/github.com/mattermost/matter | `navigate_to_url` | string | URL to navigate to. | | `use_external_browser` | bool | Whether the navigation link wll open in an external browser. | -## Special calls - -### Install - -When the app is installed and `on_install` is defined in the [manifest]{{< ref "manifest" >}}, a special call is made to inform the app that it has been installed on the instance. This call is used mainly to initialize any needed information. - -The expected responses are either OK or Error responses. diff --git a/site/content/integrate/apps/structure/manifest/_index.md b/site/content/integrate/apps/structure/manifest/_index.md index f664b3edc6..7610f0e5da 100644 --- a/site/content/integrate/apps/structure/manifest/_index.md +++ b/site/content/integrate/apps/structure/manifest/_index.md @@ -7,30 +7,30 @@ aliases: - /integrate/apps/api/manifest/ --- -All Apps should define a manifest ({{}}) as a JSON file. +All Apps should define a manifest ({{}}) as a JSON object. The fields of the manifest are: -| Name | Type | Description | -|:---------------------------|:----------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------| -| `app_id`(*) | string | ID for your App. | -| `homepage_url`(*) | string | The App homepage. Used in the Marketplace and for OAuth purposes. | -| `version` | string | The version of your App, formatted as `v00.00.0000`. | -| `display_name` | string | The display name for your App. | -| `description` | string | The description for your App. Used in the Marketplace. Provide examples of key functionality the App provides in a short paragraph. | -| `icon` | string | The icon for your App. Must be a relative path to a PNG image in the static assets folder. Used as the bot account icon and in the Marketplace. | -| `requested_permissions` | [Permissions](#permissions) | List of permissions needed by the App. | -| `requested_locations` | [Locations](#locations) | The list of top-level locations that the application intends to bind to. | -| `bindings` | [Call]({{}}) | The call invoked to retrieve bindings. Default value: `/bindings` | -| `on_install` | [Call]({{}}) | The call invoked when the App is installed. | -| `on_uninstall` | [Call]({{}}) | The call invoked when the App is uninstalled, before the App is removed. | -| `on_version_changed` | [Call]({{}}) | The call invoked when the App needs to be upgraded or downgraded. | -| `get_oauth2_connect_url` | [Call]({{}}) | The call invoked with the App's "connect to 3rd party" link is clicked, to be redirected to the OAuth flow. | -| `on_oauth2_complete` | [Call]({{}}) | The call invoked when the OAuth flow has successfully completed. | -| `on_remote_webhook` | [Call]({{}}) | The call invoked when an HTTP webhook is received from a remote system. | -| `remote_webhook_auth_type` | string | Specifies how incoming webhook messages from remote systems should be authenticated by Mattermost. | -| `aws_lambda`(*) | [AWSLambda](#aws-lambda) | Metadata for an App that can be deployed to AWS Lambda and S3 services, and is accessed using the AWS APIs. | -| `open_faas`(*) | [OpenFAAS](#openfaas) | Metadata for an App that can be deployed to OpenFAAS. | -| `http`(*) | [HTTP](#http) | Metadata for an App that is already deployed externally and is accessed using HTTP. | +| Name | Type | Description | +|:---------------------------|:----------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------| +| `app_id`(*) | string | ID for your App. | +| `homepage_url`(*) | string | The App homepage. Used in the Marketplace and for OAuth purposes. | +| `version` | string | The version of your App, formatted as `v00.00.0000`. | +| `display_name` | string | The display name for your App. | +| `description` | string | The description for your App. Used in the product Marketplace. Provide examples of key functionality the App provides in a short paragraph. | +| `icon` | string | The icon for your App. Must be a relative path to a PNG image in the static assets folder. Used as the bot account icon and in the product Marketplace. | +| `requested_permissions` | [Permissions](#permissions) | List of permissions needed by the App. | +| `requested_locations` | [Locations](#locations) | The list of top-level locations that the App intends to bind to. | +| `bindings` | [Call]({{}}) | The call invoked to retrieve bindings. Default value: `/bindings` | +| `on_install` | [Call]({{}}) | The call invoked when the App is installed. | +| `on_uninstall` | [Call]({{}}) | The call invoked when the App is uninstalled, before the App is removed. | +| `on_version_changed` | [Call]({{}}) | The call invoked when the App needs to be upgraded or downgraded. | +| `get_oauth2_connect_url` | [Call]({{}}) | The call invoked with the App's "connect to third party" link is selected, to be redirected to the OAuth flow. | +| `on_oauth2_complete` | [Call]({{}}) | The call invoked when the OAuth flow has successfully completed. | +| `on_remote_webhook` | [Call]({{}}) | The call invoked when an HTTP webhook is received from a remote system. | +| `remote_webhook_auth_type` | string | Specifies how incoming webhook messages from remote systems should be authenticated by Mattermost. | +| `aws_lambda`(*) | [AWSLambda](#aws-lambda) | Metadata for an App that can be deployed to AWS Lambda and S3 services, and is accessed using the AWS APIs. | +| `open_faas`(*) | [OpenFAAS](#openfaas) | Metadata for an App that can be deployed to OpenFAAS. | +| `http`(*) | [HTTP](#http) | Metadata for an App that is already deployed externally and is accessed using HTTP. | {{}} - The `app_id` and `homepage_url` values must be specified. @@ -45,7 +45,7 @@ For example, a typical App manifest would look like the following: "version":"v0.8.0", "display_name": "Hello, world!", "icon": "icon.png", - "homepage_url": "https://github.com/mattermost/mattermost-plugin-apps/examples/go/hello", + "homepage_url": "https://github.com/mattermost/mattermost-plugin-apps", "requested_permissions": [ "act_as_bot" ], @@ -53,6 +53,9 @@ For example, a typical App manifest would look like the following: "/channel_header", "/command" ], + "on_install": { + "path": "/install" + }, "http": { "root_url": "http://localhost:4000" } @@ -61,40 +64,40 @@ For example, a typical App manifest would look like the following: ### Permissions -Apps need to request permissions from the admin who is installing them. After an app is installed and available to end users, each user in Mattermost will need to "authenticate" with your app. Using the `act_as_user` permission, your app will be performing an API call on each authenticated user's behalf. +Apps need to request permissions from the System Admin who is installing them. After an App is installed and available to end users, each user in Mattermost will need to "authenticate" with your App. +Using the `act_as_user` permission, your App will be performing an API call on behalf of each authenticated user. Below are the supported permissions ({{}}) an app can request: -| Name | Description | -|:-----------------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------| -| `user_joined_channel_notification` | Be notified when users join channels. | -| `act_as_bot` | Use Mattermost REST API as the app's bot user. | -| `act_as_user` | Use Mattermost REST API as connected users. | -| `remote_oauth2` | Use remote (third-party) OAuth2 support, and will store secrets and tokens to third-party system(s) within the Mattermost server. | -| `remote_webhooks` | Receive webhooks from a remote (third-party) system, and process them as a bot (which will typically, will add a notification message to a channel) | - +| Name | Description | +|:-----------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------| +| `user_joined_channel_notification` | Be notified when users join channels. | +| `act_as_bot` | Use Mattermost REST API as the app's bot user. | +| `act_as_user` | Use Mattermost REST API as a connected user. | +| `remote_oauth2` | Use remote (third-party) OAuth2 support, and store secrets and tokens to third-party system(s) within the Mattermost server. | +| `remote_webhooks` | Receive webhooks from a remote (third-party) system and process them as a bot. This will typically add a notification message to a channel. | ### Locations -Locations ({{}}) are spaces in the UI where an app can add interactions. Locations in the App framework are supported on the Mobile/Desktop/Webapp clients unless otherwise noted. This list of locations will grow over time as the App Framework expands. +Locations ({{}}) are spaces in the UI where an app can add interactions. Locations in the App framework are supported on the mobile, desktop, and web app clients unless otherwise noted. This list of locations will grow over time as the App framework expands. -| Name | Description | -|:------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `/post_menu` | An item in a Mattermost post's dropdown menu (aka Message Action) where the user can leverage the message content as part of your App's action. A good example for using the post menu: someone reports a bug in a channel with some details, then using the "post-menu" button the message's content could be used to create a new "bug" object in a tracking system. | -| `/channel_header` | Webapp: A button in the channel header, Mobile: An item in the channel menu. This is used for actions that take place at the channel level, for example a button for the user to set up a notification subscription for all new tickets in system XYZ to be posted to the current channel | -| `/command` | A slash command accessed by typing `/` at the beginning of any new message in Mattermost. Slash commands are an easy way for power-users to perform actions in external systems via a "chat-command-line" that can interactively provide the users with hints and suggestions based on dynamic lookups. For example, a slash command `/ticketing --name "test Ticket" --priority high` can capture two fields and create a ticket in an external system. The options for "priority" field could be displayed to the user in a multi-select menu to reduce their need to type. | -| `/in_post` | A form that is embedded within a message in Mattermost. Used to interact with users without switching context to an Interactive Dialog. Great for confirming simple things - like "Did you complete your OKR review yet? (Yes/No)" options can be presented to the user and they can simply check off a box. | +| Name | Description | +|:------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `/post_menu` | An item in a Mattermost post's dropdown menu (a.k.a. Message Action) where the user can leverage message content as part of the App's action.

For example, someone reports a bug in a channel with some details, then using the "post-menu" button the message's content could be used to create a new "bug" object in a tracking system. | +| `/channel_header` | A button in the channel header on desktop app or the web app, and an item in the channel menu on the mobile app. This is used for actions that take place at the channel level.

For example, a button for the user to set up a notification subscription for all new tickets in system XYZ to be posted to the current channel | +| `/command` | A slash command accessed by typing `/` at the beginning of any new message in Mattermost.

For example, a slash command `/ticketing --name "test Ticket" --priority high` can capture two fields and create a ticket in an external system. The options for the `priority` field could be displayed to the user in a pick list to reduce their need to type. | +| `/in_post` | A form that is embedded within a message in Mattermost. Used to interact with users without switching context to an interactive dialog.

For example, confirming simple things like "Did you complete your OKR review yet? (Yes/No)" options can be presented to the user and they can simply check off a box. | ### Deployment methods #### HTTP -Provides configuration for accessing an app that is deployed exterally of Mattermost and is accessible via HTTP. +Provides configuration for accessing an app that is deployed externally of Mattermost and is accessible via HTTP. -| Name | Description | -|:-----------|:----------------------------------------------------------------------------------------------------------------------------------------------------------| -| `root_url` | Base URL to send all calls and static asset requests to. | -| `use_jwt` | Include a secret-based JWT in all requests to the App. The secret must be provided by the app to the sysadmin and entered at the app's installation time. | +| Name | Description | +|:-----------|:---------------------------------------------------------------------------------------------------------------------------------------------------------| +| `root_url` | Base URL for all calls and static asset requests. | +| `use_jwt` | Include a secret-based JWT in all requests to the App. The secret must be provided by the App to the System Admin and entered when the App is installed. | Example: ```json @@ -108,30 +111,31 @@ Example: #### AWS Lambda -Provides configuration for deploying an app (bundle) onto the AWS Lambda and S3 -services and accessing it there. +Provides configuration for deploying an App onto the AWS Lambda and S3 services. -| Name | Type | Description | -|:---------------|:--------------------|:------------------| -| `functions`(*) | AWS Lambda Function | List of functions | +| Name | Type | Description | +|:---------------|:---------------------|:------------------| +| `functions`(*) | AWS Lambda functions | List of functions | -Each function contains the following fields: +Each AWS Lambda function contains the following fields: -| Name | Description | -|:-------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `path`(*) | (Root) path of calls to be mapped to this function, e.g. `"/"` | -| `name`(*) | Function's base name. Is used as a base name to compose the actual AWS Lambda name. `{name}.zip` is used looking up the lambda function in an app bundle by `appsctl aws deploy` | -| `handler`(*) | The name of the handler go function | -| `runtime`(*) | AWS Lambda runtime to use, see [here](https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html) | +| Name | Description | +|:-------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `path`(*) | Root path of calls to be mapped to this function. For example: `"/"` | +| `name`(*) | Function's base name; used to compose the actual AWS Lambda name. | +| `handler`(*) | The name of the function handler. | +| `runtime`(*) | AWS Lambda runtime to use. See the {{}} documentation for a list of supported runtimes. | -Example (some fields omitted): +Example: ```json { "aws_lambda": { "functions": [ { "path": "/", - "name": "my-funct" + "name": "my-funct", + "handler": "my-funct", + "runtime": "go1.x" } ] } @@ -140,20 +144,20 @@ Example (some fields omitted): #### OpenFaaS -Provides configuration for deploying an app (bundle) onto OpenFaaS and `faasd` platforms. +Provides configuration for deploying an App onto OpenFaaS and `faasd` platforms. -| Name | Type | Description | -|:---------------|:------------------|:------------------| -| `functions`(*) | OpenFaaS Function | List of functions | +| Name | Type | Description | +|:---------------|:-------------------|:------------------| +| `functions`(*) | OpenFaaS functions | List of functions | Each function contains the following fields: -| Name | Description | -|:----------|:------------------------------------------------------------------------------------------------------------------------| -| `path`(*) | (Root) path of calls to be mapped to this function, e.g. `"/"` | -| `name`(*) | Function's base name. Is used as a base name to compose the actual OpenFaaS name, combined with the app ID and version. | +| Name | Description | +|:----------|:---------------------------------------------------------------------------------------------------------------| +| `path`(*) | Root path of calls to be mapped to this function. For example: `"/"` | +| `name`(*) | Function's base name; used to compose the actual OpenFaaS function name, combined with the App ID and version. | -Example (some fields omitted): +Example: ```json { "open_faas": { diff --git a/site/static/css/styles.css b/site/static/css/styles.css index 402dea5d2e..50fe5cf653 100644 --- a/site/static/css/styles.css +++ b/site/static/css/styles.css @@ -3121,7 +3121,7 @@ td:first-child code { } td>a { - word-break: normal; + word-break: inherit; } .container-fluid { @@ -3297,6 +3297,18 @@ h3 { font-size: 1.5rem; } +h4 { + font-size: 1.25rem; +} + +h5 { + font-size: 1rem; +} + +h6 { + font-size: 0.75rem; +} + h1:first-child, h2:first-child, h3:first-child, From 39d7798c0e9b4c3c8b3dfe27383a564465669aa6 Mon Sep 17 00:00:00 2001 From: alan lew Date: Fri, 9 Sep 2022 12:59:34 -0400 Subject: [PATCH 03/22] Add support for Compass Icons; Move FontAwesome files from fonts directory to font directory since compass-icons.css expects its files there; Update Apps structure main topic, manifest, and calls topics; Moved call metadata (expand) to its own topic --- .gitignore | 2 + Makefile | 9 +- .../integrate/apps/functionality/_index.md | 14 +- .../integrate/apps/structure/_index.md | 15 -- .../apps/structure/call-metadata/_index.md | 34 +++ .../integrate/apps/structure/call/_index.md | 203 ++++++++---------- .../apps/structure/manifest/_index.md | 82 +++---- site/layouts/partials/head.html | 3 + site/layouts/shortcodes/compass-icon.html | 1 + site/layouts/shortcodes/newtabref.html | 2 +- site/layouts/shortcodes/note.html | 3 +- site/static/css/styles.css | 8 +- site/static/{fonts => font}/FontAwesome.otf | Bin .../{fonts => font}/fontawesome-webfont.eot | Bin .../{fonts => font}/fontawesome-webfont.svg | 0 .../{fonts => font}/fontawesome-webfont.ttf | Bin .../{fonts => font}/fontawesome-webfont.woff | Bin .../{fonts => font}/fontawesome-webfont.woff2 | Bin 18 files changed, 202 insertions(+), 174 deletions(-) create mode 100644 site/content/integrate/apps/structure/call-metadata/_index.md create mode 100644 site/layouts/shortcodes/compass-icon.html rename site/static/{fonts => font}/FontAwesome.otf (100%) rename site/static/{fonts => font}/fontawesome-webfont.eot (100%) rename site/static/{fonts => font}/fontawesome-webfont.svg (100%) rename site/static/{fonts => font}/fontawesome-webfont.ttf (100%) rename site/static/{fonts => font}/fontawesome-webfont.woff (100%) rename site/static/{fonts => font}/fontawesome-webfont.woff2 (100%) diff --git a/.gitignore b/.gitignore index 342e36b19b..f98d9810c0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ /site/data/PluginGoDocs.json /site/data/PluginManifestDocs.json /site/data/PluginJSDocs.json +/site/static/css/compass-icons.css +/site/static/font/compass-icons.* /scripts/node_modules /scripts/mattermost-webapp /scripts/package-lock.json diff --git a/Makefile b/Makefile index b0bcf2705b..aedfb618b7 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ .PHONY: dist -dist: plugin-data +dist: plugin-data compass-icons rm -rf ./dist hugo -s site --destination ../dist/html @@ -27,3 +27,10 @@ run: build: rm -rf ./dist hugo -s site --destination ../dist/html --printUnusedTemplates + +.PHONY: compass-icons +compass-icons: + mkdir -p site/static/css + mkdir -p site/static/font + curl --no-progress-meter -o site/static/css/compass-icons.css https://mattermost.github.io/compass-icons/css/compass-icons.css + curl --no-progress-meter -o "site/static/font/compass-icons.#1" "https://mattermost.github.io/compass-icons/font/compass-icons.{eot,woff2,woff,ttf,svg}" diff --git a/site/content/integrate/apps/functionality/_index.md b/site/content/integrate/apps/functionality/_index.md index 1a1431f857..9a3095cc29 100644 --- a/site/content/integrate/apps/functionality/_index.md +++ b/site/content/integrate/apps/functionality/_index.md @@ -3,6 +3,16 @@ title: Functionality description: Apps API functionality weight: 60 --- +In addition to the {{}}, the Apps framework provides additional functionality: -### Coming soon! -In the future this section will explore additional functionality that Apps provide. For example, event subscriptions. +- [KV Store]({{< ref "kv-store" >}}) - a simple key-value store for App-specific data. + +- [OAuth2 Store]({{< ref "mattermost-api#apps-api" >}}) - store, expand, and retrieve user and App OAuth2 configuration data. + +- [Calling other Apps]({{< ref "mattermost-api#apps-api" >}}) - use the Call API to invoke other Apps (experimental). + +- [Subscriptions]({{< ref "subscriptions" >}}) covers how to subscribe to notifications about Mattermost events. Examples of a subscription include having your App notified whenever a message is posted in a channel that mentions your @bot account. + +- [External webhooks]({{< ref "external-webhooks" >}}) covers subscribing to webhooks from third-party systems. + +See [Authenticating with Mattermost]({{< ref "/integrate/apps/authentication/app-to-mattermost" >}}) for how to authenticate to all these services. diff --git a/site/content/integrate/apps/structure/_index.md b/site/content/integrate/apps/structure/_index.md index b5ada0c11b..0857610c2a 100644 --- a/site/content/integrate/apps/structure/_index.md +++ b/site/content/integrate/apps/structure/_index.md @@ -19,18 +19,3 @@ To interact with users an App must [bind]({{< ref "bindings" >}}) a call handler A [Binding]({{< ref "bindings" >}}) may display a [Form]({{< ref "interactivity" >}}), or it may invoke a call that will return a form. Forms allow the user to input information with limited dynamic behavior, such as dynamically-populated pick lists, or form refreshes on field changes. -## Functionality - -In addition to the {{}}, the Apps framework provides additional functionality: - -- [KV Store]({{< ref "/integrate/apps/functionality/kv-store" >}}) - a simple key-value store for App-specific data. - -- [OAuth2 Store]({{< ref "mattermost-api#apps-api" >}}) - store, expand, and retrieve user and App OAuth2 configuration data. - -- [Calling other Apps]({{< ref "mattermost-api#apps-api" >}}) - use the Call API to invoke other Apps (experimental). - -- [Subscriptions]({{< ref "subscriptions" >}}) covers how to subscribe to notifications about Mattermost events. Examples of a subscription include having your App notified whenever a message is posted in a channel that mentions your @bot account. - -- [External webhooks]({{< ref "/integrate/apps/functionality/external-webhooks" >}}) covers subscribing to webhooks from third-party systems. - -See [Authenticating with Mattermost]({{< ref "/integrate/apps/authentication/app-to-mattermost" >}}) for how to authenticate to all these services. diff --git a/site/content/integrate/apps/structure/call-metadata/_index.md b/site/content/integrate/apps/structure/call-metadata/_index.md new file mode 100644 index 0000000000..369217cf69 --- /dev/null +++ b/site/content/integrate/apps/structure/call-metadata/_index.md @@ -0,0 +1,34 @@ +--- +title: Call metadata +heading: Call metadata +weight: 25 +--- +Calls can be configured to include additional metadata in the `context` field of the [request payload]({{}}). The call's `expand` ({{}}) field contains a list of the available metadata and how much of that data should be included. +No additional metadata is included with the request by default. + +The `expand` value contains the following fields: + +| Name | Type | Description | +|:---------------------------|-------------------------------|:------------------------------------------------------| +| `app` | [ExpandLevel](#expand-levels) | Expands the app information. | +| `acting_user` | [ExpandLevel](#expand-levels) | Expands the acting user information. | +| `acting_user_access_token` | [ExpandLevel](#expand-levels) | Include the user-level access token. | +| `channel` | [ExpandLevel](#expand-levels) | Expands the channel information. | +| `post` | [ExpandLevel](#expand-levels) | Expands the post information. | +| `root_post` | [ExpandLevel](#expand-levels) | Expands the root post information. | +| `team` | [ExpandLevel](#expand-levels) | Expands the team information. | +| `user` | [ExpandLevel](#expand-levels) | Expands the subject user information. | +| `oauth2_app` | [ExpandLevel](#expand-levels) | Expands the remote OAuth2 configuration data. | +| `oauth2_user` | [ExpandLevel](#expand-levels) | Expands the remote OAuth2 user. | +| `locale` | [ExpandLevel](#expand-levels) | Expands the user locale, to be used in localizations. | + +#### Expand levels + +Each ExpandLevel (`string`) value can be one of the following: + +| Name | Description | +|-----------|-------------------------------------------| +| `none` | Include no data for the field. | +| `all` | Include all data available for the field. | +| `summary` | Include key metadata for the field. | +| `id` | Include only relevant identifiers (IDs). | diff --git a/site/content/integrate/apps/structure/call/_index.md b/site/content/integrate/apps/structure/call/_index.md index 943b2ea177..aa6755f725 100644 --- a/site/content/integrate/apps/structure/call/_index.md +++ b/site/content/integrate/apps/structure/call/_index.md @@ -1,132 +1,111 @@ --- -title: "Call" -heading: "Call" +title: "Calls" +heading: "Calls" weight: 20 aliases: - /integrate/apps/api/call/ --- - -A call ([godoc](https://pkg.go.dev/github.com/mattermost/mattermost-plugin-apps/apps#Call)) is the definition of an action. The values are: - -| Name | Type | Description | -|:---------|:-------|:----------------------------------------------------------------------------------------------------------| -| `path` | string | The path of the call. For HTTP apps, the path is appended to the app's `RootURL`. | -| `expand` | Expand | A definition of the information to expand to send to the app. | -| `state` | Object | A set of elements to be interpreted by the app. Forms and slash commands will also populate these values. | - -### Expand - -To avoid extra communication between the app and Mattermost, you can include expansions in the calls. Expansions ([godoc](https://pkg.go.dev/github.com/mattermost/mattermost-plugin-apps/apps#Expand)) will send in the call request the whole information of the required fields. You can expand each value to the following levels: `none`, `all`, or `summary`. - -TODO: Define differences between all and summary - -The possible expansions are: - -| Name | Description | -|:---------------------------|:------------------------------------------------------| -| `app` | Expands the app information. | -| `acting_user` | Expands the acting user information. | -| `acting_user_access_token` | Include the user-level access token. | -| `channel` | Expands the channel information. | -| `post` | Expands the post information. | -| `root_post` | Expands the root post information. | -| `team` | Expands the team information. | -| `user` | Expands the subject user information. | -| `oauth2_app` | Expands the remote OAuth2 configuration data. | -| `oauth2_user` | Expands the remote OAuth2 user. | -| `locale` | Expands the user locale, to be used in localizations. | - - -## Call handling - -### Call request - -When a call is performed, a POST request will be made to the endpoint defined in the call. The call will include a “Mattermost-App-Authorization” header, with a jwtToken. Along the default claims, it will also send the Acting User ID. - -The call request ([godoc](https://pkg.go.dev/github.com/mattermost/mattermost-plugin-apps/apps#CallRequest)) will include: - -| Name | Type | Description | -|:-----------------|:--------|:-------------------------------------------------------------------------------------------| -| `values` | Object | The pairs of key values present in the call. Can be populated by forms and slash commands. | -| `context` | Context | The context of the call. | -| `raw_command` | string | The unparsed command for slash commands. | -| `selected_field` | string | Used in lookups and form refresh to communicate what field. | -| `query` | string | Used in lookups and form refresh what query strings is entered by the user. | - - -The call type ([godoc](https://pkg.go.dev/github.com/mattermost/mattermost-plugin-apps/apps#CallType)) can be: - -| Type | Meaning | -|:---------|:-------------------------------------| -| `submit` | Submit. | -| `form` | Request for a form. | -| `cancel` | A form was canceled. | -| `lookup` | Lookup for dynamic selects in forms. | - -### Call context - -Depending on the location and expansions, calls will have different context. These are all the possible context ([godoc](https://pkg.go.dev/github.com/mattermost/mattermost-plugin-apps/apps#Context)) values. - -| Name | Type | Description | -|:---------------------------|:---------|:------------------------------------------------------------------------------------| -| `app_id` | string | The app ID. | -| `location` | Location | The location from which the call was performed. | -| `subject` | Subject | Event subject. | -| `bot_user_id` | string | Bot user ID. | -| `acting_user_id` | string | ID from the user performing the call. | -| `user_id` | string | ID from the user which is the subject of the call. | -| `team_id` | string | ID from the team from within which the call was performed. | -| `channel_id` | string | ID from the channel from within which the call was performed. | -| `post_id` | string | ID from the post from within which the call was performed. | -| `root_post_id` | string | If the call was performed from a post in a thread, the root post ID of that thread. | -| `app_path` | string | App's path on the Mattermost instance (appendable to `mattermost_site_url`). | -| `mattermost_site_url` | string | Mattermost base URL. | -| `user_agent` | string | User agent used to perform the call. It can be either `webapp` or `mobile`. | -| `bot_access_token` | string | (Expansion) | -| `acting_user` | User | (Expansion) | -| `acting_user_access_token` | string | (Expansion) | -| `oauth2` | App | (Expansion) | -| `app` | App | (Expansion) | -| `channel` | Channel | (Expansion) | -| `post` | Post | (Expansion) | -| `root_post` | Post | (Expansion) | -| `team` | Team | (Expansion) | -| `user` | User | (Expansion) | -| `locale` | string | (Expansion) | - -### Call response - -There are several types ([godoc](https://pkg.go.dev/github.com/mattermost/mattermost-plugin-apps/apps#CallResponseType)) of responses: - -| Value | Description | -|:-----------|:-----------------------------------| -| `ok` | OK. | -| `error` | An error has occurred. | -| `form` | Should open a form. | -| `navigate` | Should navigate the user to a URL. | - -#### OK response +A call ({{}}) defines an App action that can be invoked. + +{{}} +Content on this page refers to the Mattermost Apps framework and not to the Mattermost Calls functionality. +{{}} + +The definition of a call is: + +| Name | Type | Description | +|:---------|:------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------| +| `path` | string | The path of the call. For Apps deployed using HTTP, the path is appended to the App's `RootURL`. | +| `expand` | [Expand]({{}}) | Specifies [additional metadata]({{}}) to include in the call request, such as channel and post information. | +| `state` | Object | A set of elements to be interpreted by the App. Forms and slash commands will also populate these values. | + +## Request + +When a call is performed, a POST request will be made to the endpoint defined in the call. The call will include a JWT in the `Mattermost-App-Authorization` header. The Acting User ID is included in the request by default. + +The call request ({{}}) will include: + +| Name | Type | Description | +|:-----------------|:--------------------|:-------------------------------------------------------------------------------------------| +| `values` | Object | The pairs of key values present in the call. Can be populated by forms and slash commands. | +| `context` | [Context](#context) | The context of the call. | +| `raw_command` | string | The unparsed command for slash commands. | +| `selected_field` | string | Used in lookups and form refresh to communicate what field. | +| `query` | string | Used in lookups and form refresh what query strings is entered by the user. | + +### Context + +The request `context` field contains metadata about the request. The definition of the context ({{}}) field is: + +| Name | Type | Description | +|:-------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------| +| `acting_user_id` | string | ID from the user performing the call. | +| `subject` | Subject (`string`) | Event subject. | +| `user_id` | string | ID from the user which is the subject of the call. | +| `channel_id` | string | ID from the channel from within which the call was performed. | +| `team_id` | string | ID from the team from within which the call was performed. | +| `post_id` | string | ID from the post from within which the call was performed. | +| `root_post_id` | string | If the call was performed from a post in a thread, the root post ID of that thread. | +| `app_id` | AppID (`string`) | The app ID. | +| `location` | Location (`string`) | The location from which the call was performed. | +| `user_agent` | string | User agent used to perform the call.
Valid values are: `mobile`, `webapp`. | +| `track_as_submit` | bool | Whether the call was caused by a submit action from a binding or form. | +| `mattermost_site_url` | string | Mattermost base URL. | +| `developer_mode` | bool | Whether the Apps framework is running in Developer mode. | +| `app_path` | string | App's path on the Mattermost instance (appendable to `mattermost_site_url`). | +| `bot_user_id` | string | Bot user ID. | +| `bot_access_token`{{}} | string | (Expansion) | +| `app`{{}} | {{}} | Details about the installed record of the App. | +| `acting_user`{{}} | {{}} | (Expansion) | +| `acting_user_access_token`{{}} | string | (Expansion) | +| `locale`{{}} | string | (Expansion) | +| `channel`{{}} | {{}} | (Expansion) | +| `channel_member`{{}} | {{}} | (Expansion) | +| `team`{{}} | {{}} | (Expansion) | +| `team_member`{{}} | {{}} | (Expansion) | +| `post`{{}} | {{}} | (Expansion) | +| `root_post`{{}} | {{}} | (Expansion) | +| `user`{{}} | {{}} | (Expansion) | +| `mentioned`{{}} | {{}} (list) | (Expansion) | +| `oauth2`{{}} | {{}} | (Expansion) | + +{{}} +The data in these fields will not be populated by default. For more information on expanding metadata in the request context, see the [Call metadata]({{}}) page. +{{}} + +## Response + +There are several types of responses ({{}}) : + +| Value | Description | +|:-----------|:------------------------------------| +| `ok` | The action completed successfully. | +| `error` | An error has occurred. | +| `form` | Should open a form. | +| `navigate` | Should navigate the user to an URL. | + +### `ok` response | Name | Type | Description | |:-----------|:-------|:-----------------------------------------------------------------------------| -| `type` | string | Use `ok`. | +| `type` | string | The string "`ok`". | | `markdown` | string | (Optional) Markdown text that will be sent to the user as an ephemeral post. | -#### Error response +### `error` response | Name | Type | Description | |:--------|:-------|:------------------------------------------------------------------| -| `type` | string | Use `error`. | +| `type` | string | The string "`error`". | | `error` | string | Markdown text that will be sent to the user as an ephemeral post. | -#### Form response +### `form` response -| Name | Type | Description | -|:-------|:-------|:--------------| -| `type` | string | Use `form`. | -| `form` | form | Form to open. | +| Name | Type | Description | +|:-------|:--------------------------------------------------------------------------------------------------------------|:------------------------------------| +| `type` | string | The string "`form`". | +| `form` | {{}} | The definition of the form to open. | -#### Navigate response +### `navigate` response | Name | Type | Description | |:-----------------------|:-------|:-------------------------------------------------------------| diff --git a/site/content/integrate/apps/structure/manifest/_index.md b/site/content/integrate/apps/structure/manifest/_index.md index 7610f0e5da..ca1fab9125 100644 --- a/site/content/integrate/apps/structure/manifest/_index.md +++ b/site/content/integrate/apps/structure/manifest/_index.md @@ -10,31 +10,31 @@ aliases: All Apps should define a manifest ({{}}) as a JSON object. The fields of the manifest are: -| Name | Type | Description | -|:---------------------------|:----------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------| -| `app_id`(*) | string | ID for your App. | -| `homepage_url`(*) | string | The App homepage. Used in the Marketplace and for OAuth purposes. | -| `version` | string | The version of your App, formatted as `v00.00.0000`. | -| `display_name` | string | The display name for your App. | -| `description` | string | The description for your App. Used in the product Marketplace. Provide examples of key functionality the App provides in a short paragraph. | -| `icon` | string | The icon for your App. Must be a relative path to a PNG image in the static assets folder. Used as the bot account icon and in the product Marketplace. | -| `requested_permissions` | [Permissions](#permissions) | List of permissions needed by the App. | -| `requested_locations` | [Locations](#locations) | The list of top-level locations that the App intends to bind to. | -| `bindings` | [Call]({{}}) | The call invoked to retrieve bindings. Default value: `/bindings` | -| `on_install` | [Call]({{}}) | The call invoked when the App is installed. | -| `on_uninstall` | [Call]({{}}) | The call invoked when the App is uninstalled, before the App is removed. | -| `on_version_changed` | [Call]({{}}) | The call invoked when the App needs to be upgraded or downgraded. | -| `get_oauth2_connect_url` | [Call]({{}}) | The call invoked with the App's "connect to third party" link is selected, to be redirected to the OAuth flow. | -| `on_oauth2_complete` | [Call]({{}}) | The call invoked when the OAuth flow has successfully completed. | -| `on_remote_webhook` | [Call]({{}}) | The call invoked when an HTTP webhook is received from a remote system. | -| `remote_webhook_auth_type` | string | Specifies how incoming webhook messages from remote systems should be authenticated by Mattermost. | -| `aws_lambda`(*) | [AWSLambda](#aws-lambda) | Metadata for an App that can be deployed to AWS Lambda and S3 services, and is accessed using the AWS APIs. | -| `open_faas`(*) | [OpenFAAS](#openfaas) | Metadata for an App that can be deployed to OpenFAAS. | -| `http`(*) | [HTTP](#http) | Metadata for an App that is already deployed externally and is accessed using HTTP. | - -{{}} +| Name | Type | Description | +|:-------------------------------------------|:----------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------| +| `app_id`{{}} | string | ID for your App. | +| `homepage_url`{{}} | string | The App homepage. Used in the Marketplace and for OAuth purposes. | +| `version` | string | The version of your App, formatted as `v00.00.0000`. | +| `display_name` | string | The display name for your App. | +| `description` | string | The description for your App. Used in the product Marketplace. Provide examples of key functionality the App provides in a short paragraph. | +| `icon` | string | The icon for your App. Must be a relative path to a PNG image in the static assets folder. Used as the bot account icon and in the product Marketplace. | +| `requested_permissions` | [Permissions](#permissions) | List of permissions needed by the App. | +| `requested_locations` | [Locations](#locations) | The list of top-level locations that the App intends to bind to. | +| `bindings` | [Call]({{}}) | The call invoked to retrieve bindings. Default value: `/bindings` | +| `on_install` | [Call]({{}}) | The call invoked when the App is installed. | +| `on_uninstall` | [Call]({{}}) | The call invoked when the App is uninstalled, before the App is removed. | +| `on_version_changed` | [Call]({{}}) | The call invoked when the App needs to be upgraded or downgraded. | +| `get_oauth2_connect_url` | [Call]({{}}) | The call invoked with the App's "connect to third party" link is selected, to be redirected to the OAuth flow. | +| `on_oauth2_complete` | [Call]({{}}) | The call invoked when the OAuth flow has successfully completed. | +| `on_remote_webhook` | [Call]({{}}) | The call invoked when an HTTP webhook is received from a remote system. | +| `remote_webhook_auth_type` | string | Specifies how incoming webhook messages from remote systems should be authenticated by Mattermost. | +| `aws_lambda`{{}} | [AWSLambda](#aws-lambda) | Metadata for an App that can be deployed to AWS Lambda and S3 services, and is accessed using the AWS APIs. | +| `open_faas`{{}} | [OpenFAAS](#openfaas) | Metadata for an App that can be deployed to OpenFAAS. | +| `http`{{}} | [HTTP](#http) | Metadata for an App that is already deployed externally and is accessed using HTTP. | + +{{}} - The `app_id` and `homepage_url` values must be specified. -- A deployment method - `aws_lambda`, `open_faas`, or `http` - must be specified. +- One deployment method - `aws_lambda`, `open_faas`, or `http` - must be specified. {{}} For example, a typical App manifest would look like the following: @@ -112,19 +112,20 @@ Example: #### AWS Lambda Provides configuration for deploying an App onto the AWS Lambda and S3 services. +All fields are mandatory ({{}}). -| Name | Type | Description | -|:---------------|:---------------------|:------------------| -| `functions`(*) | AWS Lambda functions | List of functions | +| Name | Type | Description | +|:----------------------------------------|:---------------------|:------------------| +| `functions`{{}} | AWS Lambda functions | List of functions | Each AWS Lambda function contains the following fields: -| Name | Description | -|:-------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `path`(*) | Root path of calls to be mapped to this function. For example: `"/"` | -| `name`(*) | Function's base name; used to compose the actual AWS Lambda name. | -| `handler`(*) | The name of the function handler. | -| `runtime`(*) | AWS Lambda runtime to use. See the {{}} documentation for a list of supported runtimes. | +| Name | Description | +|:--------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `path`{{}} | Root path of calls to be mapped to this function. For example: `"/"` | +| `name`{{}} | Function's base name; used to compose the actual AWS Lambda name. | +| `handler`{{}} | The name of the function handler. | +| `runtime`{{}} | AWS Lambda runtime to use.
See the {{}} documentation for a list of supported runtimes. | Example: ```json @@ -145,17 +146,18 @@ Example: #### OpenFaaS Provides configuration for deploying an App onto OpenFaaS and `faasd` platforms. +All fields are mandatory ({{}}). -| Name | Type | Description | -|:---------------|:-------------------|:------------------| -| `functions`(*) | OpenFaaS functions | List of functions | +| Name | Type | Description | +|:----------------------------------------|:-------------------|:------------------| +| `functions`{{}} | OpenFaaS functions | List of functions | Each function contains the following fields: -| Name | Description | -|:----------|:---------------------------------------------------------------------------------------------------------------| -| `path`(*) | Root path of calls to be mapped to this function. For example: `"/"` | -| `name`(*) | Function's base name; used to compose the actual OpenFaaS function name, combined with the App ID and version. | +| Name | Description | +|:-----------------------------------|:-------------------------------------------------------------------------------------------------------------------| +| `path`{{}} | Root path of calls to be mapped to this function. For example: `"/"` | +| `name`{{}} | Function's base name.
Used to compose the actual OpenFaaS function name, combined with the App ID and version. | Example: ```json diff --git a/site/layouts/partials/head.html b/site/layouts/partials/head.html index 5bb0493684..75e6c8094a 100755 --- a/site/layouts/partials/head.html +++ b/site/layouts/partials/head.html @@ -52,6 +52,9 @@ + + + diff --git a/site/layouts/shortcodes/compass-icon.html b/site/layouts/shortcodes/compass-icon.html new file mode 100644 index 0000000000..adbf5ac301 --- /dev/null +++ b/site/layouts/shortcodes/compass-icon.html @@ -0,0 +1 @@ +{{- "" -}} diff --git a/site/layouts/shortcodes/newtabref.html b/site/layouts/shortcodes/newtabref.html index 96b581be4b..6b3a6c6fbf 100644 --- a/site/layouts/shortcodes/newtabref.html +++ b/site/layouts/shortcodes/newtabref.html @@ -1 +1 @@ -{{ .Get "title" }}{{- "" -}} +{{ .Get "title" }}{{- "" -}} diff --git a/site/layouts/shortcodes/note.html b/site/layouts/shortcodes/note.html index bee874277d..9f8ffda449 100644 --- a/site/layouts/shortcodes/note.html +++ b/site/layouts/shortcodes/note.html @@ -1,6 +1,7 @@ +{{- $icon := .Get 1 -}} diff --git a/site/static/css/styles.css b/site/static/css/styles.css index 50fe5cf653..ca9b10c2af 100644 --- a/site/static/css/styles.css +++ b/site/static/css/styles.css @@ -11,8 +11,12 @@ @font-face { font-family: 'FontAwesome'; - src: url("../fonts/fontawesome-webfont.eot?v=4.7.0"); - src: url("../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0") format("embedded-opentype"), url("../fonts/fontawesome-webfont.woff2?v=4.7.0") format("woff2"), url("../fonts/fontawesome-webfont.woff?v=4.7.0") format("woff"), url("../fonts/fontawesome-webfont.ttf?v=4.7.0") format("truetype"), url("../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular") format("svg"); + src: url("../font/fontawesome-webfont.eot?v=4.7.0"); + src: url("../font/fontawesome-webfont.eot?#iefix&v=4.7.0") format("embedded-opentype"), + url("../font/fontawesome-webfont.woff2?v=4.7.0") format("woff2"), + url("../font/fontawesome-webfont.woff?v=4.7.0") format("woff"), + url("../font/fontawesome-webfont.ttf?v=4.7.0") format("truetype"), + url("../font/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular") format("svg"); font-weight: normal; font-style: normal; } diff --git a/site/static/fonts/FontAwesome.otf b/site/static/font/FontAwesome.otf similarity index 100% rename from site/static/fonts/FontAwesome.otf rename to site/static/font/FontAwesome.otf diff --git a/site/static/fonts/fontawesome-webfont.eot b/site/static/font/fontawesome-webfont.eot similarity index 100% rename from site/static/fonts/fontawesome-webfont.eot rename to site/static/font/fontawesome-webfont.eot diff --git a/site/static/fonts/fontawesome-webfont.svg b/site/static/font/fontawesome-webfont.svg similarity index 100% rename from site/static/fonts/fontawesome-webfont.svg rename to site/static/font/fontawesome-webfont.svg diff --git a/site/static/fonts/fontawesome-webfont.ttf b/site/static/font/fontawesome-webfont.ttf similarity index 100% rename from site/static/fonts/fontawesome-webfont.ttf rename to site/static/font/fontawesome-webfont.ttf diff --git a/site/static/fonts/fontawesome-webfont.woff b/site/static/font/fontawesome-webfont.woff similarity index 100% rename from site/static/fonts/fontawesome-webfont.woff rename to site/static/font/fontawesome-webfont.woff diff --git a/site/static/fonts/fontawesome-webfont.woff2 b/site/static/font/fontawesome-webfont.woff2 similarity index 100% rename from site/static/fonts/fontawesome-webfont.woff2 rename to site/static/font/fontawesome-webfont.woff2 From e8d9a37c8c897110ef5e8cdc41f636de6b618783 Mon Sep 17 00:00:00 2001 From: alan lew Date: Tue, 13 Sep 2022 10:40:02 -0400 Subject: [PATCH 04/22] Add image to Apps Structure topic homepage which illustrates call handlers binding to locations --- .../integrate/apps/structure/_index.md | 3 +- .../apps-calls_bindings_locations.svg | 537 ++++++++++++++++++ 2 files changed, 539 insertions(+), 1 deletion(-) create mode 100644 site/content/integrate/apps/structure/apps-calls_bindings_locations.svg diff --git a/site/content/integrate/apps/structure/_index.md b/site/content/integrate/apps/structure/_index.md index 0857610c2a..fc6ec9c6b9 100644 --- a/site/content/integrate/apps/structure/_index.md +++ b/site/content/integrate/apps/structure/_index.md @@ -15,7 +15,8 @@ Apps consist of three kinds of assets: 3. [Static assets]({{}}) (e.g. images) -To interact with users an App must [bind]({{< ref "bindings" >}}) a call handler to a location in the Mattermost user interface. These locations may be slash commands, toolbar and menu items, or embedded in posts. +To interact with users an App must [bind]({{< ref "bindings" >}}) a call handler to a [location]({{}}) in the Mattermost user interface. These locations may be slash commands, toolbar and menu items, or embedded in posts. A [Binding]({{< ref "bindings" >}}) may display a [Form]({{< ref "interactivity" >}}), or it may invoke a call that will return a form. Forms allow the user to input information with limited dynamic behavior, such as dynamically-populated pick lists, or form refreshes on field changes. +![image](apps-calls_bindings_locations.svg) diff --git a/site/content/integrate/apps/structure/apps-calls_bindings_locations.svg b/site/content/integrate/apps/structure/apps-calls_bindings_locations.svg new file mode 100644 index 0000000000..b43077bfb2 --- /dev/null +++ b/site/content/integrate/apps/structure/apps-calls_bindings_locations.svg @@ -0,0 +1,537 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /call-handler + + + + + + + + + + + + + + + + + + + + + + + + + + + Bindings + + + + + + Locations + + + + + + + + From 8345f5a5e0c86775fedad609f96db2807a23c433 Mon Sep 17 00:00:00 2001 From: alan lew Date: Tue, 13 Sep 2022 12:15:47 -0400 Subject: [PATCH 05/22] More improvements to App Calls topic --- .../integrate/apps/structure/call/_index.md | 172 +++++++++++------- 1 file changed, 102 insertions(+), 70 deletions(-) diff --git a/site/content/integrate/apps/structure/call/_index.md b/site/content/integrate/apps/structure/call/_index.md index aa6755f725..dab2305d03 100644 --- a/site/content/integrate/apps/structure/call/_index.md +++ b/site/content/integrate/apps/structure/call/_index.md @@ -11,105 +11,137 @@ A call ({{}}) | Specifies [additional metadata]({{}}) to include in the call request, such as channel and post information. | -| `state` | Object | A set of elements to be interpreted by the App. Forms and slash commands will also populate these values. | +| `state` | map | A set of elements to be interpreted by the App. Forms and slash commands will also populate these values. | + +An example call looks like: + +```json +{ + "path": "/my-handler", + "expand": { + "app": "all", + "user": "summary" + }, + "state": {} +} +``` ## Request When a call is performed, a POST request will be made to the endpoint defined in the call. The call will include a JWT in the `Mattermost-App-Authorization` header. The Acting User ID is included in the request by default. -The call request ({{}}) will include: +The data structure of call request ({{}}) is: | Name | Type | Description | |:-----------------|:--------------------|:-------------------------------------------------------------------------------------------| -| `values` | Object | The pairs of key values present in the call. Can be populated by forms and slash commands. | +| `values` | map | The pairs of key values present in the call. Can be populated by forms and slash commands. | | `context` | [Context](#context) | The context of the call. | | `raw_command` | string | The unparsed command for slash commands. | | `selected_field` | string | Used in lookups and form refresh to communicate what field. | | `query` | string | Used in lookups and form refresh what query strings is entered by the user. | +An example call request looks like: + +```json +{ + "values": {}, + "context": { + "acting_user_id": "", + "subject": "" + }, + "raw_command": "hello" +} +``` + ### Context -The request `context` field contains metadata about the request. The definition of the context ({{}}) field is: - -| Name | Type | Description | -|:-------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------| -| `acting_user_id` | string | ID from the user performing the call. | -| `subject` | Subject (`string`) | Event subject. | -| `user_id` | string | ID from the user which is the subject of the call. | -| `channel_id` | string | ID from the channel from within which the call was performed. | -| `team_id` | string | ID from the team from within which the call was performed. | -| `post_id` | string | ID from the post from within which the call was performed. | -| `root_post_id` | string | If the call was performed from a post in a thread, the root post ID of that thread. | -| `app_id` | AppID (`string`) | The app ID. | -| `location` | Location (`string`) | The location from which the call was performed. | -| `user_agent` | string | User agent used to perform the call.
Valid values are: `mobile`, `webapp`. | -| `track_as_submit` | bool | Whether the call was caused by a submit action from a binding or form. | -| `mattermost_site_url` | string | Mattermost base URL. | -| `developer_mode` | bool | Whether the Apps framework is running in Developer mode. | -| `app_path` | string | App's path on the Mattermost instance (appendable to `mattermost_site_url`). | -| `bot_user_id` | string | Bot user ID. | -| `bot_access_token`{{}} | string | (Expansion) | -| `app`{{}} | {{}} | Details about the installed record of the App. | -| `acting_user`{{}} | {{}} | (Expansion) | -| `acting_user_access_token`{{}} | string | (Expansion) | -| `locale`{{}} | string | (Expansion) | -| `channel`{{}} | {{}} | (Expansion) | -| `channel_member`{{}} | {{}} | (Expansion) | -| `team`{{}} | {{}} | (Expansion) | -| `team_member`{{}} | {{}} | (Expansion) | -| `post`{{}} | {{}} | (Expansion) | -| `root_post`{{}} | {{}} | (Expansion) | -| `user`{{}} | {{}} | (Expansion) | -| `mentioned`{{}} | {{}} (list) | (Expansion) | -| `oauth2`{{}} | {{}} | (Expansion) | - -{{}} +The request `context` field contains metadata about the request. The data structure of the context ({{}}) field is: + +| Name | Type | Description | +|:---------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------| +| `acting_user_id` | string | ID from the user performing the call. | +| `subject` | Subject (`string`) | Event subject. | +| `user_id` | string | ID from the user which is the subject of the call. | +| `channel_id` | string | ID from the channel from within which the call was performed. | +| `team_id` | string | ID from the team from within which the call was performed. | +| `post_id` | string | ID from the post from within which the call was performed. | +| `root_post_id` | string | If the call was performed from a post in a thread, the root post ID of that thread. | +| `app_id` | AppID (`string`) | The app ID. | +| `location` | Location (`string`) | The location from which the call was performed. | +| `user_agent` | string | User agent used to perform the call.
Valid values are: `mobile`, `webapp`. | +| `track_as_submit` | bool | Whether the call was caused by a submit action from a binding or form. | +| `mattermost_site_url` | string | Mattermost base URL. | +| `developer_mode` | bool | Whether the Apps framework is running in Developer mode. | +| `app_path` | string | App's path on the Mattermost instance (appendable to `mattermost_site_url`). | +| `bot_user_id` | string | Bot user ID. | +| `bot_access_token`{{}} | string | (Expansion) | +| `app`{{}} | {{}} | Details about the installed record of the App. | +| `acting_user`{{}} | {{}} | (Expansion) | +| `acting_user_access_token`{{}} | string | (Expansion) | +| `locale`{{}} | string | (Expansion) | +| `channel`{{}} | {{}} | (Expansion) | +| `channel_member`{{}} | {{}} | (Expansion) | +| `team`{{}} | {{}} | (Expansion) | +| `team_member`{{}} | {{}} | (Expansion) | +| `post`{{}} | {{}} | (Expansion) | +| `root_post`{{}} | {{}} | (Expansion) | +| `user`{{}} | {{}} | (Expansion) | +| `mentioned`{{}} | {{}} (list) | (Expansion) | +| `oauth2`{{}} | {{}} | (Expansion) | + +{{}} The data in these fields will not be populated by default. For more information on expanding metadata in the request context, see the [Call metadata]({{}}) page. {{}} -## Response +An example context field looks like: -There are several types of responses ({{}}) : +```json +{ + "context": { + + } +} +``` -| Value | Description | -|:-----------|:------------------------------------| -| `ok` | The action completed successfully. | -| `error` | An error has occurred. | -| `form` | Should open a form. | -| `navigate` | Should navigate the user to an URL. | - -### `ok` response - -| Name | Type | Description | -|:-----------|:-------|:-----------------------------------------------------------------------------| -| `type` | string | The string "`ok`". | -| `markdown` | string | (Optional) Markdown text that will be sent to the user as an ephemeral post. | +## Response -### `error` response +The data structure of a call response is: -| Name | Type | Description | -|:--------|:-------|:------------------------------------------------------------------| -| `type` | string | The string "`error`". | -| `error` | string | Markdown text that will be sent to the user as an ephemeral post. | +| Name | Type | Description | +|------------------------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------| +| `type` | [CallResponseType](#call-response-types) | The type of response being returned | +| `text` | string | Used by the `ok` and `error` response types to return a markdown message that is sent to the user as an ephemeral post | +| `data` | map | Used by the `ok` response type to return additional data | +| `navigate_to_url` | string | Used by the `navigate` response type to redirect the user to a specified URL | +| `use_external_browser` | bool | Used by the `navigate` response type to indicate the system web browser should be used when redirecting the user to an URL | +| `call` | [Call](#data-structure) | Used by the `call` response type to specify a call to execute | +| `form` | {{}} | Used by the `form` response type to specify a form to display | -### `form` response +An example call response looks like: -| Name | Type | Description | -|:-------|:--------------------------------------------------------------------------------------------------------------|:------------------------------------| -| `type` | string | The string "`form`". | -| `form` | {{}} | The definition of the form to open. | +```json +{ + "type": "ok", + "text": "### Success!\n\nThe operation completed successfully." +} +``` -### `navigate` response +### Call response types -| Name | Type | Description | -|:-----------------------|:-------|:-------------------------------------------------------------| -| `type` | string | Use `navigate`. | -| `navigate_to_url` | string | URL to navigate to. | -| `use_external_browser` | bool | Whether the navigation link wll open in an external browser. | +There are several types of responses ({{}}): +| Value | Description | +|:-----------|:------------------------------------| +| `ok` | The action completed successfully. | +| `error` | An error has occurred. | +| `form` | Should open a form. | +| `call` | Should execute a call. | +| `navigate` | Should navigate the user to an URL. | From 7396d4e1b38b4f6ad6b9014a89197b5c1e416ec7 Mon Sep 17 00:00:00 2001 From: alan lew Date: Tue, 13 Sep 2022 14:37:11 -0400 Subject: [PATCH 06/22] Remove unimplemented or unsupported struct fields; Improve context example --- .../integrate/apps/structure/call/_index.md | 70 +++++++++++++------ 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/site/content/integrate/apps/structure/call/_index.md b/site/content/integrate/apps/structure/call/_index.md index dab2305d03..047d9137bc 100644 --- a/site/content/integrate/apps/structure/call/_index.md +++ b/site/content/integrate/apps/structure/call/_index.md @@ -5,7 +5,7 @@ weight: 20 aliases: - /integrate/apps/api/call/ --- -A call ({{}}) defines an App action that can be invoked. +A Call defines an App action that can be invoked. {{}} Content on this page refers to the Mattermost Apps framework and not to the Mattermost Calls functionality. @@ -13,7 +13,7 @@ Content on this page refers to the Mattermost Apps framework and not to the Matt ## Data structure -The data structure of a call is: +The data structure of a call ({{}}) is: | Name | Type | Description | |:---------|:------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------| @@ -36,28 +36,36 @@ An example call looks like: ## Request -When a call is performed, a POST request will be made to the endpoint defined in the call. The call will include a JWT in the `Mattermost-App-Authorization` header. The Acting User ID is included in the request by default. +When a call is performed, a POST request will be made to the endpoint defined in the call. The call will include a JWT in the `Mattermost-App-Authorization` header. The Acting User's ID is included in the request by default. The data structure of call request ({{}}) is: -| Name | Type | Description | -|:-----------------|:--------------------|:-------------------------------------------------------------------------------------------| -| `values` | map | The pairs of key values present in the call. Can be populated by forms and slash commands. | -| `context` | [Context](#context) | The context of the call. | -| `raw_command` | string | The unparsed command for slash commands. | -| `selected_field` | string | Used in lookups and form refresh to communicate what field. | -| `query` | string | Used in lookups and form refresh what query strings is entered by the user. | +| Name | Type | Description | +|:-----------------|:------------------------------------|:-------------------------------------------------------------------------------------------| +| `path` | string | (See above) | +| `expand` | [Expand]({{}}) | (See above) | +| `state` | map | (See above) | +| `values` | map | The pairs of key values present in the call. Can be populated by forms and slash commands. | +| `context` | [Context](#context) | The context of the call. | +| `raw_command` | string | The unparsed command for slash commands. | +| `selected_field` | string | Used in lookups and form refresh to communicate what field. | +| `query` | string | Used in lookups and form refresh what query strings is entered by the user. | -An example call request looks like: +An example call request looks like (some `context` fields omitted for brevity): ```json { - "values": {}, + "path": "/send", + "expand": {}, "context": { - "acting_user_id": "", - "subject": "" + "app_id": "hello-world", + "location": "/command/helloworld/send", + "acting_user": { + "id": "k86a9cy93f8azx7jjiy5xfq5jc" + }, + "oauth2": {} }, - "raw_command": "hello" + "raw_command": "/helloworld send" } ``` @@ -67,9 +75,7 @@ The request `context` field contains metadata about the request. The data struct | Name | Type | Description | |:---------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------| -| `acting_user_id` | string | ID from the user performing the call. | | `subject` | Subject (`string`) | Event subject. | -| `user_id` | string | ID from the user which is the subject of the call. | | `channel_id` | string | ID from the channel from within which the call was performed. | | `team_id` | string | ID from the team from within which the call was performed. | | `post_id` | string | ID from the post from within which the call was performed. | @@ -105,8 +111,32 @@ An example context field looks like: ```json { - "context": { - + "context": { + "app_id": "hello-world", + "location": "/command/helloworld/send", + "user_agent": "webapp", + "track_as_submit": true, + "mattermost_site_url": "http://localhost:8066", + "developer_mode": true, + "app_path": "/plugins/com.mattermost.apps/apps/hello-world", + "bot_user_id": "3sjcm1ztkbfhpnddz389ycq1pe", + "bot_access_token": "tt59irtaopd7fegi3taamd7dxw", + "acting_user": { + "id": "k86a9cy93f8azx7jjiy5xfq5jc", + "delete_at": 0, + "username": "", + "auth_service": "", + "email": "", + "nickname": "", + "first_name": "", + "last_name": "", + "position": "", + "roles": "", + "locale": "", + "timezone": null, + "disable_welcome_email": false + }, + "oauth2": {} } } ``` @@ -122,7 +152,6 @@ The data structure of a call response is: | `data` | map | Used by the `ok` response type to return additional data | | `navigate_to_url` | string | Used by the `navigate` response type to redirect the user to a specified URL | | `use_external_browser` | bool | Used by the `navigate` response type to indicate the system web browser should be used when redirecting the user to an URL | -| `call` | [Call](#data-structure) | Used by the `call` response type to specify a call to execute | | `form` | {{}} | Used by the `form` response type to specify a form to display | An example call response looks like: @@ -143,5 +172,4 @@ There are several types of responses ({{}}) file, which contains App details such as name, version, requested permissions, and deployment methods +1. A [manifest]({{< ref "manifest" >}}), which contains App details such as name, version, requested permissions, and deployment methods 2. [Call]({{< ref "call" >}}) handlers, which are functions that handle incoming requests from the Mattermost server -3. [Static assets]({{}}) (e.g. images) +3. [Static assets]({{}}), such as images To interact with users an App must [bind]({{< ref "bindings" >}}) a call handler to a [location]({{}}) in the Mattermost user interface. These locations may be slash commands, toolbar and menu items, or embedded in posts. -A [Binding]({{< ref "bindings" >}}) may display a [Form]({{< ref "interactivity" >}}), or it may invoke a call that will return a form. Forms allow the user to input information with limited dynamic behavior, such as dynamically-populated pick lists, or form refreshes on field changes. +![image](apps-calls_bindings_locations_v2.svg) -![image](apps-calls_bindings_locations.svg) +A [Binding]({{< ref "bindings" >}}) may display a [Form]({{< ref "interactivity" >}}), or it may invoke a call that will return a form. Forms allow the user to input information with limited dynamic behavior, such as dynamically-populated pick lists, or form refreshes on field changes. diff --git a/site/content/integrate/apps/structure/apps-calls_bindings_locations.svg b/site/content/integrate/apps/structure/apps-calls_bindings_locations_v2.svg similarity index 97% rename from site/content/integrate/apps/structure/apps-calls_bindings_locations.svg rename to site/content/integrate/apps/structure/apps-calls_bindings_locations_v2.svg index b43077bfb2..0ee1f65f7b 100644 --- a/site/content/integrate/apps/structure/apps-calls_bindings_locations.svg +++ b/site/content/integrate/apps/structure/apps-calls_bindings_locations_v2.svg @@ -1,16 +1,16 @@ + inkscape:current-layer="svg349" /> + id="defs161"> + width="27940" + height="21590" + id="rect155" /> + x="27" + y="21" + width="27885" + height="21547" + id="rect158" /> + id="defs188"> + id="font-face163" /> + id="missing-glyph165" /> + id="glyph167" /> + id="glyph169" /> + id="glyph171" /> + id="glyph173" /> + id="glyph175" /> + id="glyph177" /> + id="glyph179" /> + id="glyph181" /> + id="glyph183" /> + id="glyph185" /> + id="defs225"> + id="font-face190" /> + id="missing-glyph192" /> + id="glyph194" /> + id="glyph196" /> + + id="glyph200" /> + id="glyph202" /> + - + id="glyph206" /> + unicode="e" + horiz-adv-x="953" + d="M 639,-20 C 477,-20 349,29 256,128 162,227 115,364 115,539 115,716 159,856 246,960 333,1064 449,1116 596,1116 733,1116 842,1071 922,981 1002,890 1042,771 1042,623 L 1042,518 287,518 C 290,389 323,292 385,225 446,158 533,125 645,125 763,125 880,150 995,199 L 995,51 C 936,26 881,8 829,-4 776,-14 713,-20 639,-20 Z M 594,977 C 506,977 436,948 384,891 331,834 300,754 291,653 L 864,653 C 864,758 841,838 794,894 747,949 681,977 594,977 Z" + id="glyph208" /> + id="glyph210" /> + id="glyph212" /> + + + id="glyph218" /> + + + + + + + + + d="M 1192,0 L 887,0 887,653 C 887,734 873,794 844,835 815,875 770,895 707,895 622,895 560,867 522,810 484,753 465,658 465,526 L 465,0 160,0 160,1118 393,1118 434,975 451,975 C 485,1029 532,1070 592,1098 651,1125 719,1139 795,1139 925,1139 1024,1104 1091,1034 1158,963 1192,862 1192,729 L 1192,0 Z" + id="glyph231" /> + + + + + id="defs246"> + ooo:id-list="id3 id4 id5 id6" + id="g244" /> + id="defs278"> + id="path248" /> + id="path251" /> + id="path254" /> + id="path257" /> + id="path260" /> + id="path263" /> + id="path266" /> + id="path269" /> + id="path272" /> + id="path275" /> + id="g283" + transform="translate(-1750,-6500)"> @@ -312,10 +380,10 @@ + id="g347" + transform="translate(-1750,-6500)"> + id="g345"> + id="g341"> + id="g291"> + id="g289"> + x="18000" + y="8063" + width="8669" + height="5438" + id="rect285" /> + id="image287" /> + id="g304"> + y="10148" + width="7251" + height="1268" + id="rect293" /> /call-handler + id="tspan295">/call-handler + class="com.sun.star.drawing.CustomShape" + id="g313"> - + x="9999" + y="9280" + width="7254" + height="3004" + id="rect306" /> - - - - - + d="m 10000,10031 h 5750 v -750 l 1501,1500 -1501,1501 v -751 h -5750 z" + id="path308" /> - - - - - - - - + d="m 10000,10031 h 5750 v -750 l 1501,1500 -1501,1501 v -751 h -5750 z" + id="path310" /> + id="g326"> + id="id5"> + x="11400" + y="10100" + width="3651" + height="1401" + id="rect315" /> Bindings + id="tspan317">Binding + id="g339"> + id="id6"> + x="18250" + y="6500" + width="8501" + height="1213" + id="rect328" /> Locations + id="tspan330">Mattermost UI Location diff --git a/site/content/integrate/apps/structure/call-metadata/_index.md b/site/content/integrate/apps/structure/call-metadata/_index.md index 369217cf69..9961666b29 100644 --- a/site/content/integrate/apps/structure/call-metadata/_index.md +++ b/site/content/integrate/apps/structure/call-metadata/_index.md @@ -13,14 +13,17 @@ The `expand` value contains the following fields: | `app` | [ExpandLevel](#expand-levels) | Expands the app information. | | `acting_user` | [ExpandLevel](#expand-levels) | Expands the acting user information. | | `acting_user_access_token` | [ExpandLevel](#expand-levels) | Include the user-level access token. | +| `locale` | [ExpandLevel](#expand-levels) | Expands the user locale, to be used in localizations. | | `channel` | [ExpandLevel](#expand-levels) | Expands the channel information. | +| `channel_member` | [ExpandLevel](#expand-levels) | Expands channel member information. | +| `team` | [ExpandLevel](#expand-levels) | Expands the team information. | +| `team_member` | [ExpandLevel](#expand-levels) | Expands team member information. | | `post` | [ExpandLevel](#expand-levels) | Expands the post information. | | `root_post` | [ExpandLevel](#expand-levels) | Expands the root post information. | -| `team` | [ExpandLevel](#expand-levels) | Expands the team information. | | `user` | [ExpandLevel](#expand-levels) | Expands the subject user information. | | `oauth2_app` | [ExpandLevel](#expand-levels) | Expands the remote OAuth2 configuration data. | -| `oauth2_user` | [ExpandLevel](#expand-levels) | Expands the remote OAuth2 user. | -| `locale` | [ExpandLevel](#expand-levels) | Expands the user locale, to be used in localizations. | +| `oauth2_user` | [ExpandLevel](#expand-levels) | Expands the remote OAuth2 user data. | + #### Expand levels @@ -32,3 +35,22 @@ Each ExpandLevel (`string`) value can be one of the following: | `all` | Include all data available for the field. | | `summary` | Include key metadata for the field. | | `id` | Include only relevant identifiers (IDs). | + +### Available information + +The following table details what sub-fields are included for each metadata field for the `summary` and `id` ExpandLevels: + +| Metadata Field | Data Type | `summary` level | `id` level | +|---------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------| +| `app` | {{}} | `app_id`
`version`
`webhook_secret`
`bot_user_id`
`bot_username` | no sub-fields | +| `acting_user` | {{}} | `bot_description`
`delete_at`
`email`
`first_name`
`id`
`is_bot`
`last_name`
`locale`
`nickname`
`roles`
`timezone`
`username` | `id` | +| `acting_user_access_token`
(`all` level only) | string | no sub-fields | no sub-fields | +| `locale` | string | same as `all` level | _n/a_ | +| `channel` | {{}} | `id`
`deleted_at`
`team_id`
`type`
`display_name`
`name` | `id` | +| `channel_member` | {{}} | same as `all` level | no sub-fields | +| `team` | {{}} | `id`
`display_name`
`name`
`description`
`email`
`type` | `id` | +| `team_member` | {{}} | same as `all` level | no sub-fields | +| `post`/`root_post` | {{}} | `id`
`type`
`user_id`
`channel_id`
`root_id`
`message` | `id` | +| `user` | {{}} | `bot_description`
`delete_at`
`email`
`first_name`
`id`
`is_bot`
`last_name`
`locale`
`nickname`
`roles`
`timezone`
`username` | `id` | +| `oauth2_app` | {{}} | {{}}
`connect_url`
`complete_url` | no sub-fields | +| `oauth2_user` | _any_ | all data stored in the {{}} field | no data | diff --git a/site/static/css/compass-icons.css b/site/static/css/compass-icons.css new file mode 100644 index 0000000000..065117008a --- /dev/null +++ b/site/static/css/compass-icons.css @@ -0,0 +1,328 @@ +@charset "UTF-8"; +@font-face { + font-family: 'compass-icons'; + src: url('../font/compass-icons.eot?86763500'); + src: url('../font/compass-icons.eot?86763500#iefix') format('embedded-opentype'), + url('../font/compass-icons.woff2?86763500') format('woff2'), + url('../font/compass-icons.woff?86763500') format('woff'), + url('../font/compass-icons.ttf?86763500') format('truetype'), + url('../font/compass-icons.svg?86763500#compass-icons') format('svg'); + font-weight: normal; + font-style: normal; +} +/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ +/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ +/* +@media screen and (-webkit-min-device-pixel-ratio:0) { + @font-face { + font-family: 'compass-icons'; + src: url('../font/compass-icons.svg?86763500#compass-icons') format('svg'); + } +} +*/ +[class^="icon-"]:before, [class*=" icon-"]:before { + font-family: "compass-icons"; + font-style: normal; + font-weight: normal; + speak: never; + + display: inline-block; + text-decoration: inherit; + width: 1em; + margin-right: .2em; + text-align: center; + /* opacity: .8; */ + + /* For safety - reset parent styles, that can break glyph codes*/ + font-variant: normal; + text-transform: none; + + /* fix buttons height, for twitter bootstrap */ + line-height: 1em; + + /* Animation center compensation - margins should be symmetric */ + /* remove if not needed */ + margin-left: .2em; + + /* you can be more comfortable with increased icons size */ + /* font-size: 120%; */ + + /* Font smoothing. That was taken from TWBS */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + /* Uncomment for 3D effect */ + /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */ +} + +.icon-mattermost:before { content: '\e800'; } /* '' */ +.icon-gfycat:before { content: '\e804'; } /* '' */ +.icon-globe:before { content: '\e805'; } /* '' */ +.icon-iframe-list-outline:before { content: '\e806'; } /* '' */ +.icon-oauth:before { content: '\e807'; } /* '' */ +.icon-server-outline:before { content: '\e80a'; } /* '' */ +.icon-slash-forward-box-outline:before { content: '\e80b'; } /* '' */ +.icon-webhook-incoming:before { content: '\e80c'; } /* '' */ +.icon-webhook-outgoing:before { content: '\e80d'; } /* '' */ +.icon-image-area-outline:before { content: '\e80e'; } /* '' */ +.icon-emoticon-plus-outline:before { content: '\e80f'; } /* '' */ +.icon-mark-as-unread:before { content: '\e810'; } /* '' */ +.icon-arrow-back-ios:before { content: '\e811'; } /* '' */ +.icon-arrow-forward-ios:before { content: '\e812'; } /* '' */ +.icon-brand-zoom:before { content: '\e813'; } /* '' */ +.icon-menu-variant:before { content: '\e814'; } /* '' */ +.icon-message-check:before { content: '\e815'; } /* '' */ +.icon-airplane-variant:before { content: '\e816'; } /* '' */ +.icon-leaf-outline:before { content: '\e818'; } /* '' */ +.icon-basketball:before { content: '\e819'; } /* '' */ +.icon-emoticon-custom-outline:before { content: '\e81a'; } /* '' */ +.icon-message-check-outline:before { content: '\e81b'; } /* '' */ +.icon-image-broken-outline:before { content: '\e81c'; } /* '' */ +.icon-format-header:before { content: '\e81d'; } /* '' */ +.icon-circle-multiple-outline-lock:before { content: '\e81e'; } /* '' */ +.icon-server-variant:before { content: '\e81f'; } /* '' */ +.icon-server-variant-plus:before { content: '\e820'; } /* '' */ +.icon-search-list:before { content: '\e821'; } /* '' */ +.icon-brand-one-login:before { content: '\e825'; } /* '' */ +.icon-key-variant-circle:before { content: '\e827'; } /* '' */ +.icon-file-zip-outline:before { content: '\e828'; } /* '' */ +.icon-file-patch-outline:before { content: '\e829'; } /* '' */ +.icon-file-image-broken-outline:before { content: '\e82b'; } /* '' */ +.icon-product-channels:before { content: '\e82c'; } /* '' */ +.icon-product-playbooks:before { content: '\e82d'; } /* '' */ +.icon-product-boards:before { content: '\e82e'; } /* '' */ +.icon-products:before { content: '\e82f'; } /* '' */ +.icon-file-audio-outline:before { content: '\e830'; } /* '' */ +.icon-file-pdf-outline:before { content: '\e831'; } /* '' */ +.icon-account-multiple-plus-outline:before { content: '\e832'; } /* '' */ +.icon-file-gif:before { content: '\e833'; } /* '' */ +.icon-kanban:before { content: '\e834'; } /* '' */ +.icon-file-text-outline-large:before { content: '\e900'; } /* '' */ +.icon-file-word-outline-large:before { content: '\e901'; } /* '' */ +.icon-file-excel-outline-large:before { content: '\e902'; } /* '' */ +.icon-file-powerpoint-outline-large:before { content: '\e903'; } /* '' */ +.icon-file-pdf-outline-large:before { content: '\e904'; } /* '' */ +.icon-file-image-outline-large:before { content: '\e905'; } /* '' */ +.icon-file-video-outline-large:before { content: '\e906'; } /* '' */ +.icon-file-audio-outline-large:before { content: '\e907'; } /* '' */ +.icon-file-generic-outline-large:before { content: '\e908'; } /* '' */ +.icon-file-patch-outline-large:before { content: '\e909'; } /* '' */ +.icon-file-zip-outline-large:before { content: '\e90a'; } /* '' */ +.icon-file-code-outline-large:before { content: '\e90b'; } /* '' */ +.icon-file-image-broken-outline-large:before { content: '\e90c'; } /* '' */ +.icon-file-multiple-outline-large:before { content: '\e90d'; } /* '' */ +.icon-account-multiple-outline:before { content: '󰀏'; } /* '\f000f' */ +.icon-account-outline:before { content: '󰀓'; } /* '\f0013' */ +.icon-airplane:before { content: '󰀝'; } /* '\f001d' */ +.icon-alert-outline:before { content: '󰀪'; } /* '\f002a' */ +.icon-apps:before { content: '󰀻'; } /* '\f003b' */ +.icon-arrow-down:before { content: '󰁅'; } /* '\f0045' */ +.icon-arrow-down-bold-circle-outline:before { content: '󰁈'; } /* '\f0048' */ +.icon-arrow-expand-all:before { content: '󰁌'; } /* '\f004c' */ +.icon-arrow-left:before { content: '󰁍'; } /* '\f004d' */ +.icon-arrow-right:before { content: '󰁔'; } /* '\f0054' */ +.icon-arrow-up:before { content: '󰁝'; } /* '\f005d' */ +.icon-arrow-up-bold-circle-outline:before { content: '󰁠'; } /* '\f0060' */ +.icon-at:before { content: '󰁥'; } /* '\f0065' */ +.icon-flask-outline:before { content: '󰂖'; } /* '\f0096' */ +.icon-bell-outline:before { content: '󰂜'; } /* '\f009c' */ +.icon-bookmark:before { content: '󰃀'; } /* '\f00c0' */ +.icon-bookmark-outline:before { content: '󰃃'; } /* '\f00c3' */ +.icon-cellphone:before { content: '󰄜'; } /* '\f011c' */ +.icon-chart-bar:before { content: '󰄨'; } /* '\f0128' */ +.icon-chart-line:before { content: '󰄪'; } /* '\f012a' */ +.icon-check:before { content: '󰄬'; } /* '\f012c' */ +.icon-check-all:before { content: '󰄭'; } /* '\f012d' */ +.icon-checkbox-blank-outline:before { content: '󰄱'; } /* '\f0131' */ +.icon-checkbox-marked:before { content: '󰄲'; } /* '\f0132' */ +.icon-checkbox-multiple-marked-outline:before { content: '󰄹'; } /* '\f0139' */ +.icon-chevron-down:before { content: '󰅀'; } /* '\f0140' */ +.icon-chevron-left:before { content: '󰅁'; } /* '\f0141' */ +.icon-chevron-right:before { content: '󰅂'; } /* '\f0142' */ +.icon-chevron-up:before { content: '󰅃'; } /* '\f0143' */ +.icon-clock-outline:before { content: '󰅐'; } /* '\f0150' */ +.icon-close:before { content: '󰅖'; } /* '\f0156' */ +.icon-close-circle:before { content: '󰅙'; } /* '\f0159' */ +.icon-close-circle-outline:before { content: '󰅚'; } /* '\f015a' */ +.icon-code-brackets:before { content: '󰅪'; } /* '\f016a' */ +.icon-code-tags:before { content: '󰅴'; } /* '\f0174' */ +.icon-cog-outline:before { content: '󰅽'; } /* '\f017d' */ +.icon-console:before { content: '󰆍'; } /* '\f018d' */ +.icon-content-copy:before { content: '󰆏'; } /* '\f018f' */ +.icon-credit-card-outline:before { content: '󰆛'; } /* '\f019b' */ +.icon-currency-usd:before { content: '󰇁'; } /* '\f01c1' */ +.icon-dots-horizontal:before { content: '󰇘'; } /* '\f01d8' */ +.icon-dots-vertical:before { content: '󰇙'; } /* '\f01d9' */ +.icon-drag-vertical:before { content: '󰇝'; } /* '\f01dd' */ +.icon-email-outline:before { content: '󰇰'; } /* '\f01f0' */ +.icon-emoticon-outline:before { content: '󰇲'; } /* '\f01f2' */ +.icon-emoticon-happy-outline:before { content: '󰇵'; } /* '\f01f5' */ +.icon-exit-to-app:before { content: '󰈆'; } /* '\f0206' */ +.icon-file-generic-outline:before { content: '󰈤'; } /* '\f0224' */ +.icon-filter-variant:before { content: '󰈶'; } /* '\f0236' */ +.icon-fire:before { content: '󰈸'; } /* '\f0238' */ +.icon-flag:before { content: '󰈻'; } /* '\f023b' */ +.icon-flag-checkered:before { content: '󰈼'; } /* '\f023c' */ +.icon-flag-outline:before { content: '󰈽'; } /* '\f023d' */ +.icon-folder-outline:before { content: '󰉖'; } /* '\f0256' */ +.icon-format-bold:before { content: '󰉤'; } /* '\f0264' */ +.icon-format-clear:before { content: '󰉥'; } /* '\f0265' */ +.icon-format-header-1:before { content: '󰉫'; } /* '\f026b' */ +.icon-format-header-2:before { content: '󰉬'; } /* '\f026c' */ +.icon-format-header-3:before { content: '󰉭'; } /* '\f026d' */ +.icon-format-header-4:before { content: '󰉮'; } /* '\f026e' */ +.icon-format-header-5:before { content: '󰉯'; } /* '\f026f' */ +.icon-format-header-6:before { content: '󰉰'; } /* '\f0270' */ +.icon-format-italic:before { content: '󰉷'; } /* '\f0277' */ +.icon-format-list-bulleted:before { content: '󰉹'; } /* '\f0279' */ +.icon-format-list-numbered:before { content: '󰉻'; } /* '\f027b' */ +.icon-format-strikethrough-variant:before { content: '󰊁'; } /* '\f0281' */ +.icon-github-circle:before { content: '󰊤'; } /* '\f02a4' */ +.icon-glasses:before { content: '󰊪'; } /* '\f02aa' */ +.icon-brand-google:before { content: '󰊭'; } /* '\f02ad' */ +.icon-heart-outline:before { content: '󰋕'; } /* '\f02d5' */ +.icon-help:before { content: '󰋖'; } /* '\f02d6' */ +.icon-import:before { content: '󰋺'; } /* '\f02fa' */ +.icon-information-outline:before { content: '󰋽'; } /* '\f02fd' */ +.icon-key-variant:before { content: '󰌋'; } /* '\f030b' */ +.icon-laptop:before { content: '󰌢'; } /* '\f0322' */ +.icon-leaf:before { content: '󰌪'; } /* '\f032a' */ +.icon-lightbulb-outline:before { content: '󰌶'; } /* '\f0336' */ +.icon-link-variant:before { content: '󰌹'; } /* '\f0339' */ +.icon-link-variant-off:before { content: '󰌺'; } /* '\f033a' */ +.icon-lock:before { content: '󰌾'; } /* '\f033e' */ +.icon-lock-outline:before { content: '󰍁'; } /* '\f0341' */ +.icon-magnify:before { content: '󰍉'; } /* '\f0349' */ +.icon-magnify-minus:before { content: '󰍊'; } /* '\f034a' */ +.icon-magnify-plus:before { content: '󰍋'; } /* '\f034b' */ +.icon-menu:before { content: '󰍜'; } /* '\f035c' */ +.icon-menu-down:before { content: '󰍝'; } /* '\f035d' */ +.icon-menu-left:before { content: '󰍞'; } /* '\f035e' */ +.icon-menu-right:before { content: '󰍟'; } /* '\f035f' */ +.icon-menu-up:before { content: '󰍠'; } /* '\f0360' */ +.icon-message-text-outline:before { content: '󰍪'; } /* '\f036a' */ +.icon-microphone:before { content: '󰍬'; } /* '\f036c' */ +.icon-microphone-off:before { content: '󰍭'; } /* '\f036d' */ +.icon-minus:before { content: '󰍴'; } /* '\f0374' */ +.icon-minus-box:before { content: '󰍵'; } /* '\f0375' */ +.icon-minus-circle:before { content: '󰍶'; } /* '\f0376' */ +.icon-minus-circle-outline:before { content: '󰍷'; } /* '\f0377' */ +.icon-monitor:before { content: '󰍹'; } /* '\f0379' */ +.icon-brand-office-365:before { content: '󰏆'; } /* '\f03c6' */ +.icon-open-in-new:before { content: '󰏌'; } /* '\f03cc' */ +.icon-paperclip:before { content: '󰏢'; } /* '\f03e2' */ +.icon-pause:before { content: '󰏤'; } /* '\f03e4' */ +.icon-phone-hangup:before { content: '󰏵'; } /* '\f03f5' */ +.icon-phone-in-talk:before { content: '󰏶'; } /* '\f03f6' */ +.icon-pin:before { content: '󰐃'; } /* '\f0403' */ +.icon-play:before { content: '󰐊'; } /* '\f040a' */ +.icon-plus:before { content: '󰐕'; } /* '\f0415' */ +.icon-plus-box:before { content: '󰐖'; } /* '\f0416' */ +.icon-pound:before { content: '󰐣'; } /* '\f0423' */ +.icon-radiobox-blank:before { content: '󰐽'; } /* '\f043d' */ +.icon-radiobox-marked:before { content: '󰐾'; } /* '\f043e' */ +.icon-refresh:before { content: '󰑐'; } /* '\f0450' */ +.icon-send:before { content: '󰒊'; } /* '\f048a' */ +.icon-shield-outline:before { content: '󰒙'; } /* '\f0499' */ +.icon-sitemap:before { content: '󰒪'; } /* '\f04aa' */ +.icon-soccer:before { content: '󰒸'; } /* '\f04b8' */ +.icon-source-pull:before { content: '󰓂'; } /* '\f04c2' */ +.icon-star:before { content: '󰓎'; } /* '\f04ce' */ +.icon-star-outline:before { content: '󰓒'; } /* '\f04d2' */ +.icon-sync:before { content: '󰓦'; } /* '\f04e6' */ +.icon-table-large:before { content: '󰓱'; } /* '\f04f1' */ +.icon-thumbs-up-down:before { content: '󰔕'; } /* '\f0515' */ +.icon-beach-umbrella-outline:before { content: '󰕋'; } /* '\f054b' */ +.icon-volume-high:before { content: '󰕾'; } /* '\f057e' */ +.icon-sort-alphabetical-ascending:before { content: '󰖽'; } /* '\f05bd' */ +.icon-playlist-check:before { content: '󰗇'; } /* '\f05c7' */ +.icon-alert-circle-outline:before { content: '󰗖'; } /* '\f05d6' */ +.icon-check-circle:before { content: '󰗠'; } /* '\f05e0' */ +.icon-check-circle-outline:before { content: '󰗡'; } /* '\f05e1' */ +.icon-email-variant:before { content: '󰗰'; } /* '\f05f0' */ +.icon-food-fork-drink:before { content: '󰗲'; } /* '\f05f2' */ +.icon-logout-variant:before { content: '󰗽'; } /* '\f05fd' */ +.icon-arrow-collapse:before { content: '󰘕'; } /* '\f0615' */ +.icon-arrow-expand:before { content: '󰘖'; } /* '\f0616' */ +.icon-help-circle-outline:before { content: '󰘥'; } /* '\f0625' */ +.icon-source-branch:before { content: '󰘬'; } /* '\f062c' */ +.icon-tune:before { content: '󰘮'; } /* '\f062e' */ +.icon-webhook:before { content: '󰘯'; } /* '\f062f' */ +.icon-circle-multiple-outline:before { content: '󰚕'; } /* '\f0695' */ +.icon-update:before { content: '󰚰'; } /* '\f06b0' */ +.icon-eye-outline:before { content: '󰛐'; } /* '\f06d0' */ +.icon-eye-off-outline:before { content: '󰛑'; } /* '\f06d1' */ +.icon-infinity:before { content: '󰛤'; } /* '\f06e4' */ +.icon-plus-box-outline:before { content: '󰜄'; } /* '\f0704' */ +.icon-cancel:before { content: '󰜺'; } /* '\f073a' */ +.icon-format-quote-open:before { content: '󰝗'; } /* '\f0757' */ +.icon-square:before { content: '󰝤'; } /* '\f0764' */ +.icon-circle-outline:before { content: '󰝦'; } /* '\f0766' */ +.icon-account-plus-outline:before { content: '󰠁'; } /* '\f0801' */ +.icon-forum-outline:before { content: '󰠢'; } /* '\f0822' */ +.icon-settings-outline:before { content: '󰢻'; } /* '\f08bb' */ +.icon-hammer:before { content: '󰣪'; } /* '\f08ea' */ +.icon-pin-outline:before { content: '󰤱'; } /* '\f0931' */ +.icon-clock:before { content: '󰥔'; } /* '\f0954' */ +.icon-image-outline:before { content: '󰥶'; } /* '\f0976' */ +.icon-restore:before { content: '󰦛'; } /* '\f099b' */ +.icon-arrow-right-bold-outline:before { content: '󰧂'; } /* '\f09c2' */ +.icon-email-plus-outline:before { content: '󰧬'; } /* '\f09ec' */ +.icon-text-box-outline:before { content: '󰧭'; } /* '\f09ed' */ +.icon-file-text-outline:before { content: '󰧮'; } /* '\f09ee' */ +.icon-layers-outline:before { content: '󰧾'; } /* '\f09fe' */ +.icon-trash-can-outline:before { content: '󰩺'; } /* '\f0a7a' */ +.icon-bell-off-outline:before { content: '󰪑'; } /* '\f0a91' */ +.icon-account-minus-outline:before { content: '󰫬'; } /* '\f0aec' */ +.icon-bullhorn-outline:before { content: '󰬣'; } /* '\f0b23' */ +.icon-chevron-down-circle-outline:before { content: '󰬧'; } /* '\f0b27' */ +.icon-format-letter-case:before { content: '󰬴'; } /* '\f0b34' */ +.icon-book-outline:before { content: '󰭤'; } /* '\f0b64' */ +.icon-calendar-outline:before { content: '󰭧'; } /* '\f0b67' */ +.icon-download-outline:before { content: '󰮏'; } /* '\f0b8f' */ +.icon-export-variant:before { content: '󰮓'; } /* '\f0b93' */ +.icon-folder-plus-outline:before { content: '󰮝'; } /* '\f0b9d' */ +.icon-brand-gitlab:before { content: '󰮠'; } /* '\f0ba0' */ +.icon-home-variant-outline:before { content: '󰮧'; } /* '\f0ba7' */ +.icon-timeline-text-outline:before { content: '󰯔'; } /* '\f0bd4' */ +.icon-video-outline:before { content: '󰯜'; } /* '\f0bdc' */ +.icon-calendar-check-outline:before { content: '󰱄'; } /* '\f0c44' */ +.icon-food-apple:before { content: '󰲄'; } /* '\f0c84' */ +.icon-pencil-outline:before { content: '󰲶'; } /* '\f0cb6' */ +.icon-camera-outline:before { content: '󰵝'; } /* '\f0d5d' */ +.icon-phone-outline:before { content: '󰷰'; } /* '\f0df0' */ +.icon-palette-outline:before { content: '󰸌'; } /* '\f0e0c' */ +.icon-calendar-month-outline:before { content: '󰸘'; } /* '\f0e18' */ +.icon-file-video-outline:before { content: '󰸬'; } /* '\f0e2c' */ +.icon-hand-right:before { content: '󰹇'; } /* '\f0e47' */ +.icon-file-image-outline:before { content: '󰺰'; } /* '\f0eb0' */ +.icon-notebook-outline:before { content: '󰺿'; } /* '\f0ebf' */ +.icon-shield-alert-outline:before { content: '󰻍'; } /* '\f0ecd' */ +.icon-play-outline:before { content: '󰼛'; } /* '\f0f1b' */ +.icon-reply-outline:before { content: '󰼠'; } /* '\f0f20' */ +.icon-draw:before { content: '󰽉'; } /* '\f0f49' */ +.icon-slash-forward:before { content: '󰿟'; } /* '\f0fdf' */ +.icon-file-code-outline:before { content: '󱀫'; } /* '\f102b' */ +.icon-file-excel-outline:before { content: '󱀭'; } /* '\f102d' */ +.icon-file-multiple-outline:before { content: '󱀲'; } /* '\f1032' */ +.icon-file-powerpoint-outline:before { content: '󱀵'; } /* '\f1035' */ +.icon-file-word-outline:before { content: '󱀾'; } /* '\f103e' */ +.icon-dock-left:before { content: '󱂪'; } /* '\f10aa' */ +.icon-dock-window:before { content: '󱂬'; } /* '\f10ac' */ +.icon-message-plus-outline:before { content: '󱂻'; } /* '\f10bb' */ +.icon-send-outline:before { content: '󱅥'; } /* '\f1165' */ +.icon-message-minus-outline:before { content: '󱅯'; } /* '\f116f' */ +.icon-crown-outline:before { content: '󱇐'; } /* '\f11d0' */ +.icon-view-grid-plus-outline:before { content: '󱇚'; } /* '\f11da' */ +.icon-archive-outline:before { content: '󱈎'; } /* '\f120e' */ +.icon-exclamation-thick:before { content: '󱈸'; } /* '\f1238' */ +.icon-folder-move-outline:before { content: '󱉆'; } /* '\f1246' */ +.icon-archive-arrow-up-outline:before { content: '󱉜'; } /* '\f125c' */ +.icon-play-box-multiple-outline:before { content: '󱏦'; } /* '\f13e6' */ +.icon-lightning-bolt-outline:before { content: '󱐌'; } /* '\f140c' */ +.icon-power-plug-outline:before { content: '󱐥'; } /* '\f1425' */ +.icon-car-outline:before { content: '󱓭'; } /* '\f14ed' */ +.icon-share-variant-outline:before { content: '󱔔'; } /* '\f1514' */ +.icon-application-cog:before { content: '󱕷'; } /* '\f1577' */ +.icon-book-lock-outline:before { content: '󱚏'; } /* '\f168f' */ +.icon-robot-happy:before { content: '󱜙'; } /* '\f1719' */ diff --git a/site/static/font/compass-icons.eot b/site/static/font/compass-icons.eot new file mode 100644 index 0000000000000000000000000000000000000000..a5b4cc6d40933448966664274967abc27c4b6c15 GIT binary patch literal 51372 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 literal 0 HcmV?d00001 diff --git a/site/static/font/compass-icons.svg b/site/static/font/compass-icons.svg new file mode 100644 index 0000000000..dabeb63e7f --- /dev/null +++ b/site/static/font/compass-icons.svg @@ -0,0 +1,552 @@ + + + +Copyright (C) 2022 by original authors @ fontello.com + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/site/static/font/compass-icons.ttf b/site/static/font/compass-icons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..50b70ad50a121280e014f29170c67ca1a9fa7a4b GIT binary patch literal 51184 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 literal 0 HcmV?d00001 diff --git a/site/static/font/compass-icons.woff2 b/site/static/font/compass-icons.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..f66cc84d323f692f7bf7d75c478c48ce83ae39a0 GIT binary patch literal 22980 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 Date: Wed, 14 Sep 2022 14:32:27 -0400 Subject: [PATCH 08/22] Start updating Bindings sub topic --- .../apps/structure/bindings/_index.md | 78 ++++++++++++++----- .../apps/structure/call-metadata/_index.md | 4 + 2 files changed, 63 insertions(+), 19 deletions(-) diff --git a/site/content/integrate/apps/structure/bindings/_index.md b/site/content/integrate/apps/structure/bindings/_index.md index dbc5b29a14..1a69c16e88 100644 --- a/site/content/integrate/apps/structure/bindings/_index.md +++ b/site/content/integrate/apps/structure/bindings/_index.md @@ -5,32 +5,26 @@ weight: 30 aliases: - /integrate/apps/api/bindings/ --- +Bindings ({{}}) establish the relationship between [call]({{}}) handlers and [locations]({{}}). +Whenever the bindings call is executed the App provides a list of bindings based on the [request context]({{}}). -Bindings ([godoc](https://pkg.go.dev/github.com/mattermost/mattermost-plugin-apps/apps#Binding)) are what establish the relationship between locations and calls. Whenever the bindings route is called, your app needs to provide the list of bindings available according to the context ([godoc](https://pkg.go.dev/github.com/mattermost/mattermost-plugin-apps/apps#Context)). Some fields included in the context: +Bindings are refreshed when the App is installed, on every channel switch, and when an OAuth2 process has completed. Bindings may also be refreshed when the user moves to a different context, such as opening a thread or a post in a search view. -- Your app's bot user access token -- The Mattermost Site URL -- The ID of the user requesting the bindings (acting user ID) -- The ID of the team the user is currently focused on -- The ID of the channel the user is currently focused on -- The ID of the post the user is currently focused on (if applicable) -**Note:** Bindings are fetched (and refreshed) on every channel switch. When the user moves to a different context (like opening a thread, or a post in a search view) new bindings may be fetched to provide the correct bindings for the thread/post context. Bindings are also fetched when an OAuth2 process is completed and when the application gets installed. +## Top level bindings -The expected response should include the following: +Bindings are organized by top level [locations]({{}}). The data structure of a top level binding is: -| Type | Function | Description | -|:-------|:---------|:----------------------| -| `data` | bindings | The list of bindings. | +| Name | Type | Description | +|:-----------|:---------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------| +| `location` | {{}} (`string`) | Top level location. | +| `bindings` | {{}} (list) | A list of bindings under this location. | -Bindings are organized by top level locations. Top level bindings just need to define: +{{}} +Bindings for `/in_post` locations should not be included in the response to the bindings call. +{{}} -| Name | Type | Description | -|:-----------|:---------|:----------------------------------------| -| `location` | string | Top level location. | -| `bindings` | Bindings | A list of bindings under this location. | - -`/in_post` bindings don't need to be defined in this call. +## Sub-location bindings ### `/post_menu` bindings @@ -86,6 +80,52 @@ A leaf command must include: The context of the call for these bindings will include the user ID, the post ID, the root post ID (if any), the channel ID, and the team ID. It will also include the raw command. +### Bindings call response + +The response to the bindings call should take the form of an `ok` [call response]({{}}) where the `data` field contains the bindings. + +For example: +```json +{ + "type": "ok", + "data": [ + { + "location": "/channel_header", + "bindings": [ + { + "location": "send-button", + "icon": "icon.png", + "label":"send hello message", + "call": { + "path": "/send-modal" + } + } + ] + }, + { + "location": "/command", + "bindings": [ + { + "icon": "icon.png", + "label": "helloworld", + "description": "Hello World app", + "hint": "[send]", + "bindings": [ + { + "location": "send", + "label": "send", + "call": { + "path": "/send" + } + } + ] + } + ] + } + ] +} +``` + ## Example data flow
Client Bindings Request diff --git a/site/content/integrate/apps/structure/call-metadata/_index.md b/site/content/integrate/apps/structure/call-metadata/_index.md index 9961666b29..102b4e3d56 100644 --- a/site/content/integrate/apps/structure/call-metadata/_index.md +++ b/site/content/integrate/apps/structure/call-metadata/_index.md @@ -54,3 +54,7 @@ The following table details what sub-fields are included for each metadata field | `user` | {{}} | `bot_description`
`delete_at`
`email`
`first_name`
`id`
`is_bot`
`last_name`
`locale`
`nickname`
`roles`
`timezone`
`username` | `id` | | `oauth2_app` | {{}} | {{}}
`connect_url`
`complete_url` | no sub-fields | | `oauth2_user` | _any_ | all data stored in the {{}} field | no data | + +{{}} +Note that the metadata returned by the `oauth2_app` and `oauth2_user` metadata fields above will be contained in the `oauth2` field of the [request context]({{}}). +{{}} From 1f94ade73975967a3300a57a5ee9bc4085c82b61 Mon Sep 17 00:00:00 2001 From: alan lew Date: Mon, 19 Sep 2022 11:39:55 -0400 Subject: [PATCH 09/22] Further updates to Bindings, call, and call metadata topics; Update CSS styles to not word-break monospaced text in a table cell --- .../apps/structure/bindings/_index.md | 49 ++++++++++--------- .../apps/structure/call-metadata/_index.md | 28 +++++------ .../integrate/apps/structure/call/_index.md | 2 +- site/static/css/styles.css | 3 +- 4 files changed, 43 insertions(+), 39 deletions(-) diff --git a/site/content/integrate/apps/structure/bindings/_index.md b/site/content/integrate/apps/structure/bindings/_index.md index 1a69c16e88..e312538a7a 100644 --- a/site/content/integrate/apps/structure/bindings/_index.md +++ b/site/content/integrate/apps/structure/bindings/_index.md @@ -26,30 +26,33 @@ Bindings for `/in_post` locations should not be included in the response to the ## Sub-location bindings -### `/post_menu` bindings - -| Name | Type | Description | -|:-----------|:-------|:------------------------------------------------------------------------------------------------------------------| -| `location` | string | Name of this location. The whole path of locations will be added in the context. Must be unique in its level. | -| `icon` | string | (Optional) Either a fully-qualified URL, or a path for an app's static asset. | -| `label` | string | (Optional) Text to show in the item. Defaults to location. Must be unique in its level. | -| `call` | Call | (Optional) Call to perform. You must provide a call if there is no form, or the form itself does not have a call. | -| `form` | Form | (Optional) Modal form to open. You must provide a form with a call if there is no call defined in the binding. | - -The call for these bindings will include in the context the user ID, the post ID, the root post ID if any, the channel ID, and the team ID. +Sub-location bindings use the following data structure: + +| Name | Type | Description | Locations | +|----------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|---------------------------------------------------| +| `location` | string | The name of the binding location. Values must be unique within each top level binding. | all locations | +| `icon` | string | The App icon to display, either a fully-qualified URL or a path to an App static asset. Required for web app support. | `/channel_header`
`/post_menu` | +| `label` | string | The primary text to display at the binding location; defaults to the value of the `location` field. | all locations | +| `hint` | string | Secondary text to display at the binding location | `/channel_header`
`/command` | +| `description` | string | Extended help text used in modal forms and command autocomplete | `/command` | +| `submit` {{}} | Call | Executes an action associated with the binding | all locations | +| `form` {{}} | Form | The modal form to display | `/channel_header`
`/command`
`/post_menu` | +| `bindings` {{}} | {{}} (list) | Additional sub-location bindings | all locations | + +{{}} +Only one of the `submit`, `form`, and `bindings` fields can be specified in a sub-location binding. Specifying more than one is treated as an error. +{{}} -### `/channel_header` bindings +## Call context data -| Name | Type | Description | -|:-----------|:-------|:----------------------------------------------------------------------------------------------------------------------------| -| `location` | string | Name of this location. The whole path of locations will be added in the context. Must be unique in its level. | -| `icon` | string | (Optional/Web App required) Either a fully-qualified URL, or a path for an app's static asset. | -| `label` | string | (Optional) Text to show in the item on mobile and webapp collapsed view. Defaults to location. Must be unique in its level. | -| `hint` | string | (Optional/Web App required) Text to show in tooltip. | -| `call` | Call | (Optional) Call to perform. You must provide a call if there is no form, or the form itself does not have a call. | -| `form` | Form | (Optional) Modal form to open. You must provide a form with a call if there is no call defined in the binding. | +The following request context fields will be available to calls invoked at each binding location: -The context of the call for these bindings will include the user ID, the channel ID, and the team ID. +| Location | Context fields | +|-------------------|---------------------------------------------------------------------------| +| `/channel_header` | `user_id`
`channel_id`
`team_id` | +| `/command` | `user_id`
`root_post_id`
`channel_id`
`team_id` | +| `/post_menu` | `user_id`
`post_id`
`root_post_id`
`channel_id`
`team_id` | +| `/in_post` | _TBD_ | ### `/command` bindings @@ -75,12 +78,12 @@ A leaf command must include: | `label` | string | The label to use to define the command. Cannot include spaces or tabs. Defaults to location. Must be unique in its level. | | `hint` | string | (Optional) Hint line on command autocomplete. | | `description` | string | (Optional) Description line on command autocomplete. | -| `call` | Call | (Optional) Call to perform when executing the command. You must provide a call if there is no form, or the form itself does not have a call. | | +| `call` | Call | (Optional) Call to perform when executing the command. You must provide a call if there is no form, or the form itself does not have a call. | | `form` | Form | (Optional) Form representing the parameters the command can receive. If no form is provided, a form call will be made to the specified call. | The context of the call for these bindings will include the user ID, the post ID, the root post ID (if any), the channel ID, and the team ID. It will also include the raw command. -### Bindings call response +## Bindings call response The response to the bindings call should take the form of an `ok` [call response]({{}}) where the `data` field contains the bindings. diff --git a/site/content/integrate/apps/structure/call-metadata/_index.md b/site/content/integrate/apps/structure/call-metadata/_index.md index 102b4e3d56..56c657cbc6 100644 --- a/site/content/integrate/apps/structure/call-metadata/_index.md +++ b/site/content/integrate/apps/structure/call-metadata/_index.md @@ -40,20 +40,20 @@ Each ExpandLevel (`string`) value can be one of the following: The following table details what sub-fields are included for each metadata field for the `summary` and `id` ExpandLevels: -| Metadata Field | Data Type | `summary` level | `id` level | -|---------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------| -| `app` | {{}} | `app_id`
`version`
`webhook_secret`
`bot_user_id`
`bot_username` | no sub-fields | -| `acting_user` | {{}} | `bot_description`
`delete_at`
`email`
`first_name`
`id`
`is_bot`
`last_name`
`locale`
`nickname`
`roles`
`timezone`
`username` | `id` | -| `acting_user_access_token`
(`all` level only) | string | no sub-fields | no sub-fields | -| `locale` | string | same as `all` level | _n/a_ | -| `channel` | {{}} | `id`
`deleted_at`
`team_id`
`type`
`display_name`
`name` | `id` | -| `channel_member` | {{}} | same as `all` level | no sub-fields | -| `team` | {{}} | `id`
`display_name`
`name`
`description`
`email`
`type` | `id` | -| `team_member` | {{}} | same as `all` level | no sub-fields | -| `post`/`root_post` | {{}} | `id`
`type`
`user_id`
`channel_id`
`root_id`
`message` | `id` | -| `user` | {{}} | `bot_description`
`delete_at`
`email`
`first_name`
`id`
`is_bot`
`last_name`
`locale`
`nickname`
`roles`
`timezone`
`username` | `id` | -| `oauth2_app` | {{}} | {{}}
`connect_url`
`complete_url` | no sub-fields | -| `oauth2_user` | _any_ | all data stored in the {{}} field | no data | +| Metadata Field | Data Type | `summary` level
sub-fields | `id` level
sub-fields | +|---------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------| +| `app` | {{}} | `app_id`
`version`
`webhook_secret`
`bot_user_id`
`bot_username` | no sub-fields | +| `acting_user` | {{}} | `bot_description`
`delete_at`
`email`
`first_name`
`id`
`is_bot`
`last_name`
`locale`
`nickname`
`roles`
`timezone`
`username` | `id` | +| `acting_user_access_token`
(`all` level only) | string | no sub-fields | no sub-fields | +| `locale` | string | same as `all` level | _n/a_ | +| `channel` | {{}} | `id`
`deleted_at`
`team_id`
`type`
`display_name`
`name` | `id` | +| `channel_member` | {{}} | same as `all` level | no sub-fields | +| `team` | {{}} | `id`
`display_name`
`name`
`description`
`email`
`type` | `id` | +| `team_member` | {{}} | same as `all` level | no sub-fields | +| `post`/`root_post` | {{}} | `id`
`type`
`user_id`
`channel_id`
`root_id`
`message` | `id` | +| `user` | {{}} | `bot_description`
`delete_at`
`email`
`first_name`
`id`
`is_bot`
`last_name`
`locale`
`nickname`
`roles`
`timezone`
`username` | `id` | +| `oauth2_app` | {{}} | {{}}
`connect_url`
`complete_url` | no sub-fields | +| `oauth2_user` | _any_ | all data stored in the {{}} field | no data | {{}} Note that the metadata returned by the `oauth2_app` and `oauth2_user` metadata fields above will be contained in the `oauth2` field of the [request context]({{}}). diff --git a/site/content/integrate/apps/structure/call/_index.md b/site/content/integrate/apps/structure/call/_index.md index 047d9137bc..c06ffcb71e 100644 --- a/site/content/integrate/apps/structure/call/_index.md +++ b/site/content/integrate/apps/structure/call/_index.md @@ -51,7 +51,7 @@ The data structure of call request ({{}} (list) | Additional sub-location bindings | all locations | - -{{}} +| Name | Type | Description | Locations | +|-----------------------------------------|----------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|---------------------------------------------------| +| `location` | string | The name of the binding location. Values must be unique within each top level binding. | all locations | +| `icon` | string | The App icon to display, either a fully-qualified URL or a path to an App static asset. Required for web app support. | `/channel_header`
`/post_menu` | +| `label` | string | The primary text to display at the binding location; defaults to the value of the `location` field. | all locations | +| `hint` | string | Secondary text to display at the binding location | `/channel_header`
`/command` | +| `description` | string | Extended help text used in modal forms and command autocomplete | `/command` | +| `submit` {{}} | Call | Executes an action associated with the binding | all locations | +| `form` {{}} | Form | The modal form to display | `/channel_header`
`/command`
`/post_menu` | +| `bindings` {{}} | {{}} (list) | Additional sub-location bindings | all locations | + +{{}} Only one of the `submit`, `form`, and `bindings` fields can be specified in a sub-location binding. Specifying more than one is treated as an error. {{}} @@ -52,41 +52,71 @@ The following request context fields will be available to calls invoked at each | `/channel_header` | `user_id`
`channel_id`
`team_id` | | `/command` | `user_id`
`root_post_id`
`channel_id`
`team_id` | | `/post_menu` | `user_id`
`post_id`
`root_post_id`
`channel_id`
`team_id` | -| `/in_post` | _TBD_ | -### `/command` bindings +### Slash command bindings -For commands we can distinguish between leaf commands (executable subcommand) and partial commands. +The slash command (`/command`) location allows the creation of multiple, nested slash commands. +Each slash command can execute a call, display a form, or accept further parameters to trigger a nested command. -A partial command must include: +The `bindings` field for this location is used to specify nested commands. +If this field is specified, the `submit` and `form` fields can't also be specified; an error will occur. -| Name | Type | Description | -|:--------------|:---------|:--------------------------------------------------------------------------------------------------------------------------| -| `location` | string | Name of this location. The whole path of locations will be added in the context. Must be unique in its level. | -| `label` | string | The label to use to define the command. Cannot include spaces or tabs. Defaults to location. Must be unique in its level. | -| `hint` | string | (Optional) Hint line on command autocomplete. | -| `description` | string | (Optional) Description line on command autocomplete. | -| `bindings` | Bindings | List of subcommands. | -| `call` | Call | (Optional) Call to be inherited by all its subcommands. | -| `form` | Form | (Optional) Form to be inherited by all its subcommands. | +For example, a slash command binding that returns one day or one week worth of weather information: -A leaf command must include: +```json +{ + "bindings": [ + { + "location": "/command", + "bindings": [ + { + "location": "weather", + "label": "Weather conditions", + "description": "Show the weather conditions for today or the next week", + "hint": "[day|week]", + "bindings": [ + { + "location": "day", + "label": "Weather for today", + "description": "Show the weather conditions for today", + "call": { + "path": "/weather/day" + } + }, + { + "location": "week", + "label": "Weather for the next week", + "description": "Show the weather conditions for the next week", + "call": { + "path": "/weather/week" + } + } + ] + } + ] + } + ] +} +``` -| Name | Type | Description | -|:--------------|:-------|:---------------------------------------------------------------------------------------------------------------------------------------------| -| `location` | string | Name of this location. The whole path of locations will be added in the context. Must be unique in its level. | -| `label` | string | The label to use to define the command. Cannot include spaces or tabs. Defaults to location. Must be unique in its level. | -| `hint` | string | (Optional) Hint line on command autocomplete. | -| `description` | string | (Optional) Description line on command autocomplete. | -| `call` | Call | (Optional) Call to perform when executing the command. You must provide a call if there is no form, or the form itself does not have a call. | -| `form` | Form | (Optional) Form representing the parameters the command can receive. If no form is provided, a form call will be made to the specified call. | +In the Mattermost UI, typing `/weather` shows the details of the slash command: -The context of the call for these bindings will include the user ID, the post ID, the root post ID (if any), the channel ID, and the team ID. It will also include the raw command. +![image](command_location_weather.png) + +Typing `/weather week` shows the details of the nested command: + +![image](command_location_weather_week.png) + +A user could invoke the slash command using `/weather day` or `/weather week` to get weather conditions for one day or one week, respectively. ## Bindings call response The response to the bindings call should take the form of an `ok` [call response]({{}}) where the `data` field contains the bindings. +{{}} +Bindings for `/in_post` locations should not be included in the response. +{{}} + For example: ```json { diff --git a/site/content/integrate/apps/structure/bindings/command_location_weather.png b/site/content/integrate/apps/structure/bindings/command_location_weather.png new file mode 100644 index 0000000000000000000000000000000000000000..09fe52ca6f3627bfa0555136bf04a0c7eb38654a GIT binary patch literal 18284 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 literal 0 HcmV?d00001 diff --git a/site/content/integrate/apps/structure/bindings/command_location_weather_week.png b/site/content/integrate/apps/structure/bindings/command_location_weather_week.png new file mode 100644 index 0000000000000000000000000000000000000000..91d4a056f6853136162eef904e61e05c861f14f4 GIT binary patch literal 16705 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 literal 0 HcmV?d00001 diff --git a/site/content/integrate/apps/structure/call/_index.md b/site/content/integrate/apps/structure/call/_index.md index c06ffcb71e..a2b842aabf 100644 --- a/site/content/integrate/apps/structure/call/_index.md +++ b/site/content/integrate/apps/structure/call/_index.md @@ -73,37 +73,37 @@ An example call request looks like the following (some `context` fields omitted The request `context` field contains metadata about the request. The data structure of the context ({{}}) field is: -| Name | Type | Description | -|:---------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------| -| `subject` | Subject (`string`) | Event subject. | -| `channel_id` | string | ID from the channel from within which the call was performed. | -| `team_id` | string | ID from the team from within which the call was performed. | -| `post_id` | string | ID from the post from within which the call was performed. | -| `root_post_id` | string | If the call was performed from a post in a thread, the root post ID of that thread. | -| `app_id` | AppID (`string`) | The app ID. | -| `location` | Location (`string`) | The location from which the call was performed. | -| `user_agent` | string | User agent used to perform the call.
Valid values are: `mobile`, `webapp`. | -| `track_as_submit` | bool | Whether the call was caused by a submit action from a binding or form. | -| `mattermost_site_url` | string | Mattermost base URL. | -| `developer_mode` | bool | Whether the Apps framework is running in Developer mode. | -| `app_path` | string | App's path on the Mattermost instance (appendable to `mattermost_site_url`). | -| `bot_user_id` | string | Bot user ID. | -| `bot_access_token`{{}} | string | (Expansion) | -| `app`{{}} | {{}} | Details about the installed record of the App. | -| `acting_user`{{}} | {{}} | (Expansion) | -| `acting_user_access_token`{{}} | string | (Expansion) | -| `locale`{{}} | string | (Expansion) | -| `channel`{{}} | {{}} | (Expansion) | -| `channel_member`{{}} | {{}} | (Expansion) | -| `team`{{}} | {{}} | (Expansion) | -| `team_member`{{}} | {{}} | (Expansion) | -| `post`{{}} | {{}} | (Expansion) | -| `root_post`{{}} | {{}} | (Expansion) | -| `user`{{}} | {{}} | (Expansion) | -| `mentioned`{{}} | {{}} (list) | (Expansion) | -| `oauth2`{{}} | {{}} | (Expansion) | - -{{}} +| Name | Type | Description | +|:-------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------| +| `subject` | Subject (`string`) | Event subject. | +| `channel_id` | string | ID from the channel from within which the call was performed. | +| `team_id` | string | ID from the team from within which the call was performed. | +| `post_id` | string | ID from the post from within which the call was performed. | +| `root_post_id` | string | If the call was performed from a post in a thread, the root post ID of that thread. | +| `app_id` | AppID (`string`) | The app ID. | +| `location` | Location (`string`) | The location from which the call was performed. | +| `user_agent` | string | User agent used to perform the call.
Valid values are: `mobile`, `webapp`. | +| `track_as_submit` | bool | Whether the call was caused by a submit action from a binding or form. | +| `mattermost_site_url` | string | Mattermost base URL. | +| `developer_mode` | bool | Whether the Apps framework is running in Developer mode. | +| `app_path` | string | App's path on the Mattermost instance (appendable to `mattermost_site_url`). | +| `bot_user_id` | string | Bot user ID. | +| `bot_access_token`{{}} | string | (Expansion) | +| `app`{{}} | {{}} | Details about the installed record of the App. | +| `acting_user`{{}} | {{}} | (Expansion) | +| `acting_user_access_token`{{}} | string | (Expansion) | +| `locale`{{}} | string | (Expansion) | +| `channel`{{}} | {{}} | (Expansion) | +| `channel_member`{{}} | {{}} | (Expansion) | +| `team`{{}} | {{}} | (Expansion) | +| `team_member`{{}} | {{}} | (Expansion) | +| `post`{{}} | {{}} | (Expansion) | +| `root_post`{{}} | {{}} | (Expansion) | +| `user`{{}} | {{}} | (Expansion) | +| `mentioned`{{}} | {{}} (list) | (Expansion) | +| `oauth2`{{}} | {{}} | (Expansion) | + +{{}} The data in these fields will not be populated by default. For more information on expanding metadata in the request context, see the [Call metadata]({{}}) page. {{}} From c666a259c44fc1a794fdfcbf6aea64d970e9bffd Mon Sep 17 00:00:00 2001 From: alan lew Date: Tue, 20 Sep 2022 11:42:28 -0400 Subject: [PATCH 11/22] Improve support for collapsable blocks using existing Bootstrap components and Compass icons; Update collapsable blocks in bindings topic --- site/config.toml | 7 +++++++ .../integrate/apps/structure/bindings/_index.md | 17 +++++++---------- site/layouts/partials/footer.html | 17 +++++++++++++++++ site/layouts/shortcodes/collapse.html | 16 ++++++++++++++++ site/static/css/styles.css | 10 ++++++++++ 5 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 site/layouts/shortcodes/collapse.html diff --git a/site/config.toml b/site/config.toml index bf0c749643..4a59f8352b 100644 --- a/site/config.toml +++ b/site/config.toml @@ -19,6 +19,13 @@ pygmentsStyle = "manni" email = "" ghrepo = "https://github.com/mattermost/mattermost-developer-documentation/" + # Parameters controlling collapsable blocks + [params.collapse] + collapsedIcon = "icon-chevron-right" # Icon to show when the block is collapsed + expandedIcon = "icon-chevron-down" # Icon to show when the block is expanded + collapseShowClass = "show" # CSS class to add when expanding the block + toggleClass = "collapseToggle" # CSS class to control icon attributes (e.g. size) + [params.mailinglist] enable = false diff --git a/site/content/integrate/apps/structure/bindings/_index.md b/site/content/integrate/apps/structure/bindings/_index.md index 0cd3592872..899ada890c 100644 --- a/site/content/integrate/apps/structure/bindings/_index.md +++ b/site/content/integrate/apps/structure/bindings/_index.md @@ -159,15 +159,13 @@ For example: } ``` -## Example data flow - -

Client Bindings Request +## Example request and response +{{}} `GET /plugins/com.mattermost.apps/api/v1/bindings?user_id=ws4o4macctyn5ko8uhkkxmgfur&channel_id=qphz13bzbf8c7j778tdnaw3huc&scope=webapp` +{{}} -
- -
Mattermost Bindings Request +{{}} `POST /plugins/com.mattermost.apps/example/hello/bindings` @@ -187,10 +185,9 @@ For example: } } ``` -
- -
App Binding Response +{{}} +{{}} ```json { "type": "ok", @@ -246,4 +243,4 @@ For example: ] } ``` -
+{{}} diff --git a/site/layouts/partials/footer.html b/site/layouts/partials/footer.html index 6d11c4817b..8ba7fd34eb 100755 --- a/site/layouts/partials/footer.html +++ b/site/layouts/partials/footer.html @@ -51,3 +51,20 @@ crossorigin="anonymous"> + + diff --git a/site/layouts/shortcodes/collapse.html b/site/layouts/shortcodes/collapse.html new file mode 100644 index 0000000000..32620c700f --- /dev/null +++ b/site/layouts/shortcodes/collapse.html @@ -0,0 +1,16 @@ +{{- $collapseId := .Get "id" -}} +{{- $collapseHeaderId := print $collapseId "_header" -}} +{{- $collapseBodyId := print $collapseId "_body" -}} +{{- $collapseToggleId := print $collapseId "_toggle" -}} +{{- $title := .Get "title" -}} +
+
+ + {{ $title }} +
+
+
+ {{ .Inner | markdownify }} +
+
+
diff --git a/site/static/css/styles.css b/site/static/css/styles.css index fc9eb15b65..ce84b6686c 100644 --- a/site/static/css/styles.css +++ b/site/static/css/styles.css @@ -3129,6 +3129,16 @@ td>a { word-break: inherit; } +/* Make the chevron size in the collapse toggle larger than normal */ +span.collapseToggle>[class^="icon-"]:before, [class*=" icon-"]:before { + font-size: 150%; +} + +/* Add space between consecutive collapsable blocks */ +.collapseCard { + margin-bottom: 10px; +} + .container-fluid { max-width: 1140px; } From 6bf29cb3e23de2176dc7649103d5cbc74d5f2f55 Mon Sep 17 00:00:00 2001 From: alan lew Date: Tue, 20 Sep 2022 13:27:12 -0400 Subject: [PATCH 12/22] Add content in Static assets topic --- .../integrate/apps/structure/static-assets/_index.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/site/content/integrate/apps/structure/static-assets/_index.md b/site/content/integrate/apps/structure/static-assets/_index.md index eabb3692e7..6f98871f59 100644 --- a/site/content/integrate/apps/structure/static-assets/_index.md +++ b/site/content/integrate/apps/structure/static-assets/_index.md @@ -3,6 +3,12 @@ title: Static assets description: Static assets weight: 40 --- +An App's static assets include resources such as images and JSON data. -### Coming soon! -In the future this page will describe how static assets in an App are handled. +Requests for static assets are made relative to the `/static` URI path. For example, retrieving the icon named `icon.png` for a `/channel_header` binding would result in the following HTTP request: + +```http request +GET http://my-app:4000/static/icon.png HTTP/1.1 +``` + +At this time, binding icons and profile picture overrides are the only static assets that are automatically requested by the Mattermost UI. From c5e6636403cea14f430d59384a68bf08bf8bac08 Mon Sep 17 00:00:00 2001 From: Alan Lew Date: Mon, 3 Oct 2022 10:37:46 -0400 Subject: [PATCH 13/22] Apply suggestions from code review Co-authored-by: Carrie Warner (Mattermost) <74422101+cwarnermm@users.noreply.github.com> --- site/content/integrate/apps/functionality/_index.md | 2 +- site/content/integrate/apps/structure/_index.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/site/content/integrate/apps/functionality/_index.md b/site/content/integrate/apps/functionality/_index.md index 9a3095cc29..dd620f3a46 100644 --- a/site/content/integrate/apps/functionality/_index.md +++ b/site/content/integrate/apps/functionality/_index.md @@ -15,4 +15,4 @@ In addition to the {{}}) covers subscribing to webhooks from third-party systems. -See [Authenticating with Mattermost]({{< ref "/integrate/apps/authentication/app-to-mattermost" >}}) for how to authenticate to all these services. +See [Authenticating with Mattermost]({{< ref "/integrate/apps/authentication/app-to-mattermost" >}}) to learn how to authenticate to all these services. diff --git a/site/content/integrate/apps/structure/_index.md b/site/content/integrate/apps/structure/_index.md index 8f05dd33d3..0bc64b7d5c 100644 --- a/site/content/integrate/apps/structure/_index.md +++ b/site/content/integrate/apps/structure/_index.md @@ -9,13 +9,13 @@ aliases: Apps consist of three kinds of assets: -1. A [manifest]({{< ref "manifest" >}}), which contains App details such as name, version, requested permissions, and deployment methods +1. A [manifest]({{< ref "manifest" >}}), which contains App details such as name, version, requested permissions, and deployment methods. -2. [Call]({{< ref "call" >}}) handlers, which are functions that handle incoming requests from the Mattermost server +2. [Call]({{< ref "call" >}}) handlers, which are functions that handle incoming requests from the Mattermost server. -3. [Static assets]({{}}), such as images +3. [Static assets]({{}}), such as images. -To interact with users an App must [bind]({{< ref "bindings" >}}) a call handler to a [location]({{}}) in the Mattermost user interface. These locations may be slash commands, toolbar and menu items, or embedded in posts. +To interact with users, an App must [bind]({{< ref "bindings" >}}) a call handler to a [location]({{}}) in the Mattermost user interface. These locations may be slash commands, toolbar and menu items, or embedded in posts. ![image](apps-calls_bindings_locations_v2.svg) From 451fc026c6eba7e5f7b7d8fe78589ad895dad65e Mon Sep 17 00:00:00 2001 From: Alan Lew Date: Mon, 3 Oct 2022 10:45:43 -0400 Subject: [PATCH 14/22] Apply suggestions from code review Co-authored-by: Carrie Warner (Mattermost) <74422101+cwarnermm@users.noreply.github.com> --- .../integrate/apps/structure/call/_index.md | 18 +++++++++--------- .../apps/structure/manifest/_index.md | 10 +++++----- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/site/content/integrate/apps/structure/call/_index.md b/site/content/integrate/apps/structure/call/_index.md index a2b842aabf..417759087e 100644 --- a/site/content/integrate/apps/structure/call/_index.md +++ b/site/content/integrate/apps/structure/call/_index.md @@ -8,12 +8,12 @@ aliases: A Call defines an App action that can be invoked. {{}} -Content on this page refers to the Mattermost Apps framework and not to the Mattermost Calls functionality. +Content on this page refers to the Mattermost Apps framework and not to the Mattermost Calls product functionality. {{}} ## Data structure -The data structure of a call ({{}}) is: +The data structure of a call ({{}}) is described in the following table: | Name | Type | Description | |:---------|:------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------| @@ -21,7 +21,7 @@ The data structure of a call ({{}}) | Specifies [additional metadata]({{}}) to include in the call request, such as channel and post information. | | `state` | map | A set of elements to be interpreted by the App. Forms and slash commands will also populate these values. | -An example call looks like: +An example call looks like this: ```json { @@ -38,7 +38,7 @@ An example call looks like: When a call is performed, a POST request will be made to the endpoint defined in the call. The call will include a JWT in the `Mattermost-App-Authorization` header. The Acting User's ID is included in the request by default. -The data structure of call request ({{}}) is: +The data structure of a call request ({{}}) is described in the following table: | Name | Type | Description | |:-----------------|:------------------------------------|:-------------------------------------------------------------------------------------------| @@ -71,7 +71,7 @@ An example call request looks like the following (some `context` fields omitted ### Context -The request `context` field contains metadata about the request. The data structure of the context ({{}}) field is: +The request `context` field contains metadata about the request. The data structure of the context ({{}}) field is described in the following table: | Name | Type | Description | |:-------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------| @@ -107,7 +107,7 @@ The request `context` field contains metadata about the request. The data struct The data in these fields will not be populated by default. For more information on expanding metadata in the request context, see the [Call metadata]({{}}) page. {{
}} -An example context field looks like: +An example context field looks like this: ```json { @@ -143,7 +143,7 @@ An example context field looks like: ## Response -The data structure of a call response is: +The data structure of a call response is described in the following table: | Name | Type | Description | |------------------------|---------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------| @@ -154,7 +154,7 @@ The data structure of a call response is: | `use_external_browser` | bool | Used by the `navigate` response type to indicate the system web browser should be used when redirecting the user to an URL | | `form` | {{}} | Used by the `form` response type to specify a form to display | -An example call response looks like: +An example call response looks like this: ```json { @@ -165,7 +165,7 @@ An example call response looks like: ### Call response types -There are several types of responses ({{}}): +There are several types of supported responses ({{}}): | Value | Description | |:-----------|:------------------------------------| diff --git a/site/content/integrate/apps/structure/manifest/_index.md b/site/content/integrate/apps/structure/manifest/_index.md index ca1fab9125..babad4f543 100644 --- a/site/content/integrate/apps/structure/manifest/_index.md +++ b/site/content/integrate/apps/structure/manifest/_index.md @@ -8,7 +8,7 @@ aliases: --- All Apps should define a manifest ({{}}) as a JSON object. -The fields of the manifest are: +The fields of the manifest are described in the following table: | Name | Type | Description | |:-------------------------------------------|:----------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------| @@ -67,7 +67,7 @@ For example, a typical App manifest would look like the following: Apps need to request permissions from the System Admin who is installing them. After an App is installed and available to end users, each user in Mattermost will need to "authenticate" with your App. Using the `act_as_user` permission, your App will be performing an API call on behalf of each authenticated user. -Below are the supported permissions ({{}}) an app can request: +The following table lists the supported permissions ({{}}) an app can request: | Name | Description | |:-----------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------| @@ -79,12 +79,12 @@ Below are the supported permissions ({{}}) are spaces in the UI where an app can add interactions. Locations in the App framework are supported on the mobile, desktop, and web app clients unless otherwise noted. This list of locations will grow over time as the App framework expands. +Locations ({{}}) are spaces in the UI where an App can add interactions. Locations in the App framework are supported on the mobile, desktop, and web app clients unless otherwise noted. This list of locations will grow over time as the App framework expands. | Name | Description | |:------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `/post_menu` | An item in a Mattermost post's dropdown menu (a.k.a. Message Action) where the user can leverage message content as part of the App's action.

For example, someone reports a bug in a channel with some details, then using the "post-menu" button the message's content could be used to create a new "bug" object in a tracking system. | -| `/channel_header` | A button in the channel header on desktop app or the web app, and an item in the channel menu on the mobile app. This is used for actions that take place at the channel level.

For example, a button for the user to set up a notification subscription for all new tickets in system XYZ to be posted to the current channel | +| `/post_menu` | An item in a Mattermost post's dropdown menu (e.g., Message Action) where the user can leverage message content as part of the App's action.

For example, someone reports a bug in a channel with some details, then using the "post-menu" button, the message's content could be used to create a new "bug" object in a tracking system. | +| `/channel_header` | A button in the channel header on the desktop app or the web app, and an item in the channel menu on the mobile app. This is used for actions that take place at the channel level.

For example, a button for the user to set up a notification subscription for all new tickets in system XYZ to be posted to the current channel. | | `/command` | A slash command accessed by typing `/` at the beginning of any new message in Mattermost.

For example, a slash command `/ticketing --name "test Ticket" --priority high` can capture two fields and create a ticket in an external system. The options for the `priority` field could be displayed to the user in a pick list to reduce their need to type. | | `/in_post` | A form that is embedded within a message in Mattermost. Used to interact with users without switching context to an interactive dialog.

For example, confirming simple things like "Did you complete your OKR review yet? (Yes/No)" options can be presented to the user and they can simply check off a box. | From 06802d03674a832b0cd162b79ea7dbc92af9be1d Mon Sep 17 00:00:00 2001 From: alan lew Date: Mon, 3 Oct 2022 10:57:50 -0400 Subject: [PATCH 15/22] Changes based on PR feedback --- .../integrate/apps/structure/call/_index.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/site/content/integrate/apps/structure/call/_index.md b/site/content/integrate/apps/structure/call/_index.md index 417759087e..9c766e8687 100644 --- a/site/content/integrate/apps/structure/call/_index.md +++ b/site/content/integrate/apps/structure/call/_index.md @@ -36,7 +36,7 @@ An example call looks like this: ## Request -When a call is performed, a POST request will be made to the endpoint defined in the call. The call will include a JWT in the `Mattermost-App-Authorization` header. The Acting User's ID is included in the request by default. +When a call is performed, a POST request will be made to the endpoint defined in the call. The call will include a JSON Web Token (JWT) in the `Mattermost-App-Authorization` header. The Acting User's ID is included in the request by default. The data structure of a call request ({{}}) is described in the following table: @@ -48,8 +48,8 @@ The data structure of a call request ({{}} | Used by the `form` response type to specify a form to display | +| Name | Type | Description | +|------------------------|---------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------| +| `type` | [CallResponseType](#call-response-types) | The type of response being returned. | +| `text` | string | Used by the `ok` and `error` response types to return a markdown message that is sent to the user as an ephemeral post. | +| `data` | map | Used by the `ok` response type to return additional data. | +| `navigate_to_url` | string | Used by the `navigate` response type to redirect the user to a specified URL. | +| `use_external_browser` | bool | Used by the `navigate` response type to indicate the system web browser should be used when redirecting the user to an URL. | +| `form` | {{}} | Used by the `form` response type to specify a form to display. | An example call response looks like this: From c0699b663a66cb99fa9f561d2000c553410de948 Mon Sep 17 00:00:00 2001 From: Alan Lew Date: Mon, 3 Oct 2022 11:02:07 -0400 Subject: [PATCH 16/22] Apply suggestions from code review Co-authored-by: Carrie Warner (Mattermost) <74422101+cwarnermm@users.noreply.github.com> --- site/content/integrate/apps/functionality/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/integrate/apps/functionality/_index.md b/site/content/integrate/apps/functionality/_index.md index dd620f3a46..2c694ef6af 100644 --- a/site/content/integrate/apps/functionality/_index.md +++ b/site/content/integrate/apps/functionality/_index.md @@ -13,6 +13,6 @@ In addition to the {{}}) covers how to subscribe to notifications about Mattermost events. Examples of a subscription include having your App notified whenever a message is posted in a channel that mentions your @bot account. -- [External webhooks]({{< ref "external-webhooks" >}}) covers subscribing to webhooks from third-party systems. +- [External webhooks]({{< ref "external-webhooks" >}}) learn how to subscribe to webhooks from third-party systems. See [Authenticating with Mattermost]({{< ref "/integrate/apps/authentication/app-to-mattermost" >}}) to learn how to authenticate to all these services. From 4cd95c4ae1349c799e526d1b4993e704fab4c5c9 Mon Sep 17 00:00:00 2001 From: Alan Lew Date: Mon, 3 Oct 2022 11:02:38 -0400 Subject: [PATCH 17/22] Update site/content/integrate/apps/functionality/_index.md Co-authored-by: Carrie Warner (Mattermost) <74422101+cwarnermm@users.noreply.github.com> --- site/content/integrate/apps/functionality/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/integrate/apps/functionality/_index.md b/site/content/integrate/apps/functionality/_index.md index 2c694ef6af..279c9d815e 100644 --- a/site/content/integrate/apps/functionality/_index.md +++ b/site/content/integrate/apps/functionality/_index.md @@ -11,7 +11,7 @@ In addition to the {{}}) - use the Call API to invoke other Apps (experimental). -- [Subscriptions]({{< ref "subscriptions" >}}) covers how to subscribe to notifications about Mattermost events. Examples of a subscription include having your App notified whenever a message is posted in a channel that mentions your @bot account. +- [Subscriptions]({{< ref "subscriptions" >}}) learn how to subscribe to notifications about Mattermost events. For example: have your App notified whenever a message is posted in a channel that mentions your @bot account. - [External webhooks]({{< ref "external-webhooks" >}}) learn how to subscribe to webhooks from third-party systems. From 737987172d6baf304a254a5fbc18ef242e27e368 Mon Sep 17 00:00:00 2001 From: alan lew Date: Wed, 5 Oct 2022 09:53:35 -0400 Subject: [PATCH 18/22] Modify collapse, compass-icon, newtabref, and note shortcodes to use alt text and screen reader support for all icons; Add alt text and screen reader support for icons in the Structure section --- .../apps/structure/bindings/_index.md | 24 +++--- .../integrate/apps/structure/call/_index.md | 62 +++++++------- .../apps/structure/manifest/_index.md | 84 +++++++++---------- site/layouts/shortcodes/collapse.html | 2 +- site/layouts/shortcodes/compass-icon.html | 4 +- site/layouts/shortcodes/newtabref.html | 4 +- site/layouts/shortcodes/note.html | 6 +- 7 files changed, 96 insertions(+), 90 deletions(-) diff --git a/site/content/integrate/apps/structure/bindings/_index.md b/site/content/integrate/apps/structure/bindings/_index.md index 899ada890c..d22d9d0dbb 100644 --- a/site/content/integrate/apps/structure/bindings/_index.md +++ b/site/content/integrate/apps/structure/bindings/_index.md @@ -28,18 +28,18 @@ Bindings for `/in_post` locations should not be included in the response to the Sub-location bindings use the following data structure: -| Name | Type | Description | Locations | -|-----------------------------------------|----------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|---------------------------------------------------| -| `location` | string | The name of the binding location. Values must be unique within each top level binding. | all locations | -| `icon` | string | The App icon to display, either a fully-qualified URL or a path to an App static asset. Required for web app support. | `/channel_header`
`/post_menu` | -| `label` | string | The primary text to display at the binding location; defaults to the value of the `location` field. | all locations | -| `hint` | string | Secondary text to display at the binding location | `/channel_header`
`/command` | -| `description` | string | Extended help text used in modal forms and command autocomplete | `/command` | -| `submit` {{}} | Call | Executes an action associated with the binding | all locations | -| `form` {{}} | Form | The modal form to display | `/channel_header`
`/command`
`/post_menu` | -| `bindings` {{}} | {{}} (list) | Additional sub-location bindings | all locations | - -{{}} +| Name | Type | Description | Locations | +|------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|---------------------------------------------------| +| `location` | string | The name of the binding location. Values must be unique within each top level binding. | all locations | +| `icon` | string | The App icon to display, either a fully-qualified URL or a path to an App static asset. Required for web app support. | `/channel_header`
`/post_menu` | +| `label` | string | The primary text to display at the binding location; defaults to the value of the `location` field. | all locations | +| `hint` | string | Secondary text to display at the binding location | `/channel_header`
`/command` | +| `description` | string | Extended help text used in modal forms and command autocomplete | `/command` | +| `submit` {{}} | Call | Executes an action associated with the binding | all locations | +| `form` {{}} | Form | The modal form to display | `/channel_header`
`/command`
`/post_menu` | +| `bindings` {{}} | {{}} (list) | Additional sub-location bindings | all locations | + +{{}} Only one of the `submit`, `form`, and `bindings` fields can be specified in a sub-location binding. Specifying more than one is treated as an error. {{}} diff --git a/site/content/integrate/apps/structure/call/_index.md b/site/content/integrate/apps/structure/call/_index.md index 9c766e8687..ca5eff3b4f 100644 --- a/site/content/integrate/apps/structure/call/_index.md +++ b/site/content/integrate/apps/structure/call/_index.md @@ -73,37 +73,37 @@ An example call request looks like the following (some `context` fields omitted The request `context` field contains metadata about the request. The data structure of the context ({{}}) field is described in the following table: -| Name | Type | Description | -|:-------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------| -| `subject` | Subject (`string`) | Event subject. | -| `channel_id` | string | ID from the channel from within which the call was performed. | -| `team_id` | string | ID from the team from within which the call was performed. | -| `post_id` | string | ID from the post from within which the call was performed. | -| `root_post_id` | string | If the call was performed from a post in a thread, the root post ID of that thread. | -| `app_id` | AppID (`string`) | The app ID. | -| `location` | Location (`string`) | The location from which the call was performed. | -| `user_agent` | string | User agent used to perform the call.
Valid values are: `mobile`, `webapp`. | -| `track_as_submit` | bool | Whether the call was caused by a submit action from a binding or form. | -| `mattermost_site_url` | string | Mattermost base URL. | -| `developer_mode` | bool | Whether the Apps framework is running in Developer mode. | -| `app_path` | string | App's path on the Mattermost instance (appendable to `mattermost_site_url`). | -| `bot_user_id` | string | Bot user ID. | -| `bot_access_token`{{}} | string | (Expansion) | -| `app`{{}} | {{}} | Details about the installed record of the App. | -| `acting_user`{{}} | {{}} | (Expansion) | -| `acting_user_access_token`{{}} | string | (Expansion) | -| `locale`{{}} | string | (Expansion) | -| `channel`{{}} | {{}} | (Expansion) | -| `channel_member`{{}} | {{}} | (Expansion) | -| `team`{{}} | {{}} | (Expansion) | -| `team_member`{{}} | {{}} | (Expansion) | -| `post`{{}} | {{}} | (Expansion) | -| `root_post`{{}} | {{}} | (Expansion) | -| `user`{{}} | {{}} | (Expansion) | -| `mentioned`{{}} | {{}} (list) | (Expansion) | -| `oauth2`{{}} | {{}} | (Expansion) | - -{{}} +| Name | Type | Description | +|:------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------| +| `subject` | Subject (`string`) | Event subject. | +| `channel_id` | string | ID from the channel from within which the call was performed. | +| `team_id` | string | ID from the team from within which the call was performed. | +| `post_id` | string | ID from the post from within which the call was performed. | +| `root_post_id` | string | If the call was performed from a post in a thread, the root post ID of that thread. | +| `app_id` | AppID (`string`) | The app ID. | +| `location` | Location (`string`) | The location from which the call was performed. | +| `user_agent` | string | User agent used to perform the call.
Valid values are: `mobile`, `webapp`. | +| `track_as_submit` | bool | Whether the call was caused by a submit action from a binding or form. | +| `mattermost_site_url` | string | Mattermost base URL. | +| `developer_mode` | bool | Whether the Apps framework is running in Developer mode. | +| `app_path` | string | App's path on the Mattermost instance (appendable to `mattermost_site_url`). | +| `bot_user_id` | string | Bot user ID. | +| `bot_access_token`{{}} | string | (Expansion) | +| `app`{{}} | {{}} | Details about the installed record of the App. | +| `acting_user`{{}} | {{}} | (Expansion) | +| `acting_user_access_token`{{}} | string | (Expansion) | +| `locale`{{}} | string | (Expansion) | +| `channel`{{}} | {{}} | (Expansion) | +| `channel_member`{{}} | {{}} | (Expansion) | +| `team`{{}} | {{}} | (Expansion) | +| `team_member`{{}} | {{}} | (Expansion) | +| `post`{{}} | {{}} | (Expansion) | +| `root_post`{{}} | {{}} | (Expansion) | +| `user`{{}} | {{}} | (Expansion) | +| `mentioned`{{}} | {{}} (list) | (Expansion) | +| `oauth2`{{}} | {{}} | (Expansion) | + +{{}} The data in these fields will not be populated by default. For more information on expanding metadata in the request context, see the [Call metadata]({{}}) page. {{}} diff --git a/site/content/integrate/apps/structure/manifest/_index.md b/site/content/integrate/apps/structure/manifest/_index.md index babad4f543..a889f233ce 100644 --- a/site/content/integrate/apps/structure/manifest/_index.md +++ b/site/content/integrate/apps/structure/manifest/_index.md @@ -10,29 +10,29 @@ aliases: All Apps should define a manifest ({{}}) as a JSON object. The fields of the manifest are described in the following table: -| Name | Type | Description | -|:-------------------------------------------|:----------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------| -| `app_id`{{}} | string | ID for your App. | -| `homepage_url`{{}} | string | The App homepage. Used in the Marketplace and for OAuth purposes. | -| `version` | string | The version of your App, formatted as `v00.00.0000`. | -| `display_name` | string | The display name for your App. | -| `description` | string | The description for your App. Used in the product Marketplace. Provide examples of key functionality the App provides in a short paragraph. | -| `icon` | string | The icon for your App. Must be a relative path to a PNG image in the static assets folder. Used as the bot account icon and in the product Marketplace. | -| `requested_permissions` | [Permissions](#permissions) | List of permissions needed by the App. | -| `requested_locations` | [Locations](#locations) | The list of top-level locations that the App intends to bind to. | -| `bindings` | [Call]({{}}) | The call invoked to retrieve bindings. Default value: `/bindings` | -| `on_install` | [Call]({{}}) | The call invoked when the App is installed. | -| `on_uninstall` | [Call]({{}}) | The call invoked when the App is uninstalled, before the App is removed. | -| `on_version_changed` | [Call]({{}}) | The call invoked when the App needs to be upgraded or downgraded. | -| `get_oauth2_connect_url` | [Call]({{}}) | The call invoked with the App's "connect to third party" link is selected, to be redirected to the OAuth flow. | -| `on_oauth2_complete` | [Call]({{}}) | The call invoked when the OAuth flow has successfully completed. | -| `on_remote_webhook` | [Call]({{}}) | The call invoked when an HTTP webhook is received from a remote system. | -| `remote_webhook_auth_type` | string | Specifies how incoming webhook messages from remote systems should be authenticated by Mattermost. | -| `aws_lambda`{{}} | [AWSLambda](#aws-lambda) | Metadata for an App that can be deployed to AWS Lambda and S3 services, and is accessed using the AWS APIs. | -| `open_faas`{{}} | [OpenFAAS](#openfaas) | Metadata for an App that can be deployed to OpenFAAS. | -| `http`{{}} | [HTTP](#http) | Metadata for an App that is already deployed externally and is accessed using HTTP. | - -{{}} +| Name | Type | Description | +|:-------------------------------------------------------------|:----------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------| +| `app_id`{{}} | string | ID for your App. | +| `homepage_url`{{}} | string | The App homepage. Used in the Marketplace and for OAuth purposes. | +| `version` | string | The version of your App, formatted as `v00.00.0000`. | +| `display_name` | string | The display name for your App. | +| `description` | string | The description for your App. Used in the product Marketplace. Provide examples of key functionality the App provides in a short paragraph. | +| `icon` | string | The icon for your App. Must be a relative path to a PNG image in the static assets folder. Used as the bot account icon and in the product Marketplace. | +| `requested_permissions` | [Permissions](#permissions) | List of permissions needed by the App. | +| `requested_locations` | [Locations](#locations) | The list of top-level locations that the App intends to bind to. | +| `bindings` | [Call]({{}}) | The call invoked to retrieve bindings. Default value: `/bindings` | +| `on_install` | [Call]({{}}) | The call invoked when the App is installed. | +| `on_uninstall` | [Call]({{}}) | The call invoked when the App is uninstalled, before the App is removed. | +| `on_version_changed` | [Call]({{}}) | The call invoked when the App needs to be upgraded or downgraded. | +| `get_oauth2_connect_url` | [Call]({{}}) | The call invoked with the App's "connect to third party" link is selected, to be redirected to the OAuth flow. | +| `on_oauth2_complete` | [Call]({{}}) | The call invoked when the OAuth flow has successfully completed. | +| `on_remote_webhook` | [Call]({{}}) | The call invoked when an HTTP webhook is received from a remote system. | +| `remote_webhook_auth_type` | string | Specifies how incoming webhook messages from remote systems should be authenticated by Mattermost. | +| `aws_lambda`{{}} | [AWSLambda](#aws-lambda) | Metadata for an App that can be deployed to AWS Lambda and S3 services, and is accessed using the AWS APIs. | +| `open_faas`{{}} | [OpenFAAS](#openfaas) | Metadata for an App that can be deployed to OpenFAAS. | +| `http`{{}} | [HTTP](#http) | Metadata for an App that is already deployed externally and is accessed using HTTP. | + +{{}} - The `app_id` and `homepage_url` values must be specified. - One deployment method - `aws_lambda`, `open_faas`, or `http` - must be specified. {{}} @@ -84,7 +84,7 @@ Locations ({{
For example, a button for the user to set up a notification subscription for all new tickets in system XYZ to be posted to the current channel. | +| `/channel_header` | A button in the channel header on the desktop app or the web app, and an item in the channel menu on the mobile app. This is used for actions that take place at the channel level.

For example, a button for the user to set up a notification subscription for all new tickets in system XYZ to be posted to the current channel. | | `/command` | A slash command accessed by typing `/` at the beginning of any new message in Mattermost.

For example, a slash command `/ticketing --name "test Ticket" --priority high` can capture two fields and create a ticket in an external system. The options for the `priority` field could be displayed to the user in a pick list to reduce their need to type. | | `/in_post` | A form that is embedded within a message in Mattermost. Used to interact with users without switching context to an interactive dialog.

For example, confirming simple things like "Did you complete your OKR review yet? (Yes/No)" options can be presented to the user and they can simply check off a box. | @@ -112,20 +112,20 @@ Example: #### AWS Lambda Provides configuration for deploying an App onto the AWS Lambda and S3 services. -All fields are mandatory ({{}}). +All fields are mandatory ({{}}). -| Name | Type | Description | -|:----------------------------------------|:---------------------|:------------------| -| `functions`{{}} | AWS Lambda functions | List of functions | +| Name | Type | Description | +|:----------------------------------------------------------|:---------------------|:------------------| +| `functions`{{}} | AWS Lambda functions | List of functions | Each AWS Lambda function contains the following fields: -| Name | Description | -|:--------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `path`{{}} | Root path of calls to be mapped to this function. For example: `"/"` | -| `name`{{}} | Function's base name; used to compose the actual AWS Lambda name. | -| `handler`{{}} | The name of the function handler. | -| `runtime`{{}} | AWS Lambda runtime to use.
See the {{}} documentation for a list of supported runtimes. | +| Name | Description | +|:--------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `path`{{}} | Root path of calls to be mapped to this function. For example: `"/"` | +| `name`{{}} | Function's base name; used to compose the actual AWS Lambda name. | +| `handler`{{}} | The name of the function handler. | +| `runtime`{{}} | AWS Lambda runtime to use.
See the {{}} documentation for a list of supported runtimes. | Example: ```json @@ -146,18 +146,18 @@ Example: #### OpenFaaS Provides configuration for deploying an App onto OpenFaaS and `faasd` platforms. -All fields are mandatory ({{}}). +All fields are mandatory ({{}}). -| Name | Type | Description | -|:----------------------------------------|:-------------------|:------------------| -| `functions`{{}} | OpenFaaS functions | List of functions | +| Name | Type | Description | +|:----------------------------------------------------------|:-------------------|:------------------| +| `functions`{{}} | OpenFaaS functions | List of functions | Each function contains the following fields: -| Name | Description | -|:-----------------------------------|:-------------------------------------------------------------------------------------------------------------------| -| `path`{{}} | Root path of calls to be mapped to this function. For example: `"/"` | -| `name`{{}} | Function's base name.
Used to compose the actual OpenFaaS function name, combined with the App ID and version. | +| Name | Description | +|:-----------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------| +| `path`{{}} | Root path of calls to be mapped to this function. For example: `"/"` | +| `name`{{}} | Function's base name.
Used to compose the actual OpenFaaS function name, combined with the App ID and version. | Example: ```json diff --git a/site/layouts/shortcodes/collapse.html b/site/layouts/shortcodes/collapse.html index 32620c700f..9c61f58684 100644 --- a/site/layouts/shortcodes/collapse.html +++ b/site/layouts/shortcodes/collapse.html @@ -5,7 +5,7 @@ {{- $title := .Get "title" -}}
- + {{ $title }}
diff --git a/site/layouts/shortcodes/compass-icon.html b/site/layouts/shortcodes/compass-icon.html index adbf5ac301..54eac90e59 100644 --- a/site/layouts/shortcodes/compass-icon.html +++ b/site/layouts/shortcodes/compass-icon.html @@ -1 +1,3 @@ -{{- "" -}} +{{- $icon := .Get 0 -}} +{{- $description := (.Get 1 | default $icon) -}} +{{- "" -}} diff --git a/site/layouts/shortcodes/newtabref.html b/site/layouts/shortcodes/newtabref.html index 6b3a6c6fbf..19075294f1 100644 --- a/site/layouts/shortcodes/newtabref.html +++ b/site/layouts/shortcodes/newtabref.html @@ -1 +1,3 @@ -{{ .Get "title" }}{{- "" -}} +{{- $href := .Get "href" -}} +{{- $title := (.Get "title" | default "[link]") -}} +{{ $title }}{{- "" -}} diff --git a/site/layouts/shortcodes/note.html b/site/layouts/shortcodes/note.html index 9f8ffda449..5b2e3c704e 100644 --- a/site/layouts/shortcodes/note.html +++ b/site/layouts/shortcodes/note.html @@ -1,7 +1,9 @@ -{{- $icon := .Get 1 -}} +{{- $title := (.Get 0 | default "Note:") -}} +{{- $icon := (.Get 1 | default "") -}} +{{- $icon_description := (.Get 2 | default $icon) -}} From 789243f4da562abdfb569db08be336763a1c7099 Mon Sep 17 00:00:00 2001 From: alan lew Date: Tue, 11 Oct 2022 12:11:19 -0400 Subject: [PATCH 19/22] Update description of Bindings --- site/content/integrate/apps/structure/bindings/_index.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/site/content/integrate/apps/structure/bindings/_index.md b/site/content/integrate/apps/structure/bindings/_index.md index d22d9d0dbb..245327bd12 100644 --- a/site/content/integrate/apps/structure/bindings/_index.md +++ b/site/content/integrate/apps/structure/bindings/_index.md @@ -8,8 +8,7 @@ aliases: Bindings ({{}}) establish the relationship between [call]({{}}) handlers and [locations]({{}}). Whenever the bindings call is executed the App provides a list of bindings based on the [request context]({{}}). -Bindings are refreshed when the App is installed, on every channel switch, and when an OAuth2 process has completed. Bindings may also be refreshed when the user moves to a different context, such as opening a thread or a post in a search view. - +Bindings are refreshed when the App is installed, on every channel switch, and when an OAuth2 process with a third party has completed. Bindings may also be refreshed when the user moves to a different context, such as opening a thread or a post in a search view. ## Top level bindings From 7d26f2c94d0df536b56caa56c43cbcf3ae9f620f Mon Sep 17 00:00:00 2001 From: Alan Lew Date: Tue, 11 Oct 2022 12:14:18 -0400 Subject: [PATCH 20/22] Apply suggestions from code review Co-authored-by: Lev <1187448+levb@users.noreply.github.com> --- site/content/integrate/apps/structure/manifest/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/integrate/apps/structure/manifest/_index.md b/site/content/integrate/apps/structure/manifest/_index.md index a889f233ce..2b50cb5acf 100644 --- a/site/content/integrate/apps/structure/manifest/_index.md +++ b/site/content/integrate/apps/structure/manifest/_index.md @@ -34,7 +34,7 @@ The fields of the manifest are described in the following table: {{}} - The `app_id` and `homepage_url` values must be specified. -- One deployment method - `aws_lambda`, `open_faas`, or `http` - must be specified. +At least one deployment method - `aws_lambda`, `open_faas`, or `http` - must be specified. {{}} For example, a typical App manifest would look like the following: From 3c4cbaa42d2d8c88b0525f3bafec621342904e2c Mon Sep 17 00:00:00 2001 From: Alan Lew Date: Tue, 11 Oct 2022 14:12:46 -0400 Subject: [PATCH 21/22] Apply suggestions from code review Co-authored-by: Lev <1187448+levb@users.noreply.github.com> --- site/content/integrate/apps/structure/call/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/integrate/apps/structure/call/_index.md b/site/content/integrate/apps/structure/call/_index.md index ca5eff3b4f..0fd75807dd 100644 --- a/site/content/integrate/apps/structure/call/_index.md +++ b/site/content/integrate/apps/structure/call/_index.md @@ -5,7 +5,7 @@ weight: 20 aliases: - /integrate/apps/api/call/ --- -A Call defines an App action that can be invoked. +A Call defines an App action that can be invoked, or a request for App data. {{}} Content on this page refers to the Mattermost Apps framework and not to the Mattermost Calls product functionality. From eae738e542d90c57501f3856f9e41fb56185cf64 Mon Sep 17 00:00:00 2001 From: alan lew Date: Tue, 11 Oct 2022 14:14:32 -0400 Subject: [PATCH 22/22] Apply changes from PR reviews --- site/content/integrate/apps/structure/call/_index.md | 3 ++- site/content/integrate/apps/structure/manifest/_index.md | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/site/content/integrate/apps/structure/call/_index.md b/site/content/integrate/apps/structure/call/_index.md index 0fd75807dd..64a0d58f1e 100644 --- a/site/content/integrate/apps/structure/call/_index.md +++ b/site/content/integrate/apps/structure/call/_index.md @@ -104,7 +104,8 @@ The request `context` field contains metadata about the request. The data struct | `oauth2`{{}} | {{}} | (Expansion) | {{}} -The data in these fields will not be populated by default. For more information on expanding metadata in the request context, see the [Call metadata]({{}}) page. +The data in these fields will not be populated by default. The originating call's `expand` values, and the call session's permissions determine what fields are populated. +For more information on expanding metadata in the request context, see the [Call metadata]({{}}) page. {{}} An example context field looks like this: diff --git a/site/content/integrate/apps/structure/manifest/_index.md b/site/content/integrate/apps/structure/manifest/_index.md index 2b50cb5acf..761623d94d 100644 --- a/site/content/integrate/apps/structure/manifest/_index.md +++ b/site/content/integrate/apps/structure/manifest/_index.md @@ -71,7 +71,6 @@ The following table lists the supported permissions ({{