mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-25 11:51:07 +00:00
Compare commits
25 Commits
cloudshell
...
user/t-tom
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04d6a17b70 | ||
|
|
905413bf17 | ||
|
|
f519aa7be3 | ||
|
|
053e346fa4 | ||
|
|
b4909d9e13 | ||
|
|
b268b525d8 | ||
|
|
02d0353215 | ||
|
|
4fd153d676 | ||
|
|
7b1f3bb493 | ||
|
|
95b43d83d1 | ||
|
|
f9494030ac | ||
|
|
a1087b2626 | ||
|
|
5aeca52234 | ||
|
|
6c77430775 | ||
|
|
7bc78f126b | ||
|
|
e3ef515d8b | ||
|
|
7ffc1bc35a | ||
|
|
6add6d2e86 | ||
|
|
a089bac80e | ||
|
|
c0b5e185aa | ||
|
|
986fe39d07 | ||
|
|
fd511f2706 | ||
|
|
c35e23eb47 | ||
|
|
80be52685f | ||
|
|
d29fd6e957 |
23
less/chat.less
Normal file
23
less/chat.less
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
@import "./Common/Constants";
|
||||||
|
|
||||||
|
.chat {
|
||||||
|
display: grid;
|
||||||
|
justify-content: right;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
.chatButton {
|
||||||
|
margin: 0 45px 15px 0;
|
||||||
|
border: 10px;
|
||||||
|
min-height: 44px;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
>span {
|
||||||
|
font-size: 17px;
|
||||||
|
font-family: @DataExplorerFont;
|
||||||
|
color: @AccentLow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18453
package-lock.json
generated
18453
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -47,6 +47,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.14.1",
|
||||||
"canvas": "file:./canvas",
|
"canvas": "file:./canvas",
|
||||||
"clean-webpack-plugin": "3.0.0",
|
"clean-webpack-plugin": "3.0.0",
|
||||||
"clipboard-copy": "4.0.1",
|
"clipboard-copy": "4.0.1",
|
||||||
@@ -127,6 +128,7 @@
|
|||||||
"@types/react-notification-system": "0.2.39",
|
"@types/react-notification-system": "0.2.39",
|
||||||
"@types/react-redux": "7.1.7",
|
"@types/react-redux": "7.1.7",
|
||||||
"@types/react-splitter-layout": "3.0.1",
|
"@types/react-splitter-layout": "3.0.1",
|
||||||
|
"@types/react-youtube": "7.10.0",
|
||||||
"@types/sanitize-html": "1.27.2",
|
"@types/sanitize-html": "1.27.2",
|
||||||
"@types/sinon": "2.3.3",
|
"@types/sinon": "2.3.3",
|
||||||
"@types/styled-components": "5.1.1",
|
"@types/styled-components": "5.1.1",
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
allowedJunoOrigins,
|
allowedJunoOrigins,
|
||||||
allowedMongoBackendEndpoints,
|
allowedMongoBackendEndpoints,
|
||||||
allowedMsalRedirectEndpoints,
|
allowedMsalRedirectEndpoints,
|
||||||
validateEndpoint,
|
validateEndpoint
|
||||||
} from "Utils/EndpointValidation";
|
} from "Utils/EndpointValidation";
|
||||||
|
|
||||||
export enum Platform {
|
export enum Platform {
|
||||||
@@ -190,3 +190,4 @@ export async function initializeConfiguration(): Promise<ConfigContext> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export { configContext };
|
export { configContext };
|
||||||
|
|
||||||
|
|||||||
42
src/Explorer/Controls/ChatButton/ChatButtonComponent.tsx
Normal file
42
src/Explorer/Controls/ChatButton/ChatButtonComponent.tsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { IIconProps } from '@fluentui/react';
|
||||||
|
import { PrimaryButton } from '@fluentui/react/lib/Button';
|
||||||
|
import { AuthType } from 'AuthType';
|
||||||
|
import { SupportPaneComponent } from 'Explorer/Controls/SupportPaneComponent/SupportPaneComponent';
|
||||||
|
import Explorer from 'Explorer/Explorer';
|
||||||
|
import { useSidePanel } from 'hooks/useSidePanel';
|
||||||
|
import * as React from 'react';
|
||||||
|
import { userContext } from 'UserContext';
|
||||||
|
|
||||||
|
export interface ChatButtonProps {
|
||||||
|
container: Explorer;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chatIcon: IIconProps = { iconName: 'ChatSolid', style: { marginRight: 10 } };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const ChatButtonAction: React.FunctionComponent<ChatButtonProps> = props => {
|
||||||
|
const { container } = props;
|
||||||
|
if (userContext.authType === AuthType.AAD && userContext.features.enableChatbot) {
|
||||||
|
return (
|
||||||
|
<PrimaryButton className={"chatButton"} iconProps={chatIcon} onClick={() => {
|
||||||
|
useSidePanel
|
||||||
|
.getState()
|
||||||
|
.openSidePanel(
|
||||||
|
"Chat Assistant (Beta)",
|
||||||
|
<SupportPaneComponent
|
||||||
|
directLineToken={container.conversationToken()}
|
||||||
|
userToken={userContext.authorizationToken}
|
||||||
|
subId={userContext.subscriptionId}
|
||||||
|
rg={userContext.resourceGroup}
|
||||||
|
accName={userContext.databaseAccount.name}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}>
|
||||||
|
<span> Help? </span>
|
||||||
|
</PrimaryButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <div></div>
|
||||||
|
};
|
||||||
@@ -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,18 @@ 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>
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import { Activity } from "botframework-directlinejs";
|
||||||
|
import ReactWebChat from "botframework-webchat";
|
||||||
|
import React from "react";
|
||||||
|
import * as _ from "underscore";
|
||||||
|
|
||||||
|
const BotFramework = require('botframework-webchat');
|
||||||
|
|
||||||
|
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)",
|
||||||
|
suggestedActionLayout: 'flow',
|
||||||
|
markdownRespectCRLF: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const directLine = BotFramework.createDirectLine({ token: this.props.directLineToken });
|
||||||
|
const dl = {
|
||||||
|
...directLine,
|
||||||
|
postActivity: (activity: Activity) => {
|
||||||
|
activity.channelData.token = this.props.userToken;
|
||||||
|
activity.channelData.subId = this.props.subId;
|
||||||
|
activity.channelData.rg = this.props.rg;
|
||||||
|
activity.channelData.accName = this.props.accName;
|
||||||
|
|
||||||
|
return directLine.postActivity(activity);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return <ReactWebChat directLine={dl} userID={this.userId} styleOptions={styleOptions} />;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Link } from "@fluentui/react/lib/Link";
|
import { Link } from "@fluentui/react/lib/Link";
|
||||||
import { isPublicInternetAccessAllowed } from "Common/DatabaseAccountUtility";
|
import { isPublicInternetAccessAllowed } from "Common/DatabaseAccountUtility";
|
||||||
|
import { configContext } from "ConfigContext";
|
||||||
import { IGalleryItem } from "Juno/JunoClient";
|
import { IGalleryItem } from "Juno/JunoClient";
|
||||||
import * as ko from "knockout";
|
import * as ko from "knockout";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
@@ -34,6 +35,7 @@ import { userContext } from "../UserContext";
|
|||||||
import { getCollectionName, getUploadName } from "../Utils/APITypeUtils";
|
import { getCollectionName, getUploadName } from "../Utils/APITypeUtils";
|
||||||
import { update } from "../Utils/arm/generatedClients/cosmos/databaseAccounts";
|
import { update } from "../Utils/arm/generatedClients/cosmos/databaseAccounts";
|
||||||
import { listByDatabaseAccount } from "../Utils/arm/generatedClients/cosmosNotebooks/notebookWorkspaces";
|
import { listByDatabaseAccount } from "../Utils/arm/generatedClients/cosmosNotebooks/notebookWorkspaces";
|
||||||
|
import { getAuthorizationHeader } 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 +87,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;
|
||||||
@@ -106,6 +114,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);
|
||||||
@@ -455,6 +467,30 @@ export default class Explorer {
|
|||||||
useDialog.getState().openDialog(resetConfirmationDialogProps);
|
useDialog.getState().openDialog(resetConfirmationDialogProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async generateConversationToken() {
|
||||||
|
const url = `${configContext.JUNO_ENDPOINT}/api/chatbot/bot${userContext.databaseAccount.id}/conversationToken`;
|
||||||
|
const authorizationHeader = getAuthorizationHeader();
|
||||||
|
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: "GET",
|
||||||
|
headers: {
|
||||||
|
[Constants.HttpHeaders.authorization]: authorizationHeader.token,
|
||||||
|
Accept: "application/json",
|
||||||
|
[Constants.HttpHeaders.contentType]: "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
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;
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import { userContext } from "../../../UserContext";
|
|||||||
import { getCollectionName, getDatabaseName } from "../../../Utils/APITypeUtils";
|
import { getCollectionName, getDatabaseName } from "../../../Utils/APITypeUtils";
|
||||||
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";
|
||||||
@@ -195,6 +196,35 @@ 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 && userContext.features.enableChatbot) {
|
||||||
|
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,
|
||||||
|
className: "fonticoncustom",
|
||||||
|
};
|
||||||
|
buttons.push(supportPaneButton);
|
||||||
|
}
|
||||||
|
|
||||||
if (showOpenFullScreen) {
|
if (showOpenFullScreen) {
|
||||||
const label = "Open Full Screen";
|
const label = "Open Full Screen";
|
||||||
const fullScreenButton: CommandButtonComponentProps = {
|
const fullScreenButton: CommandButtonComponentProps = {
|
||||||
|
|||||||
@@ -42,6 +42,10 @@
|
|||||||
width: 18px;
|
width: 18px;
|
||||||
color: rgb(0, 120, 212);
|
color: rgb(0, 120, 212);
|
||||||
}
|
}
|
||||||
|
.fonticoncustom {
|
||||||
|
padding-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.status {
|
.status {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
|
|||||||
@@ -21,4 +21,4 @@
|
|||||||
color: @SelectionHigh;
|
color: @SelectionHigh;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// CSS Dependencies
|
// CSS Dependencies
|
||||||
import { initializeIcons } from "@fluentui/react";
|
import { initializeIcons } from "@fluentui/react";
|
||||||
import "bootstrap/dist/css/bootstrap.css";
|
import "bootstrap/dist/css/bootstrap.css";
|
||||||
|
import { ChatButtonAction } from "Explorer/Controls/ChatButton/ChatButtonComponent";
|
||||||
import { QuickstartCarousel } from "Explorer/Tutorials/QuickstartCarousel";
|
import { QuickstartCarousel } from "Explorer/Tutorials/QuickstartCarousel";
|
||||||
import { QuickstartTutorial } from "Explorer/Tutorials/QuickstartTutorial";
|
import { QuickstartTutorial } from "Explorer/Tutorials/QuickstartTutorial";
|
||||||
import { useCarousel } from "hooks/useCarousel";
|
import { useCarousel } from "hooks/useCarousel";
|
||||||
@@ -17,6 +18,7 @@ import "../externals/jquery.typeahead.min.js";
|
|||||||
import "../images/CosmosDB_rgb_ui_lighttheme.ico";
|
import "../images/CosmosDB_rgb_ui_lighttheme.ico";
|
||||||
import "../images/favicon.ico";
|
import "../images/favicon.ico";
|
||||||
import hdeConnectImage from "../images/HdeConnectCosmosDB.svg";
|
import hdeConnectImage from "../images/HdeConnectCosmosDB.svg";
|
||||||
|
import "../less/chat.less";
|
||||||
import "../less/documentDB.less";
|
import "../less/documentDB.less";
|
||||||
import "../less/forms.less";
|
import "../less/forms.less";
|
||||||
import "../less/infobox.less";
|
import "../less/infobox.less";
|
||||||
@@ -103,6 +105,9 @@ const App: React.FunctionComponent = () => {
|
|||||||
<Tabs explorer={explorer} />
|
<Tabs explorer={explorer} />
|
||||||
</div>
|
</div>
|
||||||
{/* Collections Tree and Tabs - End */}
|
{/* Collections Tree and Tabs - End */}
|
||||||
|
<div className="chat">
|
||||||
|
<ChatButtonAction container={explorer} />
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
className="dataExplorerErrorConsoleContainer"
|
className="dataExplorerErrorConsoleContainer"
|
||||||
role="contentinfo"
|
role="contentinfo"
|
||||||
@@ -111,6 +116,7 @@ const App: React.FunctionComponent = () => {
|
|||||||
>
|
>
|
||||||
<NotificationConsole />
|
<NotificationConsole />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<SidePanel />
|
<SidePanel />
|
||||||
<Dialog />
|
<Dialog />
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ export type Features = {
|
|||||||
readonly mongoProxyEndpoint?: string;
|
readonly mongoProxyEndpoint?: string;
|
||||||
readonly mongoProxyAPIs?: string;
|
readonly mongoProxyAPIs?: string;
|
||||||
readonly enableThroughputCap: boolean;
|
readonly enableThroughputCap: boolean;
|
||||||
|
readonly enableNewQuickstart: boolean;
|
||||||
|
readonly enableChatbot?: boolean;
|
||||||
|
|
||||||
|
|
||||||
// can be set via both flight and feature flag
|
// can be set via both flight and feature flag
|
||||||
autoscaleDefault: boolean;
|
autoscaleDefault: boolean;
|
||||||
@@ -90,6 +93,8 @@ export function extractFeatures(given = new URLSearchParams(window.location.sear
|
|||||||
partitionKeyDefault2: "true" === get("pkpartitionkeytest"),
|
partitionKeyDefault2: "true" === get("pkpartitionkeytest"),
|
||||||
notebooksDownBanner: "true" === get("notebooksDownBanner"),
|
notebooksDownBanner: "true" === get("notebooksDownBanner"),
|
||||||
enableThroughputCap: "true" === get("enablethroughputcap"),
|
enableThroughputCap: "true" === get("enablethroughputcap"),
|
||||||
|
enableNewQuickstart: "true" === get("enablenewquickstart"),
|
||||||
|
enableChatbot: "true" === get("enablechatbot"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user