mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-28 21:32:05 +00:00
Compare commits
9 Commits
defect2280
...
solution22
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6247d1a97d | ||
|
|
4ec6108f41 | ||
|
|
d63f1251dd | ||
|
|
40755e297d | ||
|
|
b84d5b572c | ||
|
|
c711b59f7d | ||
|
|
e945963cf9 | ||
|
|
5a660551c6 | ||
|
|
b2d59f3b3f |
@@ -18,8 +18,7 @@ module.exports = {
|
|||||||
// clearMocks: false,
|
// clearMocks: false,
|
||||||
|
|
||||||
// Indicates whether the coverage information should be collected while executing the test
|
// Indicates whether the coverage information should be collected while executing the test
|
||||||
|
collectCoverage: true,
|
||||||
collectCoverage: process.env.skipCodeCoverage === "true" ? false : true,
|
|
||||||
|
|
||||||
// An array of glob patterns indicating a set of files for which coverage information should be collected
|
// An array of glob patterns indicating a set of files for which coverage information should be collected
|
||||||
collectCoverageFrom: ["src/**/*.{js,jsx,ts,tsx}"],
|
collectCoverageFrom: ["src/**/*.{js,jsx,ts,tsx}"],
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ export const EntityValue: FunctionComponent<TableEntityProps> = ({
|
|||||||
label={entityValueLabel && entityValueLabel}
|
label={entityValueLabel && entityValueLabel}
|
||||||
className="addEntityTextField"
|
className="addEntityTextField"
|
||||||
id="entityValueId"
|
id="entityValueId"
|
||||||
autoFocus
|
|
||||||
disabled={isEntityValueDisable}
|
disabled={isEntityValueDisable}
|
||||||
type={entityValueType}
|
type={entityValueType}
|
||||||
placeholder={entityValuePlaceholder}
|
placeholder={entityValuePlaceholder}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
IStackTokens,
|
IStackTokens,
|
||||||
Stack,
|
Stack,
|
||||||
TextField,
|
TextField,
|
||||||
TooltipHost,
|
TooltipHost
|
||||||
} from "@fluentui/react";
|
} from "@fluentui/react";
|
||||||
import React, { FunctionComponent } from "react";
|
import React, { FunctionComponent } from "react";
|
||||||
import DeleteIcon from "../../images/delete.svg";
|
import DeleteIcon from "../../images/delete.svg";
|
||||||
@@ -136,6 +136,7 @@ export const TableEntity: FunctionComponent<TableEntityProps> = ({
|
|||||||
onEntityTimeValueChange={onEntityTimeValueChange}
|
onEntityTimeValueChange={onEntityTimeValueChange}
|
||||||
/>
|
/>
|
||||||
{!isEntityValueDisable && (
|
{!isEntityValueDisable && (
|
||||||
|
|
||||||
<TooltipHost content="Edit property" id="editTooltip">
|
<TooltipHost content="Edit property" id="editTooltip">
|
||||||
<div tabIndex={0}>
|
<div tabIndex={0}>
|
||||||
<Image
|
<Image
|
||||||
@@ -149,6 +150,7 @@ export const TableEntity: FunctionComponent<TableEntityProps> = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</TooltipHost>
|
</TooltipHost>
|
||||||
|
|
||||||
)}
|
)}
|
||||||
{isDeleteOptionVisible && userContext.apiType !== "Cassandra" && (
|
{isDeleteOptionVisible && userContext.apiType !== "Cassandra" && (
|
||||||
<TooltipHost content="Delete property" id="deleteTooltip">
|
<TooltipHost content="Delete property" id="deleteTooltip">
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
import { AccessibleElement } from "../../Controls/AccessibleElement/AccessibleElement";
|
||||||
import "./TabComponent.less";
|
import "./TabComponent.less";
|
||||||
|
|
||||||
export interface TabContent {
|
export interface TabContent {
|
||||||
@@ -18,15 +19,11 @@ interface TabComponentProps {
|
|||||||
onTabIndexChange: (newIndex: number) => void;
|
onTabIndexChange: (newIndex: number) => void;
|
||||||
hideHeader: boolean;
|
hideHeader: boolean;
|
||||||
}
|
}
|
||||||
interface TabRefs {
|
|
||||||
[key: string]: HTMLElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We assume there's at least one tab
|
* We assume there's at least one tab
|
||||||
*/
|
*/
|
||||||
export class TabComponent extends React.Component<TabComponentProps> {
|
export class TabComponent extends React.Component<TabComponentProps> {
|
||||||
private tabRefs: TabRefs = {};
|
|
||||||
public constructor(props: TabComponentProps) {
|
public constructor(props: TabComponentProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
@@ -36,41 +33,11 @@ export class TabComponent extends React.Component<TabComponentProps> {
|
|||||||
throw new Error(msg);
|
throw new Error(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state = {
|
|
||||||
activeTabIndex: this.props.currentTabIndex,
|
|
||||||
};
|
|
||||||
|
|
||||||
private setActiveTab(index: number): void {
|
private setActiveTab(index: number): void {
|
||||||
this.setState({ activeTabIndex: index });
|
this.setState({ activeTabIndex: index });
|
||||||
this.props.onTabIndexChange(index);
|
this.props.onTabIndexChange(index);
|
||||||
}
|
}
|
||||||
private setIndex = (index: number) => {
|
|
||||||
const tab = this.tabRefs[index];
|
|
||||||
if (tab) {
|
|
||||||
tab.focus();
|
|
||||||
this.setState({ activeTabIndex: index });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private handlekeypress = (event: React.KeyboardEvent<HTMLSpanElement>): void => {
|
|
||||||
const { tabs, onTabIndexChange } = this.props;
|
|
||||||
const { activeTabIndex } = this.state;
|
|
||||||
const count = tabs.length;
|
|
||||||
|
|
||||||
const prevTab = () => {
|
|
||||||
this.setIndex((activeTabIndex - 1 + count) % count);
|
|
||||||
onTabIndexChange((activeTabIndex - 1 + count) % count);
|
|
||||||
};
|
|
||||||
const nextTab = () => {
|
|
||||||
this.setIndex((activeTabIndex + 1) % count);
|
|
||||||
onTabIndexChange((activeTabIndex + 1) % count);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (event.key === "ArrowLeft") {
|
|
||||||
prevTab();
|
|
||||||
} else if (event.key === "ArrowRight") {
|
|
||||||
nextTab();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private renderTabTitles(): JSX.Element[] {
|
private renderTabTitles(): JSX.Element[] {
|
||||||
return this.props.tabs.map((tab: Tab, index: number) => {
|
return this.props.tabs.map((tab: Tab, index: number) => {
|
||||||
@@ -80,32 +47,26 @@ export class TabComponent extends React.Component<TabComponentProps> {
|
|||||||
|
|
||||||
let className = "toggleSwitch";
|
let className = "toggleSwitch";
|
||||||
let ariaselected;
|
let ariaselected;
|
||||||
let tabindex;
|
|
||||||
if (index === this.props.currentTabIndex) {
|
if (index === this.props.currentTabIndex) {
|
||||||
className += " selectedToggle";
|
className += " selectedToggle";
|
||||||
ariaselected = true;
|
ariaselected = true;
|
||||||
tabindex = 0;
|
|
||||||
} else {
|
} else {
|
||||||
className += " unselectedToggle";
|
className += " unselectedToggle";
|
||||||
ariaselected = false;
|
ariaselected = false;
|
||||||
tabindex = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="tab" key={index}>
|
<div className="tab" key={index}>
|
||||||
<span
|
<AccessibleElement
|
||||||
|
as="span"
|
||||||
className={className}
|
className={className}
|
||||||
role="tab"
|
role="tab"
|
||||||
onClick={() => this.setActiveTab(index)}
|
onActivated={() => this.setActiveTab(index)}
|
||||||
onKeyDown={(event: React.KeyboardEvent<HTMLSpanElement>) => this.handlekeypress(event)}
|
|
||||||
onFocus={() => this.setState({ activeTabIndex: index })}
|
|
||||||
aria-label={`Select tab: ${tab.title}`}
|
aria-label={`Select tab: ${tab.title}`}
|
||||||
aria-selected={ariaselected}
|
aria-selected={ariaselected}
|
||||||
tabIndex={tabindex}
|
|
||||||
ref={(element) => (this.tabRefs[index] = element)}
|
|
||||||
>
|
>
|
||||||
{tab.title}
|
{tab.title}
|
||||||
</span>
|
</AccessibleElement>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -201,20 +201,20 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
|
|||||||
Autoscale
|
Autoscale
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<input
|
<input
|
||||||
id="Manual-input"
|
id="Manual-input"
|
||||||
className="throughputInputRadioBtn"
|
className="throughputInputRadioBtn"
|
||||||
aria-label="Manual database throughput"
|
aria-label="Manual database throughput"
|
||||||
checked={!isAutoscaleSelected}
|
checked={!isAutoscaleSelected}
|
||||||
type="radio"
|
type="radio"
|
||||||
aria-required={true}
|
aria-required={true}
|
||||||
role="radio"
|
role="radio"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
onChange={(e) => handleOnChangeMode(e, "Manual")}
|
onChange={(e) => handleOnChangeMode(e, "Manual")}
|
||||||
/>
|
/>
|
||||||
<label className="throughputInputRadioBtnLabel" htmlFor="Manual-input">
|
<label className="throughputInputRadioBtnLabel" htmlFor="Manual-input">
|
||||||
Manual
|
Manual
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
|
|||||||
@@ -347,12 +347,14 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
|
|||||||
ariaLabel="Set the throughput — Request Units per second (RU/s) — required for the workload. A read of a 1 KB document uses 1 RU. Select manual if you plan to scale RU/s yourself. Select autoscale to allow the system to scale RU/s based on usage."
|
ariaLabel="Set the throughput — Request Units per second (RU/s) — required for the workload. A read of a 1 KB document uses 1 RU. Select manual if you plan to scale RU/s yourself. Select autoscale to allow the system to scale RU/s based on usage."
|
||||||
className="panelInfoIcon"
|
className="panelInfoIcon"
|
||||||
iconName="Info"
|
iconName="Info"
|
||||||
|
role="tooltip"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
>
|
>
|
||||||
<IconBase
|
<IconBase
|
||||||
ariaLabel="Set the throughput — Request Units per second (RU/s) — required for the workload. A read of a 1 KB document uses 1 RU. Select manual if you plan to scale RU/s yourself. Select autoscale to allow the system to scale RU/s based on usage."
|
ariaLabel="Set the throughput — Request Units per second (RU/s) — required for the workload. A read of a 1 KB document uses 1 RU. Select manual if you plan to scale RU/s yourself. Select autoscale to allow the system to scale RU/s based on usage."
|
||||||
className="panelInfoIcon"
|
className="panelInfoIcon"
|
||||||
iconName="Info"
|
iconName="Info"
|
||||||
|
role="tooltip"
|
||||||
styles={[Function]}
|
styles={[Function]}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
theme={
|
theme={
|
||||||
@@ -633,7 +635,7 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
|
|||||||
aria-label="Set the throughput — Request Units per second (RU/s) — required for the workload. A read of a 1 KB document uses 1 RU. Select manual if you plan to scale RU/s yourself. Select autoscale to allow the system to scale RU/s based on usage."
|
aria-label="Set the throughput — Request Units per second (RU/s) — required for the workload. A read of a 1 KB document uses 1 RU. Select manual if you plan to scale RU/s yourself. Select autoscale to allow the system to scale RU/s based on usage."
|
||||||
className="panelInfoIcon root-57"
|
className="panelInfoIcon root-57"
|
||||||
data-icon-name="Info"
|
data-icon-name="Info"
|
||||||
role="img"
|
role="tooltip"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
>
|
>
|
||||||
|
|
||||||
@@ -1339,12 +1341,14 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
|
|||||||
ariaLabel="Set the max RU/s to the highest RU/s you want your container to scale to. The container will scale between 10% of max RU/s to the max RU/s based on usage."
|
ariaLabel="Set the max RU/s to the highest RU/s you want your container to scale to. The container will scale between 10% of max RU/s to the max RU/s based on usage."
|
||||||
className="panelInfoIcon"
|
className="panelInfoIcon"
|
||||||
iconName="Info"
|
iconName="Info"
|
||||||
|
role="tooltip"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
>
|
>
|
||||||
<IconBase
|
<IconBase
|
||||||
ariaLabel="Set the max RU/s to the highest RU/s you want your container to scale to. The container will scale between 10% of max RU/s to the max RU/s based on usage."
|
ariaLabel="Set the max RU/s to the highest RU/s you want your container to scale to. The container will scale between 10% of max RU/s to the max RU/s based on usage."
|
||||||
className="panelInfoIcon"
|
className="panelInfoIcon"
|
||||||
iconName="Info"
|
iconName="Info"
|
||||||
|
role="tooltip"
|
||||||
styles={[Function]}
|
styles={[Function]}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
theme={
|
theme={
|
||||||
@@ -1625,7 +1629,7 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
|
|||||||
aria-label="Set the max RU/s to the highest RU/s you want your container to scale to. The container will scale between 10% of max RU/s to the max RU/s based on usage."
|
aria-label="Set the max RU/s to the highest RU/s you want your container to scale to. The container will scale between 10% of max RU/s to the max RU/s based on usage."
|
||||||
className="panelInfoIcon root-57"
|
className="panelInfoIcon root-57"
|
||||||
data-icon-name="Info"
|
data-icon-name="Info"
|
||||||
role="img"
|
role="tooltip"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
>
|
>
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
IButtonStyles,
|
IButtonStyles,
|
||||||
IconButton,
|
IconButton,
|
||||||
IContextualMenuItemProps,
|
IContextualMenuItemProps,
|
||||||
IContextualMenuProps,
|
IContextualMenuProps
|
||||||
} from "@fluentui/react";
|
} from "@fluentui/react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import AnimateHeight from "react-animate-height";
|
import AnimateHeight from "react-animate-height";
|
||||||
|
|||||||
@@ -40,30 +40,32 @@ exports[`TreeNodeComponent does not render children by default 1`] = `
|
|||||||
onKeyPress={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="treeitem"
|
role="treeitem"
|
||||||
>
|
>
|
||||||
<div
|
<div>
|
||||||
className="treeNodeHeader "
|
<div
|
||||||
data-test="label"
|
className="treeNodeHeader "
|
||||||
style={
|
data-test="label"
|
||||||
Object {
|
style={
|
||||||
"paddingLeft": 9,
|
Object {
|
||||||
|
"paddingLeft": 9,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
tabIndex={-1}
|
||||||
tabIndex={-1}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
alt="label branch is collapsed"
|
|
||||||
className="expandCollapseIcon"
|
|
||||||
onKeyPress={[Function]}
|
|
||||||
role="button"
|
|
||||||
src=""
|
|
||||||
tabIndex={0}
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
className="nodeLabel"
|
|
||||||
title="label"
|
|
||||||
>
|
>
|
||||||
label
|
<img
|
||||||
</span>
|
alt="label branch is collapsed"
|
||||||
|
className="expandCollapseIcon"
|
||||||
|
onKeyPress={[Function]}
|
||||||
|
role="button"
|
||||||
|
src=""
|
||||||
|
tabIndex={0}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
className="nodeLabel"
|
||||||
|
title="label"
|
||||||
|
>
|
||||||
|
label
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="loadingIconContainer"
|
className="loadingIconContainer"
|
||||||
@@ -143,78 +145,80 @@ exports[`TreeNodeComponent renders a simple node (sorted children, expanded) 1`]
|
|||||||
onKeyPress={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="treeitem"
|
role="treeitem"
|
||||||
>
|
>
|
||||||
<div
|
<div>
|
||||||
className="treeNodeHeader "
|
|
||||||
data-test="label"
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"paddingLeft": 23,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tabIndex={-1}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
alt="label branch is expanded"
|
|
||||||
className="expandCollapseIcon"
|
|
||||||
onKeyPress={[Function]}
|
|
||||||
role="button"
|
|
||||||
src=""
|
|
||||||
tabIndex={0}
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
className="nodeLabel"
|
|
||||||
title="label"
|
|
||||||
>
|
|
||||||
label
|
|
||||||
</span>
|
|
||||||
<div
|
<div
|
||||||
onContextMenu={[Function]}
|
className="treeNodeHeader "
|
||||||
onKeyPress={[Function]}
|
data-test="label"
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"paddingLeft": 23,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tabIndex={-1}
|
||||||
>
|
>
|
||||||
<CustomizedIconButton
|
<img
|
||||||
ariaLabel="More"
|
alt="label branch is expanded"
|
||||||
className="treeMenuEllipsis"
|
className="expandCollapseIcon"
|
||||||
menuIconProps={
|
onKeyPress={[Function]}
|
||||||
Object {
|
role="button"
|
||||||
"iconName": "More",
|
src=""
|
||||||
"styles": Object {
|
tabIndex={0}
|
||||||
"root": Object {
|
|
||||||
"fontSize": "18px",
|
|
||||||
"fontWeight": "bold",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
menuProps={
|
|
||||||
Object {
|
|
||||||
"contextualMenuItemAs": [Function],
|
|
||||||
"coverTarget": true,
|
|
||||||
"directionalHint": 3,
|
|
||||||
"isBeakVisible": false,
|
|
||||||
"items": Array [
|
|
||||||
Object {
|
|
||||||
"className": undefined,
|
|
||||||
"disabled": true,
|
|
||||||
"key": "menuLabel",
|
|
||||||
"onClick": [Function],
|
|
||||||
"onRenderIcon": [Function],
|
|
||||||
"text": "menuLabel",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
"onMenuDismissed": [Function],
|
|
||||||
"onMenuOpened": [Function],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
name="More"
|
|
||||||
styles={
|
|
||||||
Object {
|
|
||||||
"rootFocused": Object {
|
|
||||||
"outline": "1px dashed undefined",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
title="More"
|
|
||||||
/>
|
/>
|
||||||
|
<span
|
||||||
|
className="nodeLabel"
|
||||||
|
title="label"
|
||||||
|
>
|
||||||
|
label
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
onContextMenu={[Function]}
|
||||||
|
onKeyPress={[Function]}
|
||||||
|
>
|
||||||
|
<CustomizedIconButton
|
||||||
|
ariaLabel="More"
|
||||||
|
className="treeMenuEllipsis"
|
||||||
|
menuIconProps={
|
||||||
|
Object {
|
||||||
|
"iconName": "More",
|
||||||
|
"styles": Object {
|
||||||
|
"root": Object {
|
||||||
|
"fontSize": "18px",
|
||||||
|
"fontWeight": "bold",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
menuProps={
|
||||||
|
Object {
|
||||||
|
"contextualMenuItemAs": [Function],
|
||||||
|
"coverTarget": true,
|
||||||
|
"directionalHint": 3,
|
||||||
|
"isBeakVisible": false,
|
||||||
|
"items": Array [
|
||||||
|
Object {
|
||||||
|
"className": undefined,
|
||||||
|
"disabled": true,
|
||||||
|
"key": "menuLabel",
|
||||||
|
"onClick": [Function],
|
||||||
|
"onRenderIcon": [Function],
|
||||||
|
"text": "menuLabel",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"onMenuDismissed": [Function],
|
||||||
|
"onMenuOpened": [Function],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
name="More"
|
||||||
|
styles={
|
||||||
|
Object {
|
||||||
|
"rootFocused": Object {
|
||||||
|
"outline": "1px dashed undefined",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
title="More"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -294,30 +298,32 @@ exports[`TreeNodeComponent renders loading icon 1`] = `
|
|||||||
onKeyPress={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="treeitem"
|
role="treeitem"
|
||||||
>
|
>
|
||||||
<div
|
<div>
|
||||||
className="treeNodeHeader "
|
<div
|
||||||
data-test="label"
|
className="treeNodeHeader "
|
||||||
style={
|
data-test="label"
|
||||||
Object {
|
style={
|
||||||
"paddingLeft": 9,
|
Object {
|
||||||
|
"paddingLeft": 9,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
tabIndex={-1}
|
||||||
tabIndex={-1}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
alt="label branch is expanded"
|
|
||||||
className="expandCollapseIcon"
|
|
||||||
onKeyPress={[Function]}
|
|
||||||
role="button"
|
|
||||||
src=""
|
|
||||||
tabIndex={0}
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
className="nodeLabel"
|
|
||||||
title="label"
|
|
||||||
>
|
>
|
||||||
label
|
<img
|
||||||
</span>
|
alt="label branch is expanded"
|
||||||
|
className="expandCollapseIcon"
|
||||||
|
onKeyPress={[Function]}
|
||||||
|
role="button"
|
||||||
|
src=""
|
||||||
|
tabIndex={0}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
className="nodeLabel"
|
||||||
|
title="label"
|
||||||
|
>
|
||||||
|
label
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="loadingIconContainer"
|
className="loadingIconContainer"
|
||||||
@@ -368,69 +374,71 @@ exports[`TreeNodeComponent renders sorted children, expanded, leaves and parents
|
|||||||
onKeyPress={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="treeitem"
|
role="treeitem"
|
||||||
>
|
>
|
||||||
<div
|
<div>
|
||||||
className="treeNodeHeader "
|
|
||||||
data-test="label"
|
|
||||||
style={
|
|
||||||
Object {
|
|
||||||
"paddingLeft": 23,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tabIndex={-1}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
alt="label branch is expanded"
|
|
||||||
className="expandCollapseIcon"
|
|
||||||
onKeyPress={[Function]}
|
|
||||||
role="button"
|
|
||||||
src=""
|
|
||||||
tabIndex={0}
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
className="nodeLabel"
|
|
||||||
title="label"
|
|
||||||
>
|
|
||||||
label
|
|
||||||
</span>
|
|
||||||
<div
|
<div
|
||||||
onContextMenu={[Function]}
|
className="treeNodeHeader "
|
||||||
onKeyPress={[Function]}
|
data-test="label"
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"paddingLeft": 23,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tabIndex={-1}
|
||||||
>
|
>
|
||||||
<CustomizedIconButton
|
<img
|
||||||
ariaLabel="More"
|
alt="label branch is expanded"
|
||||||
className="treeMenuEllipsis"
|
className="expandCollapseIcon"
|
||||||
menuIconProps={
|
onKeyPress={[Function]}
|
||||||
Object {
|
role="button"
|
||||||
"iconName": "More",
|
src=""
|
||||||
"styles": Object {
|
tabIndex={0}
|
||||||
"root": Object {
|
|
||||||
"fontSize": "18px",
|
|
||||||
"fontWeight": "bold",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
menuProps={
|
|
||||||
Object {
|
|
||||||
"contextualMenuItemAs": [Function],
|
|
||||||
"coverTarget": true,
|
|
||||||
"directionalHint": 3,
|
|
||||||
"isBeakVisible": false,
|
|
||||||
"items": Array [],
|
|
||||||
"onMenuDismissed": [Function],
|
|
||||||
"onMenuOpened": [Function],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
name="More"
|
|
||||||
styles={
|
|
||||||
Object {
|
|
||||||
"rootFocused": Object {
|
|
||||||
"outline": "1px dashed undefined",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
title="More"
|
|
||||||
/>
|
/>
|
||||||
|
<span
|
||||||
|
className="nodeLabel"
|
||||||
|
title="label"
|
||||||
|
>
|
||||||
|
label
|
||||||
|
</span>
|
||||||
|
<div
|
||||||
|
onContextMenu={[Function]}
|
||||||
|
onKeyPress={[Function]}
|
||||||
|
>
|
||||||
|
<CustomizedIconButton
|
||||||
|
ariaLabel="More"
|
||||||
|
className="treeMenuEllipsis"
|
||||||
|
menuIconProps={
|
||||||
|
Object {
|
||||||
|
"iconName": "More",
|
||||||
|
"styles": Object {
|
||||||
|
"root": Object {
|
||||||
|
"fontSize": "18px",
|
||||||
|
"fontWeight": "bold",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
menuProps={
|
||||||
|
Object {
|
||||||
|
"contextualMenuItemAs": [Function],
|
||||||
|
"coverTarget": true,
|
||||||
|
"directionalHint": 3,
|
||||||
|
"isBeakVisible": false,
|
||||||
|
"items": Array [],
|
||||||
|
"onMenuDismissed": [Function],
|
||||||
|
"onMenuOpened": [Function],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
name="More"
|
||||||
|
styles={
|
||||||
|
Object {
|
||||||
|
"rootFocused": Object {
|
||||||
|
"outline": "1px dashed undefined",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
title="More"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -538,30 +546,32 @@ exports[`TreeNodeComponent renders unsorted children by default 1`] = `
|
|||||||
onKeyPress={[Function]}
|
onKeyPress={[Function]}
|
||||||
role="treeitem"
|
role="treeitem"
|
||||||
>
|
>
|
||||||
<div
|
<div>
|
||||||
className="treeNodeHeader "
|
<div
|
||||||
data-test="label"
|
className="treeNodeHeader "
|
||||||
style={
|
data-test="label"
|
||||||
Object {
|
style={
|
||||||
"paddingLeft": 9,
|
Object {
|
||||||
|
"paddingLeft": 9,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
tabIndex={-1}
|
||||||
tabIndex={-1}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
alt="label branch is expanded"
|
|
||||||
className="expandCollapseIcon"
|
|
||||||
onKeyPress={[Function]}
|
|
||||||
role="button"
|
|
||||||
src=""
|
|
||||||
tabIndex={0}
|
|
||||||
/>
|
|
||||||
<span
|
|
||||||
className="nodeLabel"
|
|
||||||
title="label"
|
|
||||||
>
|
>
|
||||||
label
|
<img
|
||||||
</span>
|
alt="label branch is expanded"
|
||||||
|
className="expandCollapseIcon"
|
||||||
|
onKeyPress={[Function]}
|
||||||
|
role="button"
|
||||||
|
src=""
|
||||||
|
tabIndex={0}
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
className="nodeLabel"
|
||||||
|
title="label"
|
||||||
|
>
|
||||||
|
label
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="loadingIconContainer"
|
className="loadingIconContainer"
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ describe("CommandBarComponentButtonFactory tests", () => {
|
|||||||
updateUserContext({
|
updateUserContext({
|
||||||
databaseAccount: {
|
databaseAccount: {
|
||||||
properties: {
|
properties: {
|
||||||
capabilities: [{ name: "EnableMongo" }],
|
capabilities: [{ name: "EnableTable" }],
|
||||||
},
|
},
|
||||||
} as DatabaseAccount,
|
} as DatabaseAccount,
|
||||||
});
|
});
|
||||||
@@ -38,38 +38,6 @@ describe("CommandBarComponentButtonFactory tests", () => {
|
|||||||
);
|
);
|
||||||
expect(enableAzureSynapseLinkBtn).toBeDefined();
|
expect(enableAzureSynapseLinkBtn).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Button should not be visible for Tables API", () => {
|
|
||||||
updateUserContext({
|
|
||||||
databaseAccount: {
|
|
||||||
properties: {
|
|
||||||
capabilities: [{ name: "EnableTable" }],
|
|
||||||
},
|
|
||||||
} as DatabaseAccount,
|
|
||||||
});
|
|
||||||
|
|
||||||
const buttons = CommandBarComponentButtonFactory.createStaticCommandBarButtons(mockExplorer, selectedNodeState);
|
|
||||||
const enableAzureSynapseLinkBtn = buttons.find(
|
|
||||||
(button) => button.commandButtonLabel === enableAzureSynapseLinkBtnLabel
|
|
||||||
);
|
|
||||||
expect(enableAzureSynapseLinkBtn).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Button should not be visible for Cassandra API", () => {
|
|
||||||
updateUserContext({
|
|
||||||
databaseAccount: {
|
|
||||||
properties: {
|
|
||||||
capabilities: [{ name: "EnableCassandra" }],
|
|
||||||
},
|
|
||||||
} as DatabaseAccount,
|
|
||||||
});
|
|
||||||
|
|
||||||
const buttons = CommandBarComponentButtonFactory.createStaticCommandBarButtons(mockExplorer, selectedNodeState);
|
|
||||||
const enableAzureSynapseLinkBtn = buttons.find(
|
|
||||||
(button) => button.commandButtonLabel === enableAzureSynapseLinkBtnLabel
|
|
||||||
);
|
|
||||||
expect(enableAzureSynapseLinkBtn).toBeUndefined();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Enable notebook button", () => {
|
describe("Enable notebook button", () => {
|
||||||
|
|||||||
@@ -51,13 +51,11 @@ export function createStaticCommandBarButtons(
|
|||||||
const buttons: CommandButtonComponentProps[] = [];
|
const buttons: CommandButtonComponentProps[] = [];
|
||||||
|
|
||||||
buttons.push(newCollectionBtn);
|
buttons.push(newCollectionBtn);
|
||||||
if (userContext.apiType !== "Tables" && userContext.apiType !== "Cassandra") {
|
|
||||||
const addSynapseLink = createOpenSynapseLinkDialogButton(container);
|
|
||||||
|
|
||||||
if (addSynapseLink) {
|
const addSynapseLink = createOpenSynapseLinkDialogButton(container);
|
||||||
buttons.push(createDivider());
|
if (addSynapseLink) {
|
||||||
buttons.push(addSynapseLink);
|
buttons.push(createDivider());
|
||||||
}
|
buttons.push(addSynapseLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userContext.apiType !== "Tables") {
|
if (userContext.apiType !== "Tables") {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
TeachingBubble,
|
TeachingBubble,
|
||||||
Text,
|
Text,
|
||||||
TooltipHost,
|
TooltipHost
|
||||||
} from "@fluentui/react";
|
} from "@fluentui/react";
|
||||||
import * as Constants from "Common/Constants";
|
import * as Constants from "Common/Constants";
|
||||||
import { createCollection } from "Common/dataAccess/createCollection";
|
import { createCollection } from "Common/dataAccess/createCollection";
|
||||||
@@ -100,6 +100,7 @@ export interface AddCollectionPanelState {
|
|||||||
isExecuting: boolean;
|
isExecuting: boolean;
|
||||||
isThroughputCapExceeded: boolean;
|
isThroughputCapExceeded: boolean;
|
||||||
teachingBubbleStep: number;
|
teachingBubbleStep: number;
|
||||||
|
isParentTooltipVisible:boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AddCollectionPanel extends React.Component<AddCollectionPanelProps, AddCollectionPanelState> {
|
export class AddCollectionPanel extends React.Component<AddCollectionPanelProps, AddCollectionPanelState> {
|
||||||
@@ -108,6 +109,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
private collectionThroughput: number;
|
private collectionThroughput: number;
|
||||||
private isCollectionAutoscale: boolean;
|
private isCollectionAutoscale: boolean;
|
||||||
private isCostAcknowledged: boolean;
|
private isCostAcknowledged: boolean;
|
||||||
|
|
||||||
|
|
||||||
constructor(props: AddCollectionPanelProps) {
|
constructor(props: AddCollectionPanelProps) {
|
||||||
super(props);
|
super(props);
|
||||||
@@ -134,13 +136,16 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
isExecuting: false,
|
isExecuting: false,
|
||||||
isThroughputCapExceeded: false,
|
isThroughputCapExceeded: false,
|
||||||
teachingBubbleStep: 0,
|
teachingBubbleStep: 0,
|
||||||
|
isParentTooltipVisible: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount(): void {
|
componentDidMount(): void {
|
||||||
if (this.state.teachingBubbleStep === 0 && this.props.isQuickstart) {
|
if (this.state.teachingBubbleStep === 0 && this.props.isQuickstart) {
|
||||||
this.setState({ teachingBubbleStep: 1 });
|
this.setState({ teachingBubbleStep: 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): JSX.Element {
|
render(): JSX.Element {
|
||||||
@@ -408,6 +413,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
|
|||||||
className="panelInfoIcon"
|
className="panelInfoIcon"
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
ariaLabel={`Unique identifier for the ${getCollectionName().toLocaleLowerCase()} and used for id-based routing through REST and all SDKs.`}
|
ariaLabel={`Unique identifier for the ${getCollectionName().toLocaleLowerCase()} and used for id-based routing through REST and all SDKs.`}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</TooltipHost>
|
</TooltipHost>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
TeachingBubble,
|
TeachingBubble,
|
||||||
TeachingBubbleContent,
|
TeachingBubbleContent,
|
||||||
Text,
|
Text
|
||||||
} from "@fluentui/react";
|
} from "@fluentui/react";
|
||||||
import { sendMessage } from "Common/MessageHandler";
|
import { sendMessage } from "Common/MessageHandler";
|
||||||
import { MessageTypes } from "Contracts/ExplorerContracts";
|
import { MessageTypes } from "Contracts/ExplorerContracts";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import * as Constants from "../../../Common/Constants";
|
import * as Constants from "../../../Common/Constants";
|
||||||
import { configContext } from "../../../ConfigContext";
|
import { configContext, Platform } from "../../../ConfigContext";
|
||||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||||
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";
|
||||||
@@ -9,8 +9,6 @@ import { isInvalidParentFrameOrigin, isReadyMessage } from "../../../Utils/Messa
|
|||||||
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../../Utils/NotificationConsoleUtils";
|
import { logConsoleError, logConsoleInfo, logConsoleProgress } from "../../../Utils/NotificationConsoleUtils";
|
||||||
import Explorer from "../../Explorer";
|
import Explorer from "../../Explorer";
|
||||||
import TabsBase from "../TabsBase";
|
import TabsBase from "../TabsBase";
|
||||||
import { getMongoShellOrigin } from "./getMongoShellOrigin";
|
|
||||||
import { getMongoShellUrl } from "./getMongoShellUrl";
|
|
||||||
|
|
||||||
//eslint-disable-next-line
|
//eslint-disable-next-line
|
||||||
class MessageType {
|
class MessageType {
|
||||||
@@ -49,6 +47,7 @@ export default class MongoShellTabComponent extends Component<
|
|||||||
IMongoShellTabComponentProps,
|
IMongoShellTabComponentProps,
|
||||||
IMongoShellTabComponentStates
|
IMongoShellTabComponentStates
|
||||||
> {
|
> {
|
||||||
|
private _runtimeEndpoint: string;
|
||||||
private _logTraces: Map<string, number>;
|
private _logTraces: Map<string, number>;
|
||||||
|
|
||||||
constructor(props: IMongoShellTabComponentProps) {
|
constructor(props: IMongoShellTabComponentProps) {
|
||||||
@@ -56,7 +55,7 @@ export default class MongoShellTabComponent extends Component<
|
|||||||
this._logTraces = new Map();
|
this._logTraces = new Map();
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
url: getMongoShellUrl(),
|
url: this.getURL(),
|
||||||
};
|
};
|
||||||
|
|
||||||
props.onMongoShellTabAccessor({
|
props.onMongoShellTabAccessor({
|
||||||
@@ -66,6 +65,22 @@ export default class MongoShellTabComponent extends Component<
|
|||||||
window.addEventListener("message", this.handleMessage.bind(this), false);
|
window.addEventListener("message", this.handleMessage.bind(this), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getURL(): string {
|
||||||
|
const { databaseAccount: account } = userContext;
|
||||||
|
const resourceId = account?.id;
|
||||||
|
const accountName = account?.name;
|
||||||
|
const mongoEndpoint = account?.properties?.mongoEndpoint || account?.properties?.documentEndpoint;
|
||||||
|
|
||||||
|
this._runtimeEndpoint = configContext.platform === Platform.Hosted ? configContext.BACKEND_ENDPOINT : "";
|
||||||
|
const extensionEndpoint: string = configContext.BACKEND_ENDPOINT || this._runtimeEndpoint || "";
|
||||||
|
let baseUrl = "/content/mongoshell/dist/";
|
||||||
|
if (userContext.portalEnv === "localhost") {
|
||||||
|
baseUrl = "/content/mongoshell/";
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${extensionEndpoint}${baseUrl}index.html?resourceId=${resourceId}&accountName=${accountName}&mongoEndpoint=${mongoEndpoint}`;
|
||||||
|
}
|
||||||
|
|
||||||
//eslint-disable-next-line
|
//eslint-disable-next-line
|
||||||
public setContentFocus(event: React.SyntheticEvent<HTMLIFrameElement, Event>): void {}
|
public setContentFocus(event: React.SyntheticEvent<HTMLIFrameElement, Event>): void {}
|
||||||
|
|
||||||
@@ -121,7 +136,6 @@ export default class MongoShellTabComponent extends Component<
|
|||||||
const collectionId = this.props.collection.id();
|
const collectionId = this.props.collection.id();
|
||||||
const apiEndpoint = configContext.BACKEND_ENDPOINT;
|
const apiEndpoint = configContext.BACKEND_ENDPOINT;
|
||||||
const encryptedAuthToken: string = userContext.accessToken;
|
const encryptedAuthToken: string = userContext.accessToken;
|
||||||
const targetOrigin = getMongoShellOrigin();
|
|
||||||
|
|
||||||
shellIframe.contentWindow.postMessage(
|
shellIframe.contentWindow.postMessage(
|
||||||
{
|
{
|
||||||
@@ -137,7 +151,7 @@ export default class MongoShellTabComponent extends Component<
|
|||||||
apiEndpoint: apiEndpoint,
|
apiEndpoint: apiEndpoint,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
targetOrigin
|
configContext.BACKEND_ENDPOINT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
import { extractFeatures } from "Platform/Hosted/extractFeatures";
|
|
||||||
import { configContext } from "../../../ConfigContext";
|
|
||||||
import { updateUserContext } from "../../../UserContext";
|
|
||||||
import { getMongoShellOrigin } from "./getMongoShellOrigin";
|
|
||||||
|
|
||||||
describe("getMongoShellOrigin", () => {
|
|
||||||
(window as { origin: string }).origin = "window_origin";
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
updateUserContext({
|
|
||||||
features: extractFeatures(
|
|
||||||
new URLSearchParams({
|
|
||||||
"feature.enableLegacyMongoShellV1": "false",
|
|
||||||
"feature.enableLegacyMongoShellV2": "false",
|
|
||||||
"feature.enableLegacyMongoShellV1Debug": "false",
|
|
||||||
"feature.enableLegacyMongoShellV2Debug": "false",
|
|
||||||
"feature.loadLegacyMongoShellFromBE": "false",
|
|
||||||
})
|
|
||||||
),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return by default", () => {
|
|
||||||
expect(getMongoShellOrigin()).toBe(window.origin);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return window.origin when enableLegacyMongoShellV1", () => {
|
|
||||||
updateUserContext({
|
|
||||||
features: extractFeatures(
|
|
||||||
new URLSearchParams({
|
|
||||||
"feature.enableLegacyMongoShellV1": "true",
|
|
||||||
})
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(getMongoShellOrigin()).toBe(window.origin);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return window.origin when enableLegacyMongoShellV2===true", () => {
|
|
||||||
updateUserContext({
|
|
||||||
features: extractFeatures(
|
|
||||||
new URLSearchParams({
|
|
||||||
"feature.enableLegacyMongoShellV2": "true",
|
|
||||||
})
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(getMongoShellOrigin()).toBe(window.origin);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return window.origin when enableLegacyMongoShellV1Debug===true", () => {
|
|
||||||
updateUserContext({
|
|
||||||
features: extractFeatures(
|
|
||||||
new URLSearchParams({
|
|
||||||
"feature.enableLegacyMongoShellV1Debug": "true",
|
|
||||||
})
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(getMongoShellOrigin()).toBe(window.origin);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return window.origin when enableLegacyMongoShellV2Debug===true", () => {
|
|
||||||
updateUserContext({
|
|
||||||
features: extractFeatures(
|
|
||||||
new URLSearchParams({
|
|
||||||
"feature.enableLegacyMongoShellV2Debug": "true",
|
|
||||||
})
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(getMongoShellOrigin()).toBe(window.origin);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return BACKEND_ENDPOINT when loadLegacyMongoShellFromBE===true", () => {
|
|
||||||
updateUserContext({
|
|
||||||
features: extractFeatures(
|
|
||||||
new URLSearchParams({
|
|
||||||
"feature.loadLegacyMongoShellFromBE": "true",
|
|
||||||
})
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(getMongoShellOrigin()).toBe(configContext.BACKEND_ENDPOINT);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
import { configContext } from "../../../ConfigContext";
|
|
||||||
import { userContext } from "../../../UserContext";
|
|
||||||
|
|
||||||
export function getMongoShellOrigin(): string {
|
|
||||||
if (userContext.features.loadLegacyMongoShellFromBE === true) {
|
|
||||||
return configContext.BACKEND_ENDPOINT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return window.origin;
|
|
||||||
}
|
|
||||||
@@ -1,206 +0,0 @@
|
|||||||
import { extractFeatures } from "Platform/Hosted/extractFeatures";
|
|
||||||
import { Platform, configContext, resetConfigContext, updateConfigContext } from "../../../ConfigContext";
|
|
||||||
import { updateUserContext, userContext } from "../../../UserContext";
|
|
||||||
import { getExtensionEndpoint, getMongoShellUrl } from "./getMongoShellUrl";
|
|
||||||
|
|
||||||
const mongoBackendEndpoint = "https://localhost:1234";
|
|
||||||
|
|
||||||
describe("getMongoShellUrl", () => {
|
|
||||||
let queryString = "";
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
resetConfigContext();
|
|
||||||
|
|
||||||
updateConfigContext({
|
|
||||||
BACKEND_ENDPOINT: mongoBackendEndpoint,
|
|
||||||
platform: Platform.Hosted,
|
|
||||||
});
|
|
||||||
|
|
||||||
updateUserContext({
|
|
||||||
subscriptionId: "fakeSubscriptionId",
|
|
||||||
resourceGroup: "fakeResourceGroup",
|
|
||||||
databaseAccount: {
|
|
||||||
id: "fakeId",
|
|
||||||
name: "fakeName",
|
|
||||||
location: "fakeLocation",
|
|
||||||
type: "fakeType",
|
|
||||||
kind: "fakeKind",
|
|
||||||
properties: {
|
|
||||||
documentEndpoint: "fakeDocumentEndpoint",
|
|
||||||
tableEndpoint: "fakeTableEndpoint",
|
|
||||||
gremlinEndpoint: "fakeGremlinEndpoint",
|
|
||||||
cassandraEndpoint: "fakeCassandraEndpoint",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
features: extractFeatures(
|
|
||||||
new URLSearchParams({
|
|
||||||
"feature.enableLegacyMongoShellV1": "false",
|
|
||||||
"feature.enableLegacyMongoShellV2": "false",
|
|
||||||
"feature.enableLegacyMongoShellV1Debug": "false",
|
|
||||||
"feature.enableLegacyMongoShellV2Debug": "false",
|
|
||||||
"feature.loadLegacyMongoShellFromBE": "false",
|
|
||||||
})
|
|
||||||
),
|
|
||||||
portalEnv: "prod",
|
|
||||||
});
|
|
||||||
|
|
||||||
queryString = `resourceId=${userContext.databaseAccount.id}&accountName=${userContext.databaseAccount.name}&mongoEndpoint=${userContext.databaseAccount.properties.documentEndpoint}`;
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return /mongoshell/indexv2.html by default ", () => {
|
|
||||||
expect(getMongoShellUrl()).toBe(`/mongoshell/indexv2.html?${queryString}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return /mongoshell/indexv2.html when portalEnv==localhost ", () => {
|
|
||||||
updateUserContext({
|
|
||||||
portalEnv: "localhost",
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(getMongoShellUrl()).toBe(`/mongoshell/indexv2.html?${queryString}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return /mongoshell/index.html when enableLegacyMongoShellV1===true", () => {
|
|
||||||
updateUserContext({
|
|
||||||
features: extractFeatures(
|
|
||||||
new URLSearchParams({
|
|
||||||
"feature.enableLegacyMongoShellV1": "true",
|
|
||||||
})
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(getMongoShellUrl()).toBe(`/mongoshell/index.html?${queryString}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return /mongoshell/index.html when enableLegacyMongoShellV2===true", () => {
|
|
||||||
updateUserContext({
|
|
||||||
features: extractFeatures(
|
|
||||||
new URLSearchParams({
|
|
||||||
"feature.enableLegacyMongoShellV2": "true",
|
|
||||||
})
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(getMongoShellUrl()).toBe(`/mongoshell/indexv2.html?${queryString}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return /mongoshell/index.html when enableLegacyMongoShellV1Debug===true", () => {
|
|
||||||
updateUserContext({
|
|
||||||
features: extractFeatures(
|
|
||||||
new URLSearchParams({
|
|
||||||
"feature.enableLegacyMongoShellV1Debug": "true",
|
|
||||||
})
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(getMongoShellUrl()).toBe(`/mongoshell/debug/index.html?${queryString}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return /mongoshell/index.html when enableLegacyMongoShellV2Debug===true", () => {
|
|
||||||
updateUserContext({
|
|
||||||
features: extractFeatures(
|
|
||||||
new URLSearchParams({
|
|
||||||
"feature.enableLegacyMongoShellV2Debug": "true",
|
|
||||||
})
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(getMongoShellUrl()).toBe(`/mongoshell/debug/indexv2.html?${queryString}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("loadLegacyMongoShellFromBE===true", () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
resetConfigContext();
|
|
||||||
updateConfigContext({
|
|
||||||
BACKEND_ENDPOINT: mongoBackendEndpoint,
|
|
||||||
platform: Platform.Hosted,
|
|
||||||
});
|
|
||||||
|
|
||||||
updateUserContext({
|
|
||||||
features: extractFeatures(
|
|
||||||
new URLSearchParams({
|
|
||||||
"feature.loadLegacyMongoShellFromBE": "true",
|
|
||||||
})
|
|
||||||
),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should return /mongoshell/index.html", () => {
|
|
||||||
const endpoint = getExtensionEndpoint(configContext.platform, configContext.BACKEND_ENDPOINT);
|
|
||||||
expect(getMongoShellUrl()).toBe(`${endpoint}/content/mongoshell/debug/index.html?${queryString}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("configContext.platform !== Platform.Hosted, should return /mongoshell/indexv2.html", () => {
|
|
||||||
updateConfigContext({
|
|
||||||
platform: Platform.Portal,
|
|
||||||
});
|
|
||||||
|
|
||||||
const endpoint = getExtensionEndpoint(configContext.platform, configContext.BACKEND_ENDPOINT);
|
|
||||||
expect(getMongoShellUrl()).toBe(`${endpoint}/content/mongoshell/debug/index.html?${queryString}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("configContext.BACKEND_ENDPOINT !== '' and configContext.platform !== Platform.Hosted, should return /mongoshell/indexv2.html", () => {
|
|
||||||
resetConfigContext();
|
|
||||||
updateConfigContext({
|
|
||||||
platform: Platform.Portal,
|
|
||||||
BACKEND_ENDPOINT: mongoBackendEndpoint,
|
|
||||||
});
|
|
||||||
|
|
||||||
const endpoint = getExtensionEndpoint(configContext.platform, configContext.BACKEND_ENDPOINT);
|
|
||||||
expect(getMongoShellUrl()).toBe(`${endpoint}/content/mongoshell/debug/index.html?${queryString}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("configContext.BACKEND_ENDPOINT === '' and configContext.platform === Platform.Hosted, should return /mongoshell/indexv2.html ", () => {
|
|
||||||
resetConfigContext();
|
|
||||||
updateConfigContext({
|
|
||||||
platform: Platform.Hosted,
|
|
||||||
});
|
|
||||||
|
|
||||||
const endpoint = getExtensionEndpoint(configContext.platform, configContext.BACKEND_ENDPOINT);
|
|
||||||
expect(getMongoShellUrl()).toBe(`${endpoint}/content/mongoshell/debug/index.html?${queryString}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("configContext.BACKEND_ENDPOINT === '' and configContext.platform !== Platform.Hosted, should return /mongoshell/indexv2.html", () => {
|
|
||||||
resetConfigContext();
|
|
||||||
updateConfigContext({
|
|
||||||
platform: Platform.Portal,
|
|
||||||
});
|
|
||||||
|
|
||||||
const endpoint = getExtensionEndpoint(configContext.platform, configContext.BACKEND_ENDPOINT);
|
|
||||||
expect(getMongoShellUrl()).toBe(`${endpoint}/content/mongoshell/debug/index.html?${queryString}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("getExtensionEndpoint", () => {
|
|
||||||
it("when platform === Platform.Hosted, backendEndpoint is undefined ", () => {
|
|
||||||
expect(getExtensionEndpoint(Platform.Hosted, undefined)).toBe("");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("when platform === Platform.Hosted, backendEndpoint === ''", () => {
|
|
||||||
expect(getExtensionEndpoint(Platform.Hosted, "")).toBe("");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("when platform === Platform.Hosted, backendEndpoint === null", () => {
|
|
||||||
expect(getExtensionEndpoint(Platform.Hosted, null)).toBe("");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("when platform === Platform.Hosted, backendEndpoint != '' ", () => {
|
|
||||||
expect(getExtensionEndpoint(Platform.Hosted, "foo")).toBe("foo");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("when platform === Platform.Portal, backendEndpoint is udefined ", () => {
|
|
||||||
expect(getExtensionEndpoint(Platform.Portal, undefined)).toBe("");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("when platform === Platform.Portal, backendEndpoint === '' ", () => {
|
|
||||||
expect(getExtensionEndpoint(Platform.Portal, "")).toBe("");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("when platform === Platform.Portal, backendEndpoint === null", () => {
|
|
||||||
expect(getExtensionEndpoint(Platform.Portal, null)).toBe("");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("when platform !== Platform.Portal, backendEndpoint != '' ", () => {
|
|
||||||
expect(getExtensionEndpoint(Platform.Portal, "foo")).toBe("foo");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
import { configContext, Platform } from "../../../ConfigContext";
|
|
||||||
import { userContext } from "../../../UserContext";
|
|
||||||
|
|
||||||
export function getMongoShellUrl(): string {
|
|
||||||
const { databaseAccount: account } = userContext;
|
|
||||||
const resourceId = account?.id;
|
|
||||||
const accountName = account?.name;
|
|
||||||
const mongoEndpoint = account?.properties?.mongoEndpoint || account?.properties?.documentEndpoint;
|
|
||||||
const queryString = `resourceId=${resourceId}&accountName=${accountName}&mongoEndpoint=${mongoEndpoint}`;
|
|
||||||
|
|
||||||
if (userContext.features.enableLegacyMongoShellV1 === true) {
|
|
||||||
return `/mongoshell/index.html?${queryString}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userContext.features.enableLegacyMongoShellV1Debug === true) {
|
|
||||||
return `/mongoshell/debug/index.html?${queryString}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userContext.features.enableLegacyMongoShellV2 === true) {
|
|
||||||
return `/mongoshell/indexv2.html?${queryString}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userContext.features.enableLegacyMongoShellV2Debug === true) {
|
|
||||||
return `/mongoshell/debug/indexv2.html?${queryString}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userContext.portalEnv === "localhost") {
|
|
||||||
return `/mongoshell/indexv2.html?${queryString}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (userContext.features.loadLegacyMongoShellFromBE === true) {
|
|
||||||
const extensionEndpoint: string = getExtensionEndpoint(configContext.platform, configContext.BACKEND_ENDPOINT);
|
|
||||||
return `${extensionEndpoint}/content/mongoshell/debug/index.html?${queryString}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return `/mongoshell/indexv2.html?${queryString}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getExtensionEndpoint(platform: string, backendEndpoint: string): string {
|
|
||||||
const runtimeEndpoint = platform === Platform.Hosted ? backendEndpoint : "";
|
|
||||||
|
|
||||||
const extensionEndpoint: string = backendEndpoint || runtimeEndpoint || "";
|
|
||||||
|
|
||||||
return extensionEndpoint;
|
|
||||||
}
|
|
||||||
@@ -30,11 +30,6 @@ export type Features = {
|
|||||||
readonly mongoProxyAPIs?: string;
|
readonly mongoProxyAPIs?: string;
|
||||||
readonly enableThroughputCap: boolean;
|
readonly enableThroughputCap: boolean;
|
||||||
readonly enableHierarchicalKeys: boolean;
|
readonly enableHierarchicalKeys: boolean;
|
||||||
readonly enableLegacyMongoShellV1: boolean;
|
|
||||||
readonly enableLegacyMongoShellV1Debug: boolean;
|
|
||||||
readonly enableLegacyMongoShellV2: boolean;
|
|
||||||
readonly enableLegacyMongoShellV2Debug: boolean;
|
|
||||||
readonly loadLegacyMongoShellFromBE: boolean;
|
|
||||||
|
|
||||||
// can be set via both flight and feature flag
|
// can be set via both flight and feature flag
|
||||||
autoscaleDefault: boolean;
|
autoscaleDefault: boolean;
|
||||||
@@ -97,11 +92,6 @@ export function extractFeatures(given = new URLSearchParams(window.location.sear
|
|||||||
notebooksDownBanner: "true" === get("notebooksDownBanner"),
|
notebooksDownBanner: "true" === get("notebooksDownBanner"),
|
||||||
enableThroughputCap: "true" === get("enablethroughputcap"),
|
enableThroughputCap: "true" === get("enablethroughputcap"),
|
||||||
enableHierarchicalKeys: "true" === get("enablehierarchicalkeys"),
|
enableHierarchicalKeys: "true" === get("enablehierarchicalkeys"),
|
||||||
enableLegacyMongoShellV1: "true" === get("enablelegacymongoshellv1"),
|
|
||||||
enableLegacyMongoShellV1Debug: "true" === get("enablelegacymongoshellv1debug"),
|
|
||||||
enableLegacyMongoShellV2: "true" === get("enablelegacymongoshellv2"),
|
|
||||||
enableLegacyMongoShellV2Debug: "true" === get("enablelegacymongoshellv2debug"),
|
|
||||||
loadLegacyMongoShellFromBE: "true" === get("loadlegacymongoshellfrombe"),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user