Compare commits

..

9 Commits

Author SHA1 Message Date
Sampath
6247d1a97d autofocus removed for input element 2023-04-16 22:05:10 +05:30
Sampath
4ec6108f41 Commit to my local branch 2023-04-04 11:11:10 +05:30
Sampath
d63f1251dd Merge branch 'master' of https://github.com/MokireddySampath/cosmos-explorer 2023-04-04 11:10:39 +05:30
Sampath
40755e297d Merge branch 'master' of https://github.com/MokireddySampath/cosmos-explorer 2023-03-13 12:10:26 +05:30
Sampath
b84d5b572c sev2 accessibilitydefects in data explorer 2023-03-10 23:22:42 +05:30
Sampath
c711b59f7d alt text for decorative images 2023-02-25 23:25:12 +05:30
Sampath
e945963cf9 Revert "alt text attribute for images"
This reverts commit 5a660551c6.
2023-02-25 23:11:20 +05:30
Sampath
5a660551c6 alt text attribute for images 2023-02-25 22:53:52 +05:30
Sampath
b2d59f3b3f autoscale and manual radiobuutton fixes 2023-02-06 23:48:50 +05:30
21 changed files with 368 additions and 895 deletions

View File

@@ -18,8 +18,7 @@ module.exports = {
// clearMocks: false,
// Indicates whether the coverage information should be collected while executing the test
collectCoverage: process.env.skipCodeCoverage === "true" ? false : true,
collectCoverage: true,
// An array of glob patterns indicating a set of files for which coverage information should be collected
collectCoverageFrom: ["src/**/*.{js,jsx,ts,tsx}"],

View File

@@ -55,7 +55,6 @@ export const EntityValue: FunctionComponent<TableEntityProps> = ({
label={entityValueLabel && entityValueLabel}
className="addEntityTextField"
id="entityValueId"
autoFocus
disabled={isEntityValueDisable}
type={entityValueType}
placeholder={entityValuePlaceholder}

View File

@@ -7,7 +7,7 @@ import {
IStackTokens,
Stack,
TextField,
TooltipHost,
TooltipHost
} from "@fluentui/react";
import React, { FunctionComponent } from "react";
import DeleteIcon from "../../images/delete.svg";
@@ -136,6 +136,7 @@ export const TableEntity: FunctionComponent<TableEntityProps> = ({
onEntityTimeValueChange={onEntityTimeValueChange}
/>
{!isEntityValueDisable && (
<TooltipHost content="Edit property" id="editTooltip">
<div tabIndex={0}>
<Image
@@ -149,6 +150,7 @@ export const TableEntity: FunctionComponent<TableEntityProps> = ({
/>
</div>
</TooltipHost>
)}
{isDeleteOptionVisible && userContext.apiType !== "Cassandra" && (
<TooltipHost content="Delete property" id="deleteTooltip">

View File

@@ -15,13 +15,13 @@ import {
import {
ChangeFeedPolicyState,
GeospatialConfigType,
getSanitizedInputValue,
IsComponentDirtyResult,
isDirty,
TtlOff,
TtlOn,
TtlOnNoDefault,
TtlType,
getSanitizedInputValue,
isDirty,
} from "../SettingsUtils";
import { ToolTipLabelComponent } from "./ToolTipLabelComponent";
@@ -55,18 +55,6 @@ export interface SubSettingsComponentProps {
onSubSettingsSaveableChange: (isSubSettingsSaveable: boolean) => void;
onSubSettingsDiscardableChange: (isSubSettingsDiscardable: boolean) => void;
}
const stylingforvisuallyhiddenspan = {
position: "absolute",
width: "1px",
height: "1px",
margin: "-1px",
border: 0,
padding: 0,
clip: "rect(0 0 0 0)",
overflow: "hidden",
};
export class SubSettingsComponent extends React.Component<SubSettingsComponentProps> {
private shouldCheckComponentIsDirty = true;
@@ -209,26 +197,17 @@ export class SubSettingsComponent extends React.Component<SubSettingsComponentPr
</MessageBar>
)}
{this.props.timeToLive === TtlType.On && (
<div>
<span id="timetoliveon" style={stylingforvisuallyhiddenspan}>
Time to live on
</span>
<TextField
id="timeToLiveSeconds"
styles={getTextFieldStyles(this.props.timeToLiveSeconds, this.props.timeToLiveSecondsBaseline)}
type="number"
required
min={1}
max={Int32.Max}
value={this.props.timeToLiveSeconds?.toString()}
onChange={this.onTimeToLiveSecondsChange}
suffix="second(s)"
aria-labelledby="timetoliveon secondssuffixforscreenreader"
/>
<span id="secondssuffixforscreenreader" style={stylingforvisuallyhiddenspan}>
Second(s)
</span>
</div>
<TextField
id="timeToLiveSeconds"
styles={getTextFieldStyles(this.props.timeToLiveSeconds, this.props.timeToLiveSecondsBaseline)}
type="number"
required
min={1}
max={Int32.Max}
value={this.props.timeToLiveSeconds?.toString()}
onChange={this.onTimeToLiveSecondsChange}
suffix="second(s)"
/>
)}
</Stack>
);

View File

@@ -59,68 +59,31 @@ exports[`SubSettingsComponent analyticalTimeToLive hidden 1`] = `
}
}
/>
<div>
<span
id="timetoliveon"
style={
Object {
"border": 0,
"clip": "rect(0 0 0 0)",
"height": "1px",
"margin": "-1px",
"overflow": "hidden",
"padding": 0,
"position": "absolute",
"width": "1px",
}
}
>
Time to live on
</span>
<StyledTextFieldBase
aria-labelledby="timetoliveon secondssuffixforscreenreader"
id="timeToLiveSeconds"
max={2147483647}
min={1}
onChange={[Function]}
required={true}
styles={
Object {
"fieldGroup": Object {
"borderColor": "",
"height": 25,
"selectors": Object {
":disabled": Object {
"backgroundColor": undefined,
"borderColor": undefined,
},
<StyledTextFieldBase
id="timeToLiveSeconds"
max={2147483647}
min={1}
onChange={[Function]}
required={true}
styles={
Object {
"fieldGroup": Object {
"borderColor": "",
"height": 25,
"selectors": Object {
":disabled": Object {
"backgroundColor": undefined,
"borderColor": undefined,
},
"width": 300,
},
}
"width": 300,
},
}
suffix="second(s)"
type="number"
value="1000"
/>
<span
id="secondssuffixforscreenreader"
style={
Object {
"border": 0,
"clip": "rect(0 0 0 0)",
"height": "1px",
"margin": "-1px",
"overflow": "hidden",
"padding": 0,
"position": "absolute",
"width": "1px",
}
}
>
Second(s)
</span>
</div>
}
suffix="second(s)"
type="number"
value="1000"
/>
</Stack>
<StyledChoiceGroup
id="geoSpatialConfig"
@@ -320,68 +283,31 @@ exports[`SubSettingsComponent analyticalTimeToLiveSeconds hidden 1`] = `
}
}
/>
<div>
<span
id="timetoliveon"
style={
Object {
"border": 0,
"clip": "rect(0 0 0 0)",
"height": "1px",
"margin": "-1px",
"overflow": "hidden",
"padding": 0,
"position": "absolute",
"width": "1px",
}
}
>
Time to live on
</span>
<StyledTextFieldBase
aria-labelledby="timetoliveon secondssuffixforscreenreader"
id="timeToLiveSeconds"
max={2147483647}
min={1}
onChange={[Function]}
required={true}
styles={
Object {
"fieldGroup": Object {
"borderColor": "",
"height": 25,
"selectors": Object {
":disabled": Object {
"backgroundColor": undefined,
"borderColor": undefined,
},
<StyledTextFieldBase
id="timeToLiveSeconds"
max={2147483647}
min={1}
onChange={[Function]}
required={true}
styles={
Object {
"fieldGroup": Object {
"borderColor": "",
"height": 25,
"selectors": Object {
":disabled": Object {
"backgroundColor": undefined,
"borderColor": undefined,
},
"width": 300,
},
}
"width": 300,
},
}
suffix="second(s)"
type="number"
value="1000"
/>
<span
id="secondssuffixforscreenreader"
style={
Object {
"border": 0,
"clip": "rect(0 0 0 0)",
"height": "1px",
"margin": "-1px",
"overflow": "hidden",
"padding": 0,
"position": "absolute",
"width": "1px",
}
}
>
Second(s)
</span>
</div>
}
suffix="second(s)"
type="number"
value="1000"
/>
</Stack>
<StyledChoiceGroup
id="geoSpatialConfig"
@@ -634,68 +560,31 @@ exports[`SubSettingsComponent changeFeedPolicy hidden 1`] = `
}
}
/>
<div>
<span
id="timetoliveon"
style={
Object {
"border": 0,
"clip": "rect(0 0 0 0)",
"height": "1px",
"margin": "-1px",
"overflow": "hidden",
"padding": 0,
"position": "absolute",
"width": "1px",
}
}
>
Time to live on
</span>
<StyledTextFieldBase
aria-labelledby="timetoliveon secondssuffixforscreenreader"
id="timeToLiveSeconds"
max={2147483647}
min={1}
onChange={[Function]}
required={true}
styles={
Object {
"fieldGroup": Object {
"borderColor": "",
"height": 25,
"selectors": Object {
":disabled": Object {
"backgroundColor": undefined,
"borderColor": undefined,
},
<StyledTextFieldBase
id="timeToLiveSeconds"
max={2147483647}
min={1}
onChange={[Function]}
required={true}
styles={
Object {
"fieldGroup": Object {
"borderColor": "",
"height": 25,
"selectors": Object {
":disabled": Object {
"backgroundColor": undefined,
"borderColor": undefined,
},
"width": 300,
},
}
"width": 300,
},
}
suffix="second(s)"
type="number"
value="1000"
/>
<span
id="secondssuffixforscreenreader"
style={
Object {
"border": 0,
"clip": "rect(0 0 0 0)",
"height": "1px",
"margin": "-1px",
"overflow": "hidden",
"padding": 0,
"position": "absolute",
"width": "1px",
}
}
>
Second(s)
</span>
</div>
}
suffix="second(s)"
type="number"
value="1000"
/>
</Stack>
<StyledChoiceGroup
id="geoSpatialConfig"
@@ -910,68 +799,31 @@ exports[`SubSettingsComponent renders 1`] = `
}
}
/>
<div>
<span
id="timetoliveon"
style={
Object {
"border": 0,
"clip": "rect(0 0 0 0)",
"height": "1px",
"margin": "-1px",
"overflow": "hidden",
"padding": 0,
"position": "absolute",
"width": "1px",
}
}
>
Time to live on
</span>
<StyledTextFieldBase
aria-labelledby="timetoliveon secondssuffixforscreenreader"
id="timeToLiveSeconds"
max={2147483647}
min={1}
onChange={[Function]}
required={true}
styles={
Object {
"fieldGroup": Object {
"borderColor": "",
"height": 25,
"selectors": Object {
":disabled": Object {
"backgroundColor": undefined,
"borderColor": undefined,
},
<StyledTextFieldBase
id="timeToLiveSeconds"
max={2147483647}
min={1}
onChange={[Function]}
required={true}
styles={
Object {
"fieldGroup": Object {
"borderColor": "",
"height": 25,
"selectors": Object {
":disabled": Object {
"backgroundColor": undefined,
"borderColor": undefined,
},
"width": 300,
},
}
"width": 300,
},
}
suffix="second(s)"
type="number"
value="1000"
/>
<span
id="secondssuffixforscreenreader"
style={
Object {
"border": 0,
"clip": "rect(0 0 0 0)",
"height": "1px",
"margin": "-1px",
"overflow": "hidden",
"padding": 0,
"position": "absolute",
"width": "1px",
}
}
>
Second(s)
</span>
</div>
}
suffix="second(s)"
type="number"
value="1000"
/>
</Stack>
<StyledChoiceGroup
id="geoSpatialConfig"

View File

@@ -201,20 +201,20 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
Autoscale
</label>
<input
id="Manual-input"
className="throughputInputRadioBtn"
aria-label="Manual database throughput"
checked={!isAutoscaleSelected}
type="radio"
aria-required={true}
role="radio"
tabIndex={0}
onChange={(e) => handleOnChangeMode(e, "Manual")}
/>
<label className="throughputInputRadioBtnLabel" htmlFor="Manual-input">
Manual
</label>
<input
id="Manual-input"
className="throughputInputRadioBtn"
aria-label="Manual database throughput"
checked={!isAutoscaleSelected}
type="radio"
aria-required={true}
role="radio"
tabIndex={0}
onChange={(e) => handleOnChangeMode(e, "Manual")}
/>
<label className="throughputInputRadioBtnLabel" htmlFor="Manual-input">
Manual
</label>
</div>
</Stack>

View File

@@ -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."
className="panelInfoIcon"
iconName="Info"
role="tooltip"
tabIndex={0}
>
<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."
className="panelInfoIcon"
iconName="Info"
role="tooltip"
styles={[Function]}
tabIndex={0}
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."
className="panelInfoIcon root-57"
data-icon-name="Info"
role="img"
role="tooltip"
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."
className="panelInfoIcon"
iconName="Info"
role="tooltip"
tabIndex={0}
>
<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."
className="panelInfoIcon"
iconName="Info"
role="tooltip"
styles={[Function]}
tabIndex={0}
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."
className="panelInfoIcon root-57"
data-icon-name="Info"
role="img"
role="tooltip"
tabIndex={0}
>

View File

@@ -10,7 +10,7 @@ import {
IButtonStyles,
IconButton,
IContextualMenuItemProps,
IContextualMenuProps,
IContextualMenuProps
} from "@fluentui/react";
import * as React from "react";
import AnimateHeight from "react-animate-height";

View File

@@ -40,30 +40,32 @@ exports[`TreeNodeComponent does not render children by default 1`] = `
onKeyPress={[Function]}
role="treeitem"
>
<div
className="treeNodeHeader "
data-test="label"
style={
Object {
"paddingLeft": 9,
<div>
<div
className="treeNodeHeader "
data-test="label"
style={
Object {
"paddingLeft": 9,
}
}
}
tabIndex={-1}
>
<img
alt="label branch is collapsed"
className="expandCollapseIcon"
onKeyPress={[Function]}
role="button"
src=""
tabIndex={0}
/>
<span
className="nodeLabel"
title="label"
tabIndex={-1}
>
label
</span>
<img
alt="label branch is collapsed"
className="expandCollapseIcon"
onKeyPress={[Function]}
role="button"
src=""
tabIndex={0}
/>
<span
className="nodeLabel"
title="label"
>
label
</span>
</div>
</div>
<div
className="loadingIconContainer"
@@ -143,78 +145,80 @@ exports[`TreeNodeComponent renders a simple node (sorted children, expanded) 1`]
onKeyPress={[Function]}
role="treeitem"
>
<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]}
onKeyPress={[Function]}
className="treeNodeHeader "
data-test="label"
style={
Object {
"paddingLeft": 23,
}
}
tabIndex={-1}
>
<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"
<img
alt="label branch is expanded"
className="expandCollapseIcon"
onKeyPress={[Function]}
role="button"
src=""
tabIndex={0}
/>
<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
@@ -294,30 +298,32 @@ exports[`TreeNodeComponent renders loading icon 1`] = `
onKeyPress={[Function]}
role="treeitem"
>
<div
className="treeNodeHeader "
data-test="label"
style={
Object {
"paddingLeft": 9,
<div>
<div
className="treeNodeHeader "
data-test="label"
style={
Object {
"paddingLeft": 9,
}
}
}
tabIndex={-1}
>
<img
alt="label branch is expanded"
className="expandCollapseIcon"
onKeyPress={[Function]}
role="button"
src=""
tabIndex={0}
/>
<span
className="nodeLabel"
title="label"
tabIndex={-1}
>
label
</span>
<img
alt="label branch is expanded"
className="expandCollapseIcon"
onKeyPress={[Function]}
role="button"
src=""
tabIndex={0}
/>
<span
className="nodeLabel"
title="label"
>
label
</span>
</div>
</div>
<div
className="loadingIconContainer"
@@ -368,69 +374,71 @@ exports[`TreeNodeComponent renders sorted children, expanded, leaves and parents
onKeyPress={[Function]}
role="treeitem"
>
<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]}
onKeyPress={[Function]}
className="treeNodeHeader "
data-test="label"
style={
Object {
"paddingLeft": 23,
}
}
tabIndex={-1}
>
<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"
<img
alt="label branch is expanded"
className="expandCollapseIcon"
onKeyPress={[Function]}
role="button"
src=""
tabIndex={0}
/>
<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
@@ -538,30 +546,32 @@ exports[`TreeNodeComponent renders unsorted children by default 1`] = `
onKeyPress={[Function]}
role="treeitem"
>
<div
className="treeNodeHeader "
data-test="label"
style={
Object {
"paddingLeft": 9,
<div>
<div
className="treeNodeHeader "
data-test="label"
style={
Object {
"paddingLeft": 9,
}
}
}
tabIndex={-1}
>
<img
alt="label branch is expanded"
className="expandCollapseIcon"
onKeyPress={[Function]}
role="button"
src=""
tabIndex={0}
/>
<span
className="nodeLabel"
title="label"
tabIndex={-1}
>
label
</span>
<img
alt="label branch is expanded"
className="expandCollapseIcon"
onKeyPress={[Function]}
role="button"
src=""
tabIndex={0}
/>
<span
className="nodeLabel"
title="label"
>
label
</span>
</div>
</div>
<div
className="loadingIconContainer"

View File

@@ -25,7 +25,7 @@ describe("CommandBarComponentButtonFactory tests", () => {
updateUserContext({
databaseAccount: {
properties: {
capabilities: [{ name: "EnableMongo" }],
capabilities: [{ name: "EnableTable" }],
},
} as DatabaseAccount,
});
@@ -38,38 +38,6 @@ describe("CommandBarComponentButtonFactory tests", () => {
);
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", () => {

View File

@@ -51,13 +51,11 @@ export function createStaticCommandBarButtons(
const buttons: CommandButtonComponentProps[] = [];
buttons.push(newCollectionBtn);
if (userContext.apiType !== "Tables" && userContext.apiType !== "Cassandra") {
const addSynapseLink = createOpenSynapseLinkDialogButton(container);
if (addSynapseLink) {
buttons.push(createDivider());
buttons.push(addSynapseLink);
}
const addSynapseLink = createOpenSynapseLinkDialogButton(container);
if (addSynapseLink) {
buttons.push(createDivider());
buttons.push(addSynapseLink);
}
if (userContext.apiType !== "Tables") {

View File

@@ -13,7 +13,7 @@ import {
Stack,
TeachingBubble,
Text,
TooltipHost,
TooltipHost
} from "@fluentui/react";
import * as Constants from "Common/Constants";
import { createCollection } from "Common/dataAccess/createCollection";
@@ -100,6 +100,7 @@ export interface AddCollectionPanelState {
isExecuting: boolean;
isThroughputCapExceeded: boolean;
teachingBubbleStep: number;
isParentTooltipVisible:boolean;
}
export class AddCollectionPanel extends React.Component<AddCollectionPanelProps, AddCollectionPanelState> {
@@ -108,6 +109,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
private collectionThroughput: number;
private isCollectionAutoscale: boolean;
private isCostAcknowledged: boolean;
constructor(props: AddCollectionPanelProps) {
super(props);
@@ -134,13 +136,16 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
isExecuting: false,
isThroughputCapExceeded: false,
teachingBubbleStep: 0,
isParentTooltipVisible: false,
};
}
componentDidMount(): void {
if (this.state.teachingBubbleStep === 0 && this.props.isQuickstart) {
this.setState({ teachingBubbleStep: 1 });
}
}
render(): JSX.Element {
@@ -408,6 +413,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
className="panelInfoIcon"
tabIndex={0}
ariaLabel={`Unique identifier for the ${getCollectionName().toLocaleLowerCase()} and used for id-based routing through REST and all SDKs.`}
/>
</TooltipHost>
</Stack>

View File

@@ -1,10 +1,10 @@
import { DefaultButton, IconButton, Image, Modal, PrimaryButton, Stack, Text } from "@fluentui/react";
import { Action } from "Shared/Telemetry/TelemetryConstants";
import { traceSuccess } from "Shared/Telemetry/TelemetryProcessor";
import { userContext } from "UserContext";
import { useCarousel } from "hooks/useCarousel";
import React, { useState } from "react";
import Youtube from "react-youtube";
import { Action } from "Shared/Telemetry/TelemetryConstants";
import { traceSuccess } from "Shared/Telemetry/TelemetryProcessor";
import { userContext } from "UserContext";
import Image1 from "../../../images/CarouselImage1.svg";
import Image2 from "../../../images/CarouselImage2.svg";
@@ -25,7 +25,7 @@ export const QuickstartCarousel: React.FC<QuickstartCarouselProps> = ({
<Stack>
<Stack horizontal horizontalAlign="space-between" style={{ padding: 16 }}>
<Text variant="xLarge">{getHeaderText(page)}</Text>
<IconButton iconProps={{ iconName: "Cancel" }} onClick={() => setPage(4)} ariaLabel="Close"/>
<IconButton iconProps={{ iconName: "Cancel" }} onClick={() => setPage(4)} />
</Stack>
{getContent(page)}
<Text variant="medium" style={{ padding: "0 16px" }}>

View File

@@ -9,7 +9,7 @@ import {
Stack,
TeachingBubble,
TeachingBubbleContent,
Text,
Text
} from "@fluentui/react";
import { sendMessage } from "Common/MessageHandler";
import { MessageTypes } from "Contracts/ExplorerContracts";

View File

@@ -1,6 +1,6 @@
import React, { Component } from "react";
import * as Constants from "../../../Common/Constants";
import { configContext } from "../../../ConfigContext";
import { configContext, Platform } from "../../../ConfigContext";
import * as ViewModels from "../../../Contracts/ViewModels";
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
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 Explorer from "../../Explorer";
import TabsBase from "../TabsBase";
import { getMongoShellOrigin } from "./getMongoShellOrigin";
import { getMongoShellUrl } from "./getMongoShellUrl";
//eslint-disable-next-line
class MessageType {
@@ -49,6 +47,7 @@ export default class MongoShellTabComponent extends Component<
IMongoShellTabComponentProps,
IMongoShellTabComponentStates
> {
private _runtimeEndpoint: string;
private _logTraces: Map<string, number>;
constructor(props: IMongoShellTabComponentProps) {
@@ -56,7 +55,7 @@ export default class MongoShellTabComponent extends Component<
this._logTraces = new Map();
this.state = {
url: getMongoShellUrl(),
url: this.getURL(),
};
props.onMongoShellTabAccessor({
@@ -66,6 +65,22 @@ export default class MongoShellTabComponent extends Component<
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
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 apiEndpoint = configContext.BACKEND_ENDPOINT;
const encryptedAuthToken: string = userContext.accessToken;
const targetOrigin = getMongoShellOrigin();
shellIframe.contentWindow.postMessage(
{
@@ -137,7 +151,7 @@ export default class MongoShellTabComponent extends Component<
apiEndpoint: apiEndpoint,
},
},
targetOrigin
configContext.BACKEND_ENDPOINT
);
}

View File

@@ -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);
});
});

View File

@@ -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;
}

View File

@@ -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");
});
});

View File

@@ -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;
}

View File

@@ -134,7 +134,6 @@
data-bind="click: selectQueryOptions, event: { keydown: onselectQueryOptionsKeyDown }"
tabindex="0"
role="button"
href=""
>
<span>Choose Columns... </span>
</a>

View File

@@ -30,11 +30,6 @@ export type Features = {
readonly mongoProxyAPIs?: string;
readonly enableThroughputCap: 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
autoscaleDefault: boolean;
@@ -97,11 +92,6 @@ export function extractFeatures(given = new URLSearchParams(window.location.sear
notebooksDownBanner: "true" === get("notebooksDownBanner"),
enableThroughputCap: "true" === get("enablethroughputcap"),
enableHierarchicalKeys: "true" === get("enablehierarchicalkeys"),
enableLegacyMongoShellV1: "true" === get("enablelegacymongoshellv1"),
enableLegacyMongoShellV1Debug: "true" === get("enablelegacymongoshellv1debug"),
enableLegacyMongoShellV2: "true" === get("enablelegacymongoshellv2"),
enableLegacyMongoShellV2Debug: "true" === get("enablelegacymongoshellv2debug"),
loadLegacyMongoShellFromBE: "true" === get("loadlegacymongoshellfrombe"),
};
}