Compare commits

...

10 Commits

Author SHA1 Message Date
Deborah Chen
0f1b0b01ba Updating string for partition key size checkbox 2021-12-08 12:53:12 -08:00
vaidankarswapnil
8a8c023d7b 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
2021-12-02 20:13:45 -08:00
Hardikkumar Nai
667b1e1486 1413651_Refresh_button_missing (#1169) 2021-12-02 20:12:57 -08:00
Sunil Kumar Yadav
203c2ac246 fixed horizontal scroll issue on zoom 400% (#1165)
Co-authored-by: sunilyadav <v-yadavsunil@microsoft.com>
2021-12-01 19:46:48 -08:00
victor-meng
5d235038ad Properly update table headers (#1166) 2021-11-30 15:36:35 -08:00
Srinath Narayanan
6b4d6f986e added github test env client id (#1168) 2021-12-01 03:38:38 +05:30
Karthik chakravarthy
e575b94ffa Add phoenix telemetry (#1164)
* Add phoenix telemetry

* Revert changes

* Update trace logs
2021-11-29 11:22:57 -05:00
vaidankarswapnil
42bdcaf8d1 Fix radio buttons present under 'Settings' blade like ‘Custom and Unlimited’ along with its label ‘Page options’ are not enclosed in fieldset/legend tag (#1100)
* Fix a11y setting pane radiobuttons issue

* Update test snapshot issue
2021-11-24 20:00:06 -08:00
victor-meng
94a03e5b03 Add Timestamp type to cassandra column types and wrap Timestamp value inside single quotes when creating queries (#1163) 2021-11-19 09:55:10 -08:00
victor-meng
1155557af1 Check for -1 throughput cap value (#1159) 2021-11-10 21:43:04 -08:00
23 changed files with 220 additions and 114 deletions

View File

@@ -2077,7 +2077,7 @@ a:link {
.resourceTreeAndTabs {
display: flex;
flex: 1 1 auto;
overflow-x: auto;
overflow-x: clip;
overflow-y: auto;
height: 100%;
}
@@ -2245,7 +2245,7 @@ a:link {
}
.refreshColHeader {
padding: 3px 6px 6px 6px;
padding: 3px 6px 10px 0px !important;
}
.refreshColHeader:hover {
@@ -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;
}
}

4
package-lock.json generated
View File

@@ -6326,8 +6326,8 @@
},
"@webpack-cli/serve": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.5.2.tgz",
"integrity": "sha512-vgJ5OLWadI8aKjDlOH3rb+dYyPd2GTZuQC/Tihjct6F9GpXGZINo3Y/IVuZVTM1eDQB+/AOsjPUWH/WySDaXvw==",
"resolved": "https://msazure.pkgs.visualstudio.com/_packaging/AzurePortal/npm/registry/@webpack-cli/serve/-/serve-1.5.2.tgz",
"integrity": "sha1-6lhLY3/2PFpHf28hYEtaIFtyyew=",
"dev": true
},
"@xtuc/ieee754": {

View File

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

View File

@@ -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<ConfigContext> = {
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",
],
};

View File

@@ -213,7 +213,8 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
},
};
if (userContext.databaseAccount?.properties.capacity?.totalThroughputLimit) {
const throughputCap = userContext.databaseAccount?.properties.capacity?.totalThroughputLimit;
if (throughputCap && throughputCap !== -1) {
this.calculateTotalThroughputUsed();
}
}
@@ -680,7 +681,7 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
const throughputCap = userContext.databaseAccount?.properties.capacity?.totalThroughputLimit;
const numberOfRegions = userContext.databaseAccount?.properties.locations?.length || 1;
const throughputDelta = (newThroughput - this.offer.autoscaleMaxThroughput) * numberOfRegions;
if (throughputCap && throughputCap - this.totalThroughputUsed < throughputDelta) {
if (throughputCap && throughputCap !== -1 && throughputCap - this.totalThroughputUsed < throughputDelta) {
throughputError = `Your account is currently configured with a total throughput limit of ${throughputCap} RU/s. This update isn't possible because it would increase the total throughput to ${
this.totalThroughputUsed + throughputDelta
} RU/s. Change total throughput limit in cost management.`;
@@ -693,7 +694,7 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
const throughputCap = userContext.databaseAccount?.properties.capacity?.totalThroughputLimit;
const numberOfRegions = userContext.databaseAccount?.properties.locations?.length || 1;
const throughputDelta = (newThroughput - this.offer.manualThroughput) * numberOfRegions;
if (throughputCap && throughputCap - this.totalThroughputUsed < newThroughput - this.offer.manualThroughput) {
if (throughputCap && throughputCap !== -1 && throughputCap - this.totalThroughputUsed < throughputDelta) {
throughputError = `Your account is currently configured with a total throughput limit of ${throughputCap} RU/s. This update isn't possible because it would increase the total throughput to ${
this.totalThroughputUsed + throughputDelta
} RU/s. Change total throughput limit in cost management.`;

View File

@@ -61,7 +61,7 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
totalThroughput *= numberOfRegions;
setTotalThroughputUsed(totalThroughput);
if (throughputCap && throughputCap - totalThroughput < throughput) {
if (throughputCap && throughputCap !== -1 && throughputCap - totalThroughput < throughput) {
setThroughputError(
`Your account is currently configured with a total throughput limit of ${throughputCap} RU/s. This update isn't possible because it would increase the total throughput to ${
totalThroughput + throughput * numberOfRegions
@@ -73,7 +73,7 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
}, []);
const checkThroughputCap = (newThroughput: number): boolean => {
if (throughputCap && throughputCap - totalThroughputUsed < newThroughput) {
if (throughputCap && throughputCap !== -1 && throughputCap - totalThroughputUsed < newThroughput) {
setThroughputError(
`Your account is currently configured with a total throughput limit of ${throughputCap} RU/s. This update isn't possible because it would increase the total throughput to ${
totalThroughputUsed + newThroughput * numberOfRegions

View File

@@ -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<IPhoenixConnectionInfoResult>,
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;
@@ -1176,7 +1187,8 @@ export default class Explorer {
<CassandraAddCollectionPane explorer={this} cassandraApiClient={new CassandraAPIDataClient()} />
);
} else {
userContext.databaseAccount?.properties.capacity?.totalThroughputLimit
const throughputCap = userContext.databaseAccount?.properties.capacity?.totalThroughputLimit;
throughputCap && throughputCap !== -1
? await useDatabases.getState().loadAllOffers()
: await useDatabases.getState().loadDatabaseOffers();
useSidePanel

View File

@@ -311,7 +311,8 @@ function createNewDatabase(container: Explorer): CommandButtonComponentProps {
iconSrc: AddDatabaseIcon,
iconAlt: label,
onCommandClick: async () => {
if (userContext.databaseAccount?.properties.capacity?.totalThroughputLimit) {
const throughputCap = userContext.databaseAccount?.properties.capacity?.totalThroughputLimit;
if (throughputCap && throughputCap !== -1) {
await useDatabases.getState().loadAllOffers();
}
useSidePanel.getState().openSidePanel("New " + getDatabaseName(), <AddDatabasePanel explorer={container} />);

View File

@@ -11,7 +11,7 @@ import {
Separator,
Stack,
Text,
TooltipHost,
TooltipHost
} from "@fluentui/react";
import * as Constants from "Common/Constants";
import { createCollection } from "Common/dataAccess/createCollection";
@@ -468,8 +468,8 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
directionalHint={DirectionalHint.bottomLeftEdge}
content={`You can optionally provision dedicated throughput for a ${getCollectionName().toLocaleLowerCase()} within a database that has throughput
provisioned. This dedicated throughput amount will not be shared with other ${getCollectionName(
true
).toLocaleLowerCase()} in the database and
true
).toLocaleLowerCase()} in the database and
does not count towards the throughput you provisioned for the database. This throughput amount will be
billed in addition to the throughput amount you provisioned at the database level.`}
>
@@ -667,7 +667,7 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
{userContext.apiType === "SQL" && (
<Checkbox
label="My partition key is larger than 100 bytes"
label="My partition key is larger than 101 bytes"
checked={this.state.useHashV2}
styles={{
text: { fontSize: 12 },
@@ -1019,10 +1019,10 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
const partitionKeyVersion = this.state.useHashV2 ? 2 : undefined;
const partitionKey: DataModels.PartitionKey = partitionKeyString
? {
paths: [partitionKeyString],
kind: "Hash",
version: partitionKeyVersion,
}
paths: [partitionKeyString],
kind: "Hash",
version: partitionKeyVersion,
}
: undefined;
const indexingPolicy: DataModels.IndexingPolicy = this.state.enableIndexing

View File

@@ -23,10 +23,12 @@ import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneFor
export interface AddDatabasePaneProps {
explorer: Explorer;
buttonElement?: HTMLElement;
}
export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
explorer: container,
buttonElement,
}: AddDatabasePaneProps) => {
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
let throughput: number;
@@ -78,6 +80,9 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
dataExplorerArea: Constants.Areas.ContextualPane,
};
TelemetryProcessor.trace(Action.CreateDatabase, ActionModifiers.Open, addDatabasePaneOpenMessage);
if (buttonElement) {
buttonElement.focus();
}
}, []);
const onSubmit = () => {

View File

@@ -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<HTMLInputElement>, option: IChoiceGroupOption): void => {
setPageOption(option.key);
};
const choiceButtonStyles = {
flexContainer: [
{
selectors: {
".ms-ChoiceField-wrapper label": {
fontSize: 12,
paddingTop: 0,
},
".ms-ChoiceField": {
marginTop: 0,
},
},
},
],
};
return (
<RightPaneForm {...genericPaneProps}>
<div className="paneMainContent">
{shouldShowQueryPageOptions && (
<div className="settingsSection">
<div className="settingsSectionPart pageOptionsPart">
<div className="settingsSectionLabel">
Page options
<div className="settingsSectionPart">
<Stack horizontal>
<Text id="pageOptions" className="settingsSectionLabel" variant="small">
Page options
</Text>
<InfoTooltip>
Choose Custom to specify a fixed amount of query results to show, or choose Unlimited to show as many
query results per page.
</InfoTooltip>
</div>
<ChoiceGroup selectedKey={pageOption} options={pageOptionList} onChange={handleOnPageOptionChange} />
</Stack>
<ChoiceGroup
ariaLabelledBy="pageOptions"
selectedKey={pageOption}
options={pageOptionList}
styles={choiceButtonStyles}
onChange={handleOnPageOptionChange}
/>
</div>
<div className="tabs settingsSectionPart">
{isCustomPageOptionSelected() && (

View File

@@ -14,17 +14,24 @@ exports[`Settings Pane should render Default properly 1`] = `
className="settingsSection"
>
<div
className="settingsSectionPart pageOptionsPart"
className="settingsSectionPart"
>
<div
className="settingsSectionLabel"
<Stack
horizontal={true}
>
Page options
<Text
className="settingsSectionLabel"
id="pageOptions"
variant="small"
>
Page options
</Text>
<InfoTooltip>
Choose Custom to specify a fixed amount of query results to show, or choose Unlimited to show as many query results per page.
</InfoTooltip>
</div>
</Stack>
<StyledChoiceGroup
ariaLabelledBy="pageOptions"
onChange={[Function]}
options={
Array [
@@ -39,6 +46,23 @@ exports[`Settings Pane should render Default properly 1`] = `
]
}
selectedKey="custom"
styles={
Object {
"flexContainer": Array [
Object {
"selectors": Object {
".ms-ChoiceField": Object {
"marginTop": 0,
},
".ms-ChoiceField-wrapper label": Object {
"fontSize": 12,
"paddingTop": 0,
},
},
},
],
}
}
/>
</div>
<div

View File

@@ -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 = {

View File

@@ -308,12 +308,16 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
title: "New " + getDatabaseName(),
description: undefined,
onClick: async () => {
if (userContext.databaseAccount?.properties.capacity?.totalThroughputLimit) {
const throughputCap = userContext.databaseAccount?.properties.capacity?.totalThroughputLimit;
if (throughputCap && throughputCap !== -1) {
await useDatabases.getState().loadAllOffers();
}
useSidePanel
.getState()
.openSidePanel("New " + getDatabaseName(), <AddDatabasePanel explorer={this.container} />);
.openSidePanel(
"New " + getDatabaseName(),
<AddDatabasePanel explorer={this.container} buttonElement={document.activeElement as HTMLElement} />
);
},
});
}

View File

@@ -19,6 +19,7 @@ export const CassandraType = {
Float: "Float",
Int: "Int",
Text: "Text",
Timestamp: "Timestamp",
Uuid: "Uuid",
Varchar: "Varchar",
Varint: "Varint",

View File

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

View File

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

View File

@@ -576,9 +576,8 @@ export default class Collection implements ViewModels.Collection {
public onSettingsClick = async (): Promise<void> => {
useSelectedNode.getState().setSelectedNode(this);
userContext.databaseAccount?.properties.capacity?.totalThroughputLimit
? await useDatabases.getState().loadAllOffers()
: await this.loadOffer();
const throughputCap = userContext.databaseAccount?.properties.capacity?.totalThroughputLimit;
throughputCap && throughputCap !== -1 ? await useDatabases.getState().loadAllOffers() : await this.loadOffer();
this.selectedSubnodeKind(ViewModels.CollectionTabKind.Settings);
TelemetryProcessor.trace(Action.SelectItem, ActionModifiers.Mark, {
description: "Settings node",

View File

@@ -66,7 +66,8 @@ export default class Database implements ViewModels.Database {
dataExplorerArea: Constants.Areas.ResourceTree,
});
if (userContext.databaseAccount?.properties.capacity?.totalThroughputLimit) {
const throughputCap = userContext.databaseAccount?.properties.capacity?.totalThroughputLimit;
if (throughputCap && throughputCap !== -1) {
await useDatabases.getState().loadAllOffers();
}

View File

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

View File

@@ -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) {

View File

@@ -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,

View File

@@ -1,4 +1,9 @@
// https://github.com/<owner>/<repo>/tree/<branch>
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;
}