diff --git a/CHANGELOG.md b/CHANGELOG.md index a446f21b74..0e3e87b61a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Resolves [#4316](https://github.com/microsoft/BotFramework-WebChat/issues/4316). Using [ESBuild](https://esbuild.github.io/) as development server, by [@compulim](https://github.com/compulim), in PR [#4330](https://github.com/microsoft/BotFramework-WebChat/issues/4330) +### Samples + +- Added [`01.getting-started/l.sharepoint-web-part`](../../samples/01.getting-started/l.sharepoint-web-part) for hosting Web Chat as a SharePoint web part, in PR [#4385](https://github.com/microsoft/BotFramework-WebChat/pull/4385), by [@compulim](https://github.com/compulim) + ## [4.15.2] - 2022-05-09 ### Breaking changes diff --git a/samples/01.getting-started/l.sharepoint-web-part/Dockerfile b/samples/01.getting-started/l.sharepoint-web-part/Dockerfile new file mode 100644 index 0000000000..030fac8308 --- /dev/null +++ b/samples/01.getting-started/l.sharepoint-web-part/Dockerfile @@ -0,0 +1,37 @@ +# Setting to a different base image to secure your container supply chain. +ARG REGISTRY=docker.io +ARG BASE_IMAGE=$REGISTRY/node:16 + +FROM $BASE_IMAGE + +EXPOSE 54321 35729 + +RUN npm install --location=global gulp@4 yo @microsoft/generator-sharepoint@1.15.0 + +RUN useradd --create-home --shell /bin/bash spfx && \ + usermod -aG sudo spfx && \ + mkdir -p /usr/app/spfx/ && \ + chown -R spfx:spfx /usr/app && \ + cd /usr/app/spfx +USER spfx + +RUN mkdir -p /usr/app/spfx/ + +WORKDIR /usr/app/ +RUN yo @microsoft/sharepoint --no-insight --skip-install --component-type webpart --component-name WebChat --framework react --solution-name spfx + +WORKDIR /usr/app/spfx/ +RUN npm install --save-dev concurrently http-proxy-middleware selfsigned +RUN gulp trust-dev-cert +ADD src/proxy.js /usr/app/spfx/proxy.js + +# Due to some problems in esbuild@0.12.15, either; +# 1. It has to be installed before botframework-webchat, or; +# 2. Install botframework-webchat, it will fail, then install again will succeed +RUN npm install esbuild@0.12.15 + +RUN npm install botframework-webchat + +ADD --chown=spfx:spfx src/spfx/src/webparts/webChat /usr/app/spfx/src/webparts/webChat + +ENTRYPOINT npx concurrently "node proxy" "gulp serve --nobrowser" diff --git a/samples/01.getting-started/l.sharepoint-web-part/README.md b/samples/01.getting-started/l.sharepoint-web-part/README.md new file mode 100644 index 0000000000..d00b48a455 --- /dev/null +++ b/samples/01.getting-started/l.sharepoint-web-part/README.md @@ -0,0 +1,296 @@ +# Sample - Hosting on SharePoint as web part using React template + +A simple SharePoint web part using React template hosting Web Chat from NPM. The SharePoint Framework (SPFx) development environment is hosted under Docker. + +![Web Chat hosted inside SharePoint workbench showing a weather card](./webchat-sharepoint-web-part.png) + +# How to run locally + +> Note: Please install Docker before running the following steps. + +- Fork this repository +- Navigate to `/Your-Local-WebChat/samples/01.getting-started/l.sharepoint-web-part` in command line +- Run `npm run build` +- Run `npm start` +- Browse to [https://localhost:4321/temp/manifests.js](https://localhost:4321/temp/manifests.js) and trust the self-signed certificate + - When the browser show "Your connection isn't private" page, type `thisisunsafe` on your keyboard + - It should load the JavaScript file +- Browse to https://<your-sharepoint>.sharepoint.com/sites/<your-site>/\_layouts/15/workbench.aspx +- Add web part +- Select "Web Chat" +- Click the "Edit" button next to Web Chat +- In the properties panel, put your Direct Line token to the "Token" field +- Refresh the page + +> It is **never recommended** to put the Direct Line secret in the browser or client app. To learn more about secrets and tokens for Direct Line, visit [this tutorial on authentication](https://docs.microsoft.com/en-us/azure/bot-service/rest-api/bot-framework-rest-direct-line-3-0-authentication). + +# Things to try out + +- Type `help`: you should see a full list of MockBot features +- Type `markdown`: you should see the sample of Markdown +- Type `card weather`: you should see a weather card built using Adaptive Cards +- Type `layout carousel`: you should see a carousel of cards + - Resize the window and see how the carousel changes size + +# Code + +> Jump to [completed code](#completed-code) to see the end-result. + +## Getting started + +This code host a full-feature Web Chat as a SharePoint web part using React template. Web Chat will be installed through NPM with all customization options available. + +### Preparation + +SPFx is hosted in Docker to enable cloud development. The `Dockerfile` will do the followings to prepare the development environment: + +1. Download [`gulp@4`](https://npmjs.com/package/gulp), [`yo` (Yeoman)](https://yeoman.io/), and [`@microsoft/generator-sharepoint` (SharePoint scaffold)](https://npmjs.com/package/@microsoft/generator-sharepoint) +1. Create a new user account `spfx` (requirement of Yeoman when running under Docker) +1. Create a new directory `/usr/app/spfx/` +1. Run Yeoman with SharePoint scaffold with the following answers + - What is your solution name? `spfx` + - Which type of client-side component to create? `WebPart` + - What is your Web part name? `Web Chat` + - Which template would you like to use? `React` +1. Install tooling [`concurrently`](https://npmjs.com/package/concurrently), [`http-proxy-middleware`](https://npmjs.com/package/http-proxy-middleware) and [`selfsigned`](https://npmjs.com/package/selfsigned) +1. Run `gulp trust-dev-cert` to create a self-signed certificate for Webpack/SPFx development server +1. Copy the reverse proxy + - Webpack/SPFx development server only listen to `https://localhost/` but not `https://0.0.0.0/`, the host of the Docker will not able to access it + - A reverse proxy (`proxy.js`) to proxy requests from `https://0.0.0.0:54321/` to `https://localhost:4321` + - When running the Docker image, port 54321 will be mapped back to 4321 as SharePoint workbench only accept development server from https://localhost:4321/ +1. Install [Web Chat](https://github.com/microsoft/BotFramework-WebChat/) +1. Copy web part code to the container +1. Set the entrypoint to run both reverse proxy and Webpack/SPFx development server (via `gulp serve`) + - `--nobrowser` is added as the Docker image does not have any browsers installed + +When running the Docker image, it will expose: + +- Port 54321, which will proxy to Webpack/SPFx development server at https://localhost:4321/ + - While running `npm start`, this port will be mapped to 4321 via `docker run --publish 4321:54321 ...` + - This port will use a different self-signed certificate +- Port 35729, which will point to LiveReload server + +### Web part code + +These are based on web part sample code from SharePoint scaffold and modified to host Web Chat. + +#### `webparts/webChat/components/IWebChatProps.ts` + +Added two props, `domain` and `token`. + +```diff + export interface IWebChatProps { + description: string; ++ domain: string; + isDarkTheme: boolean; + environmentMessage: string; + hasTeamsContext: boolean; ++ token: string; + userDisplayName: string; + } +``` + +#### `webparts/webChat/components/WebChat.module.scss` + +The stylesheet is being replaced. + +```css +@import '~office-ui-fabric-react/dist/sass/References.scss'; + +.webChat { + height: 800px; + width: 360px; +} +``` + +#### `webparts/webChat/components/WebChat.tsx` + +The component code is being replaced by a React function component. It connects to Direct Line or Direct Line ASE (if `domain` prop is specified). + + +```ts +import { useEffect, useState } from 'react'; +import * as React from 'react'; +import ReactWebChat, { createDirectLine, createDirectLineAppServiceExtension } from 'botframework-webchat'; + +import { IWebChatProps } from './IWebChatProps'; +import styles from './WebChat.module.scss'; + +import type { VFC } from 'react'; + +const WebChat: VFC = ({ domain, token }) => { + const [directLine, setDirectLine] = useState(); + + useEffect(() => { + (async function () { + setDirectLine( + domain ? await createDirectLineAppServiceExtension({ domain, token }) : createDirectLine({ token }) + ); + })(); + }, [setDirectLine]); + + return
{!!directLine && }
; +}; + +export default WebChat; +``` + + +#### `webparts/webChat/loc/en-us.js` + +Added localized strings for new property in the properties panel. + +```diff + define([], function () { + return { + AppLocalEnvironmentSharePoint: 'The app is running on your local environment as SharePoint web part', + AppLocalEnvironmentTeams: 'The app is running on your local environment as Microsoft Teams app', + AppSharePointEnvironment: 'The app is running on SharePoint page', + AppTeamsTabEnvironment: 'The app is running in Microsoft Teams', + BasicGroupName: 'Group Name', + DescriptionFieldLabel: 'Description Field', ++ DomainFieldLabel: 'Domain (for Direct Line ASE)', + PropertyPaneDescription: 'Description', ++ TokenFieldLabel: 'Token' + }; + }); +``` + +#### `webparts/webChat/loc/mystrings.d.ts` + +Added typing for localized strings for new properties. + +```diff + declare interface IWebChatWebPartStrings { + AppLocalEnvironmentSharePoint: string; + AppLocalEnvironmentTeams: string; + AppSharePointEnvironment: string; + AppTeamsTabEnvironment: string; + BasicGroupName: string; + DescriptionFieldLabel: string; ++ DomainFieldLabel: string; + PropertyPaneDescription: string; ++ TokenFieldLabel: string; + } + + declare module 'WebChatWebPartStrings' { + const strings: IWebChatWebPartStrings; + export = strings; + } +``` + +### `webparts/webChat/WebChatWebPart.manifest.json` + +Added default values for new properties. + +```diff + { + "$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json", + ... + "preconfiguredEntries": [ + { + "groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other + "group": { "default": "Other" }, + "title": { "default": "Web Chat" }, + "description": { "default": "Web Chat description" }, + "officeFabricIconFontName": "Page", + "properties": { + "description": "Web Chat", ++ "domain": "", ++ "token": "" + } + } + ] + } +``` + +### `webparts/webChat/WebChatWebPart.ts` + +Added two properties: `domain` and `token`. + +```diff + ... + protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { + return { + pages: [ + { + header: { + description: strings.PropertyPaneDescription + }, + groups: [ + { + groupName: strings.BasicGroupName, + groupFields: [ + PropertyPaneTextField('description', { + label: strings.DescriptionFieldLabel + }), ++ PropertyPaneTextField('domain', { ++ label: strings.DomainFieldLabel ++ }), ++ PropertyPaneTextField('token', { ++ label: strings.TokenFieldLabel ++ }) + ] + } + ] + } + ] + }; + } + ... +``` + +## Completed code + +Here is the finished `Dockerfile`: + +```dockerfile +# Setting to a different base image to secure your container supply chain. +ARG REGISTRY=docker.io +ARG BASE_IMAGE=$REGISTRY/node:16 + +FROM $BASE_IMAGE + +EXPOSE 54321 35729 + +RUN npm install --location=global gulp@4 yo @microsoft/generator-sharepoint@1.15.0 + +RUN useradd --create-home --shell /bin/bash spfx && \ + usermod -aG sudo spfx && \ + mkdir -p /usr/app/spfx/ && \ + chown -R spfx:spfx /usr/app && \ + cd /usr/app/spfx +USER spfx + +RUN mkdir -p /usr/app/spfx/ + +WORKDIR /usr/app/ +RUN yo @microsoft/sharepoint --no-insight --skip-install --component-type webpart --component-name WebChat --framework react --solution-name spfx + +WORKDIR /usr/app/spfx/ +RUN npm install --save-dev concurrently http-proxy-middleware selfsigned +RUN gulp trust-dev-cert +ADD src/proxy.js /usr/app/spfx/proxy.js + +# Due to some problems in esbuild@0.12.15, either; +# 1. It has to be installed before botframework-webchat, or; +# 2. Install botframework-webchat, it will fail, then install again will succeed +RUN npm install esbuild@0.12.15 + +RUN npm install botframework-webchat + +ADD --chown=spfx:spfx src/spfx/src/webparts/webChat /usr/app/spfx/src/webparts/webChat + +ENTRYPOINT npx concurrently "node proxy" "gulp serve --nobrowser" +``` + +# Further reading + +- https://docs.microsoft.com/en-us/sharepoint/dev/spfx/web-parts/get-started/build-a-hello-world-web-part +- https://docs.microsoft.com/en-us/sharepoint/dev/spfx/yeoman-generator-for-spfx-intro +- https://github.com/compulim/experiment-spfx-webchat/ +- https://github.com/pnp/docker-spfx + +## Full list of Web Chat hosted samples + +View the list of [available Web Chat samples](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples) diff --git a/samples/01.getting-started/l.sharepoint-web-part/package.json b/samples/01.getting-started/l.sharepoint-web-part/package.json new file mode 100644 index 0000000000..cad76b0c40 --- /dev/null +++ b/samples/01.getting-started/l.sharepoint-web-part/package.json @@ -0,0 +1,13 @@ +{ + "name": "sample-getting-started-sharepoint-web-part", + "version": "0.0.0-0", + "description": "", + "main": "src/proxy.js", + "scripts": { + "build": "docker build -t spfx .", + "start": "docker run --rm -it -p 4321:54321 -p 35729:35729 spfx" + }, + "author": "Microsoft Corporation", + "license": "MIT", + "type": "module" +} diff --git a/samples/01.getting-started/l.sharepoint-web-part/src/proxy.js b/samples/01.getting-started/l.sharepoint-web-part/src/proxy.js new file mode 100644 index 0000000000..24594535d5 --- /dev/null +++ b/samples/01.getting-started/l.sharepoint-web-part/src/proxy.js @@ -0,0 +1,15 @@ +const { createProxyMiddleware } = require('http-proxy-middleware'); +const { createServer } = require('https'); +const selfSigned = require('selfsigned'); + +const { cert, private: key } = selfSigned.generate([{ name: 'commonName', value: 'localhost:4321' }], { days: 14 }); + +createServer( + { cert, key }, + createProxyMiddleware({ + secure: false, + target: 'https://localhost:4321' + }) +).listen(54321, () => { + console.log('Proxy listening to 54321'); +}); diff --git a/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/WebChatWebPart.manifest.json b/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/WebChatWebPart.manifest.json new file mode 100644 index 0000000000..30120c55ef --- /dev/null +++ b/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/WebChatWebPart.manifest.json @@ -0,0 +1,32 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/spfx/client-side-web-part-manifest.schema.json", + "id": "a72d9f92-2da0-4201-b982-32f3bb8b9a18", + "alias": "WebChatWebPart", + "componentType": "WebPart", + + // 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": ["SharePointWebPart", "TeamsPersonalApp", "TeamsTab", "SharePointFullPage"], + "supportsThemeVariants": true, + + "preconfiguredEntries": [ + { + "groupId": "5c03119e-3074-46fd-976b-c60198311f70", // Other + "group": { "default": "Other" }, + "title": { "default": "Web Chat" }, + "description": { "default": "Web Chat description" }, + "officeFabricIconFontName": "Page", + "properties": { + "description": "Web Chat", + "domain": "", + "token": "" + } + } + ] +} diff --git a/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/WebChatWebPart.ts b/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/WebChatWebPart.ts new file mode 100644 index 0000000000..167b91719c --- /dev/null +++ b/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/WebChatWebPart.ts @@ -0,0 +1,103 @@ +import * as React from 'react'; +import * as ReactDom from 'react-dom'; +import { Version } from '@microsoft/sp-core-library'; +import { IPropertyPaneConfiguration, PropertyPaneTextField } from '@microsoft/sp-property-pane'; +import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base'; +import { IReadonlyTheme } from '@microsoft/sp-component-base'; + +import * as strings from 'WebChatWebPartStrings'; +import WebChat from './components/WebChat'; +import { IWebChatProps } from './components/IWebChatProps'; + +export interface IWebChatWebPartProps { + description: string; + domain: string; + token: string; +} + +export default class WebChatWebPart extends BaseClientSideWebPart { + private _isDarkTheme: boolean = false; + private _environmentMessage: string = ''; + + public render(): void { + const element: React.ReactElement = React.createElement(WebChat, { + description: this.properties.description, + domain: this.properties.domain, + isDarkTheme: this._isDarkTheme, + environmentMessage: this._environmentMessage, + hasTeamsContext: !!this.context.sdks.microsoftTeams, + token: this.properties.token, + userDisplayName: this.context.pageContext.user.displayName + }); + + ReactDom.render(element, this.domElement); + } + + protected onInit(): Promise { + this._environmentMessage = this._getEnvironmentMessage(); + + return super.onInit(); + } + + private _getEnvironmentMessage(): string { + if (!!this.context.sdks.microsoftTeams) { + // running in Teams + return this.context.isServedFromLocalhost ? strings.AppLocalEnvironmentTeams : strings.AppTeamsTabEnvironment; + } + + return this.context.isServedFromLocalhost + ? strings.AppLocalEnvironmentSharePoint + : strings.AppSharePointEnvironment; + } + + protected onThemeChanged(currentTheme: IReadonlyTheme | undefined): void { + if (!currentTheme) { + return; + } + + this._isDarkTheme = !!currentTheme.isInverted; + const { semanticColors } = currentTheme; + + if (semanticColors) { + this.domElement.style.setProperty('--bodyText', semanticColors.bodyText || null); + this.domElement.style.setProperty('--link', semanticColors.link || null); + this.domElement.style.setProperty('--linkHovered', semanticColors.linkHovered || null); + } + } + + protected onDispose(): void { + ReactDom.unmountComponentAtNode(this.domElement); + } + + protected get dataVersion(): Version { + return Version.parse('1.0'); + } + + protected getPropertyPaneConfiguration(): IPropertyPaneConfiguration { + return { + pages: [ + { + header: { + description: strings.PropertyPaneDescription + }, + groups: [ + { + groupName: strings.BasicGroupName, + groupFields: [ + PropertyPaneTextField('description', { + label: strings.DescriptionFieldLabel + }), + PropertyPaneTextField('domain', { + label: strings.DomainFieldLabel + }), + PropertyPaneTextField('token', { + label: strings.TokenFieldLabel + }) + ] + } + ] + } + ] + }; + } +} diff --git a/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/components/IWebChatProps.ts b/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/components/IWebChatProps.ts new file mode 100644 index 0000000000..47e92ae3c0 --- /dev/null +++ b/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/components/IWebChatProps.ts @@ -0,0 +1,9 @@ +export interface IWebChatProps { + description: string; + domain: string; + isDarkTheme: boolean; + environmentMessage: string; + hasTeamsContext: boolean; + token: string; + userDisplayName: string; +} diff --git a/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/components/WebChat.module.scss b/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/components/WebChat.module.scss new file mode 100644 index 0000000000..66543510fe --- /dev/null +++ b/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/components/WebChat.module.scss @@ -0,0 +1,6 @@ +@import '~office-ui-fabric-react/dist/sass/References.scss'; + +.webChat { + height: 800px; + width: 360px; +} diff --git a/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/components/WebChat.tsx b/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/components/WebChat.tsx new file mode 100644 index 0000000000..e5339a54de --- /dev/null +++ b/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/components/WebChat.tsx @@ -0,0 +1,24 @@ +import { useEffect, useState } from 'react'; +import * as React from 'react'; +import ReactWebChat, { createDirectLine, createDirectLineAppServiceExtension } from 'botframework-webchat'; + +import { IWebChatProps } from './IWebChatProps'; +import styles from './WebChat.module.scss'; + +import type { VFC } from 'react'; + +const WebChat: VFC = ({ domain, token }) => { + const [directLine, setDirectLine] = useState(); + + useEffect(() => { + (async function () { + setDirectLine( + domain ? await createDirectLineAppServiceExtension({ domain, token }) : createDirectLine({ token }) + ); + })(); + }, [setDirectLine]); + + return
{!!directLine && }
; +}; + +export default WebChat; diff --git a/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/loc/en-us.js b/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/loc/en-us.js new file mode 100644 index 0000000000..ced845676e --- /dev/null +++ b/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/loc/en-us.js @@ -0,0 +1,13 @@ +define([], function () { + return { + AppLocalEnvironmentSharePoint: 'The app is running on your local environment as SharePoint web part', + AppLocalEnvironmentTeams: 'The app is running on your local environment as Microsoft Teams app', + AppSharePointEnvironment: 'The app is running on SharePoint page', + AppTeamsTabEnvironment: 'The app is running in Microsoft Teams', + BasicGroupName: 'Group Name', + DescriptionFieldLabel: 'Description Field', + DomainFieldLabel: 'Domain (for Direct Line ASE)', + PropertyPaneDescription: 'Description', + TokenFieldLabel: 'Token' + }; +}); diff --git a/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/loc/mystrings.d.ts b/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/loc/mystrings.d.ts new file mode 100644 index 0000000000..bd0a7ae582 --- /dev/null +++ b/samples/01.getting-started/l.sharepoint-web-part/src/spfx/src/webparts/webChat/loc/mystrings.d.ts @@ -0,0 +1,16 @@ +declare interface IWebChatWebPartStrings { + AppLocalEnvironmentSharePoint: string; + AppLocalEnvironmentTeams: string; + AppSharePointEnvironment: string; + AppTeamsTabEnvironment: string; + BasicGroupName: string; + DescriptionFieldLabel: string; + DomainFieldLabel: string; + PropertyPaneDescription: string; + TokenFieldLabel: string; +} + +declare module 'WebChatWebPartStrings' { + const strings: IWebChatWebPartStrings; + export = strings; +} diff --git a/samples/01.getting-started/l.sharepoint-web-part/webchat-sharepoint-web-part.png b/samples/01.getting-started/l.sharepoint-web-part/webchat-sharepoint-web-part.png new file mode 100644 index 0000000000..a4e0154db8 Binary files /dev/null and b/samples/01.getting-started/l.sharepoint-web-part/webchat-sharepoint-web-part.png differ diff --git a/samples/README.md b/samples/README.md index 5a5650dad0..8d792adb41 100644 --- a/samples/README.md +++ b/samples/README.md @@ -6,11 +6,11 @@ Here you can find all hosted samples of [Web Chat](https://github.com/microsoft/ # Samples list -| Sample Name | Description | Link | -| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Migration** | | | +| Sample Name | Description | Link | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Migration** | | | | [`00.migration/a.v3-to-v4`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/00.migration/a.v3-to-v4) | Demonstrates how to migrate from your Web Chat v3 bot to v4. | [Migration Demo](https://microsoft.github.io/BotFramework-WebChat/00.migration/a.v3-to-v4) | -| **Getting started** | | | +| **Getting started** | | | | [`01.getting-started/a.full-bundle`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/01.getting-started/a.full-bundle) | Introduces Web Chat embed from a CDN, and demonstrates a simple, full-featured Web Chat. This includes Adaptive Cards, Cognitive Services, and Markdown-It dependencies. | [Full Bundle Demo](https://microsoft.github.io/BotFramework-WebChat/01.getting-started/a.full-bundle) | | [`01.getting-started/b.minimal-bundle`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/01.getting-started/b.minimal-bundle) | Introduces the minimized CDN with only basic dependencies. This does NOT include Adaptive Cards, Cognitive Services dependencies, or Markdown-It dependencies. | [Minimal Bundle Demo](https://microsoft.github.io/BotFramework-WebChat/01.getting-started/b.minimal-bundle) | | [`01.getting-started/c.es5-bundle`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/01.getting-started/c.es5-bundle) | Introduces full-featured Web Chat embed with backwards compatibility for ES5 browsers using Web Chat's ES5 ponyfill. | [ES5 Bundle Demo](https://microsoft.github.io/BotFramework-WebChat/01.getting-started/c.es5-bundle) | @@ -22,7 +22,8 @@ Here you can find all hosted samples of [Web Chat](https://github.com/microsoft/ | [`01.getting-started/i.protocol-direct-line-app-service-extension`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/01.getting-started/i.protocol-direct-line-app-service-extension) | Demonstrates how to use Direct Line App Service Extension chat adapter | [Direct Line App Service Extension Demo](https://microsoft.github.io/BotFramework-WebChat/01.getting-started/i.protocol-direct-line-app-service-extension) | | [`01.getting-started/j.bundle-with-content-security-policy`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/01.getting-started/j.bundle-with-content-security-policy) | Demonstrates how to embed on a host with Content Security Policy configured. | [Content Security Policy Demo](https://microsoft.github.io/BotFramework-WebChat/01.getting-started/j.bundle-with-content-security-policy) | | [`01.getting-started/k.direct-line-token`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/01.getting-started/k.direct-line-token) | Demonstrates how to use a Direct Line token instead of exposing the Direct Line secret. | | -| **Branding, styling, and customization** | | | +| [`01.getting-started/l.sharepoint-web-part`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/01.getting-started/l.sharepoint-web-part) | Demonstrates how to host Web Chat as a SharePoint web part. | | +| **Branding, styling, and customization** | | | | [`02.branding-styling-and-customization/a.branding-web-chat`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/02.branding-styling-and-customization/a.branding-web-chat) | Introduces the ability to style Web Chat to match your brand. This method of custom styling will not break upon Web Chat updates. | [Branding Web Chat Demo](https://microsoft.github.io/BotFramework-WebChat/02.branding-styling-and-customization/a.branding-web-chat) | | [`02.branding-styling-and-customization/b.idiosyncratic-manual-styles`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/02.branding-styling-and-customization/b.idiosyncratic-manual-styles) | Demonstrates how to make manual style changes, and is a more complicated and time-consuming way to customize styling of Web Chat. Manual styles may be broken upon Web Chat updates. | [Idiosyncratic Styling Demo](https://microsoft.github.io/BotFramework-WebChat/02.branding-styling-and-customization/b.idiosyncratic-manual-styles) | | [`02.branding-styling-and-customization/c.display-sender-initials`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/02.branding-styling-and-customization/c.display-sender-initials) | Demonstrates how to display initials for both Web Chat participants. | [Bot initials Demo](https://microsoft.github.io/BotFramework-WebChat/02.branding-styling-and-customization/c.display-sender-initials/) | @@ -34,7 +35,7 @@ Here you can find all hosted samples of [Web Chat](https://github.com/microsoft/ | [`02.branding-styling-and-customization/i.change-locale-and-direction`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/02.branding-styling-and-customization/i.change-locale-and-direction) | Demonstrates how to change locale and direction of the UI (RTL). | [Change Direction Demo](https://microsoft.github.io/BotFramework-WebChat/02.branding-styling-and-customization/i.change-locale-and-direction) | | [`02.branding-styling-and-customization/j.activity-grouping`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/02.branding-styling-and-customization/j.activity-grouping) | Demonstrates how to customize activity grouping behavior. | [Activity Grouping Demo](https://microsoft.github.io/BotFramework-WebChat/02.branding-styling-and-customization/j.activity-grouping) [(Comprehensive)](https://microsoft.github.io/BotFramework-WebChat/02.branding-styling-and-customization/j.activity-grouping/comprehensive.html) | | [`02.branding-styling-and-customization/k.enable-emoji`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/02.branding-styling-and-customization/k.enable-emoji) | Demonstrates how to enable emoji autocorrect in the send box. | [Enable Emoji Demo](https://microsoft.github.io/BotFramework-WebChat/02.branding-styling-and-customization/k.enable-emoji) | -| **Speech** | | | +| **Speech** | | | | [`03.speech/a.direct-line-speech`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/03.speech/a.direct-line-speech) | Demonstrates how to use Direct Line Speech channel in Web Chat. | [Direct Line Speech Demo](https://microsoft.github.io/BotFramework-WebChat/03.speech/a.direct-line-speech) | | [`03.speech/b.cognitive-speech-services-js`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/03.speech/b.cognitive-speech-services-js) | Introduces speech-to-text and text-to-speech ability using Cognitive Services Speech Services API. | [Speech Services with JS Demo](https://microsoft.github.io/BotFramework-WebChat/03.speech/b.cognitive-speech-services-js) | | [`03.speech/c.cognitive-speech-services-with-lexical-result`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/03.speech/c.cognitive-speech-services-with-lexical-result) | Demonstrates how to use lexical result from Cognitive Services Speech Services API. | [Lexical Result Demo](https://microsoft.github.io/BotFramework-WebChat/03.speech/c.cognitive-speech-services-with-lexical-result) | @@ -43,7 +44,7 @@ Here you can find all hosted samples of [Web Chat](https://github.com/microsoft/ | [`03.speech/f.web-browser-speech`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/03.speech/f.web-browser-speech) | Demonstrates how to implement text-to-speech using Web Chat's browser-based Web Speech API. (link to W3C standard in the sample) | [Web Speech API Demo](https://microsoft.github.io/BotFramework-WebChat/03.speech/f.web-browser-speech) | | [`03.speech/g.hybrid-speech`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/03.speech/g.hybrid-speech) | Demonstrates how to use both browser-based Web Speech API for speech-to-text, and Cognitive Services Speech Services API for text-to-speech. | [Hybrid Speech Demo](https://microsoft.github.io/BotFramework-WebChat/03.speech/g.hybrid-speech) | | [`03.speech/h.select-audio-input-device`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/03.speech/h.select-audio-input-device) | Demonstrates how to select an audio input device. | [Select Audio Input Device Demo](https://microsoft.github.io/BotFramework-WebChat/03.speech/h.select-audio-input-device) [(Comprehensive)](https://microsoft.github.io/BotFramework-WebChat/03.speech/h.select-audio-input-device/comprehensive.html) | -| **API** | | | +| **API** | | | | [`04.api/a.welcome-event`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/04.api/a.welcome-event) | Advanced tutorial: Demonstrates how to send welcome event with client capabilities such as browser language. | [Welcome Event Demo](https://microsoft.github.io/BotFramework-WebChat/04.api/a.welcome-event) | | [`04.api/b.piggyback-on-outgoing-activities`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/04.api/b.piggyback-on-outgoing-activities) | Advanced tutorial: Demonstrates how to add custom data to every outgoing activities. | [Backchannel Piggybacking Demo](https://microsoft.github.io/BotFramework-WebChat/04.api/b.piggyback-on-outgoing-activities) | | [`04.api/c.incoming-activity-event`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/04.api/c.incoming-activity-event) | Advanced tutorial: Demonstrates how to forward all incoming activities to a JavaScript event for further processing. | [Incoming Activity Demo](https://microsoft.github.io/BotFramework-WebChat/04.api/c.incoming-activity-event) | @@ -57,8 +58,8 @@ Here you can find all hosted samples of [Web Chat](https://github.com/microsoft/ | [`04.api/k.telemetry-application-insights`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/04.api/k.telemetry-application-insights) | Advanced tutorial: Demonstrates how to collect telemetry measurement using Azure Application Insights. | [Telemetry using Application Insights Demo](https://microsoft.github.io/BotFramework-WebChat/04.api/k.telemetry-application-insights) | | [`04.api/l.telemetry-google-analytics`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/04.api/l.telemetry-google-analytics) | Advanced tutorial: Demonstrates how to collect telemetry measurement using Google Analytics. | [Telemetry using Google Analytics Demo](https://microsoft.github.io/BotFramework-WebChat/04.api/l.telemetry-google-analytics) | | [`04.api/m.enable-composition-mode`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/04.api/m.enable-composition-mode) | Advanced tutorial: Demonstrates how to enable composition mode. | [Telemetry using Google Analytics Demo](https://microsoft.github.io/BotFramework-WebChat/04.api/m.enable-composition-mode) | -| [`04.api/n.save-restore-scroll-position`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/04.api/n.save-restore-scroll-position) | Advanced tutorial: Demonstrates how to save and restore scroll position. | [Telemetry using Google Analytics Demo](https://microsoft.github.io/BotFramework-WebChat/04.api/n.save-restore-scroll-position) | -| **Custom components** | | | +| [`04.api/n.save-restore-scroll-position`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/04.api/n.save-restore-scroll-position) | Advanced tutorial: Demonstrates how to save and restore scroll position. | [Save and Restore Scroll Position Demo](https://microsoft.github.io/BotFramework-WebChat/04.api/n.save-restore-scroll-position) | +| **Custom components** | | | | [`05.custom-components/a.timestamp-grouping`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/05.custom-components/a.timestamp-grouping) | Demonstrates how to customize timestamps by showing or hiding timestamps and changing the grouping of messages by time. | [Timestamp Grouping Demo](https://microsoft.github.io/BotFramework-WebChat/05.custom-components/a.timestamp-grouping) | | [`05.custom-components/b.send-typing-indicator`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/05.custom-components/b.send-typing-indicator) | Demonstrates how to send typing activity when the user start typing on the send box. | [User Typing Indicator Demo](https://microsoft.github.io/BotFramework-WebChat/05.custom-components/b.send-typing-indicator) | | [`05.custom-components/c.user-highlighting`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/05.custom-components/c.user-highlighting) | Demonstrates how to customize the styling of activities based whether the message is from the user or the bot. | [User Highlighting Demo](https://microsoft.github.io/BotFramework-WebChat/05.custom-components/c.user-highlighting) | @@ -69,12 +70,12 @@ Here you can find all hosted samples of [Web Chat](https://github.com/microsoft/ | [`05.custom-components/i.notification`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/05.custom-components/i.notification/) | Demonstrates how to use notification and customize the toast UI. | [Notification Demo](https://microsoft.github.io/BotFramework-WebChat/05.custom-components/i.notification) | | [`05.custom-components/j.typing-indicator`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/05.custom-components/j.typing-indicator/) | Demonstrates how to customize the typing indicator. | [Customize Typing Indicator Demo](https://microsoft.github.io/BotFramework-WebChat/05.custom-components/j.typing-indicator) | | [`05.custom-components/k.per-message-avatar`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/05.custom-components/k.per-message-avatar/) | Demonstrates how to customize the avatar on a per-message basis. | [Customize Avatar Demo](https://microsoft.github.io/BotFramework-WebChat/05.custom-components/k.per-message-avatar) [(Comprehensive)](https://microsoft.github.io/BotFramework-WebChat/05.custom-components/k.per-message-avatar/comprehensive.html) | -| **Recomposing UI** | | | +| **Recomposing UI** | | | | [`06.recomposing-ui/a.minimizable-web-chat`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/06.recomposing-ui/a.minimizable-web-chat) | Advanced tutorial: Demonstrates how to add the Web Chat interface to your website as a minimizable show/hide chat box. | [Minimizable Web Chat Demo](https://microsoft.github.io/BotFramework-WebChat/06.recomposing-ui/a.minimizable-web-chat) | | [`06.recomposing-ui/b.speech-ui`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/06.recomposing-ui/b.speech-ui) | Advanced tutorial: Demonstrates how to fully customize key components of your bot, in this case speech, which entirely replaces the text-based transcript UI and instead shows a simple speech button with the bot's response. | [Speech UI Demo](https://microsoft.github.io/BotFramework-WebChat/06.recomposing-ui/b.speech-ui) | | [`06.recomposing-ui/c.smart-display`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/06.recomposing-ui/c.smart-display) | Demonstrates how to compose Web Chat UI into a Smart Display | [Smart Display Demo](https://microsoft.github.io/BotFramework-WebChat/06.recomposing-ui/c.smart-display) | | [`06.recomposing-ui/d.plain-ui`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/06.recomposing-ui/d.plain-ui) | Advanced tutorial: Demonstrates how to customize the Web Chat UI by building from ground up instead of needing to rewrite entire Web Chat components. | [Plain UI Demo](https://microsoft.github.io/BotFramework-WebChat/06.recomposing-ui/d.plain-ui) | -| **Advanced Web Chat apps** | | | +| **Advanced Web Chat apps** | | | | [`07.advanced-web-chat-apps/a.upload-to-azure-storage`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/07.advanced-web-chat-apps/a.upload-to-azure-storage) | Demonstrates how to use upload attachments directly to Azure Storage | [Upload to Azure Storage Demo](https://webchat-sample-upload-to-azure.azurewebsites.net/) | | [`07.advanced-web-chat-apps/b.sso-for-enterprise`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/07.advanced-web-chat-apps/b.sso-for-enterprise) | Demonstrates how to use single sign-on for enterprise single-page applications using OAuth | [Single Sign-On for Enterprise Single-Page Applications Demo](https://webchat-sample-sso.azurewebsites.net/) | | [`07.advanced-web-chat-apps/c.sso-for-intranet`](https://github.com/microsoft/BotFramework-WebChat/tree/main/samples/07.advanced-web-chat-apps/c.sso-for-intranet) | Demonstrates how to use single sign-on for Intranet apps using Azure Active Directory | [Single Sign-On for Intranet Apps Demo](https://webchat-sample-sso-intranet.azurewebsites.net/) |