New quick start - create sample container (#1259)

* Update links and texts

* Remove unintended change

* Quick start - create sample container

* Small adjustments + fix test

* Hide coach mark behind feature flag

* Add snapshot test for AddCollectionPanel to increase coverage

* Fix snapshot

* Fix snapshot 2...

* Change runner account name

* Change portal runner account name
This commit is contained in:
victor-meng 2022-05-04 18:24:34 -07:00 committed by GitHub
parent d05a05716f
commit ebbfc5f517
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 603 additions and 24 deletions

View File

@ -39,7 +39,7 @@ export const createDatabaseContextMenu = (container: Explorer, databaseId: strin
const items: TreeNodeMenuItem[] = [
{
iconSrc: AddCollectionIcon,
onClick: () => container.onNewCollectionClicked(databaseId),
onClick: () => container.onNewCollectionClicked({ databaseId }),
label: `New ${getCollectionName()}`,
},
];

View File

@ -16,6 +16,7 @@ export interface ThroughputInputProps {
isSharded: boolean;
isFreeTier: boolean;
showFreeTierExceedThroughputTooltip: boolean;
isQuickstart?: boolean;
setThroughputValue: (throughput: number) => void;
setIsAutoscale: (isAutoscale: boolean) => void;
setIsThroughputCapExceeded: (isThroughputCapExceeded: boolean) => void;
@ -226,6 +227,7 @@ export const ThroughputInput: FunctionComponent<ThroughputInputProps> = ({
</Stack>
<TextField
id="autoscaleRUValueField"
type="number"
styles={{
fieldGroup: { width: 300, height: 27 },

View File

@ -1637,6 +1637,7 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
<StyledTextFieldBase
aria-label="Max request units per second"
errorMessage=""
id="autoscaleRUValueField"
key=".0:$.2"
min={1000}
onChange={[Function]}
@ -1660,6 +1661,7 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
aria-label="Max request units per second"
deferredValidationTime={200}
errorMessage=""
id="autoscaleRUValueField"
min={1000}
onChange={[Function]}
required={true}
@ -1955,7 +1957,7 @@ exports[`ThroughputInput Pane should render Default properly 1`] = `
<input
aria-invalid={false}
className="ms-TextField-field field-64"
id="TextField2"
id="autoscaleRUValueField"
min={1000}
onBlur={[Function]}
onChange={[Function]}

View File

@ -68,11 +68,10 @@ export class ContainerSampleGenerator {
return database.findCollectionWithId(this.sampleDataFile.collectionId);
}
private async populateContainerAsync(collection: ViewModels.Collection): Promise<void> {
public async populateContainerAsync(collection: ViewModels.Collection): Promise<void> {
if (!collection) {
throw new Error("No container to populate");
}
const promises: Q.Promise<any>[] = [];
if (userContext.apiType === "Gremlin") {
// For Gremlin, all queries are executed sequentially, because some queries might be dependent on other queries

View File

@ -1131,7 +1131,13 @@ export default class Explorer {
}
}
public async onNewCollectionClicked(databaseId?: string): Promise<void> {
public async onNewCollectionClicked(
options: {
databaseId?: string;
isQuickstart?: boolean;
showTeachingBubble?: boolean;
} = {}
): Promise<void> {
if (userContext.apiType === "Cassandra") {
useSidePanel
.getState()
@ -1146,7 +1152,7 @@ export default class Explorer {
: await useDatabases.getState().loadDatabaseOffers();
useSidePanel
.getState()
.openSidePanel("New " + getCollectionName(), <AddCollectionPanel explorer={this} databaseId={databaseId} />);
.openSidePanel("New " + getCollectionName(), <AddCollectionPanel explorer={this} {...options} />);
}
}

View File

@ -0,0 +1,15 @@
import { shallow } from "enzyme";
import React from "react";
import Explorer from "../Explorer";
import { AddCollectionPanel } from "./AddCollectionPanel";
const props = {
explorer: new Explorer(),
};
describe("AddCollectionPanel", () => {
it("should render Default properly", () => {
const wrapper = shallow(<AddCollectionPanel {...props} />);
expect(wrapper).toMatchSnapshot();
});
});

View File

@ -10,6 +10,7 @@ import {
Link,
Separator,
Stack,
TeachingBubble,
Text,
TooltipHost,
} from "@fluentui/react";
@ -30,6 +31,7 @@ import { isCapabilityEnabled, isServerlessAccount } from "Utils/CapabilityUtils"
import { getUpsellMessage } from "Utils/PricingUtils";
import { CollapsibleSectionComponent } from "../Controls/CollapsiblePanel/CollapsibleSectionComponent";
import { ThroughputInput } from "../Controls/ThroughputInput/ThroughputInput";
import { ContainerSampleGenerator } from "../DataSamples/ContainerSampleGenerator";
import Explorer from "../Explorer";
import { useDatabases } from "../useDatabases";
import { PanelFooterComponent } from "./PanelFooterComponent";
@ -39,6 +41,8 @@ import { PanelLoadingScreen } from "./PanelLoadingScreen";
export interface AddCollectionPanelProps {
explorer: Explorer;
databaseId?: string;
isQuickstart?: boolean;
showTeachingBubble?: boolean;
}
const SharedDatabaseDefault: DataModels.IndexingPolicy = {
@ -93,6 +97,7 @@ export interface AddCollectionPanelState {
showErrorDetails: boolean;
isExecuting: boolean;
isThroughputCapExceeded: boolean;
teachingBubbleStep: number;
}
export class AddCollectionPanel extends React.Component<AddCollectionPanelProps, AddCollectionPanelState> {
@ -107,11 +112,11 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
this.state = {
createNewDatabase: userContext.apiType !== "Tables" && !this.props.databaseId,
newDatabaseId: "",
newDatabaseId: props.isQuickstart ? "SampleDB" : "",
isSharedThroughputChecked: this.getSharedThroughputDefault(),
selectedDatabaseId:
userContext.apiType === "Tables" ? CollectionCreation.TablesAPIDefaultDatabase : this.props.databaseId,
collectionId: "",
collectionId: props.isQuickstart ? `Sample${getCollectionName()}` : "",
enableIndexing: true,
isSharded: userContext.apiType !== "Tables",
partitionKey: this.getPartitionKey(),
@ -124,9 +129,16 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
showErrorDetails: false,
isExecuting: false,
isThroughputCapExceeded: false,
teachingBubbleStep: 0,
};
}
componentDidMount(): void {
if (this.state.teachingBubbleStep === 0 && this.props.showTeachingBubble) {
this.setState({ teachingBubbleStep: 1 });
}
}
render(): JSX.Element {
const isFirstResourceCreated = useDatabases.getState().isFirstResourceCreated();
@ -150,6 +162,70 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
/>
)}
{this.state.teachingBubbleStep === 1 && (
<TeachingBubble
headline="Create sample database"
target={"#newDatabaseId"}
calloutProps={{ gapSpace: 16 }}
primaryButtonProps={{ text: "Next", onClick: () => this.setState({ teachingBubbleStep: 2 }) }}
secondaryButtonProps={{ text: "Cancel", onClick: () => this.setState({ teachingBubbleStep: 0 }) }}
onDismiss={() => this.setState({ teachingBubbleStep: 0 })}
footerContent="Step 1 of 4"
>
Database is the parent of a container, create a new database / use an existing one
</TeachingBubble>
)}
{this.state.teachingBubbleStep === 2 && (
<TeachingBubble
headline="Setting throughput"
target={"#autoscaleRUValueField"}
calloutProps={{ gapSpace: 16 }}
primaryButtonProps={{ text: "Next", onClick: () => this.setState({ teachingBubbleStep: 3 }) }}
secondaryButtonProps={{ text: "Previous", onClick: () => this.setState({ teachingBubbleStep: 1 }) }}
onDismiss={() => this.setState({ teachingBubbleStep: 0 })}
footerContent="Step 2 of 4"
>
Cosmos DB recommends sharing throughput across database. Autoscale will give you a flexible amount of
throughput based on the max RU/s set
</TeachingBubble>
)}
{this.state.teachingBubbleStep === 3 && (
<TeachingBubble
headline="Naming container"
target={"#collectionId"}
calloutProps={{ gapSpace: 16 }}
primaryButtonProps={{ text: "Next", onClick: () => this.setState({ teachingBubbleStep: 4 }) }}
secondaryButtonProps={{ text: "Previous", onClick: () => this.setState({ teachingBubbleStep: 2 }) }}
onDismiss={() => this.setState({ teachingBubbleStep: 0 })}
footerContent="Step 3 of 4"
>
Name your container
</TeachingBubble>
)}
{this.state.teachingBubbleStep === 4 && (
<TeachingBubble
headline="Setting partition key"
target={"#addCollection-partitionKeyValue"}
calloutProps={{ gapSpace: 16 }}
primaryButtonProps={{
text: "Create container",
onClick: () => {
this.setState({ teachingBubbleStep: 0 });
this.submit();
},
}}
secondaryButtonProps={{ text: "Previous", onClick: () => this.setState({ teachingBubbleStep: 2 }) }}
onDismiss={() => this.setState({ teachingBubbleStep: 0 })}
footerContent="Step 4 of 4"
>
Last step - you will need to define a partition key for your collection. /address was chosen for this
particular example. A good partition key should have a wide range of possible value
</TeachingBubble>
)}
<div className="panelMainContent">
<Stack hidden={userContext.apiType === "Tables"}>
<Stack horizontal>
@ -832,6 +908,9 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
if (userContext.features.partitionKeyDefault2) {
return userContext.apiType === "SQL" ? "/pk" : "pk";
}
if (this.props.isQuickstart) {
return userContext.apiType === "SQL" ? "/address" : "address";
}
return "";
}
@ -899,8 +978,11 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
}
private isSynapseLinkEnabled(): boolean {
const { properties } = userContext.databaseAccount;
if (!userContext.databaseAccount) {
return false;
}
const { properties } = userContext.databaseAccount;
if (!properties) {
return false;
}
@ -996,8 +1078,8 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
document.getElementById("collapsibleSectionContent")?.scrollIntoView();
}
private async submit(event: React.FormEvent<HTMLFormElement>): Promise<void> {
event.preventDefault();
private async submit(event?: React.FormEvent<HTMLFormElement>): Promise<void> {
event?.preventDefault();
if (!this.validateInputs()) {
return;
@ -1090,8 +1172,17 @@ export class AddCollectionPanel extends React.Component<AddCollectionPanelProps,
try {
await createCollection(createCollectionParams);
await this.props.explorer.refreshAllDatabases();
if (this.props.isQuickstart) {
const database = useDatabases.getState().findDatabaseWithId("SampleDB");
if (database) {
await database.loadCollections();
const collection = database.findCollectionWithId("SampleContainer");
const sampleGenerator = await ContainerSampleGenerator.createSampleGeneratorAsync(this.props.explorer);
sampleGenerator.populateContainerAsync(collection);
}
}
this.setState({ isExecuting: false });
this.props.explorer.refreshAllDatabases();
TelemetryProcessor.traceSuccess(Action.CreateCollection, telemetryData, startKey);
useSidePanel.getState().closeSidePanel();
} catch (error) {

View File

@ -0,0 +1,427 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`AddCollectionPanel should render Default properly 1`] = `
<form
className="panelFormWrapper"
onSubmit={[Function]}
>
<div
className="panelMainContent"
>
<Stack
hidden={false}
>
<Stack
horizontal={true}
>
<span
className="mandatoryStar"
>
* 
</span>
<Text
className="panelTextBold"
variant="small"
>
Database
id
</Text>
<StyledTooltipHostBase
content="A database is analogous to a namespace. It is the unit of management for a set of containers."
directionalHint={4}
>
<Icon
className="panelInfoIcon"
iconName="Info"
tabIndex={0}
/>
</StyledTooltipHostBase>
</Stack>
<Stack
horizontal={true}
verticalAlign="center"
>
<input
aria-checked={true}
aria-label="Create new database"
checked={true}
className="panelRadioBtn"
id="databaseCreateNew"
name="databaseType"
onChange={[Function]}
role="radio"
tabIndex={0}
type="radio"
/>
<span
className="panelRadioBtnLabel"
>
Create new
</span>
<input
aria-checked={false}
aria-label="Use existing database"
checked={false}
className="panelRadioBtn"
name="databaseType"
onChange={[Function]}
role="radio"
tabIndex={0}
type="radio"
/>
<span
className="panelRadioBtnLabel"
>
Use existing
</span>
</Stack>
<Stack
className="panelGroupSpacing"
>
<input
aria-label="New database id"
aria-required={true}
autoComplete="off"
autoFocus={true}
className="panelTextField"
id="newDatabaseId"
name="newDatabaseId"
onChange={[Function]}
pattern="[^/?#\\\\\\\\]*[^/?# \\\\\\\\]"
placeholder="Type a new database id"
required={true}
size={40}
tabIndex={0}
title="May not end with space nor contain characters '\\\\' '/' '#' '?'"
type="text"
value=""
/>
<Stack
horizontal={true}
>
<StyledCheckboxBase
checked={true}
label="Share throughput across containers"
onChange={[Function]}
styles={
Object {
"checkbox": Object {
"height": 12,
"width": 12,
},
"label": Object {
"alignItems": "center",
"padding": 0,
},
"text": Object {
"fontSize": 12,
},
}
}
/>
<StyledTooltipHostBase
content="Throughput configured at the database level will be shared across all containers within the database."
directionalHint={4}
>
<Icon
className="panelInfoIcon"
iconName="Info"
tabIndex={0}
/>
</StyledTooltipHostBase>
</Stack>
<ThroughputInput
isDatabase={true}
isSharded={true}
onCostAcknowledgeChange={[Function]}
setIsAutoscale={[Function]}
setIsThroughputCapExceeded={[Function]}
setThroughputValue={[Function]}
/>
</Stack>
<Separator
className="panelSeparator"
/>
</Stack>
<Stack>
<Stack
horizontal={true}
>
<span
className="mandatoryStar"
>
* 
</span>
<Text
className="panelTextBold"
variant="small"
>
Container id
</Text>
<StyledTooltipHostBase
content="Unique identifier for the container and used for id-based routing through REST and all SDKs."
directionalHint={4}
>
<Icon
className="panelInfoIcon"
iconName="Info"
tabIndex={0}
/>
</StyledTooltipHostBase>
</Stack>
<input
aria-label="Container id"
aria-required={true}
autoComplete="off"
className="panelTextField"
id="collectionId"
name="collectionId"
onChange={[Function]}
pattern="[^/?#\\\\\\\\]*[^/?# \\\\\\\\]"
placeholder="e.g., Container1"
required={true}
size={40}
title="May not end with space nor contain characters '\\\\' '/' '#' '?'"
type="text"
value=""
/>
</Stack>
<Stack>
<Stack
horizontal={true}
>
<span
className="mandatoryStar"
>
* 
</span>
<Text
className="panelTextBold"
variant="small"
>
Partition key
</Text>
<StyledTooltipHostBase
content="The partition key is used to automatically distribute data across partitions for scalability. Choose a property in your JSON document that has a wide range of values and evenly distributes request volume. For small read-heavy workloads or write-heavy workloads of any size, id is often a good choice."
directionalHint={4}
>
<Icon
className="panelInfoIcon"
iconName="Info"
tabIndex={0}
/>
</StyledTooltipHostBase>
</Stack>
<Text
aria-label="pkDescription"
variant="small"
/>
<input
aria-label="Partition key"
aria-required={true}
className="panelTextField"
id="addCollection-partitionKeyValue"
onChange={[Function]}
pattern=".*"
placeholder="e.g., /address/zipCode"
required={true}
size={40}
title=""
type="text"
value=""
/>
</Stack>
<Stack>
<Stack
horizontal={true}
>
<Text
className="panelTextBold"
variant="small"
>
Unique keys
</Text>
<StyledTooltipHostBase
content="Unique keys provide developers with the ability to add a layer of data integrity to their database. By creating a unique key policy when a container is created, you ensure the uniqueness of one or more values per partition key."
directionalHint={4}
>
<Icon
className="panelInfoIcon"
iconName="Info"
tabIndex={0}
/>
</StyledTooltipHostBase>
</Stack>
<CustomizedActionButton
iconProps={
Object {
"iconName": "Add",
}
}
onClick={[Function]}
styles={
Object {
"label": Object {
"fontSize": 12,
},
"root": Object {
"padding": 0,
},
}
}
>
Add unique key
</CustomizedActionButton>
</Stack>
<Stack
className="panelGroupSpacing"
>
<Stack
horizontal={true}
>
<Text
className="panelTextBold"
variant="small"
>
Analytical store
</Text>
<StyledTooltipHostBase
content={
<Text
variant="small"
>
Enable analytical store capability to perform near real-time analytics on your operational data, without impacting the performance of transactional workloads.
<StyledLinkBase
href="https://aka.ms/analytical-store-overview"
target="_blank"
>
Learn more
</StyledLinkBase>
</Text>
}
directionalHint={4}
>
<Icon
className="panelInfoIcon"
iconName="Info"
tabIndex={0}
/>
</StyledTooltipHostBase>
</Stack>
<Stack
horizontal={true}
verticalAlign="center"
>
<input
aria-checked={false}
aria-label="Enable analytical store"
checked={false}
className="panelRadioBtn"
disabled={true}
id="enableAnalyticalStoreBtn"
name="analyticalStore"
onChange={[Function]}
role="radio"
tabIndex={0}
type="radio"
/>
<span
className="panelRadioBtnLabel"
>
On
</span>
<input
aria-checked={true}
aria-label="Disable analytical store"
checked={true}
className="panelRadioBtn"
disabled={true}
id="disableAnalyticalStoreBtn"
name="analyticalStore"
onChange={[Function]}
role="radio"
tabIndex={0}
type="radio"
/>
<span
className="panelRadioBtnLabel"
>
Off
</span>
</Stack>
<Stack
className="panelGroupSpacing"
>
<Text
variant="small"
>
Azure Synapse Link is required for creating an analytical store
container
. Enable Synapse Link for this Cosmos DB account.
<StyledLinkBase
href="https://aka.ms/cosmosdb-synapselink"
target="_blank"
>
Learn more
</StyledLinkBase>
</Text>
<CustomizedDefaultButton
onClick={[Function]}
style={
Object {
"height": 27,
"width": 80,
}
}
styles={
Object {
"label": Object {
"fontSize": 12,
},
}
}
text="Enable"
/>
</Stack>
</Stack>
<CollapsibleSectionComponent
isExpandedByDefault={false}
onExpand={[Function]}
title="Advanced"
>
<Stack
className="panelGroupSpacing"
id="collapsibleSectionContent"
>
<StyledCheckboxBase
checked={false}
label="My partition key is larger than 101 bytes"
onChange={[Function]}
styles={
Object {
"checkbox": Object {
"height": 12,
"width": 12,
},
"label": Object {
"alignItems": "center",
"padding": 0,
},
"text": Object {
"fontSize": 12,
},
}
}
/>
</Stack>
</CollapsibleSectionComponent>
</div>
<PanelFooterComponent
buttonLabel="OK"
isButtonDisabled={false}
/>
</form>
`;

View File

@ -1,7 +1,7 @@
/**
* Accordion top class
*/
import { Image, Link, Stack, Text } from "@fluentui/react";
import { Coachmark, DirectionalHint, Image, Link, Stack, TeachingBubbleContent, Text } from "@fluentui/react";
import * as React from "react";
import AddDatabaseIcon from "../../../images/AddDatabase.svg";
import NewQueryIcon from "../../../images/AddSqlQuery_16x16.svg";
@ -39,6 +39,7 @@ import { useSelectedNode } from "../useSelectedNode";
export interface SplashScreenItem {
iconSrc: string;
title: string;
id?: string;
info?: string;
description: string;
onClick: () => void;
@ -48,7 +49,11 @@ export interface SplashScreenProps {
explorer: Explorer;
}
export class SplashScreen extends React.Component<SplashScreenProps> {
export interface SplashScreenState {
showCoachmark: boolean;
}
export class SplashScreen extends React.Component<SplashScreenProps, SplashScreenState> {
private static readonly seeMoreItemTitle: string = "See more Cosmos DB documentation";
private static readonly seeMoreItemUrl: string = "https://aka.ms/cosmosdbdocument";
private static readonly dataModelingUrl = "https://docs.microsoft.com/azure/cosmos-db/modeling-data";
@ -62,15 +67,19 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
super(props);
this.container = props.explorer;
this.subscriptions = [];
this.state = {
showCoachmark: userContext.features.enableNewQuickstart,
};
}
public componentWillUnmount() {
public componentWillUnmount(): void {
while (this.subscriptions.length) {
this.subscriptions.pop().dispose();
}
}
public componentDidMount() {
public componentDidMount(): void {
this.subscriptions.push(
{
dispose: useNotebook.subscribe(
@ -116,13 +125,41 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
</div>
<div className="legendContainer">
<div className="legend">{item.title}</div>
<div className={userContext.features.enableNewQuickstart ? "newDescription" : "description"}>
<div
id={item.id}
className={userContext.features.enableNewQuickstart ? "newDescription" : "description"}
>
{item.description}
</div>
</div>
</Stack>
))}
</div>
{this.state.showCoachmark && (
<Coachmark
target="#quickstartDescription"
positioningContainerProps={{ directionalHint: DirectionalHint.rightTopEdge }}
persistentBeak
>
<TeachingBubbleContent
headline={`Start with sample ${getCollectionName().toLocaleLowerCase()}`}
hasCloseButton
closeButtonAriaLabel="Close"
primaryButtonProps={{
text: "Get started",
onClick: () => {
this.setState({ showCoachmark: false });
this.container.onNewCollectionClicked({ isQuickstart: true, showTeachingBubble: true });
},
}}
secondaryButtonProps={{ text: "Cancel", onClick: () => this.setState({ showCoachmark: false }) }}
onDismiss={() => this.setState({ showCoachmark: false })}
>
You will be guided to create a sample container with sample data, then we will give you a tour of
data explorer You can also cancel launching this tour and explore yourself
</TeachingBubbleContent>
</Coachmark>
)}
<div className="moreStuffContainer">
<div className="moreStuffColumn commonTasks">
<div className="title">
@ -165,11 +202,11 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
if (userContext.features.enableNewQuickstart) {
const launchQuickstartBtn = {
id: "quickstartDescription",
iconSrc: QuickStartIcon,
title: "Launch quick start",
description: "Launch a quick start tutorial to get started with sample data",
// TODO: replace onClick function
onClick: () => 1,
onClick: () => this.container.onNewCollectionClicked({ isQuickstart: true }),
};
const newContainerBtn = {

View File

@ -11,7 +11,7 @@ const fileToUpload = `GettingStarted-ignore${Math.floor(Math.random() * 100000)}
fs.copyFileSync(path.join(__dirname, filename), path.join(__dirname, fileToUpload));
test("Notebooks", async () => {
await page.goto("https://localhost:1234/testExplorer.html?accountName=portal-sql-runner");
await page.goto("https://localhost:1234/testExplorer.html?accountName=portal-sql-runner-west-us");
const explorer = await waitForExplorer();
// Upload and Delete Notebook
await explorer.click('[data-test="My Notebooks"] [aria-label="More"]');

View File

@ -9,7 +9,7 @@ test("SQL CRUD", async () => {
const containerId = generateUniqueName("container");
page.setDefaultTimeout(50000);
await page.goto("https://localhost:1234/testExplorer.html?accountName=portal-sql-runner");
await page.goto("https://localhost:1234/testExplorer.html?accountName=portal-sql-runner-west-us");
const explorer = await waitForExplorer();
await explorer.click('[data-test="New Container"]');
await explorer.fill('[aria-label="New database id"]', databaseId);

View File

@ -15,8 +15,8 @@ const resourceGroupName = "runners";
test("Resource token", async () => {
const credentials = await msRestNodeAuth.loginWithServicePrincipalSecret(clientId, secret, tenantId);
const armClient = new CosmosDBManagementClient(credentials, subscriptionId);
const account = await armClient.databaseAccounts.get(resourceGroupName, "portal-sql-runner");
const keys = await armClient.databaseAccounts.listKeys(resourceGroupName, "portal-sql-runner");
const account = await armClient.databaseAccounts.get(resourceGroupName, "portal-sql-runner-west-us");
const keys = await armClient.databaseAccounts.listKeys(resourceGroupName, "portal-sql-runner-west-us");
const dbId = generateUniqueName("db");
const collectionId = generateUniqueName("col");
const client = new CosmosClient({

View File

@ -8,7 +8,7 @@ import { get, listKeys } from "../../src/Utils/arm/generatedClients/cosmos/datab
const resourceGroup = process.env.RESOURCE_GROUP || "";
const subscriptionId = process.env.SUBSCRIPTION_ID || "";
const urlSearchParams = new URLSearchParams(window.location.search);
const accountName = urlSearchParams.get("accountName") || "portal-sql-runner";
const accountName = urlSearchParams.get("accountName") || "portal-sql-runner-west-us";
const selfServeType = urlSearchParams.get("selfServeType") || "example";
const iframeSrc = urlSearchParams.get("iframeSrc") || "explorer.html?platform=Portal&disablePortalInitCache";