Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Ability to create a Table in AdaptiveCard #205

Closed
chandrakanthkannam opened this issue Mar 13, 2023 · 10 comments
Closed

Ability to create a Table in AdaptiveCard #205

chandrakanthkannam opened this issue Mar 13, 2023 · 10 comments
Assignees
Labels
card format/adaptivecard Adaptive Card support enhancement New feature or request
Milestone

Comments

@chandrakanthkannam
Copy link

Hi, I was wondering if we can create a table https://adaptivecards.io/explorer/Table.html using this package, if not any plans on including it?

@atc0005
Copy link
Owner

atc0005 commented Mar 14, 2023

Hi @chandrakanthkannam,

Thanks for providing that reference link.

At present that support is not present in this package.

When AdaptiveCard support was initially implemented I do not believe that schema version 1.5 was supported (for incoming webhook connectors). It has been a while since I last tested however.

I'll test and report back when I'm able.

@atc0005
Copy link
Owner

atc0005 commented Mar 14, 2023

It looks like schema 1.5 is officially supported:

https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-reference

I took the JSON payload example from https://adaptivecards.io/explorer/Table.html and added it to an attachments array as shown here:

{
    "type": "message",
    "attachments": [
        {
            // Table element payload here
        }
    ]
}

Complete JSON payload example:

Teams webhook connector payload
{
    "type": "message",
    "attachments": [
        {
            "contentType": "application/vnd.microsoft.card.adaptive",
            "contentUrl": null,
            "content": {
                "type": "AdaptiveCard",
                "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
                "version": "1.5",
                "body": [
                    {
                        "type": "Table",
                        "gridStyle": "accent",
                        "firstRowAsHeaders": true,
                        "columns": [
                            {
                                "width": 1
                            },
                            {
                                "width": 1
                            },
                            {
                                "width": 3
                            }
                        ],
                        "rows": [
                            {
                                "type": "TableRow",
                                "cells": [
                                    {
                                        "type": "TableCell",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Name",
                                                "wrap": true,
                                                "weight": "Bolder"
                                            }
                                        ]
                                    },
                                    {
                                        "type": "TableCell",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Type",
                                                "wrap": true,
                                                "weight": "Bolder"
                                            }
                                        ]
                                    },
                                    {
                                        "type": "TableCell",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Description",
                                                "wrap": true,
                                                "weight": "Bolder"
                                            }
                                        ]
                                    }
                                ],
                                "style": "accent"
                            },
                            {
                                "type": "TableRow",
                                "cells": [
                                    {
                                        "type": "TableCell",
                                        "style": "good",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "columns",
                                                "wrap": true
                                            }
                                        ]
                                    },
                                    {
                                        "type": "TableCell",
                                        "style": "warning",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "ColumnDefinition[]",
                                                "wrap": true
                                            }
                                        ]
                                    },
                                    {
                                        "type": "TableCell",
                                        "style": "accent",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Defines the table's columns (number of columns, and column sizes).",
                                                "wrap": true
                                            }
                                        ]
                                    }
                                ]
                            },
                            {
                                "type": "TableRow",
                                "cells": [
                                    {
                                        "type": "TableCell",
                                        "style": "good",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "rows",
                                                "wrap": true
                                            }
                                        ]
                                    },
                                    {
                                        "type": "TableCell",
                                        "style": "accent",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "TableRow[]",
                                                "wrap": true
                                            }
                                        ]
                                    },
                                    {
                                        "type": "TableCell",
                                        "style": "attention",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Defines the rows of the Table, each being a collection of cells. Rows are not required, which allows empty Tables to be generated via templating without breaking the rendering of the whole card.",
                                                "wrap": true
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    },
                    {
                        "type": "Table",
                        "gridStyle": "accent",
                        "firstRowAsHeaders": true,
                        "showGridLines": false,
                        "columns": [
                            {
                                "width": 1
                            },
                            {
                                "width": 1
                            },
                            {
                                "width": 3
                            }
                        ],
                        "rows": [
                            {
                                "type": "TableRow",
                                "cells": [
                                    {
                                        "type": "TableCell",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Name",
                                                "wrap": true,
                                                "weight": "Bolder"
                                            }
                                        ]
                                    },
                                    {
                                        "type": "TableCell",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Type",
                                                "wrap": true,
                                                "weight": "Bolder"
                                            }
                                        ]
                                    },
                                    {
                                        "type": "TableCell",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Description",
                                                "wrap": true,
                                                "weight": "Bolder"
                                            }
                                        ]
                                    }
                                ],
                                "style": "accent"
                            },
                            {
                                "type": "TableRow",
                                "cells": [
                                    {
                                        "type": "TableCell",
                                        "style": "good",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "columns",
                                                "wrap": true
                                            }
                                        ]
                                    },
                                    {
                                        "type": "TableCell",
                                        "style": "warning",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "ColumnDefinition[]",
                                                "wrap": true
                                            }
                                        ]
                                    },
                                    {
                                        "type": "TableCell",
                                        "style": "accent",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Defines the table's columns (number of columns, and column sizes).",
                                                "wrap": true
                                            }
                                        ]
                                    }
                                ]
                            },
                            {
                                "type": "TableRow",
                                "cells": [
                                    {
                                        "type": "TableCell",
                                        "style": "good",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "rows",
                                                "wrap": true
                                            }
                                        ]
                                    },
                                    {
                                        "type": "TableCell",
                                        "style": "accent",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "TableRow[]",
                                                "wrap": true
                                            }
                                        ]
                                    },
                                    {
                                        "type": "TableCell",
                                        "style": "attention",
                                        "items": [
                                            {
                                                "type": "TextBlock",
                                                "text": "Defines the rows of the Table, each being a collection of cells. Rows are not required, which allows empty Tables to be generated via templating without breaking the rendering of the whole card.",
                                                "wrap": true
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                ]
            }
        }
    ]
}

then saved it to a file (e.g., /tmp/table-test.json) and delivered it to a Teams channel like so:

#!/bin/bash

webhook_url="https://outlook.office365.com/webhook/a1269812-6d10-44b1-abc5-b84f93580ba0@9e7b80c7-d1eb-4b52-8582-76f921e416d9/IncomingWebhook/3fdd6767bae44ac58e5995547d66a4e4/f332c8d9-3397-4ac5-957b-b8e3fc465a8c"

curl \
    -X POST \
    -H "Content-type: application/json" \
    -d @/tmp/table-test.json \
    "${webhook_url}"

It arrived without issue in the specified Teams channel.

I borrowed the sample webhook connector URL for illustration purposes.

No estimates for implementation, but at least we know that feature is now supported by incoming webhook connectors.

atc0005 added a commit that referenced this issue Mar 14, 2023
Based on current documentation and brief testing, schema
version 1.5 appears to now be supported by Teams Incoming Webhook
Connectors.

refs GH-205
@atc0005
Copy link
Owner

atc0005 commented Mar 15, 2023

It looks like schema 1.5 is officially supported:

https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-reference

Using https://adaptivecards.io/designer/, I selected "Target version" of 1.5 and "host app" of Microsoft Teams and got this warning:

[Warning] The selected Target Version (1.5) is greater than the version supported by Microsoft Teams (1.4)

as shown here:

image

Not sure if receiving the generated table in my testing yesterday was a fluke (possible), or if the Adaptive Cards Designer warning logic is outdated (more likely?).

Probably best to assume that the warning logic is outdated for now based on the initial test results.


EDIT:

I ran into the same thing back when the adaptivecard package was first created:

@atc0005 atc0005 added the enhancement New feature or request label Mar 15, 2023
@atc0005 atc0005 added this to the Future milestone Mar 15, 2023
@atc0005
Copy link
Owner

atc0005 commented Mar 16, 2023

The more I look into this, the more this is beginning to look like a v3 feature. The earlier design (mistakenly?) attempted to simplify logic by heavily extending the "base" adaptivecard.Elements type to cover Adaptive Card elements that were listed as supported at that time:

  • ActionSet
  • ColumnSet
  • Container
  • FactSet
  • Image
  • ImageSet
  • Input.ChoiceSet
  • Input.Date
  • Input.Number
  • Input.Text
  • Input.Time
  • Input.Toggle
  • Media
  • RichTextBlock
  • Table
  • TextBlock

By incorporating (shoehorning?) fields for those Adaptive Card elements into the adaptivecard.Elements type to "keep things simple", we're now faced with the challenge of how to go about doing the same for the Table element. One of the properties for that element type is columns. There is already a field in the adaptivecard.Elements type with that name associated with the adaptivecard.ColumnSet type:

// Columns is a collection of Columns used to divide a region. This field
// is used by a ColumnSet element type.
Columns []Column `json:"columns,omitempty"`

While we could name the new adaptivecard.Elements field TableColumns, the columns JSON property name for the Table Adaptive Card element conflicts with the existing columns property associated with the adaptivecard.ColumnSet type.

Going to work with this further, but this is not encouraging.

@atc0005
Copy link
Owner

atc0005 commented Mar 17, 2023

Follow-up:

I dug further and found a way to do this. It's not exactly ideal, but should work with the current library design. I've got a lot on my plate right now, so it may be some time before the first alpha release is available to test the new support.

@atc0005 atc0005 self-assigned this Mar 17, 2023
@atc0005 atc0005 modified the milestones: Future, v2.8.0 Mar 17, 2023
@atc0005 atc0005 added the card format/adaptivecard Adaptive Card support label Mar 21, 2023
atc0005 added a commit that referenced this issue Mar 28, 2023
OVERVIEW

Add early implementation of Adaptive Card Table support.

CHANGES

- Expand base/shared Element type with fields specific to the
  Table type
- Refresh documentation for Column type to note that it serves a
  dual role
  - member of a ColumnSet
  - member of a Table (TableColumnDefinition)
- Add new types specific to tables
- Examples
  - add example of manually creating a table
  - add example of creating a table with headers
  - add example of creating a table of unordered "grid" values
- README
  - Add references to new examples
  - Add Table element documentation reference

LIMITATIONS

Support for Adaptive Card Table elements is new. There are likely
sharp edges and missing support. Feedback is welcome.

REFERENCES

- refs GH-205
- https://adaptivecards.io/explorer/Table.html
@atc0005
Copy link
Owner

atc0005 commented Mar 28, 2023

@chandrakanthkannam

Initial support is available for preview: #220.

Examples are available.

Pending no significant issues being found, I hope to merge it and tag as an alpha release in the weeks ahead. Feedback is welcome.

@atc0005
Copy link
Owner

atc0005 commented Apr 10, 2023

@chandrakanthkannam

Initial support is available for preview: #220.

Examples are available.

Pending no significant issues being found, I hope to merge it and tag as an alpha release in the weeks ahead. Feedback is welcome.

Hi @chandrakanthkannam,

Any feedback regarding the initial support provided by #220?

@atc0005
Copy link
Owner

atc0005 commented Jun 9, 2023

No feedback received.

Will proceed with merging the initial supported added by #220.

atc0005 added a commit that referenced this issue Jun 9, 2023
OVERVIEW

Add early implementation of Adaptive Card Table support.

CHANGES

- Expand base/shared Element type with fields specific to the
  Table type
- Refresh documentation for Column type to note that it serves a
  dual role
  - member of a ColumnSet
  - member of a Table (TableColumnDefinition)
- Add new types specific to tables
- Examples
  - add example of manually creating a table
  - add example of creating a table with headers
  - add example of creating a table of unordered "grid" values
- README
  - Add references to new examples
  - Add Table element documentation reference

LIMITATIONS

Support for Adaptive Card Table elements is new. There are likely
sharp edges and missing support. Feedback is welcome.

REFERENCES

- refs GH-205
- https://adaptivecards.io/explorer/Table.html
@atc0005
Copy link
Owner

atc0005 commented Jul 21, 2023

No feedback received thus far.

Going ahead with releasing the changes in the next stable release. We can further refine the implementation based on any future feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
card format/adaptivecard Adaptive Card support enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants