/** * Accordion top class */ import { Coachmark, DirectionalHint, Image, Link, Stack, TeachingBubble, TeachingBubbleContent, Text, } from "@fluentui/react"; import { sendMessage } from "Common/MessageHandler"; import { MessageTypes } from "Contracts/ExplorerContracts"; import { TerminalKind } from "Contracts/ViewModels"; import { SplashScreenButton } from "Explorer/SplashScreen/SplashScreenButton"; import { Action } from "Shared/Telemetry/TelemetryConstants"; import { traceOpen } from "Shared/Telemetry/TelemetryProcessor"; import { useCarousel } from "hooks/useCarousel"; import { usePostgres } from "hooks/usePostgres"; import { useQueryCopilot } from "hooks/useQueryCopilot"; import { ReactTabKind, useTabs } from "hooks/useTabs"; import * as React from "react"; import ConnectIcon from "../../../images/Connect_color.svg"; import ContainersIcon from "../../../images/Containers.svg"; import LinkIcon from "../../../images/Link_blue.svg"; import NotebookColorIcon from "../../../images/Notebooks.svg"; import PowerShellIcon from "../../../images/PowerShell.svg"; import CopilotIcon from "../../../images/QueryCopilotNewLogo.svg"; import QuickStartIcon from "../../../images/Quickstart_Lightning.svg"; import NotebookIcon from "../../../images/notebook/Notebook-resource.svg"; import CollectionIcon from "../../../images/tree-collection.svg"; import * as Constants from "../../Common/Constants"; import { userContext } from "../../UserContext"; import { getCollectionName } from "../../Utils/APITypeUtils"; import { FeaturePanelLauncher } from "../Controls/FeaturePanel/FeaturePanelLauncher"; import { DataSamplesUtil } from "../DataSamples/DataSamplesUtil"; import Explorer from "../Explorer"; import * as MostRecentActivity from "../MostRecentActivity/MostRecentActivity"; import { useNotebook } from "../Notebook/useNotebook"; import { useDatabases } from "../useDatabases"; import { useSelectedNode } from "../useSelectedNode"; export interface SplashScreenItem { iconSrc: string; title: string; id?: string; info?: string; description: string; showLinkIcon?: boolean; onClick: () => void; } export interface SplashScreenProps { explorer: Explorer; } export class SplashScreen extends React.Component { private readonly container: Explorer; private subscriptions: Array<{ dispose: () => void }>; constructor(props: SplashScreenProps) { super(props); this.container = props.explorer; this.subscriptions = []; } public componentWillUnmount(): void { while (this.subscriptions.length) { this.subscriptions.pop().dispose(); } } public componentDidMount(): void { this.subscriptions.push( { dispose: useNotebook.subscribe( () => this.setState({}), (state) => state.isNotebookEnabled, ), }, { dispose: useSelectedNode.subscribe(() => this.setState({})) }, { dispose: useCarousel.subscribe( () => this.setState({}), (state) => state.showCoachMark, ), }, { dispose: usePostgres.subscribe( () => this.setState({}), (state) => state.showPostgreTeachingBubble, ), }, { dispose: usePostgres.subscribe( () => this.setState({}), (state) => state.showResetPasswordBubble, ), }, { dispose: useDatabases.subscribe( () => this.setState({}), (state) => state.sampleDataResourceTokenCollection, ), }, { dispose: useQueryCopilot.subscribe( () => this.setState({}), (state) => state.copilotEnabled, ), }, ); } private clearMostRecent = (): void => { MostRecentActivity.mostRecentActivity.clear(userContext.databaseAccount?.id); this.setState({}); }; private getSplashScreenButtons = (): JSX.Element => { if ( userContext.apiType === "SQL" && useQueryCopilot.getState().copilotEnabled && useDatabases.getState().sampleDataResourceTokenCollection ) { return ( { this.container.onNewCollectionClicked({ isQuickstart: true }); traceOpen(Action.LaunchQuickstart, { apiType: userContext.apiType }); }} /> { this.container.onNewCollectionClicked(); traceOpen(Action.NewContainerHomepage, { apiType: userContext.apiType }); }} /> {useQueryCopilot.getState().copilotEnabled && ( { const copilotVersion = userContext.features.copilotVersion; if (copilotVersion === "v1.0") { useTabs.getState().openAndActivateReactTab(ReactTabKind.QueryCopilot); } else if (copilotVersion === "v2.0") { const sampleCollection = useDatabases.getState().sampleDataResourceTokenCollection; sampleCollection.onNewQueryClick(sampleCollection, undefined); } traceOpen(Action.OpenQueryCopilotFromSplashScreen, { apiType: userContext.apiType }); }} /> )} useTabs.getState().openAndActivateReactTab(ReactTabKind.Connect)} /> ); } const mainItems = this.createMainItems(); return (
{userContext.apiType === "Postgres" && usePostgres.getState().showPostgreTeachingBubble && !usePostgres.getState().showResetPasswordBubble && ( usePostgres.getState().setShowPostgreTeachingBubble(false)} calloutProps={{ directionalHint: DirectionalHint.rightCenter, directionalHintFixed: true, preventDismissOnLostFocus: true, preventDismissOnResize: true, preventDismissOnScroll: true, }} primaryButtonProps={{ text: "Get started", onClick: () => { useTabs.getState().openAndActivateReactTab(ReactTabKind.Quickstart); usePostgres.getState().setShowPostgreTeachingBubble(false); }, }} > Welcome! If you are new to Cosmos DB PGSQL and need help with getting started, here is where you can find sample data, query. )} {mainItems.map((item) => ( this.onSplashScreenItemKeyPress(event, item.onClick)} tabIndex={0} role="button" >
{item.title}
{item.showLinkIcon && }
{item.description}
))} {userContext.apiType === "Postgres" && usePostgres.getState().showResetPasswordBubble && ( { localStorage.setItem(userContext.databaseAccount.id, "true"); usePostgres.getState().setShowResetPasswordBubble(false); }} calloutProps={{ directionalHint: DirectionalHint.bottomRightEdge, directionalHintFixed: true, preventDismissOnLostFocus: true, preventDismissOnResize: true, preventDismissOnScroll: true, }} primaryButtonProps={{ text: "Create", onClick: () => { localStorage.setItem(userContext.databaseAccount.id, "true"); sendMessage({ type: MessageTypes.OpenPostgreSQLPasswordReset, }); usePostgres.getState().setShowResetPasswordBubble(false); }, }} > If you haven't changed your password yet, change it now. )}
); }; public render(): JSX.Element { let title: string; let subtitle: string; switch (userContext.apiType) { case "Postgres": title = "Welcome to Azure Cosmos DB for PostgreSQL"; subtitle = "Get started with our sample datasets, documentation, and additional tools."; break; case "VCoreMongo": title = "Welcome to Azure Cosmos DB for MongoDB (vCore)"; subtitle = "Get started with our sample datasets, documentation, and additional tools."; break; default: title = "Welcome to Azure Cosmos DB"; subtitle = "Globally distributed, multi-model database service for any scale"; } return (

{title}

{subtitle}
{this.getSplashScreenButtons()} {useCarousel.getState().showCoachMark && ( { useCarousel.getState().setShowCoachMark(false); this.container.onNewCollectionClicked({ isQuickstart: true }); }, }} secondaryButtonProps={{ text: "Cancel", onClick: () => useCarousel.getState().setShowCoachMark(false), }} onDismiss={() => useCarousel.getState().setShowCoachMark(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 )} {userContext.apiType === "Postgres" || userContext.apiType === "VCoreMongo" ? ( Next steps {this.getNextStepItems()} Tips & learn more {this.getTipsAndLearnMoreItems()} ) : (
Recents
{this.getRecentItems()}
Top 3 things you need to know
{this.top3Items()}
Learning Resources
{this.getLearningResourceItems()}
)}
); } /** * This exists to enable unit testing */ public createDataSampleUtil(): DataSamplesUtil { return new DataSamplesUtil(this.container); } /** * public for testing purposes */ public createMainItems(): SplashScreenItem[] { const heroes: SplashScreenItem[] = []; if ( userContext.apiType === "SQL" || userContext.apiType === "Mongo" || (userContext.apiType === "Postgres" && !userContext.isReplica) || userContext.apiType === "VCoreMongo" ) { const launchQuickstartBtn = { id: "quickstartDescription", iconSrc: QuickStartIcon, title: "Launch quick start", description: "Launch a quick start tutorial to get started with sample data", onClick: () => { if (userContext.apiType === "Postgres" || userContext.apiType === "VCoreMongo") { useTabs.getState().openAndActivateReactTab(ReactTabKind.Quickstart); } else { this.container.onNewCollectionClicked({ isQuickstart: true }); } traceOpen(Action.LaunchQuickstart, { apiType: userContext.apiType }); }, }; heroes.push(launchQuickstartBtn); } else if (useNotebook.getState().isPhoenixNotebooks) { const newNotebookBtn = { iconSrc: NotebookColorIcon, title: "New notebook", description: "Visualize your data stored in Azure Cosmos DB", onClick: () => this.container.onNewNotebookClicked(), }; heroes.push(newNotebookBtn); } heroes.push(this.getShellCard()); heroes.push(this.getThirdCard()); return heroes; } private getShellCard() { if (userContext.apiType === "Postgres") { return { iconSrc: PowerShellIcon, title: "PostgreSQL Shell", description: "Create table and interact with data using PostgreSQL’s shell interface", onClick: () => this.container.openNotebookTerminal(TerminalKind.Postgres), }; } if (userContext.apiType === "VCoreMongo") { return { iconSrc: PowerShellIcon, title: "Mongo Shell", description: "Create a collection and interact with data using MongoDB's shell interface", onClick: () => this.container.openNotebookTerminal(TerminalKind.VCoreMongo), }; } return { iconSrc: ContainersIcon, title: `New ${getCollectionName()}`, description: "Create a new container for storage and throughput", onClick: () => { this.container.onNewCollectionClicked(); traceOpen(Action.NewContainerHomepage, { apiType: userContext.apiType }); }, }; } private getThirdCard() { let icon = ConnectIcon; let title = "Connect"; let description = "Prefer using your own choice of tooling? Find the connection string you need to connect"; let onClick = () => useTabs.getState().openAndActivateReactTab(ReactTabKind.Connect); if (userContext.apiType === "Postgres") { title = "Connect with pgAdmin"; description = "Prefer pgAdmin? Find your connection strings here"; } if (userContext.apiType === "VCoreMongo") { icon = ContainersIcon; title = "Connect with Studio 3T"; description = "Prefer Studio 3T? Find your connection strings here"; onClick = () => useTabs.getState().openAndActivateReactTab(ReactTabKind.Connect); } return { iconSrc: icon, title: title, description: description, onClick: onClick, }; } private decorateOpenCollectionActivity({ databaseId, collectionId }: MostRecentActivity.OpenCollectionItem) { return { iconSrc: CollectionIcon, title: collectionId, description: getCollectionName(), onClick: () => { const collection = useDatabases.getState().findCollection(databaseId, collectionId); collection?.openTab(); }, }; } private decorateOpenNotebookActivity({ name, path }: MostRecentActivity.OpenNotebookItem) { return { info: path, iconSrc: NotebookIcon, title: name, description: "Notebook", onClick: () => { const notebookItem = this.container.createNotebookContentItemFile(name, path); notebookItem && this.container.openNotebook(notebookItem); }, }; } private createRecentItems(): SplashScreenItem[] { return MostRecentActivity.mostRecentActivity.getItems(userContext.databaseAccount?.id).map((activity) => { switch (activity.type) { default: { const unknownActivity: never = activity; throw new Error(`Unknown activity: ${unknownActivity}`); } case MostRecentActivity.Type.OpenNotebook: return this.decorateOpenNotebookActivity(activity); case MostRecentActivity.Type.OpenCollection: return this.decorateOpenCollectionActivity(activity); } }); } private onSplashScreenItemKeyPress(event: React.KeyboardEvent, callback: () => void) { if (event.charCode === Constants.KeyCodes.Space || event.charCode === Constants.KeyCodes.Enter) { callback(); event.stopPropagation(); } } private top3Items(): JSX.Element { let items: { link: string; title: string; description: string }[]; switch (userContext.apiType) { case "SQL": case "Postgres": items = [ { link: "https://aka.ms/msl-modeling-partitioning-2", title: "Advanced Modeling Patterns", description: "Learn advanced strategies to optimize your database.", }, { link: "https://aka.ms/msl-modeling-partitioning-1", title: "Partitioning Best Practices", description: "Learn to apply data model and partitioning strategies.", }, { link: "https://aka.ms/msl-resource-planning", title: "Plan Your Resource Requirements", description: "Get to know the different configuration choices.", }, ]; break; case "Mongo": items = [ { link: "https://aka.ms/mongodbintro", title: "What is the MongoDB API?", description: "Understand Azure Cosmos DB for MongoDB and its features.", }, { link: "https://aka.ms/mongodbfeaturesupport", title: "Features and Syntax", description: "Discover the advantages and features", }, { link: "https://aka.ms/mongodbpremigration", title: "Migrate Your Data", description: "Pre-migration steps for moving data", }, ]; break; case "Cassandra": items = [ { link: "https://aka.ms/cassandrajava", title: "Build a Java App", description: "Create a Java app using an SDK.", }, { link: "https://aka.ms/cassandrapartitioning", title: "Partitioning Best Practices", description: "Learn how partitioning works.", }, { link: "https://aka.ms/cassandraRu", title: "Request Units (RUs)", description: "Understand RU charges.", }, ]; break; case "Gremlin": items = [ { link: "https://aka.ms/Graphdatamodeling", title: "Data Modeling", description: "Graph data modeling recommendations", }, { link: "https://aka.ms/graphpartitioning", title: "Partitioning Best Practices", description: "Learn how partitioning works", }, { link: "https://aka.ms/graphapiquery", title: "Query Data", description: "Querying data with Gremlin", }, ]; break; case "Tables": items = [ { link: "https://aka.ms/tableintro", title: "What is the Table API?", description: "Understand Azure Cosmos DB for Table and its features", }, { link: "https://aka.ms/tableimport", title: "Migrate your data", description: "Learn how to migrate your data", }, { link: "https://aka.ms/tablefaq", title: "Azure Cosmos DB for Table FAQs", description: "Common questions about Azure Cosmos DB for Table", }, ]; break; default: break; } return ( {items.map((item, i) => ( traceOpen(Action.Top3ItemsClicked, { item: i + 1, apiType: userContext.apiType })} href={item.link} target="_blank" style={{ marginRight: 5 }} > {item.title} {item.title} {item.description} ))} ); } private getRecentItems(): JSX.Element { const recentItems = this.createRecentItems()?.filter((item) => item.description !== "Notebook"); return ( {recentItems.length > 0 && this.clearMostRecent()}>Clear Recents} ); } private getLearningResourceItems(): JSX.Element { interface item { link: string; title: string; description: string; } const cdbLiveTv: item = { link: "https://developer.azurecosmosdb.com/tv", title: "Learn the Fundamentals", description: "Watch Azure Cosmos DB Live TV show introductory and how to videos.", }; let items: item[]; switch (userContext.apiType) { case "SQL": case "Postgres": items = [ { link: "https://aka.ms/msl-sdk-connect", title: "Get Started using an SDK", description: "Learn about the Azure Cosmos DB SDK.", }, cdbLiveTv, { link: "https://aka.ms/msl-move-data", title: "Migrate Your Data", description: "Migrate data using Azure services and open-source solutions.", }, ]; break; case "Mongo": items = [ { link: "https://aka.ms/mongonodejs", title: "Build an app with Node.js", description: "Create a Node.js app.", }, { link: "https://aka.ms/mongopython", title: "Getting Started Guide", description: "Learn the basics to get started.", }, cdbLiveTv, ]; break; case "Cassandra": items = [ { link: "https://aka.ms/cassandracontainer", title: "Create a Container", description: "Get to know the create a container options.", }, cdbLiveTv, { link: "https://aka.ms/Cassandrathroughput", title: "Provision Throughput", description: "Learn how to configure throughput.", }, ]; break; case "Gremlin": items = [ { link: "https://aka.ms/graphquickstart", title: "Get Started ", description: "Create, query, and traverse using the Gremlin console", }, { link: "https://aka.ms/graphimport", title: "Import Graph Data", description: "Learn Bulk ingestion data using BulkExecutor", }, cdbLiveTv, ]; break; case "Tables": items = [ { link: "https://aka.ms/tabledotnet", title: "Build a .NET App", description: "How to access Azure Cosmos DB for Table from a .NET app.", }, { link: "https://aka.ms/Tablejava", title: "Build a Java App", description: "Create a Azure Cosmos DB for Table app with Java SDK ", }, cdbLiveTv, ]; break; default: break; } return ( {items.map((item, i) => ( traceOpen(Action.LearningResourcesClicked, { item: i + 1, apiType: userContext.apiType }) } href={item.link} target="_blank" style={{ marginRight: 5 }} > {item.title} {item.title} {item.description} ))} ); } private postgresNextStepItems: { link: string; title: string; description: string }[] = [ { link: "https://go.microsoft.com/fwlink/?linkid=2208312", title: "Data Modeling", description: "", }, { link: " https://go.microsoft.com/fwlink/?linkid=2206941 ", title: "How to choose a Distribution Column", description: "", }, { link: "https://go.microsoft.com/fwlink/?linkid=2207425", title: "Build Apps with Python/Java/Django", description: "", }, ]; private vcoreMongoNextStepItems: { link: string; title: string; description: string }[] = [ { link: "https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/how-to-migrate-native-tools?tabs=export-import", title: "Migrate Data", description: "", }, { link: "https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/vector-search-ai", title: "Build AI apps with Vector Search", description: "", }, { link: "https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/tutorial-nodejs-web-app?tabs=github-codespaces", title: "Build Apps with Nodejs", description: "", }, ]; private getNextStepItems(): JSX.Element { const items = userContext.apiType === "Postgres" ? this.postgresNextStepItems : this.vcoreMongoNextStepItems; return ( {items.map((item, i) => ( {item.title} {item.description} ))} ); } private postgresLearnMoreItems: { link: string; title: string; description: string }[] = [ { link: "https://go.microsoft.com/fwlink/?linkid=2207226", title: "Performance Tuning", description: "", }, { link: "https://go.microsoft.com/fwlink/?linkid=2208037", title: "Useful Diagnostic Queries", description: "", }, { link: "https://go.microsoft.com/fwlink/?linkid=2205270", title: "Distributed SQL Reference", description: "", }, ]; private vcoreMongoLearnMoreItems: { link: string; title: string; description: string }[] = [ { link: "https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/vector-search", title: "Vector Search", description: "", }, { link: "https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/how-to-create-text-index", title: "Text Indexing", description: "", }, { link: "https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/troubleshoot-common-issues", title: "Troubleshoot common issues", description: "", }, ]; private getTipsAndLearnMoreItems(): JSX.Element { const items = userContext.apiType === "Postgres" ? this.postgresLearnMoreItems : this.vcoreMongoLearnMoreItems; return ( {items.map((item, i) => ( {item.title} {item.description} ))} ); } }