Merge latest master changes to chatbot

This commit is contained in:
Bala Lakshmi Narayanasami
2021-08-03 17:11:00 +05:30
parent 4614ab3427
commit d29fd6e957
8 changed files with 4325 additions and 867 deletions

5026
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -46,6 +46,7 @@
"@types/node-fetch": "2.5.7", "@types/node-fetch": "2.5.7",
"applicationinsights": "1.8.0", "applicationinsights": "1.8.0",
"bootstrap": "3.4.1", "bootstrap": "3.4.1",
"botframework-webchat": "4.10.1",
"canvas": "file:./canvas", "canvas": "file:./canvas",
"clean-webpack-plugin": "0.1.19", "clean-webpack-plugin": "0.1.19",
"clipboard-copy": "4.0.1", "clipboard-copy": "4.0.1",

View File

@@ -1,13 +1,13 @@
/** /**
* React component for Command button component. * React component for Command button component.
*/ */
import { Icon, IIconStyles } from "@fluentui/react";
import * as React from "react"; import * as React from "react";
import CollapseChevronDownIcon from "../../../../images/QueryBuilder/CollapseChevronDown_16x.png"; import CollapseChevronDownIcon from "../../../../images/QueryBuilder/CollapseChevronDown_16x.png";
import { KeyCodes } from "../../../Common/Constants"; import { KeyCodes } from "../../../Common/Constants";
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import * as StringUtils from "../../../Utils/StringUtils"; import * as StringUtils from "../../../Utils/StringUtils";
/** /**
* Options for this component * Options for this component
*/ */
@@ -243,6 +243,7 @@ export class CommandButtonComponent extends React.Component<CommandButtonCompone
if (this.props.children && this.props.children.length > 0) { if (this.props.children && this.props.children.length > 0) {
contentClassName += " hasHiddenItems"; contentClassName += " hasHiddenItems";
} }
const iconButtonStyles: Partial<IIconStyles> = { root: { marginBottom: -3 } };
return ( return (
<div className="commandButtonReact"> <div className="commandButtonReact">
@@ -259,7 +260,13 @@ export class CommandButtonComponent extends React.Component<CommandButtonCompone
onClick={(e: React.MouseEvent<HTMLSpanElement>) => this.commandClickCallback(e)} onClick={(e: React.MouseEvent<HTMLSpanElement>) => this.commandClickCallback(e)}
> >
<div className={contentClassName}> <div className={contentClassName}>
<img className="commandIcon" src={this.props.iconSrc} alt={this.props.iconAlt} /> if (this.props.iconName) {
<div>
<Icon styles={iconButtonStyles} className="panelInfoIcon" iconName={this.props.iconName} ariaLabel="ChatBot" />
</div>
} else {
<img className="commandIcon" src={this.props.iconSrc} alt={this.props.iconAlt} />
}
{CommandButtonComponent.renderLabel(this.props)} {CommandButtonComponent.renderLabel(this.props)}
</div> </div>
</span> </span>

View File

@@ -1,5 +1,5 @@
import { DirectionalHint, Icon, IIconStyles, Stack, Text, TooltipHost } from "@fluentui/react";
import * as React from "react"; import * as React from "react";
import { Stack, Text, IIconStyles, Icon, TooltipHost, DirectionalHint } from "@fluentui/react";
import { toolTipLabelStackTokens } from "../SettingsRenderUtils"; import { toolTipLabelStackTokens } from "../SettingsRenderUtils";
export interface ToolTipLabelComponentProps { export interface ToolTipLabelComponentProps {

View File

@@ -0,0 +1,47 @@
import ReactWebChat, { createDirectLine } from "botframework-webchat";
import React from "react";
import * as _ from "underscore";
export interface SupportPaneComponentProps {
directLineToken: string;
userToken: string;
subId: string;
rg: string;
accName: string;
}
export class SupportPaneComponent extends React.Component<SupportPaneComponentProps> {
private readonly userId: string = _.uniqueId();
constructor(props: SupportPaneComponentProps) {
super(props);
}
public render(): JSX.Element {
const styleOptions = {
bubbleBackground: "rgba(0, 0, 255, .1)",
bubbleFromUserBackground: "rgba(0, 255, 0, .1)"
};
const directLine = createDirectLine({ token: this.props.directLineToken });
const dl =
{
...directLine,
postActivity: (activity: any) => {
// Add whatever needs to be added.
activity.channelData.token = this.props.userToken;
activity.channelData.subId = this.props.subId;
activity.channelData.rg = this.props.rg;
activity.channelData.accName = this.props.accName;
//activity.channelData.MyKey = "hello";
return directLine.postActivity(activity)
}
}
return <ReactWebChat directLine={dl} userid={this.userId} styleOptions={styleOptions} />;
}
}

View File

@@ -28,8 +28,9 @@ import {
get as getWorkspace, get as getWorkspace,
listByDatabaseAccount, listByDatabaseAccount,
listConnectionInfo, listConnectionInfo,
start, start
} from "../Utils/arm/generatedClients/cosmosNotebooks/notebookWorkspaces"; } from "../Utils/arm/generatedClients/cosmosNotebooks/notebookWorkspaces";
import { decryptJWTToken } from "../Utils/AuthorizationUtils";
import { stringToBlob } from "../Utils/BlobUtils"; import { stringToBlob } from "../Utils/BlobUtils";
import { isCapabilityEnabled } from "../Utils/CapabilityUtils"; import { isCapabilityEnabled } from "../Utils/CapabilityUtils";
import { fromContentUri, toRawContentUri } from "../Utils/GitHubUtils"; import { fromContentUri, toRawContentUri } from "../Utils/GitHubUtils";
@@ -85,6 +86,12 @@ export default class Explorer {
// Notebooks // Notebooks
public notebookManager?: NotebookManager; public notebookManager?: NotebookManager;
public conversationToken: ko.Observable<string>;
public userToken: ko.Observable<string>;
public subId: ko.Observable<string>;
public rg: ko.Observable<string>;
public accName: ko.Observable<string>;
private _isInitializingNotebooks: boolean; private _isInitializingNotebooks: boolean;
private notebookToImport: { private notebookToImport: {
name: string; name: string;
@@ -105,6 +112,10 @@ export default class Explorer {
this.queriesClient = new QueriesClient(this); this.queriesClient = new QueriesClient(this);
this.conversationToken = ko.observable<string>();
this.generateConversationToken();
useSelectedNode.subscribe(() => { useSelectedNode.subscribe(() => {
// Make sure switching tabs restores tabs display // Make sure switching tabs restores tabs display
this.isTabsContentExpanded(false); this.isTabsContentExpanded(false);
@@ -392,6 +403,52 @@ export default class Explorer {
useDialog.getState().openDialog(resetConfirmationDialogProps); useDialog.getState().openDialog(resetConfirmationDialogProps);
} }
private getUserName() {
const accessToken = userContext?.authorizationToken;
if (!accessToken) {
return "Cosmos DB User";
}
let name;
try {
const tokenPayload = decryptJWTToken(accessToken);
if (tokenPayload && tokenPayload.hasOwnProperty("name")) {
name = tokenPayload.name;
}
} catch (error) {
// ignore
} finally {
return name;
}
}
private async generateConversationToken() {
const response = await fetch("https://directline.botframework.com/v3/directline/tokens/generate", {
method: "POST",
headers: {
[Constants.HttpHeaders.authorization]: "Bearer BSjLmJJHZRA.PxahjJGCNOKl7q9tiodWyVcqJOIzG894vAAqCme639o",
Accept: "application/json",
[Constants.HttpHeaders.contentType]: "application/json"
},
body: JSON.stringify({
"user": {
"id": `dl_${_.uniqueId()}`,
"name": this.getUserName()
}
})
});
if (!response.ok) {
throw new Error(await response.json());
}
const tokenResponse: { conversationId: string; token: string; expires_in: number } = await response.json();
this.conversationToken(tokenResponse?.token);
if (tokenResponse?.expires_in) {
setTimeout(() => this.generateConversationToken(), (tokenResponse?.expires_in - 1000) * 1000);
}
}
private async _containsDefaultNotebookWorkspace(databaseAccount: DataModels.DatabaseAccount): Promise<boolean> { private async _containsDefaultNotebookWorkspace(databaseAccount: DataModels.DatabaseAccount): Promise<boolean> {
if (!databaseAccount) { if (!databaseAccount) {
return false; return false;

View File

@@ -27,6 +27,7 @@ import { getCollectionName, getDatabaseName } from "../../../Utils/APITypeUtils"
import { isServerlessAccount } from "../../../Utils/CapabilityUtils"; import { isServerlessAccount } from "../../../Utils/CapabilityUtils";
import { isRunningOnNationalCloud } from "../../../Utils/CloudUtils"; import { isRunningOnNationalCloud } from "../../../Utils/CloudUtils";
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent"; import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
import { SupportPaneComponent } from "../../Controls/SupportPaneComponent/SupportPaneComponent";
import Explorer from "../../Explorer"; import Explorer from "../../Explorer";
import { useNotebook } from "../../Notebook/useNotebook"; import { useNotebook } from "../../Notebook/useNotebook";
import { OpenFullScreen } from "../../OpenFullScreen"; import { OpenFullScreen } from "../../OpenFullScreen";
@@ -184,6 +185,29 @@ export function createControlCommandBarButtons(container: Explorer): CommandButt
const showOpenFullScreen = const showOpenFullScreen =
configContext.platform === Platform.Portal && !isRunningOnNationalCloud() && userContext.apiType !== "Gremlin"; configContext.platform === Platform.Portal && !isRunningOnNationalCloud() && userContext.apiType !== "Gremlin";
if (userContext.authType === AuthType.AAD) {
const label = "Chat Assistant";
const supportPaneButton: CommandButtonComponentProps = {
iconName: "ChatBot",
iconAlt: label,
onCommandClick: () => {
useSidePanel.getState().openSidePanel("Chat Assistant (Beta)", <SupportPaneComponent
directLineToken={container.conversationToken()}
userToken={userContext.authorizationToken}
subId={userContext.subscriptionId}
rg={userContext.resourceGroup}
accName={userContext.databaseAccount.name}
/>);
},
commandButtonLabel: null,
ariaLabel: label,
tooltipText: label,
hasPopup: true,
disabled: false
};
buttons.push(supportPaneButton);
}
if (showOpenFullScreen) { if (showOpenFullScreen) {
const label = "Open Full Screen"; const label = "Open Full Screen";
const fullScreenButton: CommandButtonComponentProps = { const fullScreenButton: CommandButtonComponentProps = {

View File

@@ -1,12 +1,14 @@
<!DOCTYPE html public "-//W3C//DTD HTML 4.0//en"> <!DOCTYPE html public "-//W3C//DTD HTML 4.0//en">
<html lang="en"> <html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="height=device-height, width=device-width, initial-scale=1.0" />
<meta name="robots" content="noindex, nofollow" />
<title>Azure Cosmos DB</title>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
</head>
<body></body> <head>
</html> <meta charset="UTF-8" />
<meta name="viewport" content="height=device-height, width=device-width, initial-scale=1.0" />
<meta name="robots" content="noindex, nofollow" />
<title>Azure Cosmos DB</title>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
</head>
<body></body>
</html>