mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-21 09:51:11 +00:00
Merge latest master changes to chatbot
This commit is contained in:
4998
package-lock.json
generated
4998
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -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",
|
||||||
|
|||||||
@@ -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}>
|
||||||
|
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} />
|
<img className="commandIcon" src={this.props.iconSrc} alt={this.props.iconAlt} />
|
||||||
|
}
|
||||||
{CommandButtonComponent.renderLabel(this.props)}
|
{CommandButtonComponent.renderLabel(this.props)}
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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} />;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 = {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<!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>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="height=device-height, width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="height=device-height, width=device-width, initial-scale=1.0" />
|
||||||
@@ -9,4 +10,5 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body></body>
|
<body></body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user