diff --git a/Makefile b/Makefile index c57d471514..eb11b495d4 100644 --- a/Makefile +++ b/Makefile @@ -27,3 +27,10 @@ run: build: rm -rf ./dist hugo -s site --verbose --destination ../dist/html --printUnusedTemplates --printPathWarnings --gc + +.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/config.toml b/site/config.toml index be82970d87..68537cf716 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/functionality/_index.md b/site/content/integrate/apps/functionality/_index.md index 1a1431f857..279c9d815e 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" >}}) 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. + +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 82f6683f14..0bc64b7d5c 100644 --- a/site/content/integrate/apps/structure/_index.md +++ b/site/content/integrate/apps/structure/_index.md @@ -9,54 +9,14 @@ aliases: Apps consist of three kinds of assets: -- [manifest.json]({{< ref "manifest" >}}) file +1. A [manifest]({{< ref "manifest" >}}), 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]({{}}), such as 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. +![image](apps-calls_bindings_locations_v2.svg) -- 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. - -## Use Mattermost APIs - -Apps can use all general [Mattermost REST API]({{< ref "mattermost-api" >}})s, -as well as special services that are provided to the apps. - -See [Authenticating with Mattermost]({{< ref "app-to-mattermost" >}}) for how -to authenticate to all these services. - -App services: - -- [KV Store]({{< ref "mattermost-api#apps-api" >}}) - store and retrive 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). - -## 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. - +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_v2.svg b/site/content/integrate/apps/structure/apps-calls_bindings_locations_v2.svg new file mode 100644 index 0000000000..0ee1f65f7b --- /dev/null +++ b/site/content/integrate/apps/structure/apps-calls_bindings_locations_v2.svg @@ -0,0 +1,547 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /call-handler + + + + + + + + + + + + + Binding + + + + + + Mattermost UI Location + + + + + + + + diff --git a/site/content/integrate/apps/structure/bindings/_index.md b/site/content/integrate/apps/structure/bindings/_index.md index 787d96c175..245327bd12 100644 --- a/site/content/integrate/apps/structure/bindings/_index.md +++ b/site/content/integrate/apps/structure/bindings/_index.md @@ -5,98 +5,166 @@ 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 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. -- 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) +## Top level bindings -**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. +Bindings are organized by top level [locations]({{}}). The data structure of a top level binding is: -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. +| Name | Type | Description | +|:-----------|:---------------------------------------------------------------------------------------------------------------------------------|:----------------------------------------| +| `location` | {{}} (`string`) | Top level location. | +| `bindings` | {{}} (list) | A list of bindings under this location. | -The expected response should include the following: +{{}} +Bindings for `/in_post` locations should not be included in the response to the bindings call. +{{}} -| Type | Function | Description | -|:-------|:---------|:----------------------| -| `data` | bindings | The list of bindings. | +## Sub-location bindings -Bindings are organized by top level locations. Top level bindings just need to define: +Sub-location bindings use the following data structure: -| Name | Type | Description | -|:-----------|:---------|:----------------------------------------| -| `location` | string | Top level location. | -| `bindings` | Bindings | A list of bindings under this location. | +| 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 | -`/in_post` bindings don't need to be defined in this call. +{{}} +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. +{{}} -### `/post_menu` 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) 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 following request context fields will be available to calls invoked at each binding location: -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. +| 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` | -### `/channel_header` bindings +### Slash command 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/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 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. -The context of the call for these bindings will include the user ID, the channel ID, and the team ID. +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. -### `/command` bindings +For example, a slash command binding that returns one day or one week worth of weather information: -For commands we can distinguish between leaf commands (executable subcommand) and partial commands. +```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" + } + } + ] + } + ] + } + ] +} +``` -A partial command must include: +In the Mattermost UI, typing `/weather` shows the details of the slash command: -| 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. | +![image](command_location_weather.png) -A leaf command must include: +Typing `/weather week` shows the details of the nested command: -| 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. | +![image](command_location_weather_week.png) -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. +A user could invoke the slash command using `/weather day` or `/weather week` to get weather conditions for one day or one week, respectively. -## Example data flow +## Bindings call response -
Client Bindings Request +The response to the bindings call should take the form of an `ok` [call response]({{}}) where the `data` field contains the bindings. -`GET /plugins/com.mattermost.apps/api/v1/bindings?user_id=ws4o4macctyn5ko8uhkkxmgfur&channel_id=qphz13bzbf8c7j778tdnaw3huc&scope=webapp` +{{}} +Bindings for `/in_post` locations should not be included in the response. +{{}} -
+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" + } + } + ] + } + ] + } + ] +} +``` -
Mattermost Bindings Request +## Example request and response + +{{}} +`GET /plugins/com.mattermost.apps/api/v1/bindings?user_id=ws4o4macctyn5ko8uhkkxmgfur&channel_id=qphz13bzbf8c7j778tdnaw3huc&scope=webapp` +{{}} + +{{}} `POST /plugins/com.mattermost.apps/example/hello/bindings` @@ -116,10 +184,9 @@ The context of the call for these bindings will include the user ID, the post ID } } ``` -
- -
App Binding Response +{{}} +{{}} ```json { "type": "ok", @@ -175,4 +242,4 @@ The context of the call for these bindings will include the user ID, the post ID ] } ``` -
+{{}} 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 0000000000..09fe52ca6f Binary files /dev/null and b/site/content/integrate/apps/structure/bindings/command_location_weather.png differ 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 0000000000..91d4a056f6 Binary files /dev/null and b/site/content/integrate/apps/structure/bindings/command_location_weather_week.png differ 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..56c657cbc6 --- /dev/null +++ b/site/content/integrate/apps/structure/call-metadata/_index.md @@ -0,0 +1,60 @@ +--- +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. | +| `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. | +| `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 data. | + + +#### 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). | + +### 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
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 943b2ea177..64a0d58f1e 100644 --- a/site/content/integrate/apps/structure/call/_index.md +++ b/site/content/integrate/apps/structure/call/_index.md @@ -1,136 +1,176 @@ --- -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 - -| Name | Type | Description | -|:-----------|:-------|:-----------------------------------------------------------------------------| -| `type` | string | Use `ok`. | -| `markdown` | string | (Optional) Markdown text that will be sent to the user as an ephemeral post. | - -#### Error response - -| Name | Type | Description | -|:--------|:-------|:------------------------------------------------------------------| -| `type` | string | Use `error`. | -| `error` | string | Markdown text that will be sent to the user as an ephemeral post. | - -#### Form response - -| Name | Type | Description | -|:-------|:-------|:--------------| -| `type` | string | Use `form`. | -| `form` | form | Form to open. | - -#### Navigate response - -| 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. | - +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. +{{}} + +## Data structure + +The data structure of a call ({{}}) is described in the following table: + +| 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` | 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 this: + +```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 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: + +| 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 | Specifies the field name to use for lookups and refreshes. | +| `query` | string | The user-supplied query string to use for lookups and refreshes. | + +An example call request looks like the following (some `context` fields omitted for brevity): + +```json +{ + "path": "/send", + "expand": {}, + "context": { + "app_id": "hello-world", + "location": "/command/helloworld/send", + "acting_user": { + "id": "k86a9cy93f8azx7jjiy5xfq5jc" + }, + "oauth2": {} + }, + "raw_command": "/helloworld send" +} +``` + +### Context + +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) | + +{{}} +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: + +```json +{ + "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": {} + } +} +``` + +## Response + +The data structure of a call response is described in the following table: + +| 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: + +```json +{ + "type": "ok", + "text": "### Success!\n\nThe operation completed successfully." +} +``` + +### Call response types + +There are several types of supported 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. | diff --git a/site/content/integrate/apps/structure/manifest/_index.md b/site/content/integrate/apps/structure/manifest/_index.md index 2dc2e039cf..761623d94d 100644 --- a/site/content/integrate/apps/structure/manifest/_index.md +++ b/site/content/integrate/apps/structure/manifest/_index.md @@ -1,47 +1,51 @@ --- 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 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. | + +{{}} +- The `app_id` and `homepage_url` values 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: + ```json { "app_id": "hello-world", "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" ], @@ -49,6 +53,9 @@ An example manifest looks like this: "/channel_header", "/command" ], + "on_install": { + "path": "/install" + }, "http": { "root_url": "http://localhost:4000" } @@ -57,40 +64,39 @@ An example manifest looks like this: ### 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. - -Below are the permissions ([godoc](https://pkg.go.dev/github.com/mattermost/mattermost-plugin-apps/apps#Permission)) an app can currently ask for: +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. -| 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) | +The following table lists the supported permissions ({{}}) an app can request: +| Name | Description | +|:-----------------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------| +| `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 ([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, 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 (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. | -### 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. +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 @@ -102,54 +108,57 @@ 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. +Provides configuration for deploying an App onto the AWS Lambda and S3 services. +All fields are mandatory ({{}}). -| 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" } ] } } ``` -#### `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 onto OpenFaaS and `faasd` platforms. +All fields are mandatory ({{}}). -| 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": { @@ -162,39 +171,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/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. diff --git a/site/layouts/partials/footer.html b/site/layouts/partials/footer.html index f502fa1ce1..43018cfb56 100755 --- a/site/layouts/partials/footer.html +++ b/site/layouts/partials/footer.html @@ -75,3 +75,20 @@ }); {{ end }} + + 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/collapse.html b/site/layouts/shortcodes/collapse.html new file mode 100644 index 0000000000..9c61f58684 --- /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/layouts/shortcodes/compass-icon.html b/site/layouts/shortcodes/compass-icon.html new file mode 100644 index 0000000000..54eac90e59 --- /dev/null +++ b/site/layouts/shortcodes/compass-icon.html @@ -0,0 +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 3695c16c5a..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 bee874277d..5b2e3c704e 100644 --- a/site/layouts/shortcodes/note.html +++ b/site/layouts/shortcodes/note.html @@ -1,6 +1,9 @@ +{{- $title := (.Get 0 | default "Note:") -}} +{{- $icon := (.Get 1 | default "") -}} +{{- $icon_description := (.Get 2 | default $icon) -}} diff --git a/site/static/css/compass-icons.css b/site/static/css/compass-icons.css index 2db860cf74..065117008a 100644 --- a/site/static/css/compass-icons.css +++ b/site/static/css/compass-icons.css @@ -1,12 +1,12 @@ @charset "UTF-8"; @font-face { font-family: 'compass-icons'; - src: url('../font/compass-icons.eot?68144524'); - src: url('../font/compass-icons.eot?68144524#iefix') format('embedded-opentype'), - url('../font/compass-icons.woff2?68144524') format('woff2'), - url('../font/compass-icons.woff?68144524') format('woff'), - url('../font/compass-icons.ttf?68144524') format('truetype'), - url('../font/compass-icons.svg?68144524#compass-icons') format('svg'); + 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; } @@ -16,7 +16,7 @@ @media screen and (-webkit-min-device-pixel-ratio:0) { @font-face { font-family: 'compass-icons'; - src: url('../font/compass-icons.svg?68144524#compass-icons') format('svg'); + src: url('../font/compass-icons.svg?86763500#compass-icons') format('svg'); } } */ @@ -182,6 +182,7 @@ .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' */ @@ -264,8 +265,10 @@ .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' */ @@ -315,6 +318,7 @@ .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' */ diff --git a/site/static/css/styles.css b/site/static/css/styles.css index a11806fdf6..854a5b4e27 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; } @@ -3122,6 +3126,20 @@ td>code { word-break: normal; } +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; } @@ -3295,6 +3313,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, 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/font/compass-icons.eot b/site/static/font/compass-icons.eot index ba780403cd..a5b4cc6d40 100644 Binary files a/site/static/font/compass-icons.eot and b/site/static/font/compass-icons.eot differ diff --git a/site/static/font/compass-icons.svg b/site/static/font/compass-icons.svg index 4f42ea387d..dabeb63e7f 100644 --- a/site/static/font/compass-icons.svg +++ b/site/static/font/compass-icons.svg @@ -260,6 +260,8 @@ + + @@ -424,10 +426,14 @@ + + + + @@ -526,6 +532,8 @@ + + diff --git a/site/static/font/compass-icons.ttf b/site/static/font/compass-icons.ttf index a4dcea7ce0..50b70ad50a 100644 Binary files a/site/static/font/compass-icons.ttf and b/site/static/font/compass-icons.ttf differ diff --git a/site/static/font/compass-icons.woff b/site/static/font/compass-icons.woff index 8e148bc36d..9cdba1180f 100644 Binary files a/site/static/font/compass-icons.woff and b/site/static/font/compass-icons.woff differ diff --git a/site/static/font/compass-icons.woff2 b/site/static/font/compass-icons.woff2 index 7374ba0cd3..f66cc84d32 100644 Binary files a/site/static/font/compass-icons.woff2 and b/site/static/font/compass-icons.woff2 differ 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