mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-21 01:41:31 +00:00
Add files from previous commit
This commit is contained in:
101
src/Platform/Hosted/ConnectScreen.less
Normal file
101
src/Platform/Hosted/ConnectScreen.less
Normal file
@@ -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;
|
||||||
|
}
|
||||||
52
src/Platform/Hosted/ConnectScreen.tsx
Normal file
52
src/Platform/Hosted/ConnectScreen.tsx
Normal file
@@ -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 (
|
||||||
|
<div id="connectExplorer" className="connectExplorerContainer" style={{ display: "flex" }}>
|
||||||
|
<div className="connectExplorerFormContainer">
|
||||||
|
<div className="connectExplorer">
|
||||||
|
<p className="connectExplorerContent">
|
||||||
|
<img src="images/HdeConnectCosmosDB.svg" alt="Azure Cosmos DB" />
|
||||||
|
</p>
|
||||||
|
<p className="welcomeText">Welcome to Azure Cosmos DB</p>
|
||||||
|
{isConnectionStringVisible ? (
|
||||||
|
<form id="connectWithConnectionString">
|
||||||
|
<p className="connectExplorerContent connectStringText">Connect to your account with connection string</p>
|
||||||
|
<p className="connectExplorerContent">
|
||||||
|
<input className="inputToken" type="text" required placeholder="Please enter a connection string" />
|
||||||
|
<span className="errorDetailsInfoTooltip" style={{ display: "none" }}>
|
||||||
|
<img className="errorImg" src="images/error.svg" alt="Error notification" />
|
||||||
|
<span className="errorDetails" />
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
<p className="connectExplorerContent">
|
||||||
|
<input className="filterbtnstyle" type="submit" value="Connect" />
|
||||||
|
</p>
|
||||||
|
<p className="switchConnectTypeText" onClick={() => instance.loginPopup()}>
|
||||||
|
Sign In with Azure Account
|
||||||
|
</p>
|
||||||
|
</form>
|
||||||
|
) : (
|
||||||
|
<div id="connectWithAad">
|
||||||
|
<input className="filterbtnstyle" type="button" value="Sign In" onClick={() => instance.loginPopup()} />
|
||||||
|
<p
|
||||||
|
className="switchConnectTypeText"
|
||||||
|
onClick={() => {
|
||||||
|
showConnectionString();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Connect to your account with connection string
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
8
src/hooks/useAADAccount.tsx
Normal file
8
src/hooks/useAADAccount.tsx
Normal file
@@ -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;
|
||||||
|
}
|
||||||
20
src/hooks/useAADToken.tsx
Normal file
20
src/hooks/useAADToken.tsx
Normal file
@@ -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<string>();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
31
src/hooks/useGraphPhoto.tsx
Normal file
31
src/hooks/useGraphPhoto.tsx
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useAADToken } from "./useAADToken";
|
||||||
|
|
||||||
|
export async function fetchPhoto(accessToken: string): Promise<Blob | void> {
|
||||||
|
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<string>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (token) {
|
||||||
|
fetchPhoto(token).then(response => setPhoto(URL.createObjectURL(response)));
|
||||||
|
}
|
||||||
|
}, [token]);
|
||||||
|
return photo;
|
||||||
|
}
|
||||||
75
src/hooks/useSubscriptions.tsx
Normal file
75
src/hooks/useSubscriptions.tsx
Normal file
@@ -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<Subscription[]> {
|
||||||
|
const headers = new Headers();
|
||||||
|
const bearer = `Bearer ${accessToken}`;
|
||||||
|
|
||||||
|
headers.append("Authorization", bearer);
|
||||||
|
|
||||||
|
let subscriptions: Array<Subscription> = [];
|
||||||
|
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<Subscription[]>();
|
||||||
|
|
||||||
|
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<Subscription> = [];
|
||||||
|
|
||||||
|
// 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);
|
||||||
Reference in New Issue
Block a user