From 94a03e5b03f9e3c6de22904bb6dd7c3a7e96d9ae Mon Sep 17 00:00:00 2001 From: victor-meng <56978073+victor-meng@users.noreply.github.com> Date: Fri, 19 Nov 2021 09:55:10 -0800 Subject: [PATCH 1/9] Add Timestamp type to cassandra column types and wrap Timestamp value inside single quotes when creating queries (#1163) --- src/Explorer/Panes/Tables/Validators/EntityTableHelper.tsx | 2 ++ src/Explorer/Tables/Constants.ts | 1 + src/Explorer/Tables/TableDataClient.ts | 3 ++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Explorer/Panes/Tables/Validators/EntityTableHelper.tsx b/src/Explorer/Panes/Tables/Validators/EntityTableHelper.tsx index b38f569e0..71cfa9c8b 100644 --- a/src/Explorer/Panes/Tables/Validators/EntityTableHelper.tsx +++ b/src/Explorer/Panes/Tables/Validators/EntityTableHelper.tsx @@ -33,6 +33,7 @@ const { Inet, Smallint, Tinyint, + Timestamp, } = TableConstants.CassandraType; export const cassandraOptions = [ { key: Text, text: Text }, @@ -50,6 +51,7 @@ export const cassandraOptions = [ { key: Inet, text: Inet }, { key: Smallint, text: Smallint }, { key: Tinyint, text: Tinyint }, + { key: Timestamp, text: Timestamp }, ]; export const imageProps: IImageProps = { diff --git a/src/Explorer/Tables/Constants.ts b/src/Explorer/Tables/Constants.ts index 9bb313b7a..c9917dcd8 100644 --- a/src/Explorer/Tables/Constants.ts +++ b/src/Explorer/Tables/Constants.ts @@ -19,6 +19,7 @@ export const CassandraType = { Float: "Float", Int: "Int", Text: "Text", + Timestamp: "Timestamp", Uuid: "Uuid", Varchar: "Varchar", Varint: "Varint", diff --git a/src/Explorer/Tables/TableDataClient.ts b/src/Explorer/Tables/TableDataClient.ts index afe31b711..62463abfd 100644 --- a/src/Explorer/Tables/TableDataClient.ts +++ b/src/Explorer/Tables/TableDataClient.ts @@ -535,7 +535,8 @@ export class CassandraAPIDataClient extends TableDataClient { dataType === TableConstants.CassandraType.Text || dataType === TableConstants.CassandraType.Inet || dataType === TableConstants.CassandraType.Ascii || - dataType === TableConstants.CassandraType.Varchar + dataType === TableConstants.CassandraType.Varchar || + dataType === TableConstants.CassandraType.Timestamp ); } From 42bdcaf8d1c1266154c15401e3225d36f6a87dd0 Mon Sep 17 00:00:00 2001 From: vaidankarswapnil <81285216+vaidankarswapnil@users.noreply.github.com> Date: Thu, 25 Nov 2021 09:30:06 +0530 Subject: [PATCH 2/9] =?UTF-8?q?Fix=20radio=20buttons=20present=20under=20'?= =?UTF-8?q?Settings'=20blade=20like=20=E2=80=98Custom=20and=20Unlimited?= =?UTF-8?q?=E2=80=99=20along=20with=20its=20label=20=E2=80=98Page=20option?= =?UTF-8?q?s=E2=80=99=20are=20not=20enclosed=20in=20fieldset/legend=20tag?= =?UTF-8?q?=20(#1100)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix a11y setting pane radiobuttons issue * Update test snapshot issue --- less/documentDB.less | 40 +++++++++---------- .../Panes/SettingsPane/SettingsPane.tsx | 36 ++++++++++++++--- .../__snapshots__/SettingsPane.test.tsx.snap | 34 +++++++++++++--- 3 files changed, 79 insertions(+), 31 deletions(-) diff --git a/less/documentDB.less b/less/documentDB.less index 79e9435c3..72bbce880 100644 --- a/less/documentDB.less +++ b/less/documentDB.less @@ -2869,31 +2869,31 @@ a:link { } } -settings-pane { - .settingsSection { - border-bottom: 1px solid @BaseMedium; - margin-right: 24px; - padding: @MediumSpace 0px; +.settingsSection { + border-bottom: 1px solid @BaseMedium; + margin-right: 24px; + padding: @MediumSpace 0px; - &:first-child { - padding-top: 0px; - } + &:first-child { + padding-top: 0px; + padding-bottom: 10px; + } - &:last-child { - border-bottom: none; - } + &:last-child { + border-bottom: none; + } - .settingsSectionPart { - padding-left: 8px; - } + .settingsSectionPart { + padding-left: 8px; + } - .settingsSectionLabel { - margin-bottom: @DefaultSpace; - } + .settingsSectionLabel { + margin-bottom: @DefaultSpace; + margin-right: 5px; + } - .pageOptionsPart { - padding-bottom: @MediumSpace; - } + .pageOptionsPart { + padding-bottom: @MediumSpace; } } diff --git a/src/Explorer/Panes/SettingsPane/SettingsPane.tsx b/src/Explorer/Panes/SettingsPane/SettingsPane.tsx index 92d432f34..2a06ce497 100644 --- a/src/Explorer/Panes/SettingsPane/SettingsPane.tsx +++ b/src/Explorer/Panes/SettingsPane/SettingsPane.tsx @@ -1,4 +1,4 @@ -import { Checkbox, ChoiceGroup, IChoiceGroupOption, SpinButton } from "@fluentui/react"; +import { Checkbox, ChoiceGroup, IChoiceGroupOption, SpinButton, Stack, Text } from "@fluentui/react"; import * as Constants from "Common/Constants"; import { InfoTooltip } from "Common/Tooltip/InfoTooltip"; import { configContext } from "ConfigContext"; @@ -113,20 +113,44 @@ export const SettingsPane: FunctionComponent = () => { const handleOnPageOptionChange = (ev: React.FormEvent, option: IChoiceGroupOption): void => { setPageOption(option.key); }; + + const choiceButtonStyles = { + flexContainer: [ + { + selectors: { + ".ms-ChoiceField-wrapper label": { + fontSize: 12, + paddingTop: 0, + }, + ".ms-ChoiceField": { + marginTop: 0, + }, + }, + }, + ], + }; return (
{shouldShowQueryPageOptions && (
-
-
- Page options +
+ + + Page options + Choose Custom to specify a fixed amount of query results to show, or choose Unlimited to show as many query results per page. -
- + +
{isCustomPageOptionSelected() && ( diff --git a/src/Explorer/Panes/SettingsPane/__snapshots__/SettingsPane.test.tsx.snap b/src/Explorer/Panes/SettingsPane/__snapshots__/SettingsPane.test.tsx.snap index ccc2ad3a7..4b1d6f079 100644 --- a/src/Explorer/Panes/SettingsPane/__snapshots__/SettingsPane.test.tsx.snap +++ b/src/Explorer/Panes/SettingsPane/__snapshots__/SettingsPane.test.tsx.snap @@ -14,17 +14,24 @@ exports[`Settings Pane should render Default properly 1`] = ` className="settingsSection" >
-
- Page options + + Page options + Choose Custom to specify a fixed amount of query results to show, or choose Unlimited to show as many query results per page. -
+
Date: Mon, 29 Nov 2021 11:22:57 -0500 Subject: [PATCH 3/9] Add phoenix telemetry (#1164) * Add phoenix telemetry * Revert changes * Update trace logs --- src/Explorer/Explorer.tsx | 103 ++++++++++++--------- src/Shared/Telemetry/TelemetryConstants.ts | 3 +- 2 files changed, 59 insertions(+), 47 deletions(-) diff --git a/src/Explorer/Explorer.tsx b/src/Explorer/Explorer.tsx index 9ea267ef9..a81e2fe19 100644 --- a/src/Explorer/Explorer.tsx +++ b/src/Explorer/Explorer.tsx @@ -7,7 +7,7 @@ import shallow from "zustand/shallow"; import { AuthType } from "../AuthType"; import { BindingHandlersRegisterer } from "../Bindings/BindingHandlersRegisterer"; import * as Constants from "../Common/Constants"; -import { ConnectionStatusType, HttpStatusCodes, Notebook } from "../Common/Constants"; +import { Areas, ConnectionStatusType, HttpStatusCodes, Notebook } from "../Common/Constants"; import { readCollection } from "../Common/dataAccess/readCollection"; import { readDatabases } from "../Common/dataAccess/readDatabases"; import { getErrorMessage, getErrorStack, handleError } from "../Common/ErrorHandlingUtils"; @@ -392,18 +392,36 @@ export default class Explorer { }; useNotebook.getState().setConnectionInfo(connectionStatus); try { + TelemetryProcessor.traceStart(Action.PhoenixConnection, { + dataExplorerArea: Areas.Notebook, + }); useNotebook.getState().setIsAllocating(true); const connectionInfo = await this.phoenixClient.allocateContainer(provisionData); + if (connectionInfo.status !== HttpStatusCodes.OK) { + throw new Error(`Received status code: ${connectionInfo?.status}`); + } + if (!connectionInfo?.data?.notebookServerUrl) { + throw new Error(`NotebookServerUrl is invalid!`); + } await this.setNotebookInfo(connectionInfo, connectionStatus); + TelemetryProcessor.traceSuccess(Action.PhoenixConnection, { + dataExplorerArea: Areas.Notebook, + }); } catch (error) { + TelemetryProcessor.traceFailure(Action.PhoenixConnection, { + dataExplorerArea: Areas.Notebook, + error: getErrorMessage(error), + errorStack: getErrorStack(error), + }); connectionStatus.status = ConnectionStatusType.Failed; useNotebook.getState().resetContainerConnection(connectionStatus); throw error; + } finally { + useNotebook.getState().setIsAllocating(false); + this.refreshCommandBarButtons(); + this.refreshNotebookList(); + this._isInitializingNotebooks = false; } - this.refreshCommandBarButtons(); - this.refreshNotebookList(); - - this._isInitializingNotebooks = false; } } @@ -411,28 +429,22 @@ export default class Explorer { connectionInfo: IResponse, connectionStatus: DataModels.ContainerConnectionInfo ) { - if (connectionInfo.status === HttpStatusCodes.OK && connectionInfo.data && connectionInfo.data.notebookServerUrl) { - const containerData = { - forwardingId: connectionInfo.data.forwardingId, - dbAccountName: userContext.databaseAccount.name, - }; - await this.phoenixClient.initiateContainerHeartBeat(containerData); + const containerData = { + forwardingId: connectionInfo.data.forwardingId, + dbAccountName: userContext.databaseAccount.name, + }; + await this.phoenixClient.initiateContainerHeartBeat(containerData); - connectionStatus.status = ConnectionStatusType.Connected; - useNotebook.getState().setConnectionInfo(connectionStatus); - useNotebook.getState().setNotebookServerInfo({ - notebookServerEndpoint: userContext.features.notebookServerUrl || connectionInfo.data.notebookServerUrl, - authToken: userContext.features.notebookServerToken || connectionInfo.data.notebookAuthToken, - forwardingId: connectionInfo.data.forwardingId, - }); - this.notebookManager?.notebookClient - .getMemoryUsage() - .then((memoryUsageInfo) => useNotebook.getState().setMemoryUsageInfo(memoryUsageInfo)); - } else { - connectionStatus.status = ConnectionStatusType.Failed; - useNotebook.getState().resetContainerConnection(connectionStatus); - } - useNotebook.getState().setIsAllocating(false); + connectionStatus.status = ConnectionStatusType.Connected; + useNotebook.getState().setConnectionInfo(connectionStatus); + useNotebook.getState().setNotebookServerInfo({ + notebookServerEndpoint: userContext.features.notebookServerUrl || connectionInfo.data.notebookServerUrl, + authToken: userContext.features.notebookServerToken || connectionInfo.data.notebookAuthToken, + forwardingId: connectionInfo.data.forwardingId, + }); + this.notebookManager?.notebookClient + .getMemoryUsage() + .then((memoryUsageInfo) => useNotebook.getState().setMemoryUsageInfo(memoryUsageInfo)); } public resetNotebookWorkspace(): void { @@ -517,7 +529,9 @@ export default class Explorer { logConsoleError(error); return; } - + TelemetryProcessor.traceStart(Action.PhoenixResetWorkspace, { + dataExplorerArea: Areas.Notebook, + }); if (NotebookUtil.isPhoenixEnabled()) { useTabs.getState().closeAllNotebookTabs(true); connectionStatus = { @@ -526,27 +540,24 @@ export default class Explorer { useNotebook.getState().setConnectionInfo(connectionStatus); } const connectionInfo = await this.notebookManager?.notebookClient.resetWorkspace(); - if (connectionInfo && connectionInfo.status && connectionInfo.status === HttpStatusCodes.OK) { - if (NotebookUtil.isPhoenixEnabled() && connectionInfo.data && connectionInfo.data.notebookServerUrl) { - await this.setNotebookInfo(connectionInfo, connectionStatus); - useNotebook.getState().setIsRefreshed(!useNotebook.getState().isRefreshed); - } - logConsoleInfo("Successfully reset notebook workspace"); - TelemetryProcessor.traceSuccess(Action.ResetNotebookWorkspace); - } else { - logConsoleError(`Failed to reset notebook workspace`); - TelemetryProcessor.traceFailure(Action.ResetNotebookWorkspace); - if (NotebookUtil.isPhoenixEnabled()) { - connectionStatus = { - status: ConnectionStatusType.Reconnect, - }; - useNotebook.getState().resetContainerConnection(connectionStatus); - useNotebook.getState().setIsRefreshed(!useNotebook.getState().isRefreshed); - } + if (connectionInfo?.status !== HttpStatusCodes.OK) { + throw new Error(`Reset Workspace: Received status code- ${connectionInfo?.status}`); } + if (!connectionInfo?.data?.notebookServerUrl) { + throw new Error(`Reset Workspace: NotebookServerUrl is invalid!`); + } + if (NotebookUtil.isPhoenixEnabled()) { + await this.setNotebookInfo(connectionInfo, connectionStatus); + useNotebook.getState().setIsRefreshed(!useNotebook.getState().isRefreshed); + } + logConsoleInfo("Successfully reset notebook workspace"); + TelemetryProcessor.traceSuccess(Action.PhoenixResetWorkspace, { + dataExplorerArea: Areas.Notebook, + }); } catch (error) { logConsoleError(`Failed to reset notebook workspace: ${error}`); - TelemetryProcessor.traceFailure(Action.ResetNotebookWorkspace, { + TelemetryProcessor.traceFailure(Action.PhoenixResetWorkspace, { + dataExplorerArea: Areas.Notebook, error: getErrorMessage(error), errorStack: getErrorStack(error), }); @@ -554,7 +565,7 @@ export default class Explorer { connectionStatus = { status: ConnectionStatusType.Failed, }; - useNotebook.getState().setConnectionInfo(connectionStatus); + useNotebook.getState().resetContainerConnection(connectionStatus); useNotebook.getState().setIsRefreshed(!useNotebook.getState().isRefreshed); } throw error; diff --git a/src/Shared/Telemetry/TelemetryConstants.ts b/src/Shared/Telemetry/TelemetryConstants.ts index 134340ad4..e9541b9f7 100644 --- a/src/Shared/Telemetry/TelemetryConstants.ts +++ b/src/Shared/Telemetry/TelemetryConstants.ts @@ -50,7 +50,6 @@ export enum Action { SubscriptionSwitch, TenantSwitch, DefaultTenantSwitch, - ResetNotebookWorkspace, CreateNotebookWorkspace, NotebookErrorNotification, CreateSparkCluster, @@ -82,6 +81,8 @@ export enum Action { NotebooksInsertTextCellBelowFromMenu, NotebooksMoveCellUpFromMenu, NotebooksMoveCellDownFromMenu, + PhoenixConnection, + PhoenixResetWorkspace, DeleteCellFromMenu, OpenTerminal, CreateMongoCollectionWithWildcardIndex, From 6b4d6f986e261babf8a861c54f69d12a94455258 Mon Sep 17 00:00:00 2001 From: Srinath Narayanan Date: Wed, 1 Dec 2021 03:38:38 +0530 Subject: [PATCH 4/9] added github test env client id (#1168) --- src/Common/Constants.ts | 8 ++++++++ src/ConfigContext.ts | 16 ++++++++++------ src/GitHub/GitHubOAuthService.ts | 4 ++-- src/Juno/JunoClient.ts | 3 ++- src/Utils/GitHubUtils.ts | 17 +++++++++++++++++ 5 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/Common/Constants.ts b/src/Common/Constants.ts index c627c65fd..36dfa83a1 100644 --- a/src/Common/Constants.ts +++ b/src/Common/Constants.ts @@ -412,3 +412,11 @@ export class TerminalQueryParams { public static readonly SubscriptionId = "subscriptionId"; public static readonly TerminalEndpoint = "terminalEndpoint"; } + +export class JunoEndpoints { + public static readonly Test = "https://juno-test.documents-dev.windows-int.net"; + public static readonly Test2 = "https://juno-test2.documents-dev.windows-int.net"; + public static readonly Test3 = "https://juno-test3.documents-dev.windows-int.net"; + public static readonly Prod = "https://tools.cosmos.azure.com"; + public static readonly Stage = "https://tools-staging.cosmos.azure.com"; +} diff --git a/src/ConfigContext.ts b/src/ConfigContext.ts index 224d28f8d..f89ed5d61 100644 --- a/src/ConfigContext.ts +++ b/src/ConfigContext.ts @@ -1,3 +1,5 @@ +import { JunoEndpoints } from "Common/Constants"; + export enum Platform { Portal = "Portal", Hosted = "Hosted", @@ -23,6 +25,7 @@ export interface ConfigContext { PROXY_PATH?: string; JUNO_ENDPOINT: string; GITHUB_CLIENT_ID: string; + GITHUB_TEST_ENV_CLIENT_ID: string; GITHUB_CLIENT_SECRET?: string; // No need to inject secret for prod. Juno already knows it. hostedExplorerURL: string; armAPIVersion?: string; @@ -52,15 +55,16 @@ let configContext: Readonly = { GRAPH_API_VERSION: "1.6", ARCADIA_ENDPOINT: "https://workspaceartifacts.projectarcadia.net", ARCADIA_LIVY_ENDPOINT_DNS_ZONE: "dev.azuresynapse.net", - GITHUB_CLIENT_ID: "6cb2f63cf6f7b5cbdeca", // Registered OAuth app: https://github.com/settings/applications/1189306 + GITHUB_CLIENT_ID: "6cb2f63cf6f7b5cbdeca", // Registered OAuth app: https://github.com/organizations/AzureCosmosDBNotebooks/settings/applications/1189306 + GITHUB_TEST_ENV_CLIENT_ID: "b63fc8cbf87fd3c6e2eb", // Registered OAuth app: https://github.com/organizations/AzureCosmosDBNotebooks/settings/applications/1777772 JUNO_ENDPOINT: "https://tools.cosmos.azure.com", BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com", allowedJunoOrigins: [ - "https://juno-test.documents-dev.windows-int.net", - "https://juno-test2.documents-dev.windows-int.net", - "https://juno-test3.documents-dev.windows-int.net", - "https://tools.cosmos.azure.com", - "https://tools-staging.cosmos.azure.com", + JunoEndpoints.Test, + JunoEndpoints.Test2, + JunoEndpoints.Test3, + JunoEndpoints.Prod, + JunoEndpoints.Stage, "https://localhost", ], }; diff --git a/src/GitHub/GitHubOAuthService.ts b/src/GitHub/GitHubOAuthService.ts index fb9288c7c..7a41076d7 100644 --- a/src/GitHub/GitHubOAuthService.ts +++ b/src/GitHub/GitHubOAuthService.ts @@ -1,8 +1,8 @@ import ko from "knockout"; import postRobot from "post-robot"; +import { GetGithubClientId } from "Utils/GitHubUtils"; import { HttpStatusCodes } from "../Common/Constants"; import { handleError } from "../Common/ErrorHandlingUtils"; -import { configContext } from "../ConfigContext"; import { AuthorizeAccessComponent } from "../Explorer/Controls/GitHub/AuthorizeAccessComponent"; import { JunoClient } from "../Juno/JunoClient"; import { logConsoleInfo } from "../Utils/NotificationConsoleUtils"; @@ -55,7 +55,7 @@ export class GitHubOAuthService { const params = { scope, - client_id: configContext.GITHUB_CLIENT_ID, + client_id: GetGithubClientId(), redirect_uri: new URL("./connectToGitHub.html", window.location.href).href, state: this.resetState(), }; diff --git a/src/Juno/JunoClient.ts b/src/Juno/JunoClient.ts index 1a43cccc6..540c339e8 100644 --- a/src/Juno/JunoClient.ts +++ b/src/Juno/JunoClient.ts @@ -1,4 +1,5 @@ import ko from "knockout"; +import { GetGithubClientId } from "Utils/GitHubUtils"; import { HttpHeaders, HttpStatusCodes } from "../Common/Constants"; import { configContext } from "../ConfigContext"; import * as DataModels from "../Contracts/DataModels"; @@ -522,7 +523,7 @@ export class JunoClient { private static getGitHubClientParams(): URLSearchParams { const githubParams = new URLSearchParams({ - client_id: configContext.GITHUB_CLIENT_ID, + client_id: GetGithubClientId(), }); if (configContext.GITHUB_CLIENT_SECRET) { diff --git a/src/Utils/GitHubUtils.ts b/src/Utils/GitHubUtils.ts index 13e5f828b..59b14f9a8 100644 --- a/src/Utils/GitHubUtils.ts +++ b/src/Utils/GitHubUtils.ts @@ -1,4 +1,9 @@ // https://github.com///tree/ + +import { JunoEndpoints } from "Common/Constants"; +import { configContext } from "ConfigContext"; +import { userContext } from "UserContext"; + // The url when users visit a repo/branch on github.com export const RepoUriPattern = /https:\/\/github.com\/([^/]*)\/([^/]*)\/tree\/([^?]*)/; @@ -60,3 +65,15 @@ export function toContentUri(owner: string, repo: string, branch: string, path: export function toRawContentUri(owner: string, repo: string, branch: string, path: string): string { return `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${path}`; } + +export function GetGithubClientId(): string { + const junoEndpoint = userContext.features.junoEndpoint ?? configContext.JUNO_ENDPOINT; + if ( + junoEndpoint === JunoEndpoints.Test || + junoEndpoint === JunoEndpoints.Test2 || + junoEndpoint === JunoEndpoints.Test3 + ) { + return configContext.GITHUB_TEST_ENV_CLIENT_ID; + } + return configContext.GITHUB_CLIENT_ID; +} From 5d235038ad729ecac1096f2b21593fb506b1a542 Mon Sep 17 00:00:00 2001 From: victor-meng <56978073+victor-meng@users.noreply.github.com> Date: Tue, 30 Nov 2021 15:36:35 -0800 Subject: [PATCH 5/9] Properly update table headers (#1166) --- src/Explorer/Tables/DataTable/TableEntityListViewModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Explorer/Tables/DataTable/TableEntityListViewModel.ts b/src/Explorer/Tables/DataTable/TableEntityListViewModel.ts index f11730b2b..1f1a90d9d 100644 --- a/src/Explorer/Tables/DataTable/TableEntityListViewModel.ts +++ b/src/Explorer/Tables/DataTable/TableEntityListViewModel.ts @@ -431,7 +431,7 @@ export default class TableEntityListViewModel extends DataTableViewModel { if (newHeaders.length > 0) { // Any new columns found will be added into headers array, which will trigger a re-render of the DataTable. // So there is no need to call it here. - this.updateHeaders(newHeaders, /* notifyColumnChanges */ true); + this.updateHeaders(selectedHeadersUnion, /* notifyColumnChanges */ true); } else { if (columnSortOrder) { this.sortColumns(columnSortOrder, oSettings); From 203c2ac246e4f155f63ad2c8dc7945fab6f1e909 Mon Sep 17 00:00:00 2001 From: Sunil Kumar Yadav <79906609+sunilyadav840@users.noreply.github.com> Date: Thu, 2 Dec 2021 09:16:48 +0530 Subject: [PATCH 6/9] fixed horizontal scroll issue on zoom 400% (#1165) Co-authored-by: sunilyadav --- less/documentDB.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/less/documentDB.less b/less/documentDB.less index 72bbce880..50b5eafd8 100644 --- a/less/documentDB.less +++ b/less/documentDB.less @@ -2077,7 +2077,7 @@ a:link { .resourceTreeAndTabs { display: flex; flex: 1 1 auto; - overflow-x: auto; + overflow-x: clip; overflow-y: auto; height: 100%; } From 667b1e1486011cc39feb6540ec21727f0e75fe37 Mon Sep 17 00:00:00 2001 From: Hardikkumar Nai <80053762+hardiknai-techm@users.noreply.github.com> Date: Fri, 3 Dec 2021 09:42:57 +0530 Subject: [PATCH 7/9] 1413651_Refresh_button_missing (#1169) --- less/documentDB.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/less/documentDB.less b/less/documentDB.less index 50b5eafd8..7ccaf4255 100644 --- a/less/documentDB.less +++ b/less/documentDB.less @@ -2245,7 +2245,7 @@ a:link { } .refreshColHeader { - padding: 3px 6px 6px 6px; + padding: 3px 6px 10px 0px !important; } .refreshColHeader:hover { From 8a8c023d7be983e862f2b20e0e307a38bf45add0 Mon Sep 17 00:00:00 2001 From: vaidankarswapnil <81285216+vaidankarswapnil@users.noreply.github.com> Date: Fri, 3 Dec 2021 09:43:45 +0530 Subject: [PATCH 8/9] Fix Keyboard focus New Database button (#1167) * Fix a11y new database button focus issue * Update test snapshot and other issues * fix issue for the menu button * Issue fixed in Splash screen --- src/Explorer/Panes/AddDatabasePanel/AddDatabasePanel.tsx | 5 +++++ src/Explorer/SplashScreen/SplashScreen.tsx | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Explorer/Panes/AddDatabasePanel/AddDatabasePanel.tsx b/src/Explorer/Panes/AddDatabasePanel/AddDatabasePanel.tsx index 0c3568ecf..4b0535175 100644 --- a/src/Explorer/Panes/AddDatabasePanel/AddDatabasePanel.tsx +++ b/src/Explorer/Panes/AddDatabasePanel/AddDatabasePanel.tsx @@ -23,10 +23,12 @@ import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneFor export interface AddDatabasePaneProps { explorer: Explorer; + buttonElement?: HTMLElement; } export const AddDatabasePanel: FunctionComponent = ({ explorer: container, + buttonElement, }: AddDatabasePaneProps) => { const closeSidePanel = useSidePanel((state) => state.closeSidePanel); let throughput: number; @@ -78,6 +80,9 @@ export const AddDatabasePanel: FunctionComponent = ({ dataExplorerArea: Constants.Areas.ContextualPane, }; TelemetryProcessor.trace(Action.CreateDatabase, ActionModifiers.Open, addDatabasePaneOpenMessage); + if (buttonElement) { + buttonElement.focus(); + } }, []); const onSubmit = () => { diff --git a/src/Explorer/SplashScreen/SplashScreen.tsx b/src/Explorer/SplashScreen/SplashScreen.tsx index d6afda063..031214867 100644 --- a/src/Explorer/SplashScreen/SplashScreen.tsx +++ b/src/Explorer/SplashScreen/SplashScreen.tsx @@ -314,7 +314,10 @@ export class SplashScreen extends React.Component { } useSidePanel .getState() - .openSidePanel("New " + getDatabaseName(), ); + .openSidePanel( + "New " + getDatabaseName(), + + ); }, }); } From ada95eae1f57852120627454ec5fe64e27017f4b Mon Sep 17 00:00:00 2001 From: victor-meng <56978073+victor-meng@users.noreply.github.com> Date: Wed, 8 Dec 2021 15:41:27 -0800 Subject: [PATCH 9/9] Fix execute sproc pane textfield focus issue (#1170) * Fix execute sproc pane textfield focus issue * Update snapshot --- .../ExecuteSprocParamsPane.tsx | 136 +- .../ExecuteSprocParamsPane/InputParameter.tsx | 5 +- .../ExecuteSprocParamsPane.test.tsx.snap | 9968 +++++++++-------- 3 files changed, 5050 insertions(+), 5059 deletions(-) diff --git a/src/Explorer/Panes/ExecuteSprocParamsPane/ExecuteSprocParamsPane.tsx b/src/Explorer/Panes/ExecuteSprocParamsPane/ExecuteSprocParamsPane.tsx index 064aadd5a..81653a025 100644 --- a/src/Explorer/Panes/ExecuteSprocParamsPane/ExecuteSprocParamsPane.tsx +++ b/src/Explorer/Panes/ExecuteSprocParamsPane/ExecuteSprocParamsPane.tsx @@ -1,6 +1,6 @@ import { IDropdownOption, IImageProps, Image, Stack, Text } from "@fluentui/react"; import { useBoolean } from "@fluentui/react-hooks"; -import React, { FunctionComponent, useState } from "react"; +import React, { FunctionComponent, useRef, useState } from "react"; import AddPropertyIcon from "../../../../images/Add-property.svg"; import { useSidePanel } from "../../../hooks/useSidePanel"; import { logConsoleError } from "../../../Utils/NotificationConsoleUtils"; @@ -25,19 +25,16 @@ interface UnwrappedExecuteSprocParam { export const ExecuteSprocParamsPane: FunctionComponent = ({ storedProcedure, }: ExecuteSprocParamsPaneProps): JSX.Element => { + const paramKeyValuesRef = useRef([{ key: "string", text: "" }]); + const partitionValueRef = useRef(); + const partitionKeyRef = useRef("string"); const closeSidePanel = useSidePanel((state) => state.closeSidePanel); + const [numberOfParams, setNumberOfParams] = useState(1); const [isLoading, { setTrue: setLoadingTrue, setFalse: setLoadingFalse }] = useBoolean(false); - const [paramKeyValues, setParamKeyValues] = useState([{ key: "string", text: "" }]); - const [partitionValue, setPartitionValue] = useState(); // Defaulting to undefined here is important. It is not the same partition key as "" - const [selectedKey, setSelectedKey] = React.useState({ key: "string", text: "" }); const [formError, setFormError] = useState(""); - const onPartitionKeyChange = (event: React.FormEvent, item: IDropdownOption): void => { - setSelectedKey(item); - }; - const validateUnwrappedParams = (): boolean => { - const unwrappedParams: UnwrappedExecuteSprocParam[] = paramKeyValues; + const unwrappedParams: UnwrappedExecuteSprocParam[] = paramKeyValuesRef.current; for (let i = 0; i < unwrappedParams.length; i++) { const { key: paramType, text: paramValue } = unwrappedParams[i]; if (paramType === "custom" && (paramValue === "" || paramValue === undefined)) { @@ -53,8 +50,9 @@ export const ExecuteSprocParamsPane: FunctionComponent { - const wrappedSprocParams: UnwrappedExecuteSprocParam[] = paramKeyValues; - const { key: partitionKey } = selectedKey; + const wrappedSprocParams: UnwrappedExecuteSprocParam[] = paramKeyValuesRef.current; + const partitionValue: string = partitionValueRef.current; + const partitionKey: string = partitionKeyRef.current; if (partitionKey === "custom" && (partitionValue === "" || partitionValue === undefined)) { setInvalidParamError(partitionValue); return; @@ -78,37 +76,21 @@ export const ExecuteSprocParamsPane: FunctionComponent { - const cloneParamKeyValue = [...paramKeyValues]; - cloneParamKeyValue.splice(indexToRemove, 1); - setParamKeyValues(cloneParamKeyValue); + paramKeyValuesRef.current.splice(indexToRemove, 1); + setNumberOfParams(numberOfParams - 1); }; const addNewParamAtIndex = (indexToAdd: number): void => { - const cloneParamKeyValue = [...paramKeyValues]; - cloneParamKeyValue.splice(indexToAdd, 0, { key: "string", text: "" }); - setParamKeyValues(cloneParamKeyValue); - }; - - const paramValueChange = (value: string, indexOfInput: number): void => { - const cloneParamKeyValue = [...paramKeyValues]; - cloneParamKeyValue[indexOfInput].text = value; - setParamKeyValues(cloneParamKeyValue); - }; - - const paramKeyChange = ( - _event: React.FormEvent, - selectedParam: IDropdownOption, - indexOfParam: number - ): void => { - const cloneParamKeyValue = [...paramKeyValues]; - cloneParamKeyValue[indexOfParam].key = selectedParam.key.toString(); - setParamKeyValues(cloneParamKeyValue); + paramKeyValuesRef.current.splice(indexToAdd, 0, { key: "string", text: "" }); + setNumberOfParams(numberOfParams + 1); }; const addNewParamAtLastIndex = (): void => { - const cloneParamKeyValue = [...paramKeyValues]; - cloneParamKeyValue.splice(cloneParamKeyValue.length, 0, { key: "string", text: "" }); - setParamKeyValues(cloneParamKeyValue); + paramKeyValuesRef.current.push({ + key: "string", + text: "", + }); + setNumberOfParams(numberOfParams + 1); }; const props: RightPaneFormProps = { @@ -118,46 +100,52 @@ export const ExecuteSprocParamsPane: FunctionComponent submit(), }; + const getInputParameterComponent = (): JSX.Element[] => { + const inputParameters: JSX.Element[] = []; + for (let i = 0; i < numberOfParams; i++) { + const paramKeyValue = paramKeyValuesRef.current[i]; + inputParameters.push( + deleteParamAtIndex(i)} + onAddNewParamKeyPress={() => addNewParamAtIndex(i + 1)} + onParamValueChange={(_event, newInput?: string) => (paramKeyValuesRef.current[i].text = newInput)} + onParamKeyChange={(_event, selectedParam: IDropdownOption) => + (paramKeyValuesRef.current[i].key = selectedParam.key.toString()) + } + paramValue={paramKeyValue.text} + selectedKey={paramKeyValue.key} + /> + ); + } + + return inputParameters; + }; + return ( -
-
- { - setPartitionValue(newInput); - }} - onParamKeyChange={onPartitionKeyChange} - paramValue={partitionValue} - selectedKey={selectedKey.key} - /> - {paramKeyValues.map((paramKeyValue, index) => ( - deleteParamAtIndex(index)} - onAddNewParamKeyPress={() => addNewParamAtIndex(index + 1)} - onParamValueChange={(event, newInput?: string) => { - paramValueChange(newInput, index); - }} - onParamKeyChange={(event: React.FormEvent, selectedParam: IDropdownOption) => { - paramKeyChange(event, selectedParam, index); - }} - paramValue={paramKeyValue && paramKeyValue.text} - selectedKey={paramKeyValue && paramKeyValue.key} - /> - ))} - - Add param - Add New Param - -
+
+ (partitionValueRef.current = newInput)} + onParamKeyChange={(_event: React.FormEvent, item: IDropdownOption) => + (partitionKeyRef.current = item.key.toString()) + } + paramValue={partitionValueRef.current} + selectedKey={partitionKeyRef.current} + /> + {getInputParameterComponent()} + addNewParamAtLastIndex()} tabIndex={0}> + Add param + Add New Param +
); diff --git a/src/Explorer/Panes/ExecuteSprocParamsPane/InputParameter.tsx b/src/Explorer/Panes/ExecuteSprocParamsPane/InputParameter.tsx index 677158b61..6fcea9328 100644 --- a/src/Explorer/Panes/ExecuteSprocParamsPane/InputParameter.tsx +++ b/src/Explorer/Panes/ExecuteSprocParamsPane/InputParameter.tsx @@ -55,7 +55,7 @@ export const InputParameter: FunctionComponent = ({ = ({ {isAddRemoveVisible && ( <> diff --git a/src/Explorer/Panes/ExecuteSprocParamsPane/__snapshots__/ExecuteSprocParamsPane.test.tsx.snap b/src/Explorer/Panes/ExecuteSprocParamsPane/__snapshots__/ExecuteSprocParamsPane.test.tsx.snap index 3f163902a..e5bc2cbef 100644 --- a/src/Explorer/Panes/ExecuteSprocParamsPane/__snapshots__/ExecuteSprocParamsPane.test.tsx.snap +++ b/src/Explorer/Panes/ExecuteSprocParamsPane/__snapshots__/ExecuteSprocParamsPane.test.tsx.snap @@ -17,4983 +17,351 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = ` onSubmit={[Function]} >
-
- - - + - - - - -
- - - -
- - - - - - -
-
-
-
- - -
-
- - - - - -
- -
-
-
-
-
-
-
-
- - - - - - - -
- - - -
- - - - - - -
-
-
-
- - -
-
- - - - - -
- -
-
-
-
-
-
- - -
- Delete param -
-
-
-
-
- - -
- Add param -
-
-
-
-
-
-
+ Partition key value + + +
- - -
- Add param -
-
-
- + + + + + + +
+ + + + - - Add New Param - - +
+
+ + + + + +
+ +
+
+
+ +
-
+ + + + + + + + +
+ + + +
+ + + + + + +
+
+
+
+ + +
+
+ + + + + +
+ +
+
+
+
+
+
+ + +
+ Delete param +
+
+
+
+
+ + +
+ Add param +
+
+
+
+
+
+
+ +
+ + +
+ Add param +
+
+
+ + + Add New Param + + +
+