Move setting pane to react (#543)

Co-authored-by: Steve Faulkner <471400+southpolesteve@users.noreply.github.com>
This commit is contained in:
Hardikkumar Nai 2021-04-01 01:52:52 +05:30 committed by GitHub
parent 69ac4e218d
commit 458cca8e01
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 3658 additions and 1391 deletions

View File

@ -132,8 +132,6 @@ src/Explorer/Panes/NewVertexPane.ts
src/Explorer/Panes/PaneComponents.ts
src/Explorer/Panes/RenewAdHocAccessPane.ts
src/Explorer/Panes/SaveQueryPane.ts
src/Explorer/Panes/SettingsPane.test.ts
src/Explorer/Panes/SettingsPane.ts
src/Explorer/Panes/SetupNotebooksPane.ts
src/Explorer/Panes/StringInputPane.ts
src/Explorer/Panes/SwitchDirectoryPane.ts

1479
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,7 @@
"@types/mkdirp": "1.0.1",
"@types/node-fetch": "2.5.7",
"@uifabric/react-cards": "0.109.110",
"@uifabric/react-hooks": "7.14.0",
"@uifabric/styling": "7.13.7",
"applicationinsights": "1.8.0",
"bootstrap": "3.4.1",

View File

@ -0,0 +1,24 @@
import { useId } from "@uifabric/react-hooks";
import { ITooltipHostStyles, TooltipHost } from "office-ui-fabric-react/lib/Tooltip";
import * as React from "react";
import InfoBubble from "../../../images/info-bubble.svg";
const calloutProps = { gapSpace: 0 };
const hostStyles: Partial<ITooltipHostStyles> = { root: { display: "inline-block" } };
export interface TooltipProps {
children: string;
}
export const Tooltip: React.FunctionComponent = ({ children }: TooltipProps) => {
const tooltipId = useId("tooltip");
return children ? (
<span>
<TooltipHost content={children} id={tooltipId} calloutProps={calloutProps} styles={hostStyles}>
<img className="infoImg" src={InfoBubble} alt="More information" />
</TooltipHost>
</span>
) : (
<></>
);
};

View File

@ -1,31 +1,30 @@
import * as ko from "knockout";
import * as PaneComponents from "./Panes/PaneComponents";
import { DiffEditorComponent } from "./Controls/DiffEditor/DiffEditorComponent";
import { DynamicListComponent } from "./Controls/DynamicList/DynamicListComponent";
import { EditorComponent } from "./Controls/Editor/EditorComponent";
import { ErrorDisplayComponent } from "./Controls/ErrorDisplayComponent/ErrorDisplayComponent";
import { GraphStyleComponent } from "./Graph/GraphStyleComponent/GraphStyleComponent";
import { InputTypeaheadComponent } from "./Controls/InputTypeahead/InputTypeahead";
import { JsonEditorComponent } from "./Controls/JsonEditor/JsonEditorComponent";
import { NewVertexComponent } from "./Graph/NewVertexComponent/NewVertexComponent";
import { ThroughputInputComponentAutoPilotV3 } from "./Controls/ThroughputInput/ThroughputInputComponentAutoPilotV3";
import { GraphStyleComponent } from "./Graph/GraphStyleComponent/GraphStyleComponent";
import { NewVertexComponent } from "./Graph/NewVertexComponent/NewVertexComponent";
import * as PaneComponents from "./Panes/PaneComponents";
import ConflictsTab from "./Tabs/ConflictsTab";
import DatabaseSettingsTab from "./Tabs/DatabaseSettingsTab";
import DocumentsTab from "./Tabs/DocumentsTab";
import StoredProcedureTab from "./Tabs/StoredProcedureTab";
import TriggerTab from "./Tabs/TriggerTab";
import UserDefinedFunctionTab from "./Tabs/UserDefinedFunctionTab";
import { DatabaseSettingsTabV2, SettingsTabV2 } from "./Tabs/SettingsTabV2";
import QueryTab from "./Tabs/QueryTab";
import QueryTablesTab from "./Tabs/QueryTablesTab";
import GalleryTab from "./Tabs/GalleryTab";
import GraphTab from "./Tabs/GraphTab";
import MongoShellTab from "./Tabs/MongoShellTab";
import ConflictsTab from "./Tabs/ConflictsTab";
import NotebookTabV2 from "./Tabs/NotebookV2Tab";
import TerminalTab from "./Tabs/TerminalTab";
import GalleryTab from "./Tabs/GalleryTab";
import NotebookViewerTab from "./Tabs/NotebookViewerTab";
import DatabaseSettingsTab from "./Tabs/DatabaseSettingsTab";
import QueryTab from "./Tabs/QueryTab";
import QueryTablesTab from "./Tabs/QueryTablesTab";
import { DatabaseSettingsTabV2, SettingsTabV2 } from "./Tabs/SettingsTabV2";
import StoredProcedureTab from "./Tabs/StoredProcedureTab";
import TabsManagerTemplate from "./Tabs/TabsManager.html";
import TerminalTab from "./Tabs/TerminalTab";
import TriggerTab from "./Tabs/TriggerTab";
import UserDefinedFunctionTab from "./Tabs/UserDefinedFunctionTab";
ko.components.register("input-typeahead", new InputTypeaheadComponent());
ko.components.register("new-vertex-form", NewVertexComponent);
@ -76,7 +75,6 @@ ko.components.register("table-edit-entity-pane", new PaneComponents.TableEditEnt
ko.components.register("table-column-options-pane", new PaneComponents.TableColumnOptionsPaneComponent());
ko.components.register("table-query-select-pane", new PaneComponents.TableQuerySelectPaneComponent());
ko.components.register("cassandra-add-collection-pane", new PaneComponents.CassandraAddCollectionPaneComponent());
ko.components.register("settings-pane", new PaneComponents.SettingsPaneComponent());
ko.components.register("upload-items-pane", new PaneComponents.UploadItemsPaneComponent());
ko.components.register("load-query-pane", new PaneComponents.LoadQueryPaneComponent());
ko.components.register("save-query-pane", new PaneComponents.SaveQueryPaneComponent());

View File

@ -350,11 +350,11 @@ exports[`test render renders with filters 1`] = `
}
>
<div
className="ms-ScrollablePane root-40"
className="ms-ScrollablePane root-72"
data-is-scrollable="true"
>
<div
className="stickyAbove-42"
className="stickyAbove-74"
style={
Object {
"height": 0,
@ -365,7 +365,7 @@ exports[`test render renders with filters 1`] = `
}
/>
<div
className="ms-ScrollablePane--contentContainer contentContainer-41"
className="ms-ScrollablePane--contentContainer contentContainer-73"
data-is-scrollable={true}
>
<Sticky
@ -691,18 +691,18 @@ exports[`test render renders with filters 1`] = `
validateOnLoad={true}
>
<div
className="ms-TextField directoryListFilterTextBox root-46"
className="ms-TextField directoryListFilterTextBox root-78"
>
<div
className="ms-TextField-wrapper"
>
<div
className="ms-TextField-fieldGroup fieldGroup-47"
className="ms-TextField-fieldGroup fieldGroup-79"
>
<input
aria-invalid={false}
aria-label="Directory filter text box"
className="ms-TextField-field field-48"
className="ms-TextField-field field-80"
id="TextField0"
onBlur={[Function]}
onChange={[Function]}
@ -1900,7 +1900,7 @@ exports[`test render renders with filters 1`] = `
>
<button
aria-disabled={true}
className="ms-Button ms-Button--default is-disabled directoryListButton root-57"
className="ms-Button ms-Button--default is-disabled directoryListButton root-89"
data-is-focusable={false}
disabled={true}
onClick={[Function]}
@ -1912,7 +1912,7 @@ exports[`test render renders with filters 1`] = `
type="button"
>
<span
className="ms-Button-flexContainer flexContainer-58"
className="ms-Button-flexContainer flexContainer-90"
data-automationid="splitbuttonprimary"
>
<div
@ -1943,7 +1943,7 @@ exports[`test render renders with filters 1`] = `
</List>
</div>
<div
className="stickyBelow-43"
className="stickyBelow-75"
style={
Object {
"bottom": "0px",
@ -1954,7 +1954,7 @@ exports[`test render renders with filters 1`] = `
}
>
<div
className="stickyBelowItems-44"
className="stickyBelowItems-76"
/>
</div>
</div>

View File

@ -386,29 +386,6 @@ exports[`SettingsComponent renders 1`] = `
"userTableQuery": [Function],
"visible": [Function],
},
SettingsPane {
"container": [Circular],
"crossPartitionQueryEnabled": [Function],
"customItemPerPage": [Function],
"explorerVersion": undefined,
"firstFieldHasFocus": [Function],
"formErrors": [Function],
"formErrorsDetails": [Function],
"graphAutoVizDisabled": [Function],
"id": "settingspane",
"isCustomPageOptionSelected": [Function],
"isExecuting": [Function],
"isTemplateReady": [Function],
"isUnlimitedPageOptionSelected": [Function],
"maxDegreeOfParallelism": [Function],
"pageOption": [Function],
"shouldShowCrossPartitionOption": [Function],
"shouldShowGraphAutoVizOption": [Function],
"shouldShowParallelismOption": [Function],
"shouldShowQueryPageOptions": [Function],
"title": [Function],
"visible": [Function],
},
UploadItemsPane {
"container": [Circular],
"fileUploadSummaryText": [Function],
@ -1007,29 +984,6 @@ exports[`SettingsComponent renders 1`] = `
"setInProgressConsoleDataIdToBeDeleted": undefined,
"setIsNotificationConsoleExpanded": undefined,
"setNotificationConsoleData": undefined,
"settingsPane": SettingsPane {
"container": [Circular],
"crossPartitionQueryEnabled": [Function],
"customItemPerPage": [Function],
"explorerVersion": undefined,
"firstFieldHasFocus": [Function],
"formErrors": [Function],
"formErrorsDetails": [Function],
"graphAutoVizDisabled": [Function],
"id": "settingspane",
"isCustomPageOptionSelected": [Function],
"isExecuting": [Function],
"isTemplateReady": [Function],
"isUnlimitedPageOptionSelected": [Function],
"maxDegreeOfParallelism": [Function],
"pageOption": [Function],
"shouldShowCrossPartitionOption": [Function],
"shouldShowGraphAutoVizOption": [Function],
"shouldShowParallelismOption": [Function],
"shouldShowQueryPageOptions": [Function],
"title": [Function],
"visible": [Function],
},
"setupNotebooksPane": SetupNotebooksPane {
"container": [Circular],
"description": [Function],
@ -1530,29 +1484,6 @@ exports[`SettingsComponent renders 1`] = `
"userTableQuery": [Function],
"visible": [Function],
},
SettingsPane {
"container": [Circular],
"crossPartitionQueryEnabled": [Function],
"customItemPerPage": [Function],
"explorerVersion": undefined,
"firstFieldHasFocus": [Function],
"formErrors": [Function],
"formErrorsDetails": [Function],
"graphAutoVizDisabled": [Function],
"id": "settingspane",
"isCustomPageOptionSelected": [Function],
"isExecuting": [Function],
"isTemplateReady": [Function],
"isUnlimitedPageOptionSelected": [Function],
"maxDegreeOfParallelism": [Function],
"pageOption": [Function],
"shouldShowCrossPartitionOption": [Function],
"shouldShowGraphAutoVizOption": [Function],
"shouldShowParallelismOption": [Function],
"shouldShowQueryPageOptions": [Function],
"title": [Function],
"visible": [Function],
},
UploadItemsPane {
"container": [Circular],
"fileUploadSummaryText": [Function],
@ -2151,29 +2082,6 @@ exports[`SettingsComponent renders 1`] = `
"setInProgressConsoleDataIdToBeDeleted": undefined,
"setIsNotificationConsoleExpanded": undefined,
"setNotificationConsoleData": undefined,
"settingsPane": SettingsPane {
"container": [Circular],
"crossPartitionQueryEnabled": [Function],
"customItemPerPage": [Function],
"explorerVersion": undefined,
"firstFieldHasFocus": [Function],
"formErrors": [Function],
"formErrorsDetails": [Function],
"graphAutoVizDisabled": [Function],
"id": "settingspane",
"isCustomPageOptionSelected": [Function],
"isExecuting": [Function],
"isTemplateReady": [Function],
"isUnlimitedPageOptionSelected": [Function],
"maxDegreeOfParallelism": [Function],
"pageOption": [Function],
"shouldShowCrossPartitionOption": [Function],
"shouldShowGraphAutoVizOption": [Function],
"shouldShowParallelismOption": [Function],
"shouldShowQueryPageOptions": [Function],
"title": [Function],
"visible": [Function],
},
"setupNotebooksPane": SetupNotebooksPane {
"container": [Circular],
"description": [Function],
@ -2687,29 +2595,6 @@ exports[`SettingsComponent renders 1`] = `
"userTableQuery": [Function],
"visible": [Function],
},
SettingsPane {
"container": [Circular],
"crossPartitionQueryEnabled": [Function],
"customItemPerPage": [Function],
"explorerVersion": undefined,
"firstFieldHasFocus": [Function],
"formErrors": [Function],
"formErrorsDetails": [Function],
"graphAutoVizDisabled": [Function],
"id": "settingspane",
"isCustomPageOptionSelected": [Function],
"isExecuting": [Function],
"isTemplateReady": [Function],
"isUnlimitedPageOptionSelected": [Function],
"maxDegreeOfParallelism": [Function],
"pageOption": [Function],
"shouldShowCrossPartitionOption": [Function],
"shouldShowGraphAutoVizOption": [Function],
"shouldShowParallelismOption": [Function],
"shouldShowQueryPageOptions": [Function],
"title": [Function],
"visible": [Function],
},
UploadItemsPane {
"container": [Circular],
"fileUploadSummaryText": [Function],
@ -3308,29 +3193,6 @@ exports[`SettingsComponent renders 1`] = `
"setInProgressConsoleDataIdToBeDeleted": undefined,
"setIsNotificationConsoleExpanded": undefined,
"setNotificationConsoleData": undefined,
"settingsPane": SettingsPane {
"container": [Circular],
"crossPartitionQueryEnabled": [Function],
"customItemPerPage": [Function],
"explorerVersion": undefined,
"firstFieldHasFocus": [Function],
"formErrors": [Function],
"formErrorsDetails": [Function],
"graphAutoVizDisabled": [Function],
"id": "settingspane",
"isCustomPageOptionSelected": [Function],
"isExecuting": [Function],
"isTemplateReady": [Function],
"isUnlimitedPageOptionSelected": [Function],
"maxDegreeOfParallelism": [Function],
"pageOption": [Function],
"shouldShowCrossPartitionOption": [Function],
"shouldShowGraphAutoVizOption": [Function],
"shouldShowParallelismOption": [Function],
"shouldShowQueryPageOptions": [Function],
"title": [Function],
"visible": [Function],
},
"setupNotebooksPane": SetupNotebooksPane {
"container": [Circular],
"description": [Function],
@ -3831,29 +3693,6 @@ exports[`SettingsComponent renders 1`] = `
"userTableQuery": [Function],
"visible": [Function],
},
SettingsPane {
"container": [Circular],
"crossPartitionQueryEnabled": [Function],
"customItemPerPage": [Function],
"explorerVersion": undefined,
"firstFieldHasFocus": [Function],
"formErrors": [Function],
"formErrorsDetails": [Function],
"graphAutoVizDisabled": [Function],
"id": "settingspane",
"isCustomPageOptionSelected": [Function],
"isExecuting": [Function],
"isTemplateReady": [Function],
"isUnlimitedPageOptionSelected": [Function],
"maxDegreeOfParallelism": [Function],
"pageOption": [Function],
"shouldShowCrossPartitionOption": [Function],
"shouldShowGraphAutoVizOption": [Function],
"shouldShowParallelismOption": [Function],
"shouldShowQueryPageOptions": [Function],
"title": [Function],
"visible": [Function],
},
UploadItemsPane {
"container": [Circular],
"fileUploadSummaryText": [Function],
@ -4452,29 +4291,6 @@ exports[`SettingsComponent renders 1`] = `
"setInProgressConsoleDataIdToBeDeleted": undefined,
"setIsNotificationConsoleExpanded": undefined,
"setNotificationConsoleData": undefined,
"settingsPane": SettingsPane {
"container": [Circular],
"crossPartitionQueryEnabled": [Function],
"customItemPerPage": [Function],
"explorerVersion": undefined,
"firstFieldHasFocus": [Function],
"formErrors": [Function],
"formErrorsDetails": [Function],
"graphAutoVizDisabled": [Function],
"id": "settingspane",
"isCustomPageOptionSelected": [Function],
"isExecuting": [Function],
"isTemplateReady": [Function],
"isUnlimitedPageOptionSelected": [Function],
"maxDegreeOfParallelism": [Function],
"pageOption": [Function],
"shouldShowCrossPartitionOption": [Function],
"shouldShowGraphAutoVizOption": [Function],
"shouldShowParallelismOption": [Function],
"shouldShowQueryPageOptions": [Function],
"title": [Function],
"visible": [Function],
},
"setupNotebooksPane": SetupNotebooksPane {
"container": [Circular],
"description": [Function],

View File

@ -212,7 +212,6 @@ export default class Explorer {
public querySelectPane: QuerySelectPane;
public newVertexPane: NewVertexPane;
public cassandraAddCollectionPane: CassandraAddCollectionPane;
public settingsPane: SettingsPane;
public uploadItemsPane: UploadItemsPane;
public uploadItemsPaneAdapter: UploadItemsPaneAdapter;
public loadQueryPane: LoadQueryPane;
@ -624,13 +623,6 @@ export default class Explorer {
container: this,
});
this.settingsPane = new SettingsPane({
id: "settingspane",
visible: ko.observable<boolean>(false),
container: this,
});
this.uploadItemsPane = new UploadItemsPane({
id: "uploaditemspane",
visible: ko.observable<boolean>(false),
@ -696,7 +688,6 @@ export default class Explorer {
this.querySelectPane,
this.newVertexPane,
this.cassandraAddCollectionPane,
this.settingsPane,
this.uploadItemsPane,
this.loadQueryPane,
this.saveQueryPane,
@ -2454,6 +2445,10 @@ export default class Explorer {
);
}
public openSettingPane(): void {
this.openSidePanel("Settings", <SettingsPane explorer={this} closePanel={this.closeSidePanel} />);
}
public openExecuteSprocParamsPanel(): void {
this.openSidePanel(
"Input parameters",

View File

@ -164,7 +164,7 @@ export function createControlCommandBarButtons(container: Explorer): CommandButt
const settingsPaneButton: CommandButtonComponentProps = {
iconSrc: SettingsIcon,
iconAlt: label,
onCommandClick: () => container.settingsPane.open(),
onCommandClick: () => container.openSettingPane(),
commandButtonLabel: undefined,
ariaLabel: label,
tooltipText: label,

View File

@ -1,7 +1,7 @@
// TODO convert this file to an action registry in order to have actions and their handlers be more tightly coupled.
import * as ViewModels from "../Contracts/ViewModels";
import { ActionContracts } from "../Contracts/ExplorerContracts";
import * as ViewModels from "../Contracts/ViewModels";
import Explorer from "./Explorer";
export function handleOpenAction(
@ -145,7 +145,7 @@ function openPane(action: ActionContracts.OpenPane, explorer: Explorer) {
(<any>action).paneKind === ActionContracts.PaneKind[ActionContracts.PaneKind.GlobalSettings]
) {
explorer.closeAllPanes();
explorer.settingsPane.open();
explorer.openSettingPane();
}
}

View File

@ -1061,7 +1061,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
>
<button
aria-label="Close pane"
className="ms-Button ms-Button--icon closePaneBtn root-40"
className="ms-Button ms-Button--icon closePaneBtn root-72"
data-is-focusable={true}
onClick={[Function]}
onKeyDown={[Function]}
@ -1074,16 +1074,16 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
type="button"
>
<span
className="ms-Button-flexContainer flexContainer-41"
className="ms-Button-flexContainer flexContainer-73"
data-automationid="splitbuttonprimary"
>
<Component
className="ms-Button-icon icon-43"
className="ms-Button-icon icon-75"
iconName="Cancel"
>
<i
aria-hidden={true}
className="ms-Icon root-37 css-48 ms-Button-icon icon-43"
className="ms-Icon root-37 css-80 ms-Button-icon icon-75"
data-icon-name="Cancel"
role="presentation"
style={
@ -1429,7 +1429,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
}
>
<label
className="ms-Label root-49"
className="ms-Label root-81"
>
Partition key value
</label>
@ -1439,7 +1439,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
horizontal={true}
>
<div
className="ms-Stack css-50"
className="ms-Stack css-82"
>
<StyledWithResponsiveMode
key=".0:$.0"
@ -2336,7 +2336,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
}
>
<label
className="ms-Label ms-Dropdown-label root-67"
className="ms-Label ms-Dropdown-label root-99"
id="Dropdown3-label"
>
Key
@ -2348,7 +2348,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
aria-expanded="false"
aria-haspopup="listbox"
aria-labelledby="Dropdown3-label Dropdown3-option"
className="ms-Dropdown dropdown-51"
className="ms-Dropdown dropdown-83"
data-is-focusable={true}
id="Dropdown3"
onBlur={[Function]}
@ -2368,23 +2368,23 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
aria-posinset={1}
aria-selected={true}
aria-setsize={2}
className="ms-Dropdown-title title-52"
className="ms-Dropdown-title title-84"
id="Dropdown3-option"
role="option"
>
String
</span>
<span
className="ms-Dropdown-caretDownWrapper caretDownWrapper-53"
className="ms-Dropdown-caretDownWrapper caretDownWrapper-85"
>
<StyledIconBase
aria-hidden={true}
className="ms-Dropdown-caretDown caretDown-54"
className="ms-Dropdown-caretDown caretDown-86"
iconName="ChevronDown"
>
<IconBase
aria-hidden={true}
className="ms-Dropdown-caretDown caretDown-54"
className="ms-Dropdown-caretDown caretDown-86"
iconName="ChevronDown"
styles={[Function]}
theme={
@ -2663,7 +2663,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
>
<i
aria-hidden={true}
className="ms-Dropdown-caretDown caretDown-68"
className="ms-Dropdown-caretDown caretDown-100"
data-icon-name="ChevronDown"
>
@ -2971,7 +2971,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
value=""
>
<div
className="ms-TextField root-70"
className="ms-TextField root-102"
>
<div
className="ms-TextField-wrapper"
@ -3260,7 +3260,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
}
>
<label
className="ms-Label root-49"
className="ms-Label root-81"
htmlFor="confirmCollectionId"
id="TextFieldLabel6"
>
@ -3269,13 +3269,13 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
</LabelBase>
</StyledLabelBase>
<div
className="ms-TextField-fieldGroup fieldGroup-71"
className="ms-TextField-fieldGroup fieldGroup-103"
>
<input
aria-invalid={false}
aria-labelledby="TextFieldLabel6"
autoFocus={true}
className="ms-TextField-field field-72"
className="ms-TextField-field field-104"
id="confirmCollectionId"
onBlur={[Function]}
onChange={[Function]}
@ -3583,7 +3583,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
}
>
<label
className="ms-Label root-49"
className="ms-Label root-81"
>
Enter input parameters (if any)
</label>
@ -3593,7 +3593,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
horizontal={true}
>
<div
className="ms-Stack css-50"
className="ms-Stack css-82"
>
<StyledWithResponsiveMode
key=".0:$.0"
@ -4490,7 +4490,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
}
>
<label
className="ms-Label ms-Dropdown-label root-67"
className="ms-Label ms-Dropdown-label root-99"
id="Dropdown7-label"
>
Key
@ -4502,7 +4502,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
aria-expanded="false"
aria-haspopup="listbox"
aria-labelledby="Dropdown7-label Dropdown7-option"
className="ms-Dropdown dropdown-51"
className="ms-Dropdown dropdown-83"
data-is-focusable={true}
id="Dropdown7"
onBlur={[Function]}
@ -4522,23 +4522,23 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
aria-posinset={1}
aria-selected={true}
aria-setsize={2}
className="ms-Dropdown-title title-52"
className="ms-Dropdown-title title-84"
id="Dropdown7-option"
role="option"
>
String
</span>
<span
className="ms-Dropdown-caretDownWrapper caretDownWrapper-53"
className="ms-Dropdown-caretDownWrapper caretDownWrapper-85"
>
<StyledIconBase
aria-hidden={true}
className="ms-Dropdown-caretDown caretDown-54"
className="ms-Dropdown-caretDown caretDown-86"
iconName="ChevronDown"
>
<IconBase
aria-hidden={true}
className="ms-Dropdown-caretDown caretDown-54"
className="ms-Dropdown-caretDown caretDown-86"
iconName="ChevronDown"
styles={[Function]}
theme={
@ -4817,7 +4817,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
>
<i
aria-hidden={true}
className="ms-Dropdown-caretDown caretDown-68"
className="ms-Dropdown-caretDown caretDown-100"
data-icon-name="ChevronDown"
>
@ -5125,7 +5125,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
value=""
>
<div
className="ms-TextField root-70"
className="ms-TextField root-102"
>
<div
className="ms-TextField-wrapper"
@ -5414,7 +5414,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
}
>
<label
className="ms-Label root-49"
className="ms-Label root-81"
htmlFor="confirmCollectionId"
id="TextFieldLabel10"
>
@ -5423,13 +5423,13 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
</LabelBase>
</StyledLabelBase>
<div
className="ms-TextField-fieldGroup fieldGroup-71"
className="ms-TextField-fieldGroup fieldGroup-103"
>
<input
aria-invalid={false}
aria-labelledby="TextFieldLabel10"
autoFocus={true}
className="ms-TextField-field field-72"
className="ms-TextField-field field-104"
id="confirmCollectionId"
onBlur={[Function]}
onChange={[Function]}
@ -5737,7 +5737,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
width={20}
>
<div
className="ms-Image addRemoveIconLabel root-81"
className="ms-Image addRemoveIconLabel root-113"
style={
Object {
"height": 30,
@ -5747,7 +5747,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
>
<img
alt="Delete param"
className="ms-Image-image ms-Image-image--portrait is-notLoaded is-fadeIn image-82"
className="ms-Image-image ms-Image-image--portrait is-notLoaded is-fadeIn image-114"
id="deleteparam"
key="fabricImage"
onClick={[Function]}
@ -6052,7 +6052,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
width={20}
>
<div
className="ms-Image addRemoveIconLabel root-81"
className="ms-Image addRemoveIconLabel root-113"
style={
Object {
"height": 30,
@ -6062,7 +6062,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
>
<img
alt="Add param"
className="ms-Image-image ms-Image-image--portrait is-notLoaded is-fadeIn image-82"
className="ms-Image-image ms-Image-image--portrait is-notLoaded is-fadeIn image-114"
id="addparam"
key="fabricImage"
onClick={[Function]}
@ -6081,7 +6081,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
onClick={[Function]}
>
<div
className="ms-Stack css-50"
className="ms-Stack css-82"
onClick={[Function]}
>
<StyledImageBase
@ -6373,7 +6373,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
width={20}
>
<div
className="ms-Image root-81"
className="ms-Image root-113"
style={
Object {
"height": 30,
@ -6383,7 +6383,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
>
<img
alt="Add param"
className="ms-Image-image ms-Image-image--portrait is-notLoaded is-fadeIn image-82"
className="ms-Image-image ms-Image-image--portrait is-notLoaded is-fadeIn image-114"
key="fabricImage"
onError={[Function]}
onLoad={[Function]}
@ -6397,7 +6397,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
key=".0:$.1"
>
<span
className="addNewParamStyle css-83"
className="addNewParamStyle css-115"
>
Add New Param
</span>
@ -8123,7 +8123,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
>
<button
aria-label="Submit"
className="ms-Button ms-Button--primary genericPaneSubmitBtn root-84"
className="ms-Button ms-Button--primary genericPaneSubmitBtn root-116"
data-is-focusable={true}
onClick={[Function]}
onKeyDown={[Function]}
@ -8141,14 +8141,14 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
type="button"
>
<span
className="ms-Button-flexContainer flexContainer-41"
className="ms-Button-flexContainer flexContainer-73"
data-automationid="splitbuttonprimary"
>
<span
className="ms-Button-textContainer textContainer-42"
className="ms-Button-textContainer textContainer-74"
>
<span
className="ms-Button-label label-85"
className="ms-Button-label label-117"
id="id__11"
key="id__11"
>

View File

@ -9,7 +9,6 @@ import GraphNewVertexPaneTemplate from "./GraphNewVertexPane.html";
import GraphStylingPaneTemplate from "./GraphStylingPane.html";
import LoadQueryPaneTemplate from "./LoadQueryPane.html";
import SaveQueryPaneTemplate from "./SaveQueryPane.html";
import SettingsPaneTemplate from "./SettingsPane.html";
import SetupNotebooksPaneTemplate from "./SetupNotebooksPane.html";
import StringInputPaneTemplate from "./StringInputPane.html";
import TableAddEntityPaneTemplate from "./Tables/TableAddEntityPane.html";
@ -124,15 +123,6 @@ export class CassandraAddCollectionPaneComponent {
}
}
export class SettingsPaneComponent {
constructor() {
return {
viewModel: PaneComponent,
template: SettingsPaneTemplate,
};
}
}
export class UploadItemsPaneComponent {
constructor() {
return {

View File

@ -1,268 +0,0 @@
<!-- TODO: Move Pane to REACT -->
<div data-bind="visible: visible, event: { keydown: onPaneKeyDown }">
<div
class="contextual-pane-out"
data-bind="
click: cancel,
clickBubble: false"
></div>
<div class="contextual-pane" id="settingspane">
<!-- Settings Confirmation form - Start -->
<div class="contextual-pane-in">
<form class="paneContentContainer" data-bind="submit: submit">
<!-- Settings Confirmation header - Start -->
<div class="firstdivbg headerline">
<span role="heading" aria-level="2" data-bind="text: title"></span>
<div
class="closeImg"
role="button"
aria-label="Close pane"
tabindex="0"
data-bind="
click: cancel, event: { keydown: onCloseKeyPress }"
>
<img src="../../../images/close-black.svg" title="Close" alt="Close" />
</div>
</div>
<!-- Settings Confirmation header - End -->
<!-- Settings Confirmation errors - Start -->
<div
class="warningErrorContainer"
aria-live="assertive"
data-bind="visible: formErrors() && formErrors() !== ''"
>
<div class="warningErrorContent">
<span><img class="paneErrorIcon" src="/error_red.svg" alt="Error" /></span>
<span class="warningErrorDetailsLinkContainer">
<span class="formErrors" data-bind="text: formErrors, attr: { title: formErrors }"></span>
<a
class="errorLink"
role="link"
data-bind="
visible: formErrorsDetails() && formErrorsDetails() !== '',
click: showErrorDetails"
>More details</a
>
</span>
</div>
</div>
<!-- Settings Confirmation errors - End -->
<!-- Settings Confirmation inputs - Start -->
<div class="paneMainContent">
<div>
<div class="settingsSection" data-bind="visible: shouldShowQueryPageOptions">
<div class="settingsSectionPart pageOptionsPart">
<div class="settingsSectionLabel">
Page options
<span class="infoTooltip" role="tooltip" tabindex="0">
<img class="infoImg" src="/info-bubble.svg" alt="More information" />
<span class="tooltiptext pageOptionTooltipWidth">
Choose Custom to specify a fixed amount of query results to show, or choose Unlimited to show as
many query results per page.
</span>
</span>
</div>
<div class="tabs" role="radiogroup" aria-label="Page options">
<!-- Fixed option button - Start -->
<div class="tab">
<input
type="radio"
id="customItemPerPage"
name="pageOption"
value="custom"
data-bind="checked: pageOption"
/>
<label
for="customItemPerPage"
id="custom-selection"
tabindex="0"
role="radio"
data-bind=" attr:{
'aria-checked': pageOption() === 'custom' ? 'true' : 'false' },
event: { keydown: onCustomPageOptionsKeyDown
}"
>Custom</label
>
</div>
<!-- Fixed option button - End -->
<!-- Unlimited option button - Start -->
<div class="tab">
<input
type="radio"
id="unlimitedItemPerPage"
name="pageOption"
value="unlimited"
data-bind="checked: pageOption"
/>
<label
for="unlimitedItemPerPage"
id="unlimited-selection"
tabindex="0"
role="radio"
data-bind=" attr:{
'aria-checked': pageOption() === 'unlimited' ? 'true' : 'false' },
event: { keydown: onUnlimitedPageOptionKeyDown
}"
>Unlimited</label
>
</div>
<!-- Unlimited option button - End -->
</div>
</div>
<div class="tabs settingsSectionPart">
<div class="tabcontent" data-bind="visible: isCustomPageOptionSelected()">
<div class="settingsSectionLabel">
Query results per page
<span class="infoTooltip" role="tooltip" tabindex="0">
<img class="infoImg" src="/info-bubble.svg" alt="More information" />
<span class="tooltiptext pageOptionTooltipWidth">
Enter the number of query results that should be shown per page.
</span>
</span>
</div>
<input
type="number"
required
min="1"
step="1"
class="textfontclr collid"
aria-label="Custom query items per page"
data-bind="textInput: customItemPerPage, enable: isCustomPageOptionSelected()"
/>
</div>
</div>
</div>
<div class="settingsSection" data-bind="visible: shouldShowCrossPartitionOption">
<div class="settingsSectionPart">
<div class="settingsSectionLabel">
Enable cross-partition query
<span class="infoTooltip" role="tooltip" tabindex="0">
<img class="infoImg" src="/info-bubble.svg" alt="More information" />
<span class="tooltiptext pageOptionTooltipWidth">
Send more than one request while executing a query. More than one request is necessary if the
query is not scoped to single partition key value.
</span>
</span>
</div>
<input
type="checkbox"
tabindex="0"
aria-label="Enable cross partition query"
data-bind="checked: crossPartitionQueryEnabled"
/>
</div>
</div>
<div class="settingsSection" data-bind="visible: shouldShowParallelismOption">
<div class="settingsSectionPart">
<div class="settingsSectionLabel">
Max degree of parallelism
<span class="infoTooltip" role="tooltip" tabindex="0">
<img class="infoImg" src="/info-bubble.svg" alt="More information" />
<span class="tooltiptext pageOptionTooltipWidth">
Gets or sets the number of concurrent operations run client side during parallel query execution.
A positive property value limits the number of concurrent operations to the set value. If it is
set to less than 0, the system automatically decides the number of concurrent operations to run.
</span>
</span>
</div>
<input
type="number"
required
min="-1"
step="1"
class="textfontclr collid"
role="textbox"
tabindex="0"
id="max-degree"
aria-label="Max degree of parallelism"
data-bind="value: maxDegreeOfParallelism"
autofocus
/>
</div>
</div>
<div class="settingsSection" data-bind="visible: shouldShowGraphAutoVizOption">
<div class="settingsSectionPart">
<div class="settingsSectionLabel">
Display Gremlin query results as:&nbsp;
<span class="infoTooltip" role="tooltip" tabindex="0">
<img class="infoImg" src="/info-bubble.svg" alt="More information" />
<span class="tooltiptext pageOptionTooltipWidth">
Select Graph to automatically visualize the query results as a Graph or JSON to display the
results as JSON.
</span>
</span>
</div>
<div class="tabs" role="radiogroup" aria-label="Graph Auto-visualization">
<!-- Fixed option button - Start -->
<div class="tab">
<input
type="radio"
id="graphAutoVizOn"
name="graphAutoVizOption"
value="false"
data-bind="checked: graphAutoVizDisabled"
/>
<label
for="graphAutoVizOn"
id="graph-display"
tabindex="0"
role="radio"
data-bind="
attr: { 'aria-checked': graphAutoVizDisabled() === 'false' ? 'true' : 'false' },
event: { keypress: onGraphDisplayResultsKeyDown
}"
>Graph</label
>
</div>
<!-- Fixed option button - End -->
<!-- Unlimited option button - Start -->
<div class="tab">
<input
type="radio"
id="graphAutoVizOff"
name="graphAutoVizOption"
value="true"
data-bind="checked: graphAutoVizDisabled"
/>
<label
for="graphAutoVizOff"
tabindex="0"
role="radio"
data-bind="
attr: { 'aria-checked': graphAutoVizDisabled() === 'true' ? 'true' : 'false' },
event: { keypress: onJsonDisplayResultsKeyDown
}"
>JSON</label
>
</div>
<!-- Unlimited option button - End -->
</div>
</div>
</div>
<div class="settingsSection">
<div class="settingsSectionPart">
<div class="settingsSectionLabel">Explorer Version</div>
<div data-bind="text: explorerVersion"></div>
</div>
</div>
</div>
</div>
<div class="paneFooter">
<div class="leftpanel-okbut"><input type="submit" value="Apply" class="btncreatecoll1" /></div>
</div>
<!-- Settings Confirmation inputs - End -->
</form>
</div>
<!-- Settings Confirmation form - Start -->
<!-- Loader - Start -->
<div class="dataExplorerLoaderContainer dataExplorerPaneLoaderContainer" data-bind="visible: isExecuting">
<img class="dataExplorerLoader" src="/LoadingIndicator_3Squares.gif" />
</div>
<!-- Loader - End -->
</div>
</div>

View File

@ -1,38 +0,0 @@
import * as Constants from "../../Common/Constants";
import * as ViewModels from "../../Contracts/ViewModels";
import Explorer from "../Explorer";
describe("Settings Pane", () => {
describe("shouldShowQueryPageOptions()", () => {
let explorer: Explorer;
beforeEach(() => {
explorer = new Explorer();
});
it("should be true for SQL API", () => {
explorer.defaultExperience(Constants.DefaultAccountExperience.DocumentDB.toLowerCase());
expect(explorer.settingsPane.shouldShowQueryPageOptions()).toBe(true);
});
it("should be false for Cassandra API", () => {
explorer.defaultExperience(Constants.DefaultAccountExperience.Cassandra.toLowerCase());
expect(explorer.settingsPane.shouldShowQueryPageOptions()).toBe(false);
});
it("should be false for Tables API", () => {
explorer.defaultExperience(Constants.DefaultAccountExperience.Table.toLowerCase());
expect(explorer.settingsPane.shouldShowQueryPageOptions()).toBe(false);
});
it("should be false for Graph API", () => {
explorer.defaultExperience(Constants.DefaultAccountExperience.Graph.toLowerCase());
expect(explorer.settingsPane.shouldShowQueryPageOptions()).toBe(false);
});
it("should be false for Mongo API", () => {
explorer.defaultExperience(Constants.DefaultAccountExperience.MongoDB.toLowerCase());
expect(explorer.settingsPane.shouldShowQueryPageOptions()).toBe(false);
});
});
});

View File

@ -1,185 +0,0 @@
import * as Constants from "../../Common/Constants";
import * as ko from "knockout";
import * as ViewModels from "../../Contracts/ViewModels";
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
import { ContextualPaneBase } from "./ContextualPaneBase";
import { LocalStorageUtility, StorageKey } from "../../Shared/StorageUtility";
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
import * as StringUtility from "../../Shared/StringUtility";
import { configContext } from "../../ConfigContext";
export class SettingsPane extends ContextualPaneBase {
public pageOption: ko.Observable<string>;
public customItemPerPage: ko.Observable<number>;
public crossPartitionQueryEnabled: ko.Observable<boolean>;
public maxDegreeOfParallelism: ko.Observable<number>;
public explorerVersion: string;
public shouldShowQueryPageOptions: ko.Computed<boolean>;
public shouldShowGraphAutoVizOption: ko.Computed<boolean>;
private graphAutoVizDisabled: ko.Observable<string>;
private shouldShowCrossPartitionOption: ko.Computed<boolean>;
private shouldShowParallelismOption: ko.Computed<boolean>;
constructor(options: ViewModels.PaneOptions) {
super(options);
this.title("Settings");
this.resetData();
this.pageOption = ko.observable<string>();
this.customItemPerPage = ko.observable<number>();
const crossPartitionQueryEnabledState: boolean = LocalStorageUtility.hasItem(
StorageKey.IsCrossPartitionQueryEnabled
)
? LocalStorageUtility.getEntryString(StorageKey.IsCrossPartitionQueryEnabled) === "true"
: true;
this.crossPartitionQueryEnabled = ko.observable<boolean>(crossPartitionQueryEnabledState);
const maxDegreeOfParallelismState: number = LocalStorageUtility.hasItem(StorageKey.MaxDegreeOfParellism)
? LocalStorageUtility.getEntryNumber(StorageKey.MaxDegreeOfParellism)
: Constants.Queries.DefaultMaxDegreeOfParallelism;
this.maxDegreeOfParallelism = ko.observable<number>(maxDegreeOfParallelismState);
const isGraphAutoVizDisabled: boolean = LocalStorageUtility.hasItem(StorageKey.IsGraphAutoVizDisabled)
? LocalStorageUtility.getEntryBoolean(StorageKey.IsGraphAutoVizDisabled)
: false;
this.graphAutoVizDisabled = ko.observable<string>(`${isGraphAutoVizDisabled}`);
this.explorerVersion = configContext.gitSha;
this.shouldShowQueryPageOptions = ko.computed<boolean>(() => this.container.isPreferredApiDocumentDB());
this.shouldShowCrossPartitionOption = ko.computed<boolean>(() => !this.container.isPreferredApiGraph());
this.shouldShowParallelismOption = ko.computed<boolean>(() => !this.container.isPreferredApiGraph());
this.shouldShowGraphAutoVizOption = ko.computed<boolean>(() => this.container.isPreferredApiGraph());
}
public open() {
this._loadSettings();
super.open();
const pageOptionsFocus = document.getElementById("custom-selection");
const displayQueryFocus = document.getElementById("graph-display");
const maxDegreeFocus = document.getElementById("max-degree");
if (this.container.isPreferredApiGraph()) {
displayQueryFocus && displayQueryFocus.focus();
} else if (this.container.isPreferredApiTable()) {
maxDegreeFocus && maxDegreeFocus.focus();
}
pageOptionsFocus && pageOptionsFocus.focus();
}
public submit() {
this.formErrors("");
this.isExecuting(true);
LocalStorageUtility.setEntryNumber(
StorageKey.ActualItemPerPage,
this.isCustomPageOptionSelected() ? this.customItemPerPage() : Constants.Queries.unlimitedItemsPerPage
);
LocalStorageUtility.setEntryNumber(StorageKey.CustomItemPerPage, this.customItemPerPage());
LocalStorageUtility.setEntryString(
StorageKey.IsCrossPartitionQueryEnabled,
this.crossPartitionQueryEnabled().toString()
);
LocalStorageUtility.setEntryNumber(StorageKey.MaxDegreeOfParellism, this.maxDegreeOfParallelism());
if (this.shouldShowGraphAutoVizOption()) {
LocalStorageUtility.setEntryBoolean(
StorageKey.IsGraphAutoVizDisabled,
StringUtility.toBoolean(this.graphAutoVizDisabled())
);
}
this.isExecuting(false);
NotificationConsoleUtils.logConsoleMessage(
ConsoleDataType.Info,
`Updated items per page setting to ${LocalStorageUtility.getEntryNumber(StorageKey.ActualItemPerPage)}`
);
NotificationConsoleUtils.logConsoleMessage(
ConsoleDataType.Info,
`${this.crossPartitionQueryEnabled() ? "Enabled" : "Disabled"} cross-partition query feed option`
);
NotificationConsoleUtils.logConsoleMessage(
ConsoleDataType.Info,
`Updated the max degree of parallelism query feed option to ${LocalStorageUtility.getEntryNumber(
StorageKey.MaxDegreeOfParellism
)}`
);
if (this.shouldShowGraphAutoVizOption()) {
NotificationConsoleUtils.logConsoleMessage(
ConsoleDataType.Info,
`Graph result will be displayed as ${
LocalStorageUtility.getEntryBoolean(StorageKey.IsGraphAutoVizDisabled) ? "JSON" : "Graph"
}`
);
}
NotificationConsoleUtils.logConsoleMessage(
ConsoleDataType.Info,
`Updated query setting to ${LocalStorageUtility.getEntryString(StorageKey.SetPartitionKeyUndefined)}`
);
this.close();
}
public isCustomPageOptionSelected = (): boolean => {
return this.pageOption() === Constants.Queries.CustomPageOption;
};
public isUnlimitedPageOptionSelected = (): boolean => {
return this.pageOption() === Constants.Queries.UnlimitedPageOption;
};
public onUnlimitedPageOptionKeyDown(source: any, event: KeyboardEvent): boolean {
if (event.keyCode === Constants.KeyCodes.Enter || event.keyCode === Constants.KeyCodes.Space) {
this.pageOption(Constants.Queries.UnlimitedPageOption);
event.stopPropagation();
return false;
}
return true;
}
public onCustomPageOptionsKeyDown(source: any, event: KeyboardEvent): boolean {
if (event.keyCode === Constants.KeyCodes.Enter || event.keyCode === Constants.KeyCodes.Space) {
this.pageOption(Constants.Queries.CustomPageOption);
event.stopPropagation();
return false;
}
return true;
}
public onJsonDisplayResultsKeyDown(source: any, event: KeyboardEvent): boolean {
if (event.keyCode === Constants.KeyCodes.Enter || event.keyCode === Constants.KeyCodes.Space) {
this.graphAutoVizDisabled("true");
event.stopPropagation();
return false;
}
return true;
}
public onGraphDisplayResultsKeyDown(source: any, event: KeyboardEvent): boolean {
if (event.keyCode === Constants.KeyCodes.Enter || event.keyCode === Constants.KeyCodes.Space) {
this.graphAutoVizDisabled("false");
event.stopPropagation();
return false;
}
return true;
}
private _loadSettings() {
this.isExecuting(true);
try {
this.pageOption(
LocalStorageUtility.getEntryNumber(StorageKey.ActualItemPerPage) == Constants.Queries.unlimitedItemsPerPage
? Constants.Queries.UnlimitedPageOption
: Constants.Queries.CustomPageOption
);
this.customItemPerPage(LocalStorageUtility.getEntryNumber(StorageKey.CustomItemPerPage));
} catch (exception) {
this.formErrors("Unable to load your settings");
this.formErrorsDetails(exception);
} finally {
this.isExecuting(false);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
import { shallow } from "enzyme";
import React from "react";
import { SettingsPane } from ".";
import { DatabaseAccount } from "../../../Contracts/DataModels";
import { updateUserContext } from "../../../UserContext";
import Explorer from "../../Explorer";
const props = {
explorer: new Explorer(),
closePanel: (): void => undefined,
};
describe("Settings Pane", () => {
it("should render Default properly", () => {
const wrapper = shallow(<SettingsPane {...props} />);
expect(wrapper).toMatchSnapshot();
});
it("should render Gremlin properly", () => {
updateUserContext({
databaseAccount: {
properties: {
capabilities: [{ name: "EnableGremlin" }],
},
} as DatabaseAccount,
});
const wrapper = shallow(<SettingsPane {...props} />);
expect(wrapper).toMatchSnapshot();
});
});

View File

@ -0,0 +1,253 @@
import { Checkbox, ChoiceGroup, IChoiceGroupOption, SpinButton } from "office-ui-fabric-react";
import React, { FunctionComponent, MouseEvent, useState } from "react";
import * as Constants from "../../../Common/Constants";
import { Tooltip } from "../../../Common/Tooltip";
import { configContext } from "../../../ConfigContext";
import { LocalStorageUtility, StorageKey } from "../../../Shared/StorageUtility";
import * as StringUtility from "../../../Shared/StringUtility";
import { userContext } from "../../../UserContext";
import { logConsoleInfo } from "../../../Utils/NotificationConsoleUtils";
import Explorer from "../../Explorer";
import { GenericRightPaneComponent, GenericRightPaneProps } from "../GenericRightPaneComponent";
export interface SettingsPaneProps {
explorer: Explorer;
closePanel: () => void;
}
export const SettingsPane: FunctionComponent<SettingsPaneProps> = ({
explorer: container,
closePanel,
}: SettingsPaneProps) => {
const [formErrors, setFormErrors] = useState<string>("");
const [isExecuting, setIsExecuting] = useState<boolean>(false);
const [pageOption, setPageOption] = useState<string>(
LocalStorageUtility.getEntryNumber(StorageKey.ActualItemPerPage) === Constants.Queries.unlimitedItemsPerPage
? Constants.Queries.UnlimitedPageOption
: Constants.Queries.CustomPageOption
);
const [customItemPerPage, setCustomItemPerPage] = useState<number>(
LocalStorageUtility.getEntryNumber(StorageKey.CustomItemPerPage) || 0
);
const [crossPartitionQueryEnabled, setCrossPartitionQueryEnabled] = useState<boolean>(
LocalStorageUtility.hasItem(StorageKey.IsCrossPartitionQueryEnabled)
? LocalStorageUtility.getEntryString(StorageKey.IsCrossPartitionQueryEnabled) === "true"
: true
);
const [graphAutoVizDisabled, setGraphAutoVizDisabled] = useState<string>(
LocalStorageUtility.hasItem(StorageKey.IsGraphAutoVizDisabled)
? LocalStorageUtility.getEntryString(StorageKey.IsGraphAutoVizDisabled)
: "false"
);
const [maxDegreeOfParallelism, setMaxDegreeOfParallelism] = useState<number>(
LocalStorageUtility.hasItem(StorageKey.MaxDegreeOfParellism)
? LocalStorageUtility.getEntryNumber(StorageKey.MaxDegreeOfParellism)
: Constants.Queries.DefaultMaxDegreeOfParallelism
);
const explorerVersion = configContext.gitSha;
const shouldShowQueryPageOptions = userContext.apiType === "SQL";
const shouldShowGraphAutoVizOption = userContext.apiType === "Gremlin";
const shouldShowCrossPartitionOption = userContext.apiType !== "Gremlin";
const shouldShowParallelismOption = userContext.apiType !== "Gremlin";
const handlerOnSubmit = (e: MouseEvent<HTMLButtonElement>) => {
setFormErrors("");
setIsExecuting(true);
LocalStorageUtility.setEntryNumber(
StorageKey.ActualItemPerPage,
isCustomPageOptionSelected() ? customItemPerPage : Constants.Queries.unlimitedItemsPerPage
);
LocalStorageUtility.setEntryNumber(StorageKey.CustomItemPerPage, customItemPerPage);
LocalStorageUtility.setEntryString(StorageKey.IsCrossPartitionQueryEnabled, crossPartitionQueryEnabled.toString());
LocalStorageUtility.setEntryNumber(StorageKey.MaxDegreeOfParellism, maxDegreeOfParallelism);
if (shouldShowGraphAutoVizOption) {
LocalStorageUtility.setEntryBoolean(
StorageKey.IsGraphAutoVizDisabled,
StringUtility.toBoolean(graphAutoVizDisabled)
);
}
setIsExecuting(false);
logConsoleInfo(
`Updated items per page setting to ${LocalStorageUtility.getEntryNumber(StorageKey.ActualItemPerPage)}`
);
logConsoleInfo(`${crossPartitionQueryEnabled ? "Enabled" : "Disabled"} cross-partition query feed option`);
logConsoleInfo(
`Updated the max degree of parallelism query feed option to ${LocalStorageUtility.getEntryNumber(
StorageKey.MaxDegreeOfParellism
)}`
);
if (shouldShowGraphAutoVizOption) {
logConsoleInfo(
`Graph result will be displayed as ${
LocalStorageUtility.getEntryBoolean(StorageKey.IsGraphAutoVizDisabled) ? "JSON" : "Graph"
}`
);
}
logConsoleInfo(
`Updated query setting to ${LocalStorageUtility.getEntryString(StorageKey.SetPartitionKeyUndefined)}`
);
closePanel();
e.preventDefault();
};
const isCustomPageOptionSelected = () => {
return pageOption === Constants.Queries.CustomPageOption;
};
const handleOnGremlinChange = (ev: React.FormEvent<HTMLInputElement>, option: IChoiceGroupOption): void => {
setGraphAutoVizDisabled(option.key);
};
const genericPaneProps: GenericRightPaneProps = {
container,
formError: formErrors,
formErrorDetail: "",
id: "settingspane",
isExecuting,
title: "Setting",
submitButtonText: "Apply",
onClose: () => closePanel(),
onSubmit: () => handlerOnSubmit(undefined),
};
const pageOptionList: IChoiceGroupOption[] = [
{ key: Constants.Queries.CustomPageOption, text: "Custom" },
{ key: Constants.Queries.UnlimitedPageOption, text: "Unlimited" },
];
const graphAutoOptionList: IChoiceGroupOption[] = [
{ key: "false", text: "Graph" },
{ key: "true", text: "JSON" },
];
const handleOnPageOptionChange = (ev: React.FormEvent<HTMLInputElement>, option: IChoiceGroupOption): void => {
setPageOption(option.key);
};
return (
<GenericRightPaneComponent {...genericPaneProps}>
<div className="paneMainContent">
{shouldShowQueryPageOptions && (
<div className="settingsSection">
<div className="settingsSectionPart pageOptionsPart">
<div className="settingsSectionLabel">
Page options
<Tooltip>
Choose Custom to specify a fixed amount of query results to show, or choose Unlimited to show as many
query results per page.
</Tooltip>
</div>
<ChoiceGroup selectedKey={pageOption} options={pageOptionList} onChange={handleOnPageOptionChange} />
</div>
<div className="tabs settingsSectionPart">
{isCustomPageOptionSelected() && (
<div className="tabcontent">
<div className="settingsSectionLabel">
Query results per page
<Tooltip>Enter the number of query results that should be shown per page.</Tooltip>
</div>
<SpinButton
ariaLabel="Custom query items per page"
value={"" + customItemPerPage}
onIncrement={(newValue) => {
setCustomItemPerPage(parseInt(newValue) + 1 || customItemPerPage);
}}
onDecrement={(newValue) => setCustomItemPerPage(parseInt(newValue) - 1 || customItemPerPage)}
onValidate={(newValue) => setCustomItemPerPage(parseInt(newValue) || customItemPerPage)}
min={1}
step={1}
className="textfontclr"
incrementButtonAriaLabel="Increase value by 1"
decrementButtonAriaLabel="Decrease value by 1"
/>
</div>
)}
</div>
</div>
)}
{shouldShowCrossPartitionOption && (
<div className="settingsSection">
<div className="settingsSectionPart">
<div className="settingsSectionLabel">
Enable cross-partition query
<Tooltip>
Send more than one request while executing a query. More than one request is necessary if the query is
not scoped to single partition key value.
</Tooltip>
</div>
<Checkbox
styles={{
label: { padding: 0 },
}}
className="padding"
tabIndex={0}
ariaLabel="Enable cross partition query"
checked={crossPartitionQueryEnabled}
onChange={() => setCrossPartitionQueryEnabled(!crossPartitionQueryEnabled)}
/>
</div>
</div>
)}
{shouldShowParallelismOption && (
<div className="settingsSection">
<div className="settingsSectionPart">
<div className="settingsSectionLabel">
Max degree of parallelism
<Tooltip>
Gets or sets the number of concurrent operations run client side during parallel query execution. A
positive property value limits the number of concurrent operations to the set value. If it is set to
less than 0, the system automatically decides the number of concurrent operations to run.
</Tooltip>
</div>
<SpinButton
min={-1}
step={1}
className="textfontclr"
role="textbox"
tabIndex={0}
id="max-degree"
value={"" + maxDegreeOfParallelism}
onIncrement={(newValue) => setMaxDegreeOfParallelism(parseInt(newValue) + 1 || maxDegreeOfParallelism)}
onDecrement={(newValue) => setMaxDegreeOfParallelism(parseInt(newValue) - 1 || maxDegreeOfParallelism)}
onValidate={(newValue) => setMaxDegreeOfParallelism(parseInt(newValue) || maxDegreeOfParallelism)}
ariaLabel="Max degree of parallelism"
/>
</div>
</div>
)}
{shouldShowGraphAutoVizOption && (
<div className="settingsSection">
<div className="settingsSectionPart">
<div className="settingsSectionLabel">
Display Gremlin query results as:&nbsp;
<Tooltip>
Select Graph to automatically visualize the query results as a Graph or JSON to display the results as
JSON.
</Tooltip>
</div>
<ChoiceGroup
selectedKey={graphAutoVizDisabled}
options={graphAutoOptionList}
onChange={handleOnGremlinChange}
aria-label="Graph Auto-visualization"
/>
</div>
</div>
)}
<div className="settingsSection">
<div className="settingsSectionPart">
<div className="settingsSectionLabel">Explorer Version</div>
<div>{explorerVersion}</div>
</div>
</div>
</div>
</GenericRightPaneComponent>
);
};

View File

@ -30,7 +30,7 @@ exports[`Delete Collection Confirmation Pane submit() should call delete collect
verticalAlign="start"
>
<div
className="ms-Stack panelInfoErrorContainer css-140"
className="ms-Stack panelInfoErrorContainer css-204"
>
<StyledIconBase
className="panelWarningIcon"
@ -317,7 +317,7 @@ exports[`Delete Collection Confirmation Pane submit() should call delete collect
>
<i
aria-hidden={true}
className="panelWarningIcon root-142"
className="panelWarningIcon root-206"
data-icon-name="WarningSolid"
>
@ -333,7 +333,7 @@ exports[`Delete Collection Confirmation Pane submit() should call delete collect
variant="small"
>
<span
className="panelWarningErrorMessage css-143"
className="panelWarningErrorMessage css-207"
>
Warning! The action you are about to take cannot be undone. Continuing will permanently delete this resource and all of its children resources.
@ -358,7 +358,7 @@ exports[`Delete Collection Confirmation Pane submit() should call delete collect
variant="small"
>
<span
className="css-143"
className="css-207"
>
Confirm by typing the collection id
</span>
@ -659,18 +659,18 @@ exports[`Delete Collection Confirmation Pane submit() should call delete collect
validateOnLoad={true}
>
<div
className="ms-TextField root-145"
className="ms-TextField root-209"
>
<div
className="ms-TextField-wrapper"
>
<div
className="ms-TextField-fieldGroup fieldGroup-146"
className="ms-TextField-fieldGroup fieldGroup-210"
>
<input
aria-invalid={false}
autoFocus={true}
className="ms-TextField-field field-147"
className="ms-TextField-field field-211"
id="confirmCollectionId"
onBlur={[Function]}
onChange={[Function]}
@ -693,7 +693,7 @@ exports[`Delete Collection Confirmation Pane submit() should call delete collect
variant="small"
>
<span
className="css-156"
className="css-220"
>
Help us improve Azure Cosmos DB!
</span>
@ -703,7 +703,7 @@ exports[`Delete Collection Confirmation Pane submit() should call delete collect
variant="small"
>
<span
className="css-156"
className="css-220"
>
What is the reason why you are deleting this container?
</span>
@ -1006,17 +1006,17 @@ exports[`Delete Collection Confirmation Pane submit() should call delete collect
validateOnLoad={true}
>
<div
className="ms-TextField ms-TextField--multiline root-145"
className="ms-TextField ms-TextField--multiline root-209"
>
<div
className="ms-TextField-wrapper"
>
<div
className="ms-TextField-fieldGroup fieldGroup-157"
className="ms-TextField-fieldGroup fieldGroup-221"
>
<textarea
aria-invalid={false}
className="ms-TextField-field field-158"
className="ms-TextField-field field-222"
id="deleteCollectionFeedbackInput"
onBlur={[Function]}
onChange={[Function]}
@ -2708,7 +2708,7 @@ exports[`Delete Collection Confirmation Pane submit() should call delete collect
variantClassName="ms-Button--primary"
>
<button
className="ms-Button ms-Button--primary root-160"
className="ms-Button ms-Button--primary root-224"
data-is-focusable={true}
id="sidePanelOkButton"
onClick={[Function]}
@ -2720,14 +2720,14 @@ exports[`Delete Collection Confirmation Pane submit() should call delete collect
type="submit"
>
<span
className="ms-Button-flexContainer flexContainer-161"
className="ms-Button-flexContainer flexContainer-225"
data-automationid="splitbuttonprimary"
>
<span
className="ms-Button-textContainer textContainer-162"
className="ms-Button-textContainer textContainer-226"
>
<span
className="ms-Button-label label-164"
className="ms-Button-label label-228"
id="id__6"
key="id__6"
>

View File

@ -241,7 +241,6 @@ const App: React.FunctionComponent = () => {
<div data-bind='component: { name: "table-column-options-pane", params: { data: tableColumnOptionsPane} }' />
<div data-bind='component: { name: "table-query-select-pane", params: { data: querySelectPane} }' />
<div data-bind='component: { name: "cassandra-add-collection-pane", params: { data: cassandraAddCollectionPane} }' />
<div data-bind='component: { name: "settings-pane", params: { data: settingsPane} }' />
<div data-bind='component: { name: "upload-items-pane", params: { data: uploadItemsPane} }' />
<div data-bind='component: { name: "load-query-pane", params: { data: loadQueryPane} }' />
<div data-bind='component: { name: "save-query-pane", params: { data: saveQueryPane} }' />

60
src/userContext.test.ts Normal file
View File

@ -0,0 +1,60 @@
import { DatabaseAccount } from "./Contracts/DataModels";
import { updateUserContext, userContext } from "./UserContext";
describe("shouldShowQueryPageOptions()", () => {
it("should be SQL for Default API", () => {
updateUserContext({});
expect(userContext.apiType).toBe("SQL");
});
it("should be Cassandra for EnableCassandra API", () => {
updateUserContext({
databaseAccount: {
properties: {
capabilities: [{ name: "EnableCassandra" }],
},
} as DatabaseAccount,
});
expect(userContext.apiType).toBe("Cassandra");
});
it("should be Gremlin for EnableGremlin API", () => {
updateUserContext({
databaseAccount: {
properties: {
capabilities: [{ name: "EnableGremlin" }],
},
} as DatabaseAccount,
});
expect(userContext.apiType).toBe("Gremlin");
});
it("should be Tables for EnableTable API", () => {
updateUserContext({
databaseAccount: {
properties: {
capabilities: [{ name: "EnableTable" }],
},
} as DatabaseAccount,
});
expect(userContext.apiType).toBe("Tables");
});
it("should be Mongo for MongoDB API", () => {
updateUserContext({
databaseAccount: {
kind: "MongoDB",
} as DatabaseAccount,
});
expect(userContext.apiType).toBe("Mongo");
});
it("should be Mongo for Parse API", () => {
updateUserContext({
databaseAccount: {
kind: "Parse",
} as DatabaseAccount,
});
expect(userContext.apiType).toBe("Mongo");
});
});