Compare commits

..

3 Commits

Author SHA1 Message Date
MokireddySampath
7e309f16b6 Merge branch 'master' into rework1704149 2023-02-06 18:06:42 +05:30
Sampath
c054ec23ba updating snapshots for addcollectionpane 2023-02-06 17:32:15 +05:30
Sampath
27e6e886d7 rework for defect-1704149 2023-02-03 15:07:55 +05:30
21 changed files with 383 additions and 6663 deletions

View File

@@ -92,11 +92,11 @@ jobs:
name: dist name: dist
path: dist/ path: dist/
- name: Upload build to preview blob storage - name: Upload build to preview blob storage
run: az storage blob upload-batch -d '$web' -s 'dist' --account-name cosmosexplorerpreview --destination-path "${{github.event.pull_request.head.sha || github.sha}}" --account-key="${PREVIEW_STORAGE_KEY}" --overwrite true run: az storage blob upload-batch -d '$web' -s 'dist' --account-name cosmosexplorerpreview --destination-path "${{github.event.pull_request.head.sha || github.sha}}" --account-key="${PREVIEW_STORAGE_KEY}"
env: env:
PREVIEW_STORAGE_KEY: ${{ secrets.PREVIEW_STORAGE_KEY }} PREVIEW_STORAGE_KEY: ${{ secrets.PREVIEW_STORAGE_KEY }}
- name: Upload preview config to blob storage - name: Upload preview config to blob storage
run: az storage blob upload -c '$web' -f ./preview/config.json --account-name cosmosexplorerpreview --name "${{github.event.pull_request.head.sha || github.sha}}/config.json" --account-key="${PREVIEW_STORAGE_KEY}" --overwrite true run: az storage blob upload -c '$web' -f ./preview/config.json --account-name cosmosexplorerpreview --name "${{github.event.pull_request.head.sha || github.sha}}/config.json" --account-key="${PREVIEW_STORAGE_KEY}"
env: env:
PREVIEW_STORAGE_KEY: ${{ secrets.PREVIEW_STORAGE_KEY }} PREVIEW_STORAGE_KEY: ${{ secrets.PREVIEW_STORAGE_KEY }}
endtoendemulator: endtoendemulator:
@@ -182,7 +182,7 @@ jobs:
with: with:
name: dist name: dist
- run: cp ./configs/prod.json config.json - run: cp ./configs/prod.json config.json
- run: nuget sources add -Name "ADO" -Source "$NUGET_SOURCE" -UserName "jawelton@microsoft.com" -Password "$AZURE_DEVOPS_PAT" - run: nuget sources add -Name "ADO" -Source "$NUGET_SOURCE" -UserName "vimeng@microsoft.com" -Password "$AZURE_DEVOPS_PAT"
- run: nuget pack -Version "2.0.0-github-${GITHUB_SHA}" - run: nuget pack -Version "2.0.0-github-${GITHUB_SHA}"
- run: nuget push -SkipDuplicate -Source "$NUGET_SOURCE" -ApiKey Az *.nupkg - run: nuget push -SkipDuplicate -Source "$NUGET_SOURCE" -ApiKey Az *.nupkg
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
@@ -207,7 +207,7 @@ jobs:
name: dist name: dist
- run: cp ./configs/mpac.json config.json - run: cp ./configs/mpac.json config.json
- run: sed -i 's/Azure.Cosmos.DB.Data.Explorer/Azure.Cosmos.DB.Data.Explorer.MPAC/g' DataExplorer.nuspec - run: sed -i 's/Azure.Cosmos.DB.Data.Explorer/Azure.Cosmos.DB.Data.Explorer.MPAC/g' DataExplorer.nuspec
- run: nuget sources add -Name "ADO" -Source "$NUGET_SOURCE" -UserName "jawelton@microsoft.com" -Password "$AZURE_DEVOPS_PAT" - run: nuget sources add -Name "ADO" -Source "$NUGET_SOURCE" -UserName "vimeng@microsoft.com" -Password "$AZURE_DEVOPS_PAT"
- run: nuget pack -Version "2.0.0-github-${GITHUB_SHA}" - run: nuget pack -Version "2.0.0-github-${GITHUB_SHA}"
- run: nuget push -SkipDuplicate -Source "$NUGET_SOURCE" -ApiKey Az *.nupkg - run: nuget push -SkipDuplicate -Source "$NUGET_SOURCE" -ApiKey Az *.nupkg
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" ?> <?xml version="1.0" ?>
<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'> <!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<svg enable-background="new 0 0 256 256" height="256px" id="Layer_1" version="1.1" viewBox="0 0 256 256" width="256px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <svg enable-background="new 0 0 256 256" height="256px" id="Layer_1" version="1.1" viewBox="0 0 256 256" width="256px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<path stroke="white" stroke-width="0.5" fill="#000" d="M179.199,38.399c0,1.637-0.625,3.274-1.875,4.524l-85.076,85.075l85.076,85.075c2.5,2.5,2.5,6.55,0,9.05s-6.55,2.5-9.05,0 l-89.601-89.6c-2.5-2.5-2.5-6.551,0-9.051l89.601-89.6c2.5-2.5,6.55-2.5,9.05,0C178.574,35.124,179.199,36.762,179.199,38.399z"/> <path stroke="white" stroke-width="0.5" fill="#b5a3a3" d="M179.199,38.399c0,1.637-0.625,3.274-1.875,4.524l-85.076,85.075l85.076,85.075c2.5,2.5,2.5,6.55,0,9.05s-6.55,2.5-9.05,0 l-89.601-89.6c-2.5-2.5-2.5-6.551,0-9.051l89.601-89.6c2.5-2.5,6.55-2.5,9.05,0C178.574,35.124,179.199,36.762,179.199,38.399z"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 649 B

After

Width:  |  Height:  |  Size: 652 B

File diff suppressed because it is too large Load Diff

View File

@@ -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,20 +136,17 @@ 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}>
<Image <Image
{...imageProps} {...imageProps}
src={EditIcon} src={EditIcon}
alt="editEntity" alt="editEntity"
id="editEntity" id="editEntity"
onClick={onEditEntity} onClick={onEditEntity}
tabIndex={0}
onKeyPress={handleKeyPress} onKeyPress={handleKeyPress}
/> />
</div>
</TooltipHost> </TooltipHost>
)} )}
{isDeleteOptionVisible && userContext.apiType !== "Cassandra" && ( {isDeleteOptionVisible && userContext.apiType !== "Cassandra" && (
<TooltipHost content="Delete property" id="deleteTooltip"> <TooltipHost content="Delete property" id="deleteTooltip">

View File

@@ -1,5 +1,5 @@
import { HoverCard, HoverCardType, Icon, Label, Link, Stack } from "@fluentui/react";
import * as React from "react"; import * as React from "react";
import { Icon, Label, Stack, HoverCard, HoverCardType, Link } from "@fluentui/react";
import { CodeOfConductEndpoints } from "../../../../Common/Constants"; import { CodeOfConductEndpoints } from "../../../../Common/Constants";
import "./InfoComponent.less"; import "./InfoComponent.less";
@@ -41,7 +41,7 @@ export class InfoComponent extends React.Component<InfoComponentProps> {
public render(): JSX.Element { public render(): JSX.Element {
return ( return (
<HoverCard plainCardProps={{ onRenderPlainCard: this.onHover }} instantOpenOnClick type={HoverCardType.plain}> <HoverCard plainCardProps={{ onRenderPlainCard: this.onHover }} instantOpenOnClick type={HoverCardType.plain}>
<div className="infoPanelMain" tabIndex={0}> <div className="infoPanelMain">
<Icon className="infoIconMain" iconName="Help" styles={{ root: { verticalAlign: "middle" } }} /> <Icon className="infoIconMain" iconName="Help" styles={{ root: { verticalAlign: "middle" } }} />
<Label className="infoLabelMain">Help</Label> <Label className="infoLabelMain">Help</Label>
</div> </div>

View File

@@ -12,7 +12,6 @@ exports[`InfoComponent renders 1`] = `
> >
<div <div
className="infoPanelMain" className="infoPanelMain"
tabIndex={0}
> >
<Icon <Icon
className="infoIconMain" className="infoIconMain"

View File

@@ -23,12 +23,12 @@ describe("ThroughputInput Pane", () => {
}); });
it("should switch mode properly", () => { it("should switch mode properly", () => {
wrapper.find('[aria-label="Manual database throughput"]').simulate("change"); wrapper.find('[aria-label="Manual mode"]').simulate("change");
expect(wrapper.find('[aria-label="Throughput header"]').at(0).text()).toBe( expect(wrapper.find('[aria-label="Throughput header"]').at(0).text()).toBe(
"Container throughput (400 - unlimited RU/s)" "Container throughput (400 - unlimited RU/s)"
); );
wrapper.find('[aria-label="Autoscale database throughput"]').simulate("change"); wrapper.find('[aria-label="Autoscale mode"]').simulate("change");
expect(wrapper.find('[aria-label="Throughput header"]').at(0).text()).toBe("Container throughput (autoscale)"); expect(wrapper.find('[aria-label="Throughput header"]').at(0).text()).toBe("Container throughput (autoscale)");
}); });
}); });

View File

@@ -185,11 +185,10 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
</Stack> </Stack>
<Stack horizontal verticalAlign="center"> <Stack horizontal verticalAlign="center">
<div role="radiogroup">
<input <input
id="Autoscale-input" id="Autoscale-input"
className="throughputInputRadioBtn" className="throughputInputRadioBtn"
aria-label="Autoscale database throughput" aria-label="Autoscale mode"
aria-required={true} aria-required={true}
checked={isAutoscaleSelected} checked={isAutoscaleSelected}
type="radio" type="radio"
@@ -204,7 +203,7 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
<input <input
id="Manual-input" id="Manual-input"
className="throughputInputRadioBtn" className="throughputInputRadioBtn"
aria-label="Manual database throughput" aria-label="Manual mode"
checked={!isAutoscaleSelected} checked={!isAutoscaleSelected}
type="radio" type="radio"
aria-required={true} aria-required={true}
@@ -215,7 +214,6 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
<label className="throughputInputRadioBtnLabel" htmlFor="Manual-input"> <label className="throughputInputRadioBtnLabel" htmlFor="Manual-input">
Manual Manual
</label> </label>
</div>
</Stack> </Stack>
{isAutoscaleSelected && ( {isAutoscaleSelected && (

View File

@@ -347,14 +347,12 @@ 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={
@@ -635,7 +633,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="tooltip" role="img"
tabIndex={0} tabIndex={0}
> >
@@ -656,12 +654,8 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
<div <div
className="ms-Stack css-58" className="ms-Stack css-58"
> >
<div
key=".0:$.0"
role="radiogroup"
>
<input <input
aria-label="Autoscale database throughput" aria-label="Autoscale mode"
aria-required={true} aria-required={true}
checked={true} checked={true}
className="throughputInputRadioBtn" className="throughputInputRadioBtn"
@@ -680,7 +674,7 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
Autoscale Autoscale
</label> </label>
<input <input
aria-label="Manual database throughput" aria-label="Manual mode"
aria-required={true} aria-required={true}
checked={false} checked={false}
className="throughputInputRadioBtn" className="throughputInputRadioBtn"
@@ -696,9 +690,8 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
htmlFor="Manual-input" htmlFor="Manual-input"
key=".0:$.3" key=".0:$.3"
> >
Manual Manual
</label> </label>
</div>
</div> </div>
</Stack> </Stack>
<Stack <Stack
@@ -1345,14 +1338,12 @@ 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={
@@ -1633,7 +1624,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="tooltip" role="img"
tabIndex={0} tabIndex={0}
> >

View File

@@ -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";
@@ -195,7 +195,7 @@ export class TreeNodeComponent extends React.Component<TreeNodeComponentProps, T
</div> </div>
{node.children && ( {node.children && (
<AnimateHeight duration={TreeNodeComponent.transitionDurationMS} height={this.state.isExpanded ? "auto" : 0}> <AnimateHeight duration={TreeNodeComponent.transitionDurationMS} height={this.state.isExpanded ? "auto" : 0}>
<div className="nodeChildren" data-test={node.label} role="group"> <div className="nodeChildren" data-test={node.label}>
{TreeNodeComponent.getSortedChildren(node).map((childNode: TreeNode) => ( {TreeNodeComponent.getSortedChildren(node).map((childNode: TreeNode) => (
<TreeNodeComponent <TreeNodeComponent
key={`${childNode.label}-${generation + 1}-${childNode.timestamp}`} key={`${childNode.label}-${generation + 1}-${childNode.timestamp}`}

View File

@@ -40,32 +40,30 @@ exports[`TreeNodeComponent does not render children by default 1`] = `
onKeyPress={[Function]} onKeyPress={[Function]}
role="treeitem" role="treeitem"
> >
<div> <div
<div className="treeNodeHeader "
className="treeNodeHeader " data-test="label"
data-test="label" style={
style={ Object {
Object { "paddingLeft": 9,
"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"
> >
<img label
alt="label branch is collapsed" </span>
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"
@@ -102,7 +100,6 @@ exports[`TreeNodeComponent does not render children by default 1`] = `
<div <div
className="nodeChildren" className="nodeChildren"
data-test="label" data-test="label"
role="group"
> >
<TreeNodeComponent <TreeNodeComponent
generation={3} generation={3}
@@ -145,80 +142,78 @@ exports[`TreeNodeComponent renders a simple node (sorted children, expanded) 1`]
onKeyPress={[Function]} onKeyPress={[Function]}
role="treeitem" role="treeitem"
> >
<div> <div
<div className="treeNodeHeader "
className="treeNodeHeader " data-test="label"
data-test="label" style={
style={ Object {
Object { "paddingLeft": 23,
"paddingLeft": 23,
}
} }
tabIndex={-1} }
tabIndex={-1}
>
<img
alt="label branch is expanded"
className="expandCollapseIcon"
onKeyPress={[Function]}
role="button"
src=""
tabIndex={0}
/>
<span
className="nodeLabel"
title="label"
> >
<img label
alt="label branch is expanded" </span>
className="expandCollapseIcon" <div
onKeyPress={[Function]} onContextMenu={[Function]}
role="button" onKeyPress={[Function]}
src="" >
tabIndex={0} <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"
/> />
<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
@@ -256,7 +251,6 @@ exports[`TreeNodeComponent renders a simple node (sorted children, expanded) 1`]
<div <div
className="nodeChildren" className="nodeChildren"
data-test="label" data-test="label"
role="group"
> >
<TreeNodeComponent <TreeNodeComponent
generation={13} generation={13}
@@ -298,32 +292,30 @@ exports[`TreeNodeComponent renders loading icon 1`] = `
onKeyPress={[Function]} onKeyPress={[Function]}
role="treeitem" role="treeitem"
> >
<div> <div
<div className="treeNodeHeader "
className="treeNodeHeader " data-test="label"
data-test="label" style={
style={ Object {
Object { "paddingLeft": 9,
"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"
> >
<img label
alt="label branch is expanded" </span>
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"
@@ -360,7 +352,6 @@ exports[`TreeNodeComponent renders loading icon 1`] = `
<div <div
className="nodeChildren" className="nodeChildren"
data-test="label" data-test="label"
role="group"
/> />
</AnimateHeight> </AnimateHeight>
</div> </div>
@@ -374,71 +365,69 @@ exports[`TreeNodeComponent renders sorted children, expanded, leaves and parents
onKeyPress={[Function]} onKeyPress={[Function]}
role="treeitem" role="treeitem"
> >
<div> <div
<div className="treeNodeHeader "
className="treeNodeHeader " data-test="label"
data-test="label" style={
style={ Object {
Object { "paddingLeft": 23,
"paddingLeft": 23,
}
} }
tabIndex={-1} }
tabIndex={-1}
>
<img
alt="label branch is expanded"
className="expandCollapseIcon"
onKeyPress={[Function]}
role="button"
src=""
tabIndex={0}
/>
<span
className="nodeLabel"
title="label"
> >
<img label
alt="label branch is expanded" </span>
className="expandCollapseIcon" <div
onKeyPress={[Function]} onContextMenu={[Function]}
role="button" onKeyPress={[Function]}
src="" >
tabIndex={0} <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"
/> />
<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
@@ -476,7 +465,6 @@ exports[`TreeNodeComponent renders sorted children, expanded, leaves and parents
<div <div
className="nodeChildren" className="nodeChildren"
data-test="label" data-test="label"
role="group"
> >
<TreeNodeComponent <TreeNodeComponent
generation={13} generation={13}
@@ -546,32 +534,30 @@ exports[`TreeNodeComponent renders unsorted children by default 1`] = `
onKeyPress={[Function]} onKeyPress={[Function]}
role="treeitem" role="treeitem"
> >
<div> <div
<div className="treeNodeHeader "
className="treeNodeHeader " data-test="label"
data-test="label" style={
style={ Object {
Object { "paddingLeft": 9,
"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"
> >
<img label
alt="label branch is expanded" </span>
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"
@@ -608,7 +594,6 @@ exports[`TreeNodeComponent renders unsorted children by default 1`] = `
<div <div
className="nodeChildren" className="nodeChildren"
data-test="label" data-test="label"
role="group"
> >
<TreeNodeComponent <TreeNodeComponent
generation={3} generation={3}

View File

@@ -40,7 +40,6 @@ export class GraphVizComponent extends React.Component<GraphVizComponentProps> {
{/* svg load more icon inlined as-is here: remove the style="fill:#374649;" so we can override it */} {/* svg load more icon inlined as-is here: remove the style="fill:#374649;" so we can override it */}
<svg <svg
role="img" role="img"
aria-label="graph"
version="1.1" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink" xmlnsXlink="http://www.w3.org/1999/xlink"
@@ -136,7 +135,6 @@ export class GraphVizComponent extends React.Component<GraphVizComponentProps> {
<g id="triangleRight"> <g id="triangleRight">
<svg <svg
role="img" role="img"
aria-label="graph"
version="1.1" version="1.1"
id="Layer_1" id="Layer_1"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"

View File

@@ -17,20 +17,19 @@ export class MiddlePaneComponent extends React.Component<MiddlePaneComponentProp
<div className="middlePane"> <div className="middlePane">
<div className="graphTitle"> <div className="graphTitle">
<span className="paneTitle">Graph</span> <span className="paneTitle">Graph</span>
<button <span
style={{border:'none',background:'none'}}
className="graphExpandCollapseBtn pull-right" className="graphExpandCollapseBtn pull-right"
onClick={this.props.toggleExpandGraph} onClick={this.props.toggleExpandGraph}
role="button" role="button"
aria-expanded={this.props.isTabsContentExpanded} aria-expanded={this.props.isTabsContentExpanded}
aria-name="View graph in full screen" aria-name="View graph in full screen"
tabIndex={0}
> >
<img <img
src={this.props.isTabsContentExpanded ? CollapseArrowIcon : ExpandIcon} src={this.props.isTabsContentExpanded ? CollapseArrowIcon : ExpandIcon}
alt={this.props.isTabsContentExpanded ? "collapse graph content" : "expand graph content"} alt={this.props.isTabsContentExpanded ? "collapse graph content" : "expand graph content"}
/> />
</button> </span>
</div> </div>
<div className="maingraphContainer"> <div className="maingraphContainer">
<GraphVizComponent forceGraphParams={this.props.graphVizProps.forceGraphParams} /> <GraphVizComponent forceGraphParams={this.props.graphVizProps.forceGraphParams} />

View File

@@ -147,10 +147,12 @@ export class NotificationConsoleComponent extends React.Component<
<div className="notificationConsoleControls"> <div className="notificationConsoleControls">
<Dropdown <Dropdown
label="Filter:" label="Filter:"
role="combobox"
selectedKey={this.state.selectedFilter} selectedKey={this.state.selectedFilter}
options={NotificationConsoleComponent.FilterOptions} options={NotificationConsoleComponent.FilterOptions}
onChange={this.onFilterSelected.bind(this)} onChange={this.onFilterSelected.bind(this)}
aria-labelledby="consoleFilterLabel"
aria-label={this.state.selectedFilter}
/> />
<span className="consoleSplitter" /> <span className="consoleSplitter" />
<span <span

View File

@@ -112,6 +112,8 @@ exports[`NotificationConsoleComponent renders the console 1`] = `
className="notificationConsoleControls" className="notificationConsoleControls"
> >
<Dropdown <Dropdown
aria-label="All"
aria-labelledby="consoleFilterLabel"
label="Filter:" label="Filter:"
onChange={[Function]} onChange={[Function]}
options={ options={
@@ -276,6 +278,8 @@ exports[`NotificationConsoleComponent renders the console 2`] = `
className="notificationConsoleControls" className="notificationConsoleControls"
> >
<Dropdown <Dropdown
aria-label="All"
aria-labelledby="consoleFilterLabel"
label="Filter:" label="Filter:"
onChange={[Function]} onChange={[Function]}
options={ options={

View File

@@ -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,7 +100,6 @@ 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> {
@@ -109,7 +108,6 @@ 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);
@@ -136,16 +134,13 @@ 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 {
@@ -279,7 +274,6 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
</Stack> </Stack>
<Stack horizontal verticalAlign="center"> <Stack horizontal verticalAlign="center">
<div role='radiogroup'>
<input <input
className="panelRadioBtn" className="panelRadioBtn"
checked={this.state.createNewDatabase} checked={this.state.createNewDatabase}
@@ -306,7 +300,6 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
onChange={this.onUseExistingDatabaseRadioBtnChange.bind(this)} onChange={this.onUseExistingDatabaseRadioBtnChange.bind(this)}
/> />
<span className="panelRadioBtnLabel">Use existing</span> <span className="panelRadioBtnLabel">Use existing</span>
</div>
</Stack> </Stack>
{this.state.createNewDatabase && ( {this.state.createNewDatabase && (
@@ -412,7 +405,6 @@ 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.`}
role="button"
/> />
</TooltipHost> </TooltipHost>
</Stack> </Stack>
@@ -803,14 +795,13 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
iconName="Info" iconName="Info"
className="panelInfoIcon" className="panelInfoIcon"
tabIndex={0} tabIndex={0}
ariaLabel="Enable analytical store capability to perform near real-time analytics on your operational data, without ariaLabel='Enable analytical store capability to perform near real-time analytics on your operational data, without
impacting the performance of transactional workloads." impacting the performance of transactional workloads.{" "}'
/> />
</TooltipHost> </TooltipHost>
</Stack> </Stack>
<Stack horizontal verticalAlign="center"> <Stack horizontal verticalAlign="center">
<div role="radiogroup">
<input <input
className="panelRadioBtn" className="panelRadioBtn"
checked={this.state.enableAnalyticalStore} checked={this.state.enableAnalyticalStore}
@@ -840,7 +831,6 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
onChange={this.onDisableAnalyticalStoreRadioBtnChange.bind(this)} onChange={this.onDisableAnalyticalStoreRadioBtnChange.bind(this)}
/> />
<span className="panelRadioBtnLabel">Off</span> <span className="panelRadioBtnLabel">Off</span>
</div>
</Stack> </Stack>
{!this.isSynapseLinkEnabled() && ( {!this.isSynapseLinkEnabled() && (
@@ -989,7 +979,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
private getPartitionKeyPlaceHolder(index?: number): string { private getPartitionKeyPlaceHolder(index?: number): string {
switch (userContext.apiType) { switch (userContext.apiType) {
case "Mongo": case "Mongo":
return "e.g., categoryId"; return "e.g., address.zipCode";
case "Gremlin": case "Gremlin":
return "e.g., /address"; return "e.g., /address";
case "SQL": case "SQL":
@@ -1121,7 +1111,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
return userContext.apiType === "SQL" ? "/pk" : "pk"; return userContext.apiType === "SQL" ? "/pk" : "pk";
} }
if (this.props.isQuickstart) { if (this.props.isQuickstart) {
return userContext.apiType === "SQL" ? "/categoryId" : "categoryId"; return userContext.apiType === "SQL" ? "/address" : "address";
} }
return ""; return "";
} }

View File

@@ -42,43 +42,39 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
horizontal={true} horizontal={true}
verticalAlign="center" verticalAlign="center"
> >
<div <input
role="radiogroup" aria-checked={true}
aria-label="Create new database"
checked={true}
className="panelRadioBtn"
id="databaseCreateNew"
name="databaseType"
onChange={[Function]}
role="radio"
tabIndex={0}
type="radio"
/>
<span
className="panelRadioBtnLabel"
> >
<input Create new
aria-checked={true} </span>
aria-label="Create new database" <input
checked={true} aria-checked={false}
className="panelRadioBtn" aria-label="Use existing database"
id="databaseCreateNew" checked={false}
name="databaseType" className="panelRadioBtn"
onChange={[Function]} name="databaseType"
role="radio" onChange={[Function]}
tabIndex={0} role="radio"
type="radio" tabIndex={0}
/> type="radio"
<span />
className="panelRadioBtnLabel" <span
> className="panelRadioBtnLabel"
Create new >
</span> Use existing
<input </span>
aria-checked={false}
aria-label="Use existing database"
checked={false}
className="panelRadioBtn"
name="databaseType"
onChange={[Function]}
role="radio"
tabIndex={0}
type="radio"
/>
<span
className="panelRadioBtnLabel"
>
Use existing
</span>
</div>
</Stack> </Stack>
<Stack <Stack
className="panelGroupSpacing" className="panelGroupSpacing"
@@ -172,7 +168,6 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
ariaLabel="Unique identifier for the container and used for id-based routing through REST and all SDKs." ariaLabel="Unique identifier for the container and used for id-based routing through REST and all SDKs."
className="panelInfoIcon" className="panelInfoIcon"
iconName="Info" iconName="Info"
role="button"
tabIndex={0} tabIndex={0}
/> />
</StyledTooltipHostBase> </StyledTooltipHostBase>
@@ -336,7 +331,9 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
directionalHint={4} directionalHint={4}
> >
<Icon <Icon
ariaLabel="Enable analytical store capability to perform near real-time analytics on your operational data, without impacting the performance of transactional workloads." ariaLabel="Enable analytical store capability to perform near real-time analytics on your operational data, without
impacting the performance of transactional workloads.{\\" \\"}"
className="panelInfoIcon" className="panelInfoIcon"
iconName="Info" iconName="Info"
tabIndex={0} tabIndex={0}
@@ -347,46 +344,42 @@ exports[`AddCollectionPanel should render Default properly 1`] = `
horizontal={true} horizontal={true}
verticalAlign="center" verticalAlign="center"
> >
<div <input
role="radiogroup" aria-checked={false}
aria-label="Enable analytical store"
checked={false}
className="panelRadioBtn"
disabled={true}
id="enableAnalyticalStoreBtn"
name="analyticalStore"
onChange={[Function]}
role="radio"
tabIndex={0}
type="radio"
/>
<span
className="panelRadioBtnLabel"
> >
<input On
aria-checked={false} </span>
aria-label="Enable analytical store" <input
checked={false} aria-checked={true}
className="panelRadioBtn" aria-label="Disable analytical store"
disabled={true} checked={true}
id="enableAnalyticalStoreBtn" className="panelRadioBtn"
name="analyticalStore" disabled={true}
onChange={[Function]} id="disableAnalyticalStoreBtn"
role="radio" name="analyticalStore"
tabIndex={0} onChange={[Function]}
type="radio" role="radio"
/> tabIndex={0}
<span type="radio"
className="panelRadioBtnLabel" />
> <span
On className="panelRadioBtnLabel"
</span> >
<input Off
aria-checked={true} </span>
aria-label="Disable analytical store"
checked={true}
className="panelRadioBtn"
disabled={true}
id="disableAnalyticalStoreBtn"
name="analyticalStore"
onChange={[Function]}
role="radio"
tabIndex={0}
type="radio"
/>
<span
className="panelRadioBtnLabel"
>
Off
</span>
</div>
</Stack> </Stack>
<Stack <Stack
className="panelGroupSpacing" className="panelGroupSpacing"

View File

@@ -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";
@@ -116,9 +116,7 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
<form className="connectExplorerFormContainer"> <form className="connectExplorerFormContainer">
<div className="splashScreenContainer"> <div className="splashScreenContainer">
<div className="splashScreen"> <div className="splashScreen">
<div className="title" aria-label={userContext.apiType === "Postgres" <div className="title">
? "Welcome to Azure Cosmos DB for PostgreSQL"
: "Welcome to Azure Cosmos DB"}>
{userContext.apiType === "Postgres" {userContext.apiType === "Postgres"
? "Welcome to Azure Cosmos DB for PostgreSQL" ? "Welcome to Azure Cosmos DB for PostgreSQL"
: "Welcome to Azure Cosmos DB"} : "Welcome to Azure Cosmos DB"}
@@ -530,7 +528,7 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
> >
{item.title} {item.title}
</Link> </Link>
<Image src={LinkIcon} alt=" " /> <Image src={LinkIcon} />
</Stack> </Stack>
<Text>{item.description}</Text> <Text>{item.description}</Text>
</Stack> </Stack>
@@ -565,17 +563,7 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
} }
private getLearningResourceItems(): JSX.Element { private getLearningResourceItems(): JSX.Element {
interface item { let items: { link: string; title: string; description: string }[];
link: string;
title: string;
description: string;
}
const cdbLiveTv: item = {
link: "https://developer.azurecosmosdb.com/tv",
title: "Learn the Fundamentals",
description: "Watch Azure Cosmos DB Live TV show introductory and how to videos.",
};
let items: item[];
switch (userContext.apiType) { switch (userContext.apiType) {
case "SQL": case "SQL":
case "Postgres": case "Postgres":
@@ -585,7 +573,11 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
title: "Get Started using an SDK", title: "Get Started using an SDK",
description: "Learn about the Azure Cosmos DB SDK.", description: "Learn about the Azure Cosmos DB SDK.",
}, },
cdbLiveTv, {
link: "https://aka.ms/msl-complex-queries",
title: "Master Complex Queries",
description: "Learn how to author complex queries.",
},
{ {
link: "https://aka.ms/msl-move-data", link: "https://aka.ms/msl-move-data",
title: "Migrate Your Data", title: "Migrate Your Data",
@@ -605,7 +597,11 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
title: "Getting Started Guide", title: "Getting Started Guide",
description: "Learn the basics to get started.", description: "Learn the basics to get started.",
}, },
cdbLiveTv, {
link: "http://aka.ms/mongodotnet",
title: "Build a web API",
description: "Create a web API with the.NET SDK.",
},
]; ];
break; break;
case "Cassandra": case "Cassandra":
@@ -615,7 +611,11 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
title: "Create a Container", title: "Create a Container",
description: "Get to know the create a container options.", description: "Get to know the create a container options.",
}, },
cdbLiveTv, {
link: "https://aka.ms/cassandraserverdiagnostics",
title: "Run Server Diagnostics",
description: "Learn how to run server diagnostics.",
},
{ {
link: "https://aka.ms/Cassandrathroughput", link: "https://aka.ms/Cassandrathroughput",
title: "Provision Throughput", title: "Provision Throughput",
@@ -635,7 +635,11 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
title: "Import Graph Data", title: "Import Graph Data",
description: "Learn Bulk ingestion data using BulkExecutor", description: "Learn Bulk ingestion data using BulkExecutor",
}, },
cdbLiveTv, {
link: "https://aka.ms/graphoptimize",
title: "Optimize your Queries",
description: "Learn how to evaluate your Gremlin queries",
},
]; ];
break; break;
case "Tables": case "Tables":
@@ -650,7 +654,11 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
title: "Build a Java App", title: "Build a Java App",
description: "Create a Azure Cosmos DB for Table app with Java SDK ", description: "Create a Azure Cosmos DB for Table app with Java SDK ",
}, },
cdbLiveTv, {
link: "https://aka.ms/tablenodejs",
title: "Build a Node.js App",
description: "Create a Azure Cosmos DB for Table app with Node.js SDK",
},
]; ];
break; break;
} }

View File

@@ -21,23 +21,6 @@ function isValidOrigin(allowedOrigins: ReadonlyArray<string>, event: MessageEven
return false; return false;
} }
export function shouldProcessMessage(event: MessageEvent): boolean {
if (typeof event.data !== "object") {
return false;
}
if (event.data["signature"] !== "pcIframe") {
return false;
}
if (!("data" in event.data)) {
return false;
}
if (typeof event.data["data"] !== "object") {
return false;
}
return true;
}
export function isReadyMessage(event: MessageEvent): boolean { export function isReadyMessage(event: MessageEvent): boolean {
if (!event?.data?.kind && !event?.data?.data) { if (!event?.data?.kind && !event?.data?.data) {
return false; return false;

View File

@@ -10,7 +10,7 @@ const PortalIPs: { [key: string]: string[] } = {
usnat: ["7.28.202.68"], usnat: ["7.28.202.68"],
}; };
export const getNetworkSettingsWarningMessage = (): string => { export const getNetworkSettingsWarningMessage = (clientIpAddress: string): string => {
const accountProperties = userContext.databaseAccount?.properties; const accountProperties = userContext.databaseAccount?.properties;
if (!accountProperties) { if (!accountProperties) {
@@ -40,7 +40,13 @@ export const getNetworkSettingsWarningMessage = (): string => {
if (numberOfMatches !== portalIPs.length) { if (numberOfMatches !== portalIPs.length) {
return "The Network settings for this account are preventing access from Data Explorer. Please allow access from Azure Portal to proceed."; return "The Network settings for this account are preventing access from Data Explorer. Please allow access from Azure Portal to proceed.";
} }
}
return ""; return "";
} else {
if (!clientIpAddress || ipRules.some((ipRule) => ipRule.ipAddressOrRange === clientIpAddress)) {
return "";
}
return "The Network settings for this account are preventing access from Data Explorer. Please add your current IP to the firewall rules to proceed.";
}
}; };

View File

@@ -1,4 +1,3 @@
import Explorer from "Explorer/Explorer";
import { ReactTabKind, useTabs } from "hooks/useTabs"; import { ReactTabKind, useTabs } from "hooks/useTabs";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { getNetworkSettingsWarningMessage } from "Utils/NetworkUtility"; import { getNetworkSettingsWarningMessage } from "Utils/NetworkUtility";
@@ -11,6 +10,7 @@ import { configContext, Platform, updateConfigContext } from "../ConfigContext";
import { ActionType, DataExplorerAction } from "../Contracts/ActionContracts"; import { ActionType, DataExplorerAction } from "../Contracts/ActionContracts";
import { MessageTypes } from "../Contracts/ExplorerContracts"; import { MessageTypes } from "../Contracts/ExplorerContracts";
import { DataExplorerInputsFrame } from "../Contracts/ViewModels"; import { DataExplorerInputsFrame } from "../Contracts/ViewModels";
import Explorer from "../Explorer/Explorer";
import { handleOpenAction } from "../Explorer/OpenActions/OpenActions"; import { handleOpenAction } from "../Explorer/OpenActions/OpenActions";
import { useDatabases } from "../Explorer/useDatabases"; import { useDatabases } from "../Explorer/useDatabases";
import { import {
@@ -33,7 +33,7 @@ import { Node, PortalEnv, updateUserContext, userContext } from "../UserContext"
import { listKeys } from "../Utils/arm/generatedClients/cosmos/databaseAccounts"; import { listKeys } from "../Utils/arm/generatedClients/cosmos/databaseAccounts";
import { DatabaseAccountListKeysResult } from "../Utils/arm/generatedClients/cosmos/types"; import { DatabaseAccountListKeysResult } from "../Utils/arm/generatedClients/cosmos/types";
import { getMsalInstance } from "../Utils/AuthorizationUtils"; import { getMsalInstance } from "../Utils/AuthorizationUtils";
import { isInvalidParentFrameOrigin, shouldProcessMessage } from "../Utils/MessageValidation"; import { isInvalidParentFrameOrigin } from "../Utils/MessageValidation";
// This hook will create a new instance of Explorer.ts and bind it to the DOM // This hook will create a new instance of Explorer.ts and bind it to the DOM
// This hook has a LOT of magic, but ideally we can delete it once we have removed KO and switched entirely to React // This hook has a LOT of magic, but ideally we can delete it once we have removed KO and switched entirely to React
@@ -239,7 +239,6 @@ async function configurePortal(): Promise<Explorer> {
updateUserContext({ updateUserContext({
authType: AuthType.AAD, authType: AuthType.AAD,
}); });
let explorer: Explorer;
return new Promise((resolve) => { return new Promise((resolve) => {
// In development mode, try to load the iframe message from session storage. // In development mode, try to load the iframe message from session storage.
// This allows webpack hot reload to function properly in the portal // This allows webpack hot reload to function properly in the portal
@@ -252,7 +251,7 @@ async function configurePortal(): Promise<Explorer> {
); );
console.dir(message); console.dir(message);
updateContextsFromPortalMessage(message); updateContextsFromPortalMessage(message);
explorer = new Explorer(); const explorer = new Explorer();
// In development mode, save the iframe message from the portal in session storage. // In development mode, save the iframe message from the portal in session storage.
// This allows webpack hot reload to funciton properly // This allows webpack hot reload to funciton properly
if (process.env.NODE_ENV === "development") { if (process.env.NODE_ENV === "development") {
@@ -288,7 +287,7 @@ async function configurePortal(): Promise<Explorer> {
} }
updateContextsFromPortalMessage(inputs); updateContextsFromPortalMessage(inputs);
explorer = new Explorer(); const explorer = new Explorer();
resolve(explorer); resolve(explorer);
if (openAction) { if (openAction) {
handleOpenAction(openAction, useDatabases.getState().databases, explorer); handleOpenAction(openAction, useDatabases.getState().databases, explorer);
@@ -301,8 +300,6 @@ async function configurePortal(): Promise<Explorer> {
} else { } else {
useTabs.getState().closeTabsByComparator((tab) => tab.tabId === event.data?.data?.tabId); useTabs.getState().closeTabsByComparator((tab) => tab.tabId === event.data?.data?.tabId);
} }
} else if (message?.type === MessageTypes.RefreshResources) {
explorer.onRefreshResourcesClick();
} }
}, },
false false
@@ -317,6 +314,23 @@ function shouldForwardMessage(message: PortalMessage, messageOrigin: string) {
return messageOrigin === window.document.location.origin && message.type === MessageTypes.TelemetryInfo; return messageOrigin === window.document.location.origin && message.type === MessageTypes.TelemetryInfo;
} }
function shouldProcessMessage(event: MessageEvent): boolean {
if (typeof event.data !== "object") {
return false;
}
if (event.data["signature"] !== "pcIframe") {
return false;
}
if (!("data" in event.data)) {
return false;
}
if (typeof event.data["data"] !== "object") {
return false;
}
return true;
}
function updateContextsFromPortalMessage(inputs: DataExplorerInputsFrame) { function updateContextsFromPortalMessage(inputs: DataExplorerInputsFrame) {
if ( if (
configContext.BACKEND_ENDPOINT && configContext.BACKEND_ENDPOINT &&
@@ -368,7 +382,7 @@ function updateContextsFromPortalMessage(inputs: DataExplorerInputsFrame) {
} }
} }
const warningMessage = getNetworkSettingsWarningMessage(); const warningMessage = getNetworkSettingsWarningMessage(inputs.clientIpAddress);
useTabs.getState().setNetworkSettingsWarning(warningMessage); useTabs.getState().setNetworkSettingsWarning(warningMessage);
if (inputs.features) { if (inputs.features) {