From 26e1859ce319c60ed2cbbd57cbd5072006efe828 Mon Sep 17 00:00:00 2001 From: Marcin Wojciechowski Date: Thu, 5 May 2022 10:58:49 +0200 Subject: [PATCH] added sample for ACE --- samples/react-graph-auto-batching/.yo-rc.json | 5 +- .../config/config.json | 11 ++- .../package-lock.json | 15 ++++ .../react-graph-auto-batching/package.json | 3 +- ...ileCardAdaptiveCardExtension.manifest.json | 29 +++++++ .../ProfileCardAdaptiveCardExtension.ts | 81 +++++++++++++++++++ .../profileCard/ProfileCardPropertyPane.ts | 34 ++++++++ .../profileCard/assets/SharePointLogo.svg | 8 ++ .../profileCard/cardView/CardView.ts | 26 ++++++ .../profileCard/loc/en-us.js | 14 ++++ .../profileCard/loc/mystring.d.ts | 17 ++++ .../profileCard/quickView/QuickView.ts | 27 +++++++ .../quickView/template/QuickViewTemplate.json | 33 ++++++++ .../graphAutoBatching/components/UserCard.tsx | 2 +- 14 files changed, 300 insertions(+), 5 deletions(-) create mode 100644 samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/ProfileCardAdaptiveCardExtension.manifest.json create mode 100644 samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/ProfileCardAdaptiveCardExtension.ts create mode 100644 samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/ProfileCardPropertyPane.ts create mode 100644 samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/assets/SharePointLogo.svg create mode 100644 samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/cardView/CardView.ts create mode 100644 samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/loc/en-us.js create mode 100644 samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/loc/mystring.d.ts create mode 100644 samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/quickView/QuickView.ts create mode 100644 samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/quickView/template/QuickViewTemplate.json diff --git a/samples/react-graph-auto-batching/.yo-rc.json b/samples/react-graph-auto-batching/.yo-rc.json index f1ac25fbf..bbe4735fa 100644 --- a/samples/react-graph-auto-batching/.yo-rc.json +++ b/samples/react-graph-auto-batching/.yo-rc.json @@ -5,9 +5,10 @@ "libraryId": "03631505-3899-4de0-bebe-f59283d991ba", "environment": "spo", "packageManager": "npm", - "isCreatingSolution": true, + "isCreatingSolution": false, "plusBeta": true, "isDomainIsolated": false, - "componentType": "webpart" + "componentType": "adaptiveCardExtension", + "templateType": "Image" } } \ No newline at end of file diff --git a/samples/react-graph-auto-batching/config/config.json b/samples/react-graph-auto-batching/config/config.json index ffe9fdcbd..f6b0fc749 100644 --- a/samples/react-graph-auto-batching/config/config.json +++ b/samples/react-graph-auto-batching/config/config.json @@ -9,10 +9,19 @@ "manifest": "./src/webparts/graphAutoBatching/GraphAutoBatchingWebPart.manifest.json" } ] + }, + "profile-card-adaptive-card-extension": { + "components": [ + { + "entrypoint": "./lib/adaptiveCardExtensions/profileCard/ProfileCardAdaptiveCardExtension.js", + "manifest": "./src/adaptiveCardExtensions/profileCard/ProfileCardAdaptiveCardExtension.manifest.json" + } + ] } }, "externals": {}, "localizedResources": { - "GraphAutoBatchingWebPartStrings": "lib/webparts/graphAutoBatching/loc/{locale}.js" + "GraphAutoBatchingWebPartStrings": "lib/webparts/graphAutoBatching/loc/{locale}.js", + "ProfileCardAdaptiveCardExtensionStrings": "lib/adaptiveCardExtensions/profileCard/loc/{locale}.js" } } diff --git a/samples/react-graph-auto-batching/package-lock.json b/samples/react-graph-auto-batching/package-lock.json index b8c0e3cca..c1ddacfcc 100644 --- a/samples/react-graph-auto-batching/package-lock.json +++ b/samples/react-graph-auto-batching/package-lock.json @@ -2466,6 +2466,21 @@ "typescript": "~3.7.2" } }, + "@microsoft/sp-adaptive-card-extension-base": { + "version": "1.13.0-beta.17", + "resolved": "https://registry.npmjs.org/@microsoft/sp-adaptive-card-extension-base/-/sp-adaptive-card-extension-base-1.13.0-beta.17.tgz", + "integrity": "sha512-7dN6fMG1WMPptPnhrsKo/cCZIBSWt9ypEfr80aatwT+DSrnezi4aZgz4gQZ1sQc2KdEjpeoikQRajZlnM6/zUg==", + "requires": { + "@microsoft/sp-component-base": "1.13.0-beta.17", + "@microsoft/sp-core-library": "1.13.0-beta.17", + "@microsoft/sp-diagnostics": "1.13.0-beta.17", + "@microsoft/sp-loader": "1.13.0-beta.17", + "@microsoft/sp-lodash-subset": "1.13.0-beta.17", + "@microsoft/sp-module-interfaces": "1.13.0-beta.17", + "@microsoft/sp-property-pane": "1.13.0-beta.17", + "tslib": "~1.10.0" + } + }, "@microsoft/sp-build-core-tasks": { "version": "1.13.0-beta.17", "resolved": "https://registry.npmjs.org/@microsoft/sp-build-core-tasks/-/sp-build-core-tasks-1.13.0-beta.17.tgz", diff --git a/samples/react-graph-auto-batching/package.json b/samples/react-graph-auto-batching/package.json index 8b6b5d855..d70e57c17 100644 --- a/samples/react-graph-auto-batching/package.json +++ b/samples/react-graph-auto-batching/package.json @@ -16,7 +16,8 @@ "@microsoft/sp-property-pane": "1.13.0-beta.17", "@microsoft/sp-webpart-base": "1.13.0-beta.17", "@microsoft/sp-lodash-subset": "1.13.0-beta.17", - "@microsoft/sp-office-ui-fabric-core": "1.13.0-beta.17" + "@microsoft/sp-office-ui-fabric-core": "1.13.0-beta.17", + "@microsoft/sp-adaptive-card-extension-base": "1.13.0-beta.17" }, "devDependencies": { "@microsoft/rush-stack-compiler-3.7": "0.2.3", diff --git a/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/ProfileCardAdaptiveCardExtension.manifest.json b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/ProfileCardAdaptiveCardExtension.manifest.json new file mode 100644 index 000000000..185555755 --- /dev/null +++ b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/ProfileCardAdaptiveCardExtension.manifest.json @@ -0,0 +1,29 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json", + "id": "f8630005-04bf-4a6f-a91b-26578106f9a5", + "alias": "ProfileCardAdaptiveCardExtension", + "componentType": "AdaptiveCardExtension", + + // The "*" signifies that the version should be taken from the package.json + "version": "*", + "manifestVersion": 2, + + // If true, the component can only be installed on sites where Custom Script is allowed. + // Components that allow authors to embed arbitrary script code should set this to true. + // https://support.office.com/en-us/article/Turn-scripting-capabilities-on-or-off-1f2c515f-5d7e-448a-9fd7-835da935584f + "requiresCustomScript": false, + "supportedHosts": ["Dashboard", "SharePointWebPart"], + + "preconfiguredEntries": [{ + "groupId": "bd067b1e-3ad5-4d5d-a5fe-505f07d7f59c", // Dashboard + "group": { "default": "Dashboard" }, + "title": { "default": "ProfileCard" }, + "description": { "default": "ProfileCard description" }, + "officeFabricIconFontName": "SharePointLogo", + "properties": { + "title": "ProfileCard", + "description": "ProfileCard description", + "iconProperty": "" // Default to sharepointlogo + } + }] +} \ No newline at end of file diff --git a/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/ProfileCardAdaptiveCardExtension.ts b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/ProfileCardAdaptiveCardExtension.ts new file mode 100644 index 000000000..21fb27abf --- /dev/null +++ b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/ProfileCardAdaptiveCardExtension.ts @@ -0,0 +1,81 @@ +import { IPropertyPaneConfiguration } from '@microsoft/sp-property-pane'; +import { BaseAdaptiveCardExtension } from '@microsoft/sp-adaptive-card-extension-base'; +import { CardView } from './cardView/CardView'; +import { QuickView } from './quickView/QuickView'; +import { ProfileCardPropertyPane } from './ProfileCardPropertyPane'; +import { BatchGraphClient } from '../../dal/http/BatchGraphClient'; +import { SPFxHttpClient } from '../../dal/http/SPFxHttpClient'; +import { IHttpClient } from '../../dal/http/IHttpClient'; +import { StringUtilities } from '../../utils/StringUtilities'; + +export interface IProfileCardAdaptiveCardExtensionProps { + title: string; + description: string; + iconProperty: string; + userId: string; +} + +export interface IProfileCardAdaptiveCardExtensionState { + user: any; + userPresence: any; + photo: string; +} + +const CARD_VIEW_REGISTRY_ID: string = 'ProfileCard_CARD_VIEW'; +export const QUICK_VIEW_REGISTRY_ID: string = 'ProfileCard_QUICK_VIEW'; + +export default class ProfileCardAdaptiveCardExtension extends BaseAdaptiveCardExtension< + IProfileCardAdaptiveCardExtensionProps, + IProfileCardAdaptiveCardExtensionState +> { + private _deferredPropertyPane: ProfileCardPropertyPane | undefined; + private httpClient: IHttpClient; + public async onInit(): Promise { + let client = await this.context.aadHttpClientFactory.getClient('https://graph.microsoft.com'); + this.httpClient = new BatchGraphClient(new SPFxHttpClient(client)); + let userQuery = this.properties.userId ? `/users/${this.properties.userId}` : "/me" + const [userInfoRequest, userPhotoRequest, presenceInfo] = await Promise.all([this.httpClient.get(userQuery), + this.httpClient.get(userQuery+ "/photo/$value"), + this.httpClient.get(userQuery+ "/presence")]); + const [userResult, photo, presence] = await Promise.all([userInfoRequest.json(), userPhotoRequest.text(),presenceInfo.json()]); + + this.state = { + user: userResult, + userPresence: presence.availability, + photo: `data:image/png;base64,${photo.replace("\"","").replace("\"","")}` + }; + + this.cardNavigator.register(CARD_VIEW_REGISTRY_ID, () => new CardView()); + this.quickViewNavigator.register(QUICK_VIEW_REGISTRY_ID, () => new QuickView()); + + return Promise.resolve(); + } + + public get title(): string { + return this.state?.user?.displayName || ""; + } + + protected get iconProperty(): string { + return this.properties.iconProperty || require('./assets/SharePointLogo.svg'); + } + + protected loadPropertyPaneResources(): Promise { + return import( + /* webpackChunkName: 'ProfileCard-property-pane'*/ + './ProfileCardPropertyPane' + ) + .then( + (component) => { + this._deferredPropertyPane = new component.ProfileCardPropertyPane(); + } + ); + } + + protected renderCard(): string | undefined { + return CARD_VIEW_REGISTRY_ID; + } + + protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { + return this._deferredPropertyPane!.getPropertyPaneConfiguration(); + } +} diff --git a/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/ProfileCardPropertyPane.ts b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/ProfileCardPropertyPane.ts new file mode 100644 index 000000000..91caba35e --- /dev/null +++ b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/ProfileCardPropertyPane.ts @@ -0,0 +1,34 @@ +import { IPropertyPaneConfiguration, PropertyPaneTextField } from '@microsoft/sp-property-pane'; +import * as strings from 'ProfileCardAdaptiveCardExtensionStrings'; + +export class ProfileCardPropertyPane { + public getPropertyPaneConfiguration(): IPropertyPaneConfiguration { + return { + pages: [ + { + header: { description: strings.PropertyPaneDescription }, + groups: [ + { + groupName: strings.BasicGroupName, + groupFields: [ + PropertyPaneTextField('title', { + label: strings.TitleFieldLabel + }), + PropertyPaneTextField('iconProperty', { + label: strings.IconPropertyFieldLabel + }), + PropertyPaneTextField('userId', { + label: "User Id" + }), + PropertyPaneTextField('description', { + label: strings.DescriptionFieldLabel, + multiline: true + }) + ] + } + ] + } + ] + }; + } +} diff --git a/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/assets/SharePointLogo.svg b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/assets/SharePointLogo.svg new file mode 100644 index 000000000..b68c77abe --- /dev/null +++ b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/assets/SharePointLogo.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/cardView/CardView.ts b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/cardView/CardView.ts new file mode 100644 index 000000000..c843d037e --- /dev/null +++ b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/cardView/CardView.ts @@ -0,0 +1,26 @@ +import { + BaseImageCardView, + IImageCardParameters, + IExternalLinkCardAction, + IQuickViewCardAction +} from '@microsoft/sp-adaptive-card-extension-base'; +import * as strings from 'ProfileCardAdaptiveCardExtensionStrings'; +import { IProfileCardAdaptiveCardExtensionProps, IProfileCardAdaptiveCardExtensionState } from '../ProfileCardAdaptiveCardExtension'; + +export class CardView extends BaseImageCardView { + public get data(): IImageCardParameters { + return { + primaryText: this.state.userPresence, + imageUrl: this.state.photo + }; + } + + public get onCardSelection(): IQuickViewCardAction | IExternalLinkCardAction | undefined { + return { + type: 'ExternalLink', + parameters: { + target: 'https://www.bing.com' + } + }; + } +} diff --git a/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/loc/en-us.js b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/loc/en-us.js new file mode 100644 index 000000000..7e8046f7f --- /dev/null +++ b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/loc/en-us.js @@ -0,0 +1,14 @@ +define([], function() { + return { + "PropertyPaneDescription": "Description", + "BasicGroupName": "Group Name", + "DescriptionFieldLabel": "Description Field", + "TitleFieldLabel": "Card Title", + "IconPropertyFieldLabel": "Card Icon", + "Title": "Adaptive Card Extension", + "SubTitle": "Quick View", + "Description": "Create your SPFx Adaptive Card Extension solution!", + "PrimaryText": "SPFx Adaptive Card Extension", + "QuickViewButton": "Quick View" + } +}); \ No newline at end of file diff --git a/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/loc/mystring.d.ts b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/loc/mystring.d.ts new file mode 100644 index 000000000..59530cece --- /dev/null +++ b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/loc/mystring.d.ts @@ -0,0 +1,17 @@ +declare interface IProfileCardAdaptiveCardExtensionStrings { + PropertyPaneDescription: string; + BasicGroupName: string; + DescriptionFieldLabel: string; + TitleFieldLabel: string; + IconPropertyFieldLabel: string; + Title: string; + SubTitle: string; + Description: string; + PrimaryText: string; + QuickViewButton: string; +} + +declare module 'ProfileCardAdaptiveCardExtensionStrings' { + const strings: IProfileCardAdaptiveCardExtensionStrings; + export = strings; +} diff --git a/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/quickView/QuickView.ts b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/quickView/QuickView.ts new file mode 100644 index 000000000..cb62a3905 --- /dev/null +++ b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/quickView/QuickView.ts @@ -0,0 +1,27 @@ +import { ISPFxAdaptiveCard, BaseAdaptiveCardView } from '@microsoft/sp-adaptive-card-extension-base'; +import * as strings from 'ProfileCardAdaptiveCardExtensionStrings'; +import { IProfileCardAdaptiveCardExtensionProps, IProfileCardAdaptiveCardExtensionState } from '../ProfileCardAdaptiveCardExtension'; + +export interface IQuickViewData { + subTitle: string; + title: string; + description: string; +} + +export class QuickView extends BaseAdaptiveCardView< + IProfileCardAdaptiveCardExtensionProps, + IProfileCardAdaptiveCardExtensionState, + IQuickViewData +> { + public get data(): IQuickViewData { + return { + subTitle: strings.SubTitle, + title: strings.Title, + description: this.properties.description + }; + } + + public get template(): ISPFxAdaptiveCard { + return require('./template/QuickViewTemplate.json'); + } +} \ No newline at end of file diff --git a/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/quickView/template/QuickViewTemplate.json b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/quickView/template/QuickViewTemplate.json new file mode 100644 index 000000000..09f12237b --- /dev/null +++ b/samples/react-graph-auto-batching/src/adaptiveCardExtensions/profileCard/quickView/template/QuickViewTemplate.json @@ -0,0 +1,33 @@ +{ + "schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "type": "AdaptiveCard", + "version": "1.2", + "body": [ + { + "type": "TextBlock", + "weight": "Bolder", + "text": "${title}" + }, + { + "type": "ColumnSet", + "columns": [ + { + "type": "Column", + "items": [ + { + "type": "TextBlock", + "weight": "Bolder", + "text": "${subTitle}", + "wrap": true + } + ] + } + ] + }, + { + "type": "TextBlock", + "text": "${description}", + "wrap": true + } + ] +} \ No newline at end of file diff --git a/samples/react-graph-auto-batching/src/webparts/graphAutoBatching/components/UserCard.tsx b/samples/react-graph-auto-batching/src/webparts/graphAutoBatching/components/UserCard.tsx index dd9a729dd..5f1ddf3cf 100644 --- a/samples/react-graph-auto-batching/src/webparts/graphAutoBatching/components/UserCard.tsx +++ b/samples/react-graph-auto-batching/src/webparts/graphAutoBatching/components/UserCard.tsx @@ -20,7 +20,7 @@ export function UserCard(props: IUserCardProps){ setUser({ ...userResult, presence: presence.availability, - photo: photo.replace("\"","").replace("\"","") + photo: `data:image/png;base64,${photo.replace("\"","").replace("\"","")}` }); setLoading(false); };