diff --git a/src/Platform/Hosted/ConnectScreen.less b/src/Platform/Hosted/ConnectScreen.less
new file mode 100644
index 000000000..0514e41ab
--- /dev/null
+++ b/src/Platform/Hosted/ConnectScreen.less
@@ -0,0 +1,101 @@
+.connectExplorerContainer {
+ height: 100%;
+ width: 100%;
+}
+.connectExplorerContainer .connectExplorerFormContainer {
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: -ms-flex;
+ display: flex;
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
+ height: 100%;
+ width: 100%;
+}
+.connectExplorerContainer .connectExplorer {
+ text-align: center;
+ display: -webkit-flex;
+ display: -ms-flexbox;
+ display: -ms-flex;
+ display: flex;
+ -webkit-flex-direction: column;
+ -ms-flex-direction: column;
+ flex-direction: column;
+ justify-content: center;
+ height: 100%;
+ margin-bottom: 60px;
+}
+.connectExplorerContainer .connectExplorer .welcomeText {
+ font-size: 14px;
+ color: #393939;
+ margin: 8px 8px 16px 8px;
+}
+.connectExplorerContainer .connectExplorer .switchConnectTypeText {
+ margin: 8px;
+ font-size: 12px;
+ color: #0058ad;
+ cursor: pointer;
+}
+.connectExplorerContainer .connectExplorer .connectStringText {
+ font-size: 12px;
+ color: #393939;
+}
+.connectExplorerContainer .connectExplorer .connectExplorerContent {
+ margin: 8px;
+ color: #393939;
+}
+.connectExplorerContainer .connectExplorer .connectExplorerContent .inputToken {
+ width: 300px;
+ padding: 0px 4px;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ white-space: nowrap;
+}
+.connectExplorerContainer .connectExplorer .connectExplorerContent .inputToken::placeholder {
+ font-style: italic;
+}
+.connectExplorerContainer .connectExplorer .connectExplorerContent .errorDetailsInfoTooltip {
+ position: relative;
+ display: inline-block;
+ padding-left: 4px;
+ vertical-align: top;
+}
+.connectExplorerContainer .connectExplorer .connectExplorerContent .errorDetailsInfoTooltip:hover .errorDetails {
+ visibility: visible;
+}
+.connectExplorerContainer .connectExplorer .connectExplorerContent .errorDetailsInfoTooltip .errorDetails {
+ bottom: 24px;
+ width: 145px;
+ visibility: hidden;
+ background-color: #393939;
+ color: #ffffff;
+ position: absolute;
+ z-index: 1;
+ left: -10px;
+ padding: 6px;
+}
+.connectExplorerContainer .connectExplorer .connectExplorerContent .errorDetailsInfoTooltip .errorDetails:after {
+ border-width: 10px 10px 0px 10px;
+ bottom: -8px;
+ content: "";
+ position: absolute;
+ right: 100%;
+ border-style: solid;
+ left: 12px;
+ width: 0;
+ height: 0;
+ border-color: #3b3b3b transparent;
+}
+.connectExplorerContainer .connectExplorer .connectExplorerContent .errorDetailsInfoTooltip .errorImg {
+ height: 14px;
+ width: 14px;
+}
+
+.filterbtnstyle {
+ background: #0058ad;
+ width: 90px;
+ height: 25px;
+ color: white;
+ border: solid 1px;
+}
diff --git a/src/Platform/Hosted/ConnectScreen.tsx b/src/Platform/Hosted/ConnectScreen.tsx
new file mode 100644
index 000000000..f7e5bf7b5
--- /dev/null
+++ b/src/Platform/Hosted/ConnectScreen.tsx
@@ -0,0 +1,52 @@
+import "./ConnectScreen.less";
+import * as React from "react";
+import { useMsal } from "@azure/msal-react";
+import { useBoolean } from "@uifabric/react-hooks";
+
+export const ConnectScreen: React.FunctionComponent = () => {
+ const { instance } = useMsal();
+ const [isConnectionStringVisible, { setTrue: showConnectionString }] = useBoolean(false);
+
+ return (
+
+
+
+
+
+
+
Welcome to Azure Cosmos DB
+ {isConnectionStringVisible ? (
+
+ ) : (
+
+
instance.loginPopup()} />
+
{
+ showConnectionString();
+ }}
+ >
+ Connect to your account with connection string
+
+
+ )}
+
+
+
+ );
+};
diff --git a/src/hooks/useAADAccount.tsx b/src/hooks/useAADAccount.tsx
new file mode 100644
index 000000000..19b223392
--- /dev/null
+++ b/src/hooks/useAADAccount.tsx
@@ -0,0 +1,8 @@
+import { AccountInfo } from "@azure/msal-browser";
+import { useAccount, useMsal } from "@azure/msal-react";
+
+export function useAADAccount(): AccountInfo {
+ const { accounts } = useMsal();
+ const account = useAccount(accounts[0] || {});
+ return account;
+}
diff --git a/src/hooks/useAADToken.tsx b/src/hooks/useAADToken.tsx
new file mode 100644
index 000000000..2582eb54b
--- /dev/null
+++ b/src/hooks/useAADToken.tsx
@@ -0,0 +1,20 @@
+import { useMsal } from "@azure/msal-react";
+import { useEffect, useState } from "react";
+import { useAADAccount } from "./useAADAccount";
+
+export function useAADToken(): string {
+ const { instance } = useMsal();
+ const account = useAADAccount();
+ const [state, setState] = useState();
+
+ useEffect(() => {
+ console.log("Current account", account);
+ if (account) {
+ instance.acquireTokenSilent({ account, scopes: ["User.Read"] }).then(response => {
+ console.log("Fetched token", response.accessToken);
+ setState(response.accessToken);
+ });
+ }
+ }, [account]);
+ return state;
+}
diff --git a/src/hooks/useGraphPhoto.tsx b/src/hooks/useGraphPhoto.tsx
new file mode 100644
index 000000000..3a9f75bff
--- /dev/null
+++ b/src/hooks/useGraphPhoto.tsx
@@ -0,0 +1,31 @@
+import { useEffect, useState } from "react";
+import { useAADToken } from "./useAADToken";
+
+export async function fetchPhoto(accessToken: string): Promise {
+ const headers = new Headers();
+ const bearer = `Bearer ${accessToken}`;
+
+ headers.append("Authorization", bearer);
+ headers.append("Content-Type", "image/jpg");
+
+ const options = {
+ method: "GET",
+ headers: headers
+ };
+
+ return fetch("https://graph.microsoft.com/v1.0/me/photo/$value", options)
+ .then(response => response.blob())
+ .catch(error => console.log(error));
+}
+
+export function useGraphPhoto(): string {
+ const token = useAADToken();
+ const [photo, setPhoto] = useState();
+
+ useEffect(() => {
+ if (token) {
+ fetchPhoto(token).then(response => setPhoto(URL.createObjectURL(response)));
+ }
+ }, [token]);
+ return photo;
+}
diff --git a/src/hooks/useSubscriptions.tsx b/src/hooks/useSubscriptions.tsx
new file mode 100644
index 000000000..f9d89baf6
--- /dev/null
+++ b/src/hooks/useSubscriptions.tsx
@@ -0,0 +1,75 @@
+import { useEffect, useState } from "react";
+import { Subscription } from "../Contracts/DataModels";
+import { useAADToken } from "./useAADToken";
+
+interface SubscriptionListResult {
+ nextLink: string;
+ value: Subscription[];
+}
+
+export async function fetchSubscriptions(accessToken: string): Promise {
+ const headers = new Headers();
+ const bearer = `Bearer ${accessToken}`;
+
+ headers.append("Authorization", bearer);
+
+ let subscriptions: Array = [];
+ let nextLink = `https://management.azure.com/subscriptions?api-version=2020-01-01`;
+
+ while (nextLink) {
+ const response = await fetch(nextLink, { headers });
+ const result: SubscriptionListResult =
+ response.status === 204 || response.status === 304 ? undefined : await response.json();
+ if (!response.ok) {
+ throw result;
+ }
+ nextLink = result.nextLink;
+ const validSubscriptions = result.value.filter(
+ sub => sub.state === "Enabled" || sub.state === "Warned" || sub.state === "PastDue"
+ );
+ subscriptions = [...subscriptions, ...validSubscriptions];
+ }
+ return subscriptions;
+}
+
+export function useSubscriptions(): Subscription[] {
+ const token = useAADToken();
+ const [state, setState] = useState();
+
+ useEffect(() => {
+ if (token) {
+ fetchSubscriptions(token).then(response => setState(response));
+ }
+ }, [token]);
+ return state || [];
+}
+
+// const { accounts } = useMsal();
+// const account = useAccount(accounts[0] || {});
+// const { isLoading, isError, data, error } = useQuery(
+// ["subscriptions", account.tenantId],
+// async () => {
+// let subscriptions: Array = [];
+
+// const fetchHeaders = await ArmResourceUtils._getAuthHeader(ArmResourceUtils._armAuthArea, tenantId);
+// let nextLink = `${ArmResourceUtils._armEndpoint}/subscriptions?api-version=${ArmResourceUtils._armApiVersion}`;
+
+// while (nextLink) {
+// const response: Response = await fetch(nextLink, { headers: fetchHeaders });
+// const result: SubscriptionListResult =
+// response.status === 204 || response.status === 304 ? null : await response.json();
+// if (!response.ok) {
+// throw result;
+// }
+// nextLink = result.nextLink;
+// const validSubscriptions = result.value.filter(
+// sub => sub.state === "Enabled" || sub.state === "Warned" || sub.state === "PastDue"
+// );
+// subscriptions = [...subscriptions, ...validSubscriptions];
+// }
+// return subscriptions;
+// },
+// { enabled: account.tenantId }
+// );
+
+// console.log(isLoading, isError, data, error);