Skip to content

Commit cbd7366

Browse files
committed
AdaptiveCardHost - Added "context" property
1 parent 109eba8 commit cbd7366

File tree

5 files changed

+64
-18
lines changed

5 files changed

+64
-18
lines changed

docs/documentation/docs/controls/AdaptiveCardHost.md

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,19 @@ Three custom themes have been created for Microsoft Teams to emulate the colors
1111

1212
All Elements and Actions of Adaptive Cards have been redefined using Fluent UI React, both for SharePoint and Microsoft Teams (in this case the "Fluent UI Northstar" library is not used), adding and improving features that are not managed in Microsoft's implementation of the "adaptivecards-fluentui" library (Theme support for example).
1313

14+
Thanks to the "context" property that allows you to pass the SPFx context, whether the "data" property is passed or not, a new field called @context will be injected into the data object.
15+
16+
This allows, using Adaptive Cards templating syntax, to access to the context informations using the following fields (for more information on these fields, refer to the [BaseComponentContext](https://docs.microsoft.com/en-us/javascript/api/sp-component-base/basecomponentcontext) class):
17+
- "aadInfo": property "aadInfo" of the SPFx context object.
18+
- "cultureInfo": "cultureInfo" property of the SPFx context object.
19+
- "legacyPageContext": "legacyPageContext" property of the SPFx context object.
20+
- "list": property "list" of the SPFx context object.
21+
- "listItem": property "listItem" of the SPFx context object.
22+
- "site": property "site" of the SPFx context object.
23+
- "user": "user" property of the SPFx context object.
24+
- "web": "web" property of the SPFx context object.
25+
- "theme": property "theme" from the current theme applied to the card.
26+
1427
The Adaptive Cards version supported is 1.5, by using the 'adaptivecards' npm package version 2.10.0.
1528

1629
Here is an example of the control in action inside a Web Part:
@@ -32,17 +45,18 @@ import { AdaptiveCardHost, IAdaptiveCardHostActionResult, AdaptiveCardHostThemeT
3245

3346
- Example on use the `AdaptiveCardHost` control with only required properties:
3447

35-
```TSX
48+
```TypeScript
3649
<AdaptiveCardHost
3750
card={card}
3851
onInvokeAction={(action) => alert(JSON.stringify(action))}
3952
onError={(error) => alert(error.message)}
53+
context={this.props.context}
4054
/>
4155
```
4256

4357
- Example on use the `AdaptiveCardHost` control with all properties:
4458

45-
```TSX
59+
```TypeScript
4660
<AdaptiveCardHost
4761
card={card}
4862
data={data}
@@ -63,62 +77,68 @@ import { AdaptiveCardHost, IAdaptiveCardHostActionResult, AdaptiveCardHostThemeT
6377
hostCapabilities.setCustomProperty("CustomPropertyName", Date.now);
6478
}}
6579
isUniqueControlInPage={true}
80+
context={this.props.context}
6681
/>
6782
```
6883

6984
- Example on use the `AdaptiveCardHost` control with SharePoint Theme:
7085

71-
```TSX
86+
```TypeScript
7287
<AdaptiveCardHost
7388
card={card}
7489
themeType={AdaptiveCardHostThemeType.SharePoint}
7590
onInvokeAction={(action) => alert(JSON.stringify(action))}
7691
onError={(error) => alert(error.message)}
92+
context={this.props.context}
7793
/>
7894
```
7995

8096
- Example on use the `AdaptiveCardHost` control with SharePoint Theme "Section Variation" ('this.props.theme' is the theme that come from the Web Part) */):
8197

82-
```TSX
98+
```TypeScript
8399
<AdaptiveCardHost
84100
card={card}
85101
theme={this.props.theme}
86102
themeType={AdaptiveCardHostThemeType.SharePoint}
87103
onInvokeAction={(action) => alert(JSON.stringify(action))}
88104
onError={(error) => alert(error.message)}
105+
context={this.props.context}
89106
/>
90107
```
91108

92109
- Example on use the `AdaptiveCardHost` control with Teams "Default" Theme:
93110

94-
```TSX
111+
```TypeScript
95112
<AdaptiveCardHost
96113
card={card}
97114
themeType={AdaptiveCardHostThemeType.Teams}
98115
onInvokeAction={(action) => alert(JSON.stringify(action))}
99116
onError={(error) => alert(error.message)}
117+
context={this.props.context}
100118
/>
101119
```
102120

103121
- Example on use the `AdaptiveCardHost` control with Teams "Dark" Theme:
104122

105-
```TSX
123+
```TypeScript
106124
<AdaptiveCardHost
107125
card={card}
108126
themeType={AdaptiveCardHostThemeType.TeamsDark}
109127
onInvokeAction={(action) => alert(JSON.stringify(action))}
110128
onError={(error) => alert(error.message)}
129+
context={this.props.context}
111130
/>
112131
```
113132

114133
- Example on use the `AdaptiveCardHost` control with Teams "High Contrast" Theme:
115134

116-
```TSX
135+
```TypeScript
117136
<AdaptiveCardHost
118137
card={card}
119138
themeType={AdaptiveCardHostThemeType.TeamsHighContrast}
120139
onInvokeAction={(action) => alert(JSON.stringify(action))}
121140
onError={(error) => alert(error.message)}
141+
context={this.props.context}
122142
/>
123143
```
124144

@@ -141,6 +161,7 @@ The `AdaptiveCardHost` control can be configured with the following properties:
141161
| onSetCustomActions | (registry: CardObjectRegistry<Action>) => void | no | Invoked to manage Actions to the current Adaptive Card instance. |
142162
| onUpdateHostCapabilities | (hostCapabilities: HostCapabilities) => void | no | Invoked to manage the HostCapabilities object like add custom properties. |
143163
| isUniqueControlInPage | boolean | no | Set to true if you want to use only one instance of this control per page, false for multiple controls. This affects how CSS variables are set. |
164+
| context | BaseComponentContext | yes | Set the context from SPFx component. |
144165

145166
Interface `IAdaptiveCardHostActionResult`
146167

src/controls/adaptiveCardHost/AdaptiveCardHost.tsx

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
useRef
1313
} from 'react';
1414
import './AdaptiveCardHost.css';
15-
import { convertFromPartialThemeToTheme, createDarkTeamsHostConfig, createDefaultTeamsHostConfig, createHighContrastTeamsHostConfig, createSharePointHostConfig, initProcessMarkdown, setFluentUIThemeAsCSSVariables } from './AdaptiveCardHostHelpers';
15+
import { convertFromPartialThemeToTheme, createDarkTeamsHostConfig, createDefaultTeamsHostConfig, createHighContrastTeamsHostConfig, createSharePointHostConfig, initProcessMarkdown, injectContextProperty, setFluentUIThemeAsCSSVariables } from './AdaptiveCardHostHelpers';
1616
import { createDarkTeamsTheme, createDefaultTeamsTheme, createHighContrastTeamsTheme, getDefaultFluentUITheme, setFluentUIThemeAsHostCapability, useLocalFluentUI } from './fluentUI';
1717
import { AdaptiveCardHostThemeType, IAdaptiveCardHostActionResult, IAdaptiveCardHostProps } from './IAdaptiveCardHostProps';
1818

@@ -201,14 +201,9 @@ export const AdaptiveCardHost = (props: IAdaptiveCardHostProps) => {
201201

202202
let currentAdaptiveCard = adaptiveCardInstanceRef.current;
203203
try {
204-
let cardPayload;
205-
if (props.data) {
206-
let template = new Template(props.card);
207-
cardPayload = template.expand(props.data);
208-
}
209-
else {
210-
cardPayload = props.card;
211-
}
204+
let template = new Template(props.card);
205+
let evaluationContext = injectContextProperty(props.data, fluentUIThemeInstanceRef.current, props.context);
206+
let cardPayload = template.expand(evaluationContext);
212207

213208
currentAdaptiveCard.parse(cardPayload, serializationContextInstanceRef.current);
214209

@@ -232,4 +227,4 @@ export const AdaptiveCardHost = (props: IAdaptiveCardHostProps) => {
232227
/>
233228
</ThemeProvider>
234229
);
235-
};
230+
};

src/controls/adaptiveCardHost/AdaptiveCardHostHelpers.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { LocalizedFontFamilies } from '@fluentui/theme/lib/fonts';
22
import { mergeThemes } from '@fluentui/theme/lib/mergeThemes';
3-
import { IReadonlyTheme } from '@microsoft/sp-component-base';
3+
import { BaseComponentContext, IReadonlyTheme } from '@microsoft/sp-component-base';
44
import { ActionAlignment, AdaptiveCard, TextColor, TextWeight } from 'adaptivecards';
5+
import { IEvaluationContext } from 'adaptivecards-templating/lib/template-engine';
56
import * as markdown from 'markdown-it';
67
import { IPartialTheme, ITheme } from 'office-ui-fabric-react/lib/Styling';
78
import { getDefaultFluentUITheme } from './fluentUI';
@@ -1024,4 +1025,27 @@ const setCSSVariables = (domElement: HTMLElement, prefix: string, obj: any) => {
10241025
domElement.style.setProperty(`--${prefix}-${key}`, obj[key]);
10251026
});
10261027
}
1028+
};
1029+
1030+
export const injectContextProperty = (dataObject: { "$root": object }, theme: ITheme, spfxContext: BaseComponentContext): IEvaluationContext => {
1031+
let evaluationContext: IEvaluationContext;
1032+
let context = {
1033+
theme: theme,
1034+
aadInfo: (spfxContext?.pageContext?.aadInfo) ? JSON.parse(JSON.stringify(spfxContext?.pageContext?.aadInfo)) : undefined,
1035+
cultureInfo: (spfxContext?.pageContext?.cultureInfo) ? JSON.parse(JSON.stringify(spfxContext?.pageContext?.cultureInfo)) : undefined,
1036+
legacyPageContext: (spfxContext?.pageContext?.legacyPageContext) ? JSON.parse(JSON.stringify(spfxContext?.pageContext?.legacyPageContext)) : undefined,
1037+
list: (spfxContext?.pageContext?.list) ? JSON.parse(JSON.stringify(spfxContext?.pageContext?.list)) : undefined,
1038+
listItem: (spfxContext?.pageContext?.listItem) ? JSON.parse(JSON.stringify(spfxContext?.pageContext?.listItem)) : undefined,
1039+
site: (spfxContext?.pageContext?.site) ? JSON.parse(JSON.stringify(spfxContext?.pageContext?.site)) : undefined,
1040+
user: (spfxContext?.pageContext?.user) ? JSON.parse(JSON.stringify(spfxContext?.pageContext?.user)) : undefined,
1041+
web: (spfxContext?.pageContext?.web) ? JSON.parse(JSON.stringify(spfxContext?.pageContext?.web)) : undefined
1042+
};
1043+
1044+
if (dataObject) {
1045+
evaluationContext = { $root: { ...dataObject?.$root, "@context": context } };
1046+
} else {
1047+
evaluationContext = { $root: { "@context": context } };
1048+
}
1049+
1050+
return evaluationContext;
10271051
};

src/controls/adaptiveCardHost/IAdaptiveCardHostProps.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { BaseComponentContext } from '@microsoft/sp-component-base';
12
import { Action, CardElement, CardObjectRegistry, HostCapabilities } from 'adaptivecards';
23
import { IPartialTheme, ITheme } from 'office-ui-fabric-react/lib/Styling';
34

@@ -77,6 +78,10 @@ export interface IAdaptiveCardHostProps {
7778
* Set to true if you want to use only one instance of this control per page, false for multiple controls. This affects how CSS variables are set.
7879
*/
7980
isUniqueControlInPage?: boolean;
81+
/**
82+
* Set the context from SPFx component.
83+
*/
84+
context: BaseComponentContext;
8085
}
8186

8287
export enum AdaptiveCardHostThemeType {

src/webparts/controlsTest/components/ControlsTest.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2244,6 +2244,7 @@ export default class ControlsTest extends React.Component<IControlsTestProps, IC
22442244
onInvokeAction={(action: IAdaptiveCardHostActionResult) => { alert(JSON.stringify(action)); }}
22452245
onError={(error: Error) => { alert(error.message); }}
22462246
isUniqueControlInPage={true}
2247+
context={this.props.context}
22472248
/>
22482249
</div>
22492250

0 commit comments

Comments
 (0)