mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-20 17:30:46 +00:00
MSAL 2.0 checkpoint
This commit is contained in:
@@ -16,7 +16,7 @@ body {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
:focus {
|
:focus {
|
||||||
.focus()
|
.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ body {
|
|||||||
right: 14px;
|
right: 14px;
|
||||||
border-width: 0 9px 9px;
|
border-width: 0 9px 9px;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: #FFF rgba(0, 0, 0, 0);
|
border-color: #fff rgba(0, 0, 0, 0);
|
||||||
display: block;
|
display: block;
|
||||||
width: 0;
|
width: 0;
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,6 @@ body {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
|
|
||||||
.urlContainer {
|
.urlContainer {
|
||||||
margin-left: @DefaultSpace;
|
margin-left: @DefaultSpace;
|
||||||
|
|
||||||
@@ -179,7 +178,8 @@ body {
|
|||||||
.active();
|
.active();
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus .urlTokenCopyTooltiptext, &:focus .urlTokenCopyTooltiptext {
|
&:focus .urlTokenCopyTooltiptext,
|
||||||
|
&:focus .urlTokenCopyTooltiptext {
|
||||||
.tooltipVisible();
|
.tooltipVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,7 +217,7 @@ body {
|
|||||||
|
|
||||||
.shareLink {
|
.shareLink {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
background-color: #FFFFFF;
|
background-color: #ffffff;
|
||||||
border: 1px solid @BaseMedium;
|
border: 1px solid @BaseMedium;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
@@ -722,7 +722,8 @@ stored-procedure-tab {
|
|||||||
@ToggleHeight: 30px;
|
@ToggleHeight: 30px;
|
||||||
@ToggleWidth: 180px;
|
@ToggleWidth: 180px;
|
||||||
|
|
||||||
.results-container, .errors-container {
|
.results-container,
|
||||||
|
.errors-container {
|
||||||
padding: @MediumSpace 0px 0px @MediumSpace;
|
padding: @MediumSpace 0px 0px @MediumSpace;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
.flex-display();
|
.flex-display();
|
||||||
@@ -934,19 +935,19 @@ menuQuickStart {
|
|||||||
.content {
|
.content {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
transition: all .4s ease-in-out;
|
transition: all 0.4s ease-in-out;
|
||||||
-ms-transition: all .4s ease-in-out;
|
-ms-transition: all 0.4s ease-in-out;
|
||||||
-webkit-transition: all .4s ease-in-out;
|
-webkit-transition: all 0.4s ease-in-out;
|
||||||
-moz-transition: all .4s ease-in-out;
|
-moz-transition: all 0.4s ease-in-out;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mini {
|
.mini {
|
||||||
width: 0%;
|
width: 0%;
|
||||||
float: left;
|
float: left;
|
||||||
transition: all .4s ease-in-out;
|
transition: all 0.4s ease-in-out;
|
||||||
-webkit-transition: all .4s ease-in-out;
|
-webkit-transition: all 0.4s ease-in-out;
|
||||||
-moz-transition: all .4s ease-in-out;
|
-moz-transition: all 0.4s ease-in-out;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
}
|
}
|
||||||
@@ -1097,7 +1098,7 @@ menuQuickStart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#tbodycontent > tr > td {
|
#tbodycontent > tr > td {
|
||||||
border-bottom: 1px solid #CCCCCC;
|
border-bottom: 1px solid #cccccc;
|
||||||
border-top: none;
|
border-top: none;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
}
|
}
|
||||||
@@ -1205,7 +1206,7 @@ menuQuickStart {
|
|||||||
|
|
||||||
.gridRowSelected:hover {
|
.gridRowSelected:hover {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
.hover()
|
.hover();
|
||||||
}
|
}
|
||||||
|
|
||||||
.gridRowHighlighted {
|
.gridRowHighlighted {
|
||||||
@@ -1240,7 +1241,7 @@ menuQuickStart {
|
|||||||
border-top: 1px solid #eee;
|
border-top: 1px solid #eee;
|
||||||
margin-left: -17px;
|
margin-left: -17px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
color: 1px solid #53575B;
|
color: 1px solid #53575b;
|
||||||
}
|
}
|
||||||
|
|
||||||
.partitioning-btn {
|
.partitioning-btn {
|
||||||
@@ -1308,7 +1309,7 @@ menuQuickStart {
|
|||||||
|
|
||||||
.collid-white {
|
.collid-white {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: solid 1px #DDD;
|
border: solid 1px #ddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plusimg-but {
|
.plusimg-but {
|
||||||
@@ -1631,7 +1632,6 @@ p {
|
|||||||
margin-left: -32px;
|
margin-left: -32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Variant of paddingspan3 without the margins */
|
/* Variant of paddingspan3 without the margins */
|
||||||
|
|
||||||
.contextual-pane .paddingspan3b {
|
.contextual-pane .paddingspan3b {
|
||||||
@@ -1644,7 +1644,7 @@ p {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.contextual-pane hr {
|
.contextual-pane hr {
|
||||||
border: 1px solid #53575B;
|
border: 1px solid #53575b;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1818,11 +1818,11 @@ label {
|
|||||||
|
|
||||||
.datalist-arrow:focus:after,
|
.datalist-arrow:focus:after,
|
||||||
.datalist-arrow:active:after {
|
.datalist-arrow:active:after {
|
||||||
background: #1EBBEE;
|
background: #1ebbee;
|
||||||
}
|
}
|
||||||
|
|
||||||
input::-webkit-calendar-picker-indicator::after {
|
input::-webkit-calendar-picker-indicator::after {
|
||||||
content: '\276F';
|
content: "\276F";
|
||||||
right: 0;
|
right: 0;
|
||||||
top: -8%;
|
top: -8%;
|
||||||
display: block;
|
display: block;
|
||||||
@@ -1836,7 +1836,7 @@ input::-webkit-calendar-picker-indicator::after {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.datalist-arrow:after:hover {
|
.datalist-arrow:after:hover {
|
||||||
content: '\276F';
|
content: "\276F";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 1px;
|
right: 1px;
|
||||||
top: 6%;
|
top: 6%;
|
||||||
@@ -1848,7 +1848,7 @@ input::-webkit-calendar-picker-indicator::after {
|
|||||||
color: #fff;
|
color: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
background-color: #1EBBEE;
|
background-color: #1ebbee;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Introline3 {
|
.Introline3 {
|
||||||
@@ -1912,7 +1912,7 @@ input::-webkit-calendar-picker-indicator::after {
|
|||||||
|
|
||||||
.nav-tabs-margin {
|
.nav-tabs-margin {
|
||||||
padding-top: 8px;
|
padding-top: 8px;
|
||||||
background-color: #F2F2F2;
|
background-color: #f2f2f2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navTabHeight {
|
.navTabHeight {
|
||||||
@@ -1978,7 +1978,7 @@ input::-webkit-calendar-picker-indicator::after {
|
|||||||
.atags {
|
.atags {
|
||||||
color: @AccentMediumHigh;
|
color: @AccentMediumHigh;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
cursor: pointer
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.qsmenuicons {
|
.qsmenuicons {
|
||||||
@@ -2218,7 +2218,7 @@ a:link {
|
|||||||
.documentsGridHeaderContainer {
|
.documentsGridHeaderContainer {
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-bottom: 1px solid #CCCCCC;
|
border-bottom: 1px solid #cccccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.documentsGridHeaderContainer > table {
|
.documentsGridHeaderContainer > table {
|
||||||
@@ -2234,7 +2234,7 @@ a:link {
|
|||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
background-color: #fff !important;
|
background-color: #fff !important;
|
||||||
border-bottom: 1px solid #CCCCCC !important;
|
border-bottom: 1px solid #cccccc !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2383,7 +2383,7 @@ a:link {
|
|||||||
color: #393939;
|
color: #393939;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab [type=radio] {
|
.tab [type="radio"] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2395,40 +2395,40 @@ a:link {
|
|||||||
padding: @MediumSpace 0px;
|
padding: @MediumSpace 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab [type=radio]:checked~label {
|
.tab [type="radio"]:checked ~ label {
|
||||||
border: 1px solid #0072c6;
|
border: 1px solid #0072c6;
|
||||||
background-color: @AccentMediumHigh;
|
background-color: @AccentMediumHigh;
|
||||||
color: white;
|
color: white;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab [type=radio]:checked~label:hover {
|
.tab [type="radio"]:checked ~ label:hover {
|
||||||
border: 1px solid @AccentMediumHigh;
|
border: 1px solid @AccentMediumHigh;
|
||||||
background-color: @AccentMediumHigh;
|
background-color: @AccentMediumHigh;
|
||||||
color: white;
|
color: white;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab [type=radio]:checked~label:active {
|
.tab [type="radio"]:checked ~ label:active {
|
||||||
border: 1px solid #0072c6;
|
border: 1px solid #0072c6;
|
||||||
background-color: #0072c6;
|
background-color: #0072c6;
|
||||||
color: white;
|
color: white;
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab [type=radio]:checked~label~.tabcontent {
|
.tab [type="radio"]:checked ~ label ~ .tabcontent {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
display: initial;
|
display: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab [type=radio]:not(:checked)~label:hover {
|
.tab [type="radio"]:not(:checked) ~ label:hover {
|
||||||
border: 1px solid #969696;
|
border: 1px solid #969696;
|
||||||
background-color: #969696;
|
background-color: #969696;
|
||||||
color: white;
|
color: white;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab [type=radio]:not(:checked)~label~.tabcontent {
|
.tab [type="radio"]:not(:checked) ~ label ~ .tabcontent {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2732,7 +2732,7 @@ a:link {
|
|||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
flex-grow: 1
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabIconSection {
|
.tabIconSection {
|
||||||
@@ -2822,17 +2822,17 @@ a:link {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tabCommandDisabled {
|
.tabCommandDisabled {
|
||||||
color: #CCCCCC;
|
color: #cccccc;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
background-color: #FFFFFF;
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabCommandDisabled:active {
|
.tabCommandDisabled:active {
|
||||||
border: 1px solid #FFFFFF;
|
border: 1px solid #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabCommandDisabled:hover {
|
.tabCommandDisabled:hover {
|
||||||
background-color: #FFFFFF;
|
background-color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
#explorerNotificationConsole {
|
#explorerNotificationConsole {
|
||||||
@@ -2940,13 +2940,13 @@ settings-pane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.linkDarkBackground {
|
.linkDarkBackground {
|
||||||
color: @AccentExtraHigh
|
color: @AccentExtraHigh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.linkDarkBackground:hover,
|
.linkDarkBackground:hover,
|
||||||
.linkDarkBackground:active,
|
.linkDarkBackground:active,
|
||||||
.linkDarkBackground:focus {
|
.linkDarkBackground:focus {
|
||||||
color: @AccentHigh
|
color: @AccentHigh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.library-add-button {
|
.library-add-button {
|
||||||
@@ -2983,7 +2983,7 @@ settings-pane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.enableAnalyticalStorageRadioLabel {
|
.enableAnalyticalStorageRadioLabel {
|
||||||
padding: 0px
|
padding: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2993,18 +2993,18 @@ settings-pane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.button.enabled {
|
.button.enabled {
|
||||||
background: #FFF;
|
background: #fff;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
color: #323130;
|
color: #323130;
|
||||||
padding: 3px 20px;
|
padding: 3px 20px;
|
||||||
border: 1px solid #8A8886;
|
border: 1px solid #8a8886;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button.disabled {
|
.button.disabled {
|
||||||
background: #F3F2F1;
|
background: #f3f2f1;
|
||||||
border: 0px solid #8A8886;
|
border: 0px solid #8a8886;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
color: #A19F9D;
|
color: #a19f9d;
|
||||||
padding: 3px 20px;
|
padding: 3px 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3017,11 +3017,11 @@ settings-pane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.warningErrorContent a {
|
.warningErrorContent a {
|
||||||
color: @AccentMediumHigh
|
color: @AccentMediumHigh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.infoBoxContent a {
|
.infoBoxContent a {
|
||||||
color: @AccentMediumHigh
|
color: @AccentMediumHigh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.collapsibleSection :hover {
|
.collapsibleSection :hover {
|
||||||
|
|||||||
23
package-lock.json
generated
23
package-lock.json
generated
@@ -15328,6 +15328,15 @@
|
|||||||
"tinyqueue": "^1.1.0"
|
"tinyqueue": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"match-sorter": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-SDRLNlWof9GnAUEyhKP0O5525MMGXUGt+ep4MrrqQ2StAh3zjvICVZseiwg7Zijn3GazpJDiwuRr/mFDHd92NQ==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.12.5",
|
||||||
|
"remove-accents": "0.4.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"matchdep": {
|
"matchdep": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz",
|
||||||
@@ -17775,6 +17784,15 @@
|
|||||||
"warning": "^4.0.2"
|
"warning": "^4.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-query": {
|
||||||
|
"version": "3.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-query/-/react-query-3.5.5.tgz",
|
||||||
|
"integrity": "sha512-WYZcHcAs5K5lPGT6CI8fz3lU62S8IfZhvB1K4aZH27wg9T6CWei+y7IRyZwti9X18LX134O4olgEuNth9LEX+w==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime": "^7.5.5",
|
||||||
|
"match-sorter": "^6.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-redux": {
|
"react-redux": {
|
||||||
"version": "7.1.3",
|
"version": "7.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.1.3.tgz",
|
||||||
@@ -18167,6 +18185,11 @@
|
|||||||
"superagent-proxy": "^2.0.0"
|
"superagent-proxy": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"remove-accents": {
|
||||||
|
"version": "0.4.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz",
|
||||||
|
"integrity": "sha1-CkPTqq4egNuRngeuJUsoXZ4ce7U="
|
||||||
|
},
|
||||||
"remove-trailing-separator": {
|
"remove-trailing-separator": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
|
||||||
|
|||||||
@@ -85,6 +85,7 @@
|
|||||||
"react-dom": "16.9.0",
|
"react-dom": "16.9.0",
|
||||||
"react-hotkeys": "2.0.0",
|
"react-hotkeys": "2.0.0",
|
||||||
"react-notification-system": "0.2.17",
|
"react-notification-system": "0.2.17",
|
||||||
|
"react-query": "3.5.5",
|
||||||
"react-redux": "7.1.3",
|
"react-redux": "7.1.3",
|
||||||
"redux": "4.0.4",
|
"redux": "4.0.4",
|
||||||
"rx-jupyter": "5.5.12",
|
"rx-jupyter": "5.5.12",
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { AuthType } from "../../../AuthType";
|
|
||||||
import { StyleConstants } from "../../../Common/Constants";
|
import { StyleConstants } from "../../../Common/Constants";
|
||||||
import { DatabaseAccount, Subscription } from "../../../Contracts/DataModels";
|
import { DatabaseAccount, Subscription } from "../../../Contracts/DataModels";
|
||||||
|
|
||||||
@@ -6,39 +5,21 @@ import * as React from "react";
|
|||||||
import { DefaultButton, IButtonStyles, IButtonProps } from "office-ui-fabric-react/lib/Button";
|
import { DefaultButton, IButtonStyles, IButtonProps } from "office-ui-fabric-react/lib/Button";
|
||||||
import { IContextualMenuProps } from "office-ui-fabric-react/lib/ContextualMenu";
|
import { IContextualMenuProps } from "office-ui-fabric-react/lib/ContextualMenu";
|
||||||
import { Dropdown, IDropdownOption, IDropdownProps } from "office-ui-fabric-react/lib/Dropdown";
|
import { Dropdown, IDropdownOption, IDropdownProps } from "office-ui-fabric-react/lib/Dropdown";
|
||||||
|
import { useSubscriptions } from "../../../hooks/useSubscriptions";
|
||||||
|
|
||||||
export interface AccountSwitchComponentProps {
|
export const AccountSwitchComponent: React.FunctionComponent = () => {
|
||||||
authType: AuthType;
|
const subscriptions = useSubscriptions();
|
||||||
selectedAccountName: string;
|
|
||||||
accounts: DatabaseAccount[];
|
|
||||||
isLoadingAccounts: boolean;
|
|
||||||
onAccountChange: (newAccount: DatabaseAccount) => void;
|
|
||||||
selectedSubscriptionId: string;
|
|
||||||
subscriptions: Subscription[];
|
|
||||||
isLoadingSubscriptions: boolean;
|
|
||||||
onSubscriptionChange: (newSubscription: Subscription) => void;
|
|
||||||
displayText?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class AccountSwitchComponent extends React.Component<AccountSwitchComponentProps> {
|
|
||||||
public render(): JSX.Element {
|
|
||||||
return this.props.authType === AuthType.AAD ? this._renderSwitchDropDown() : this._renderAccountName();
|
|
||||||
}
|
|
||||||
|
|
||||||
private _renderSwitchDropDown(): JSX.Element {
|
|
||||||
const { displayText, selectedAccountName } = this.props;
|
|
||||||
|
|
||||||
const menuProps: IContextualMenuProps = {
|
const menuProps: IContextualMenuProps = {
|
||||||
directionalHintFixed: true,
|
directionalHintFixed: true,
|
||||||
className: "accountSwitchContextualMenu",
|
className: "accountSwitchContextualMenu",
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
key: "switchSubscription",
|
key: "switchSubscription",
|
||||||
onRender: this._renderSubscriptionDropdown.bind(this)
|
onRender: () => renderSubscriptionDropdown(subscriptions)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "switchAccount",
|
key: "switchAccount",
|
||||||
onRender: this._renderAccountDropDown.bind(this)
|
onRender: renderAccountDropDown
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
@@ -75,7 +56,7 @@ export class AccountSwitchComponent extends React.Component<AccountSwitchCompone
|
|||||||
};
|
};
|
||||||
|
|
||||||
const buttonProps: IButtonProps = {
|
const buttonProps: IButtonProps = {
|
||||||
text: displayText || selectedAccountName,
|
text: "foo",
|
||||||
menuProps: menuProps,
|
menuProps: menuProps,
|
||||||
styles: buttonStyles,
|
styles: buttonStyles,
|
||||||
className: "accountSwitchButton",
|
className: "accountSwitchButton",
|
||||||
@@ -83,10 +64,12 @@ export class AccountSwitchComponent extends React.Component<AccountSwitchCompone
|
|||||||
};
|
};
|
||||||
|
|
||||||
return <DefaultButton {...buttonProps} />;
|
return <DefaultButton {...buttonProps} />;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
function renderSubscriptionDropdown(subscriptions: Subscription[]): JSX.Element {
|
||||||
|
const selectedSubscriptionId = "";
|
||||||
|
const isLoadingSubscriptions = false;
|
||||||
|
|
||||||
private _renderSubscriptionDropdown(): JSX.Element {
|
|
||||||
const { subscriptions, selectedSubscriptionId, isLoadingSubscriptions } = this.props;
|
|
||||||
const options: IDropdownOption[] = subscriptions.map(sub => {
|
const options: IDropdownOption[] = subscriptions.map(sub => {
|
||||||
return {
|
return {
|
||||||
key: sub.subscriptionId,
|
key: sub.subscriptionId,
|
||||||
@@ -105,7 +88,7 @@ export class AccountSwitchComponent extends React.Component<AccountSwitchCompone
|
|||||||
label: "Subscription",
|
label: "Subscription",
|
||||||
className: "accountSwitchSubscriptionDropdown",
|
className: "accountSwitchSubscriptionDropdown",
|
||||||
options: options,
|
options: options,
|
||||||
onChange: this._onSubscriptionDropdownChange,
|
onChange: () => {},
|
||||||
defaultSelectedKey: selectedSubscriptionId,
|
defaultSelectedKey: selectedSubscriptionId,
|
||||||
placeholder: placeHolderText,
|
placeholder: placeHolderText,
|
||||||
styles: {
|
styles: {
|
||||||
@@ -116,16 +99,10 @@ export class AccountSwitchComponent extends React.Component<AccountSwitchCompone
|
|||||||
return <Dropdown {...dropdownProps} />;
|
return <Dropdown {...dropdownProps} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _onSubscriptionDropdownChange = (e: React.FormEvent<HTMLDivElement>, option: IDropdownOption): void => {
|
function renderAccountDropDown(): JSX.Element {
|
||||||
if (!option) {
|
const accounts = [];
|
||||||
return;
|
const selectedAccountName = "foo";
|
||||||
}
|
const isLoadingAccounts = false;
|
||||||
|
|
||||||
this.props.onSubscriptionChange(option.data);
|
|
||||||
};
|
|
||||||
|
|
||||||
private _renderAccountDropDown(): JSX.Element {
|
|
||||||
const { accounts, selectedAccountName, isLoadingAccounts } = this.props;
|
|
||||||
const options: IDropdownOption[] = accounts.map(account => {
|
const options: IDropdownOption[] = accounts.map(account => {
|
||||||
return {
|
return {
|
||||||
key: account.name,
|
key: account.name,
|
||||||
@@ -151,7 +128,7 @@ export class AccountSwitchComponent extends React.Component<AccountSwitchCompone
|
|||||||
label: "Cosmos DB Account Name",
|
label: "Cosmos DB Account Name",
|
||||||
className: "accountSwitchAccountDropdown",
|
className: "accountSwitchAccountDropdown",
|
||||||
options: options,
|
options: options,
|
||||||
onChange: this._onAccountDropdownChange,
|
onChange: () => {},
|
||||||
defaultSelectedKey: selectedAccountName,
|
defaultSelectedKey: selectedAccountName,
|
||||||
placeholder: placeHolderText,
|
placeholder: placeHolderText,
|
||||||
styles: {
|
styles: {
|
||||||
@@ -161,17 +138,3 @@ export class AccountSwitchComponent extends React.Component<AccountSwitchCompone
|
|||||||
|
|
||||||
return <Dropdown {...dropdownProps} />;
|
return <Dropdown {...dropdownProps} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _onAccountDropdownChange = (e: React.FormEvent<HTMLDivElement>, option: IDropdownOption): void => {
|
|
||||||
if (!option) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.props.onAccountChange(option.data);
|
|
||||||
};
|
|
||||||
|
|
||||||
private _renderAccountName(): JSX.Element {
|
|
||||||
const { displayText, selectedAccountName } = this.props;
|
|
||||||
return <span className="accountNameHeader">{displayText || selectedAccountName}</span>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Configuration, PublicClientApplication } from "@azure/msal-browser";
|
import { Configuration, PublicClientApplication } from "@azure/msal-browser";
|
||||||
import { AuthenticatedTemplate, MsalProvider, UnauthenticatedTemplate } from "@azure/msal-react";
|
import { AuthenticatedTemplate, MsalProvider, UnauthenticatedTemplate, useMsal } from "@azure/msal-react";
|
||||||
import { useBoolean } from "@uifabric/react-hooks";
|
import { useBoolean } from "@uifabric/react-hooks";
|
||||||
import {
|
import {
|
||||||
DefaultButton,
|
DefaultButton,
|
||||||
@@ -15,30 +15,51 @@ import * as React from "react";
|
|||||||
import { render } from "react-dom";
|
import { render } from "react-dom";
|
||||||
import FeedbackIcon from "../images/Feedback.svg";
|
import FeedbackIcon from "../images/Feedback.svg";
|
||||||
import ConnectIcon from "../images/HostedConnectwhite.svg";
|
import ConnectIcon from "../images/HostedConnectwhite.svg";
|
||||||
|
import ChevronRight from "../images/chevron-right.svg";
|
||||||
import "../less/hostedexplorer.less";
|
import "../less/hostedexplorer.less";
|
||||||
|
import { AccountSwitchComponent } from "./Explorer/Controls/AccountSwitch/AccountSwitchComponent";
|
||||||
import { CommandButtonComponent } from "./Explorer/Controls/CommandButton/CommandButtonComponent";
|
import { CommandButtonComponent } from "./Explorer/Controls/CommandButton/CommandButtonComponent";
|
||||||
import { DefaultDirectoryDropdownComponent } from "./Explorer/Controls/Directory/DefaultDirectoryDropdownComponent";
|
import { DefaultDirectoryDropdownComponent } from "./Explorer/Controls/Directory/DefaultDirectoryDropdownComponent";
|
||||||
import { DirectoryListComponent } from "./Explorer/Controls/Directory/DirectoryListComponent";
|
import { DirectoryListComponent } from "./Explorer/Controls/Directory/DirectoryListComponent";
|
||||||
import "./Explorer/Menus/NavBar/MeControlComponent.less";
|
import "./Explorer/Menus/NavBar/MeControlComponent.less";
|
||||||
import { useGraphProfile } from "./hooks/useGraphProfile";
|
import { useGraphPhoto } from "./hooks/useGraphPhoto";
|
||||||
|
import { ConnectScreen } from "./Platform/Hosted/ConnectScreen";
|
||||||
import "./Shared/appInsights";
|
import "./Shared/appInsights";
|
||||||
|
import { useAADAccount } from "./hooks/useAADAccount";
|
||||||
|
|
||||||
initializeIcons();
|
initializeIcons();
|
||||||
|
|
||||||
// MSAL configuration
|
// MSAL configuration
|
||||||
const configuration: Configuration = {
|
const configuration: Configuration = {
|
||||||
auth: {
|
auth: {
|
||||||
clientId: "e8ae3d28-de2a-4dc8-8fa3-2d2998b1c38f",
|
clientId: "203f1145-856a-4232-83d4-a43568fba23d",
|
||||||
redirectUri: "https://localhost:1234/hostedExplorer.html",
|
redirectUri: "https://localhost:1234/hostedExplorer.html",
|
||||||
authority: "https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47"
|
authority: "https://login.windows-ppe.net/common"
|
||||||
|
},
|
||||||
|
cache: {
|
||||||
|
cacheLocation: "sessionStorage",
|
||||||
|
storeAuthStateInCookie: false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// const configuration: Configuration = {
|
||||||
|
// auth: {
|
||||||
|
// clientId: "b4d07291-7936-4c8e-b413-f58b6d1c67e8",
|
||||||
|
// redirectUri: "https://localhost:1234/hostedExplorer.html",
|
||||||
|
// authority: "https://login.microsoftonline.com/907765e9-1846-4d84-ad7f-a2f5030ef5ba"
|
||||||
|
// },
|
||||||
|
// cache: {
|
||||||
|
// cacheLocation: "sessionStorage"
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
const application = new PublicClientApplication(configuration);
|
const application = new PublicClientApplication(configuration);
|
||||||
|
|
||||||
const App: React.FunctionComponent = () => {
|
const App: React.FunctionComponent = () => {
|
||||||
const [isOpen, { setTrue: openPanel, setFalse: dismissPanel }] = useBoolean(false);
|
const [isOpen, { setTrue: openPanel, setFalse: dismissPanel }] = useBoolean(false);
|
||||||
const { graphData, photo } = useGraphProfile();
|
const { instance } = useMsal();
|
||||||
|
const account = useAADAccount();
|
||||||
|
const photo = useGraphPhoto();
|
||||||
|
|
||||||
const menuProps = {
|
const menuProps = {
|
||||||
className: "mecontrolContextualMenu",
|
className: "mecontrolContextualMenu",
|
||||||
@@ -123,23 +144,18 @@ const App: React.FunctionComponent = () => {
|
|||||||
<div className="cosmosDBTitle">
|
<div className="cosmosDBTitle">
|
||||||
<span
|
<span
|
||||||
className="title"
|
className="title"
|
||||||
data-bind="click: openAzurePortal, event: { keypress: onOpenAzurePortalKeyPress }"
|
onClick={() => window.open("https://portal.azure.com", "_blank")}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
title="Go to Azure Portal"
|
title="Go to Azure Portal"
|
||||||
>
|
>
|
||||||
Microsoft Azure
|
Microsoft Azure
|
||||||
</span>
|
</span>
|
||||||
<span className="accontSplitter" /> <span className="serviceTitle">Cosmos DB</span>
|
<span className="accontSplitter" /> <span className="serviceTitle">Cosmos DB</span>
|
||||||
<img
|
<img className="chevronRight" src={ChevronRight} alt="account separator" />
|
||||||
className="chevronRight"
|
<span className="accountSwitchComponentContainer">
|
||||||
src="/chevron-right.svg"
|
{/* <AccountSwitchComponent /> */}
|
||||||
alt="account separator"
|
<span className="accountNameHeader">REPLACE ME - Connection string mode</span>;
|
||||||
data-bind="visible: isAccountActive"
|
</span>
|
||||||
/>
|
|
||||||
<span
|
|
||||||
className="accountSwitchComponentContainer"
|
|
||||||
data-bind="react: accountSwitchComponentAdapter, visible: isAccountActive"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="feedbackConnectSettingIcons">
|
<div className="feedbackConnectSettingIcons">
|
||||||
<AuthenticatedTemplate>
|
<AuthenticatedTemplate>
|
||||||
@@ -177,8 +193,8 @@ const App: React.FunctionComponent = () => {
|
|||||||
<DefaultButton {...buttonProps}>
|
<DefaultButton {...buttonProps}>
|
||||||
<Persona
|
<Persona
|
||||||
imageUrl={photo}
|
imageUrl={photo}
|
||||||
text={graphData?.displayName}
|
text={account?.name}
|
||||||
secondaryText={graphData?.displayName}
|
secondaryText={account?.username}
|
||||||
showSecondaryText={true}
|
showSecondaryText={true}
|
||||||
showInitialsUntilImageLoads={true}
|
showInitialsUntilImageLoads={true}
|
||||||
initialsColor={PersonaInitialsColor.teal}
|
initialsColor={PersonaInitialsColor.teal}
|
||||||
@@ -193,7 +209,10 @@ const App: React.FunctionComponent = () => {
|
|||||||
className="mecontrolSigninButton"
|
className="mecontrolSigninButton"
|
||||||
text="Sign In"
|
text="Sign In"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
instance.loginPopup();
|
instance.loginPopup({
|
||||||
|
scopes: ["https://graph.microsoft-ppe.com/" + "/.default"],
|
||||||
|
redirectUri: "https://localhost:1234/hostedExplorer.html"
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
styles={{
|
styles={{
|
||||||
rootHovered: { backgroundColor: "#393939", color: "#fff" },
|
rootHovered: { backgroundColor: "#393939", color: "#fff" },
|
||||||
@@ -205,30 +224,30 @@ const App: React.FunctionComponent = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
<AuthenticatedTemplate>
|
||||||
|
<p>LOGGED IN!</p>
|
||||||
{/* <iframe
|
{/* <iframe
|
||||||
id="explorerMenu"
|
id="explorerMenu"
|
||||||
name="explorer"
|
name="explorer"
|
||||||
className="iframe"
|
className="iframe"
|
||||||
title="explorer"
|
title="explorer"
|
||||||
src="explorer.html?v=1.0.1&platform=Hosted"
|
src="explorer.html?v=1.0.1&platform=Portal"
|
||||||
data-bind="visible: navigationSelection() === 'explorer'"
|
|
||||||
></iframe> */}
|
></iframe> */}
|
||||||
|
</AuthenticatedTemplate>
|
||||||
|
<UnauthenticatedTemplate>
|
||||||
|
<ConnectScreen />
|
||||||
|
</UnauthenticatedTemplate>
|
||||||
|
<ConnectScreen />
|
||||||
<div data-bind="react: firewallWarningComponentAdapter" />
|
<div data-bind="react: firewallWarningComponentAdapter" />
|
||||||
<div data-bind="react: dialogComponentAdapter" />
|
<div data-bind="react: dialogComponentAdapter" />
|
||||||
<Panel
|
<Panel headerText="Select Directory" isOpen={isOpen} onDismiss={dismissPanel} closeButtonAriaLabel="Close">
|
||||||
headerText="Select Directory"
|
{/* <div className="directoryDropdownContainer">
|
||||||
isOpen={!isOpen}
|
|
||||||
onDismiss={dismissPanel}
|
|
||||||
// You MUST provide this prop! Otherwise screen readers will just say "button" with no label.
|
|
||||||
closeButtonAriaLabel="Close"
|
|
||||||
>
|
|
||||||
<div className="directoryDropdownContainer">
|
|
||||||
<DefaultDirectoryDropdownComponent />
|
<DefaultDirectoryDropdownComponent />
|
||||||
</div>
|
</div>
|
||||||
<div className="directoryDivider" />
|
<div className="directoryDivider" />
|
||||||
<div className="directoryListContainer">
|
<div className="directoryListContainer">
|
||||||
<DirectoryListComponent />
|
<DirectoryListComponent />
|
||||||
</div>
|
</div> */}
|
||||||
</Panel>
|
</Panel>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { configContext } from "../../ConfigContext";
|
|||||||
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
|
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
|
||||||
|
|
||||||
// TODO: 421864 - add a fetch wrapper
|
// TODO: 421864 - add a fetch wrapper
|
||||||
export abstract class ArmResourceUtils {
|
export class ArmResourceUtils {
|
||||||
private static readonly _armEndpoint: string = configContext.ARM_ENDPOINT;
|
private static readonly _armEndpoint: string = configContext.ARM_ENDPOINT;
|
||||||
private static readonly _armApiVersion: string = configContext.ARM_API_VERSION;
|
private static readonly _armApiVersion: string = configContext.ARM_API_VERSION;
|
||||||
private static readonly _armAuthArea: string = configContext.ARM_AUTH_AREA;
|
private static readonly _armAuthArea: string = configContext.ARM_AUTH_AREA;
|
||||||
|
|||||||
@@ -20,20 +20,7 @@ export default class AuthHeadersUtil {
|
|||||||
private static readonly _graphEndpoint: string = configContext.GRAPH_ENDPOINT;
|
private static readonly _graphEndpoint: string = configContext.GRAPH_ENDPOINT;
|
||||||
private static readonly _graphApiVersion: string = configContext.GRAPH_API_VERSION;
|
private static readonly _graphApiVersion: string = configContext.GRAPH_API_VERSION;
|
||||||
|
|
||||||
private static _authContext: AuthenticationContext = new AuthenticationContext({
|
private static _authContext: any = {};
|
||||||
instance: AuthHeadersUtil._aadEndpoint,
|
|
||||||
clientId: AuthHeadersUtil._firstPartyAppId,
|
|
||||||
postLogoutRedirectUri: window.location.origin,
|
|
||||||
endpoints: {
|
|
||||||
aad: AuthHeadersUtil._aadEndpoint,
|
|
||||||
graph: AuthHeadersUtil._graphEndpoint,
|
|
||||||
armAuthArea: AuthHeadersUtil._armAuthArea,
|
|
||||||
armEndpoint: AuthHeadersUtil._armEndpoint,
|
|
||||||
arcadiaEndpoint: AuthHeadersUtil._arcadiaEndpoint
|
|
||||||
},
|
|
||||||
tenant: undefined,
|
|
||||||
cacheLocation: window.navigator.userAgent.indexOf("Edge") > -1 ? "localStorage" : undefined
|
|
||||||
});
|
|
||||||
|
|
||||||
public static getAccessInputMetadata(accessInput: string): Q.Promise<DataModels.AccessInputMetadata> {
|
public static getAccessInputMetadata(accessInput: string): Q.Promise<DataModels.AccessInputMetadata> {
|
||||||
const deferred: Q.Deferred<DataModels.AccessInputMetadata> = Q.defer<DataModels.AccessInputMetadata>();
|
const deferred: Q.Deferred<DataModels.AccessInputMetadata> = Q.defer<DataModels.AccessInputMetadata>();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useAccount, useMsal } from "@azure/msal-react";
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import { useAADToken } from "./useAADToken";
|
||||||
|
|
||||||
export async function fetchMe(accessToken: string): Promise<GraphMeResponse> {
|
export async function fetchMe(accessToken: string): Promise<ProfileResponse> {
|
||||||
const headers = new Headers();
|
const headers = new Headers();
|
||||||
const bearer = `Bearer ${accessToken}`;
|
const bearer = `Bearer ${accessToken}`;
|
||||||
|
|
||||||
@@ -12,32 +12,12 @@ export async function fetchMe(accessToken: string): Promise<GraphMeResponse> {
|
|||||||
headers: headers
|
headers: headers
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log("EXECUTING REQUEST");
|
|
||||||
return fetch("https://graph.microsoft.com/v1.0/me", options)
|
return fetch("https://graph.microsoft.com/v1.0/me", options)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.catch(error => console.log(error));
|
.catch(error => console.log(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchPhoto(accessToken: string): Promise<Blob | void> {
|
interface ProfileResponse {
|
||||||
const headers = new Headers();
|
|
||||||
const bearer = `Bearer ${accessToken}`;
|
|
||||||
|
|
||||||
headers.append("Authorization", bearer);
|
|
||||||
headers.append("Content-Type", "image/jpg");
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
method: "GET",
|
|
||||||
headers: headers
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log("EXECUTING REQUEST");
|
|
||||||
return fetch("https://graph.microsoft.com/v1.0/me/photo/$value", options)
|
|
||||||
.then(response => response.blob())
|
|
||||||
.catch(error => console.log(error));
|
|
||||||
}
|
|
||||||
|
|
||||||
interface GraphMeResponse {
|
|
||||||
businessPhones: any[];
|
|
||||||
displayName: string;
|
displayName: string;
|
||||||
givenName: string;
|
givenName: string;
|
||||||
jobTitle: string;
|
jobTitle: string;
|
||||||
@@ -50,25 +30,14 @@ interface GraphMeResponse {
|
|||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useGraphProfile(): { graphData: GraphMeResponse; photo: string } {
|
export function useGraphProfile(): ProfileResponse {
|
||||||
const { instance, accounts } = useMsal();
|
const token = useAADToken();
|
||||||
const account = useAccount(accounts[0] || {});
|
const [profileResponse, setProfileResponse] = useState<ProfileResponse>();
|
||||||
const [graphData, setGraphData] = useState<GraphMeResponse>();
|
|
||||||
const [photo, setPhoto] = useState<string>();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("account", account);
|
if (token) {
|
||||||
if (account) {
|
fetchMe(token).then(response => setProfileResponse(response));
|
||||||
instance
|
|
||||||
.acquireTokenSilent({
|
|
||||||
scopes: ["User.Read"],
|
|
||||||
account
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
fetchMe(response.accessToken).then(response => setGraphData(response));
|
|
||||||
fetchPhoto(response.accessToken).then(response => setPhoto(URL.createObjectURL(response)));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}, [account]);
|
}, [token]);
|
||||||
return { graphData, photo };
|
return profileResponse;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"downlevelIteration": true,
|
"downlevelIteration": true,
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"target": "es5",
|
"target": "es2017",
|
||||||
"lib": ["es5", "es6", "dom", "webworker.importscripts"],
|
"lib": ["es5", "es6", "dom", "webworker.importscripts"],
|
||||||
"jsx": "react",
|
"jsx": "react",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ const ModulesRule = {
|
|||||||
loader: "babel-loader",
|
loader: "babel-loader",
|
||||||
options: {
|
options: {
|
||||||
cacheDirectory: ".cache/babel",
|
cacheDirectory: ".cache/babel",
|
||||||
presets: [["@babel/preset-env", { targets: { ie: "11" }, useBuiltIns: false }]]
|
presets: [["@babel/preset-env", { targets: { chrome: "80" }, useBuiltIns: false }]]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user