mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2026-01-23 11:44:03 +00:00
Compare commits
3 Commits
codescan
...
user/swvis
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3db6276f48 | ||
|
|
bd00e5eb9b | ||
|
|
821f665e78 |
@@ -112,7 +112,6 @@ describe("endpoint", () => {
|
|||||||
|
|
||||||
describe("requestPlugin", () => {
|
describe("requestPlugin", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
delete window.dataExplorerPlatform;
|
|
||||||
resetConfigContext();
|
resetConfigContext();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ describe("GalleryCardComponent", () => {
|
|||||||
downloads: 0,
|
downloads: 0,
|
||||||
favorites: 0,
|
favorites: 0,
|
||||||
views: 0,
|
views: 0,
|
||||||
newCellId: undefined
|
newCellId: undefined,
|
||||||
|
policyViolations: undefined,
|
||||||
|
pendingScanJobIds: undefined
|
||||||
},
|
},
|
||||||
isFavorite: false,
|
isFavorite: false,
|
||||||
showDownload: true,
|
showDownload: true,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
Dropdown,
|
Dropdown,
|
||||||
FocusZone,
|
FocusZone,
|
||||||
|
FontWeights,
|
||||||
IDropdownOption,
|
IDropdownOption,
|
||||||
IPageSpecification,
|
IPageSpecification,
|
||||||
IPivotItemProps,
|
IPivotItemProps,
|
||||||
@@ -11,7 +12,8 @@ import {
|
|||||||
Pivot,
|
Pivot,
|
||||||
PivotItem,
|
PivotItem,
|
||||||
SearchBox,
|
SearchBox,
|
||||||
Stack
|
Stack,
|
||||||
|
Text
|
||||||
} from "office-ui-fabric-react";
|
} from "office-ui-fabric-react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import * as Logger from "../../../Common/Logger";
|
import * as Logger from "../../../Common/Logger";
|
||||||
@@ -151,7 +153,7 @@ export class GalleryViewerComponent extends React.Component<GalleryViewerCompone
|
|||||||
// explicitly checking if isCodeOfConductAccepted is not false, as it is initially undefined.
|
// explicitly checking if isCodeOfConductAccepted is not false, as it is initially undefined.
|
||||||
// Displaying code of conduct component on gallery load should not be the default behavior.
|
// Displaying code of conduct component on gallery load should not be the default behavior.
|
||||||
if (this.state.isCodeOfConductAccepted !== false) {
|
if (this.state.isCodeOfConductAccepted !== false) {
|
||||||
tabs.push(this.createTab(GalleryTab.Published, this.state.publishedNotebooks));
|
tabs.push(this.createPublishedNotebooksTab(GalleryTab.Published, this.state.publishedNotebooks));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,10 +199,59 @@ export class GalleryViewerComponent extends React.Component<GalleryViewerCompone
|
|||||||
private createTab(tab: GalleryTab, data: IGalleryItem[]): GalleryTabInfo {
|
private createTab(tab: GalleryTab, data: IGalleryItem[]): GalleryTabInfo {
|
||||||
return {
|
return {
|
||||||
tab,
|
tab,
|
||||||
content: this.createTabContent(data)
|
content: this.createSearchBarHeader(this.createCardsTabContent(data))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private createPublishedNotebooksTab = (tab: GalleryTab, data: IGalleryItem[]): GalleryTabInfo => {
|
||||||
|
return {
|
||||||
|
tab,
|
||||||
|
content: this.createPublishedNotebooksTabContent(data)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
private createPublishedNotebooksTabContent = (data: IGalleryItem[]): JSX.Element => {
|
||||||
|
const { published, underReview, removed } = GalleryUtils.filterPublishedNotebooks(data);
|
||||||
|
const content = (
|
||||||
|
<Stack tokens={{ childrenGap: 10 }}>
|
||||||
|
{published?.length > 0 &&
|
||||||
|
this.createPublishedNotebooksSectionContent(
|
||||||
|
undefined,
|
||||||
|
"You have successfully published the following notebook(s) to public gallery and shared with other Azure Cosmos DB users.",
|
||||||
|
this.createCardsTabContent(published)
|
||||||
|
)}
|
||||||
|
{underReview?.length > 0 &&
|
||||||
|
this.createPublishedNotebooksSectionContent(
|
||||||
|
"Under Review",
|
||||||
|
"Content of a notebook you published is currently being scanned for illegal content. It will not be available to public gallery until the review is completed (may take a few days)",
|
||||||
|
this.createCardsTabContent(underReview)
|
||||||
|
)}
|
||||||
|
{removed?.length > 0 &&
|
||||||
|
this.createPublishedNotebooksSectionContent(
|
||||||
|
"Removed",
|
||||||
|
"These notebooks were found to contain illegal content and has been taken down.",
|
||||||
|
this.createPolicyViolationsListContent(removed)
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
|
||||||
|
return this.createSearchBarHeader(content);
|
||||||
|
};
|
||||||
|
|
||||||
|
private createPublishedNotebooksSectionContent = (
|
||||||
|
title: string,
|
||||||
|
description: string,
|
||||||
|
content: JSX.Element
|
||||||
|
): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<Stack tokens={{ childrenGap: 5 }}>
|
||||||
|
{title && <Text styles={{ root: { fontWeight: FontWeights.semibold } }}>{title}</Text>}
|
||||||
|
{description && <Text>{description}</Text>}
|
||||||
|
{content}
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
private createPublicGalleryTabContent(data: IGalleryItem[], acceptedCodeOfConduct: boolean): JSX.Element {
|
private createPublicGalleryTabContent(data: IGalleryItem[], acceptedCodeOfConduct: boolean): JSX.Element {
|
||||||
return acceptedCodeOfConduct === false ? (
|
return acceptedCodeOfConduct === false ? (
|
||||||
<CodeOfConductComponent
|
<CodeOfConductComponent
|
||||||
@@ -210,11 +261,11 @@ export class GalleryViewerComponent extends React.Component<GalleryViewerCompone
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
this.createTabContent(data)
|
this.createSearchBarHeader(this.createCardsTabContent(data))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private createTabContent(data: IGalleryItem[]): JSX.Element {
|
private createSearchBarHeader(content: JSX.Element): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Stack tokens={{ childrenGap: 10 }}>
|
<Stack tokens={{ childrenGap: 10 }}>
|
||||||
<Stack horizontal tokens={{ childrenGap: 20, padding: 10 }}>
|
<Stack horizontal tokens={{ childrenGap: 20, padding: 10 }}>
|
||||||
@@ -233,7 +284,7 @@ export class GalleryViewerComponent extends React.Component<GalleryViewerCompone
|
|||||||
</Stack.Item>
|
</Stack.Item>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
{data && this.createCardsTabContent(data)}
|
<Stack.Item>{content}</Stack.Item>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -251,6 +302,25 @@ export class GalleryViewerComponent extends React.Component<GalleryViewerCompone
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private createPolicyViolationsListContent(data: IGalleryItem[]): JSX.Element {
|
||||||
|
return (
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Policy violations</th>
|
||||||
|
</tr>
|
||||||
|
{data.map(item => (
|
||||||
|
<tr key={`policy-violations-tr-${item.id}`}>
|
||||||
|
<td>{item.name}</td>
|
||||||
|
<td>{item.policyViolations.join(", ")}</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private loadTabContent(tab: GalleryTab, searchText: string, sortBy: SortBy, offline: boolean): void {
|
private loadTabContent(tab: GalleryTab, searchText: string, sortBy: SortBy, offline: boolean): void {
|
||||||
switch (tab) {
|
switch (tab) {
|
||||||
case GalleryTab.OfficialSamples:
|
case GalleryTab.OfficialSamples:
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export class InfoComponent extends React.Component<InfoComponentProps> {
|
|||||||
<Stack.Item>
|
<Stack.Item>
|
||||||
{this.getInfoPanel("KnowledgeArticle", "Microsoft Terms of Use", CodeOfConductEndpoints.termsOfUse)}
|
{this.getInfoPanel("KnowledgeArticle", "Microsoft Terms of Use", CodeOfConductEndpoints.termsOfUse)}
|
||||||
</Stack.Item>
|
</Stack.Item>
|
||||||
{this.props.onReportAbuseClick !== undefined && (
|
{this.props.onReportAbuseClick && (
|
||||||
<Stack.Item>
|
<Stack.Item>
|
||||||
{this.getInfoPanel("ReportHacked", "Report Abuse", undefined, () => this.props.onReportAbuseClick())}
|
{this.getInfoPanel("ReportHacked", "Report Abuse", undefined, () => this.props.onReportAbuseClick())}
|
||||||
</Stack.Item>
|
</Stack.Item>
|
||||||
|
|||||||
@@ -81,6 +81,21 @@ exports[`GalleryViewerComponent renders 1`] = `
|
|||||||
<InfoComponent />
|
<InfoComponent />
|
||||||
</StackItem>
|
</StackItem>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
<StackItem>
|
||||||
|
<FocusZone
|
||||||
|
direction={2}
|
||||||
|
isCircularNavigation={false}
|
||||||
|
shouldRaiseClicks={true}
|
||||||
|
>
|
||||||
|
<List
|
||||||
|
getPageSpecification={[Function]}
|
||||||
|
onRenderCell={[Function]}
|
||||||
|
renderedWindowsAhead={3}
|
||||||
|
renderedWindowsBehind={2}
|
||||||
|
startIndex={0}
|
||||||
|
/>
|
||||||
|
</FocusZone>
|
||||||
|
</StackItem>
|
||||||
</Stack>
|
</Stack>
|
||||||
</PivotItem>
|
</PivotItem>
|
||||||
</StyledPivotBase>
|
</StyledPivotBase>
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ describe("NotebookMetadataComponent", () => {
|
|||||||
downloads: 0,
|
downloads: 0,
|
||||||
favorites: 0,
|
favorites: 0,
|
||||||
views: 0,
|
views: 0,
|
||||||
newCellId: undefined
|
newCellId: undefined,
|
||||||
|
policyViolations: undefined,
|
||||||
|
pendingScanJobIds: undefined
|
||||||
},
|
},
|
||||||
isFavorite: false,
|
isFavorite: false,
|
||||||
downloadButtonText: "Download",
|
downloadButtonText: "Download",
|
||||||
@@ -48,7 +50,9 @@ describe("NotebookMetadataComponent", () => {
|
|||||||
downloads: 0,
|
downloads: 0,
|
||||||
favorites: 0,
|
favorites: 0,
|
||||||
views: 0,
|
views: 0,
|
||||||
newCellId: undefined
|
newCellId: undefined,
|
||||||
|
policyViolations: undefined,
|
||||||
|
pendingScanJobIds: undefined
|
||||||
},
|
},
|
||||||
isFavorite: true,
|
isFavorite: true,
|
||||||
downloadButtonText: "Download",
|
downloadButtonText: "Download",
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { container, collection } from "../TestUtils";
|
|||||||
import { ThroughputInputAutoPilotV3Component } from "./ThroughputInputComponents/ThroughputInputAutoPilotV3Component";
|
import { ThroughputInputAutoPilotV3Component } from "./ThroughputInputComponents/ThroughputInputAutoPilotV3Component";
|
||||||
import Explorer from "../../../Explorer";
|
import Explorer from "../../../Explorer";
|
||||||
import * as Constants from "../../../../Common/Constants";
|
import * as Constants from "../../../../Common/Constants";
|
||||||
import { PlatformType } from "../../../../PlatformType";
|
|
||||||
import * as DataModels from "../../../../Contracts/DataModels";
|
import * as DataModels from "../../../../Contracts/DataModels";
|
||||||
import { throughputUnit } from "../SettingsRenderUtils";
|
import { throughputUnit } from "../SettingsRenderUtils";
|
||||||
import * as SharedConstants from "../../../../Shared/Constants";
|
import * as SharedConstants from "../../../../Shared/Constants";
|
||||||
@@ -13,7 +12,6 @@ import ko from "knockout";
|
|||||||
|
|
||||||
describe("ScaleComponent", () => {
|
describe("ScaleComponent", () => {
|
||||||
const nonNationalCloudContainer = new Explorer();
|
const nonNationalCloudContainer = new Explorer();
|
||||||
nonNationalCloudContainer.getPlatformType = () => PlatformType.Portal;
|
|
||||||
nonNationalCloudContainer.isRunningOnNationalCloud = () => false;
|
nonNationalCloudContainer.isRunningOnNationalCloud = () => false;
|
||||||
|
|
||||||
const targetThroughput = 6000;
|
const targetThroughput = 6000;
|
||||||
@@ -119,7 +117,7 @@ describe("ScaleComponent", () => {
|
|||||||
|
|
||||||
it("getThroughputTitle", () => {
|
it("getThroughputTitle", () => {
|
||||||
let scaleComponent = new ScaleComponent(baseProps);
|
let scaleComponent = new ScaleComponent(baseProps);
|
||||||
expect(scaleComponent.getThroughputTitle()).toEqual("Throughput (6,000 - 40,000 RU/s)");
|
expect(scaleComponent.getThroughputTitle()).toEqual("Throughput (6,000 - unlimited RU/s)");
|
||||||
|
|
||||||
let newProps = { ...baseProps, container: nonNationalCloudContainer };
|
let newProps = { ...baseProps, container: nonNationalCloudContainer };
|
||||||
scaleComponent = new ScaleComponent(newProps);
|
scaleComponent = new ScaleComponent(newProps);
|
||||||
@@ -132,7 +130,7 @@ describe("ScaleComponent", () => {
|
|||||||
|
|
||||||
it("canThroughputExceedMaximumValue", () => {
|
it("canThroughputExceedMaximumValue", () => {
|
||||||
let scaleComponent = new ScaleComponent(baseProps);
|
let scaleComponent = new ScaleComponent(baseProps);
|
||||||
expect(scaleComponent.canThroughputExceedMaximumValue()).toEqual(false);
|
expect(scaleComponent.canThroughputExceedMaximumValue()).toEqual(true);
|
||||||
|
|
||||||
const newProps = { ...baseProps, container: nonNationalCloudContainer };
|
const newProps = { ...baseProps, container: nonNationalCloudContainer };
|
||||||
scaleComponent = new ScaleComponent(newProps);
|
scaleComponent = new ScaleComponent(newProps);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import * as ViewModels from "../../../../Contracts/ViewModels";
|
|||||||
import * as DataModels from "../../../../Contracts/DataModels";
|
import * as DataModels from "../../../../Contracts/DataModels";
|
||||||
import * as SharedConstants from "../../../../Shared/Constants";
|
import * as SharedConstants from "../../../../Shared/Constants";
|
||||||
import Explorer from "../../../Explorer";
|
import Explorer from "../../../Explorer";
|
||||||
import { PlatformType } from "../../../../PlatformType";
|
|
||||||
import {
|
import {
|
||||||
getTextFieldStyles,
|
getTextFieldStyles,
|
||||||
subComponentStackProps,
|
subComponentStackProps,
|
||||||
@@ -78,7 +77,7 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
public getMaxRUThroughputInputLimit = (): number => {
|
public getMaxRUThroughputInputLimit = (): number => {
|
||||||
if (this.props.container?.getPlatformType() === PlatformType.Hosted && this.props.collection.partitionKey) {
|
if (configContext.platform === Platform.Hosted && this.props.collection.partitionKey) {
|
||||||
return SharedConstants.CollectionCreation.DefaultCollectionRUs1Million;
|
return SharedConstants.CollectionCreation.DefaultCollectionRUs1Million;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,8 +99,7 @@ export class ScaleComponent extends React.Component<ScaleComponentProps> {
|
|||||||
|
|
||||||
public canThroughputExceedMaximumValue = (): boolean => {
|
public canThroughputExceedMaximumValue = (): boolean => {
|
||||||
const isPublicAzurePortal: boolean =
|
const isPublicAzurePortal: boolean =
|
||||||
this.props.container.getPlatformType() === PlatformType.Portal &&
|
configContext.platform === Platform.Portal && !this.props.container.isRunningOnNationalCloud();
|
||||||
!this.props.container.isRunningOnNationalCloud();
|
|
||||||
const hasPartitionKey = !!this.props.collection.partitionKey;
|
const hasPartitionKey = !!this.props.collection.partitionKey;
|
||||||
|
|
||||||
return isPublicAzurePortal && hasPartitionKey;
|
return isPublicAzurePortal && hasPartitionKey;
|
||||||
|
|||||||
@@ -39,13 +39,13 @@ exports[`ScaleComponent renders with correct intiial notification 1`] = `
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ThroughputInputAutoPilotV3Component
|
<ThroughputInputAutoPilotV3Component
|
||||||
canExceedMaximumValue={false}
|
canExceedMaximumValue={true}
|
||||||
getThroughputWarningMessage={[Function]}
|
getThroughputWarningMessage={[Function]}
|
||||||
isAutoPilotSelected={false}
|
isAutoPilotSelected={false}
|
||||||
isEmulator={false}
|
isEmulator={false}
|
||||||
isEnabled={true}
|
isEnabled={true}
|
||||||
isFixed={false}
|
isFixed={false}
|
||||||
label="Throughput (6,000 - 40,000 RU/s)"
|
label="Throughput (6,000 - unlimited RU/s)"
|
||||||
maxAutoPilotThroughput={4000}
|
maxAutoPilotThroughput={4000}
|
||||||
maxAutoPilotThroughputBaseline={4000}
|
maxAutoPilotThroughputBaseline={4000}
|
||||||
maximum={40000}
|
maximum={40000}
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ import { BindingHandlersRegisterer } from "../Bindings/BindingHandlersRegisterer
|
|||||||
import { BrowseQueriesPane } from "./Panes/BrowseQueriesPane";
|
import { BrowseQueriesPane } from "./Panes/BrowseQueriesPane";
|
||||||
import { CassandraAPIDataClient, TableDataClient, TablesAPIDataClient } from "./Tables/TableDataClient";
|
import { CassandraAPIDataClient, TableDataClient, TablesAPIDataClient } from "./Tables/TableDataClient";
|
||||||
import { CommandBarComponentAdapter } from "./Menus/CommandBar/CommandBarComponentAdapter";
|
import { CommandBarComponentAdapter } from "./Menus/CommandBar/CommandBarComponentAdapter";
|
||||||
import { configContext, updateConfigContext } from "../ConfigContext";
|
import { RecommendationsAdapter } from "./Recommendations/RecommendationsAdapter";
|
||||||
|
import { configContext, Platform, updateConfigContext } from "../ConfigContext";
|
||||||
import { ConsoleData, ConsoleDataType } from "./Menus/NotificationConsole/NotificationConsoleComponent";
|
import { ConsoleData, ConsoleDataType } from "./Menus/NotificationConsole/NotificationConsoleComponent";
|
||||||
import { decryptJWTToken, getAuthorizationHeader } from "../Utils/AuthorizationUtils";
|
import { decryptJWTToken, getAuthorizationHeader } from "../Utils/AuthorizationUtils";
|
||||||
import { DefaultExperienceUtility } from "../Shared/DefaultExperienceUtility";
|
import { DefaultExperienceUtility } from "../Shared/DefaultExperienceUtility";
|
||||||
@@ -58,7 +59,6 @@ import { NotebookUtil } from "./Notebook/NotebookUtil";
|
|||||||
import { NotebookWorkspaceManager } from "../NotebookWorkspaceManager/NotebookWorkspaceManager";
|
import { NotebookWorkspaceManager } from "../NotebookWorkspaceManager/NotebookWorkspaceManager";
|
||||||
import { NotificationConsoleComponentAdapter } from "./Menus/NotificationConsole/NotificationConsoleComponentAdapter";
|
import { NotificationConsoleComponentAdapter } from "./Menus/NotificationConsole/NotificationConsoleComponentAdapter";
|
||||||
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
import * as NotificationConsoleUtils from "../Utils/NotificationConsoleUtils";
|
||||||
import { PlatformType } from "../PlatformType";
|
|
||||||
import { QueriesClient } from "../Common/QueriesClient";
|
import { QueriesClient } from "../Common/QueriesClient";
|
||||||
import { QuerySelectPane } from "./Panes/Tables/QuerySelectPane";
|
import { QuerySelectPane } from "./Panes/Tables/QuerySelectPane";
|
||||||
import { RenewAdHocAccessPane } from "./Panes/RenewAdHocAccessPane";
|
import { RenewAdHocAccessPane } from "./Panes/RenewAdHocAccessPane";
|
||||||
@@ -208,6 +208,7 @@ export default class Explorer {
|
|||||||
public isLinkInjectionEnabled: ko.Computed<boolean>;
|
public isLinkInjectionEnabled: ko.Computed<boolean>;
|
||||||
public isSettingsV2Enabled: ko.Observable<boolean>;
|
public isSettingsV2Enabled: ko.Observable<boolean>;
|
||||||
public isGitHubPaneEnabled: ko.Observable<boolean>;
|
public isGitHubPaneEnabled: ko.Observable<boolean>;
|
||||||
|
public isRecosEnabled: ko.Observable<boolean>;
|
||||||
public isPublishNotebookPaneEnabled: ko.Observable<boolean>;
|
public isPublishNotebookPaneEnabled: ko.Observable<boolean>;
|
||||||
public isCopyNotebookPaneEnabled: ko.Observable<boolean>;
|
public isCopyNotebookPaneEnabled: ko.Observable<boolean>;
|
||||||
public isHostedDataExplorerEnabled: ko.Computed<boolean>;
|
public isHostedDataExplorerEnabled: ko.Computed<boolean>;
|
||||||
@@ -262,6 +263,7 @@ export default class Explorer {
|
|||||||
private _dialogProps: ko.Observable<DialogProps>;
|
private _dialogProps: ko.Observable<DialogProps>;
|
||||||
private addSynapseLinkDialog: DialogComponentAdapter;
|
private addSynapseLinkDialog: DialogComponentAdapter;
|
||||||
private _addSynapseLinkDialogProps: ko.Observable<DialogProps>;
|
private _addSynapseLinkDialogProps: ko.Observable<DialogProps>;
|
||||||
|
private recommendationsAdapter: RecommendationsAdapter
|
||||||
|
|
||||||
private static readonly MaxNbDatabasesToAutoExpand = 5;
|
private static readonly MaxNbDatabasesToAutoExpand = 5;
|
||||||
|
|
||||||
@@ -416,6 +418,7 @@ export default class Explorer {
|
|||||||
//this.isSettingsV2Enabled = ko.computed<boolean>(() => this.isFeatureEnabled(Constants.Features.enableSettingsV2));
|
//this.isSettingsV2Enabled = ko.computed<boolean>(() => this.isFeatureEnabled(Constants.Features.enableSettingsV2));
|
||||||
this.isSettingsV2Enabled = ko.observable(false);
|
this.isSettingsV2Enabled = ko.observable(false);
|
||||||
this.isGitHubPaneEnabled = ko.observable<boolean>(false);
|
this.isGitHubPaneEnabled = ko.observable<boolean>(false);
|
||||||
|
this.isRecosEnabled = ko.observable<boolean>(false);
|
||||||
this.isPublishNotebookPaneEnabled = ko.observable<boolean>(false);
|
this.isPublishNotebookPaneEnabled = ko.observable<boolean>(false);
|
||||||
this.isCopyNotebookPaneEnabled = ko.observable<boolean>(false);
|
this.isCopyNotebookPaneEnabled = ko.observable<boolean>(false);
|
||||||
|
|
||||||
@@ -565,9 +568,7 @@ export default class Explorer {
|
|||||||
|
|
||||||
this.isHostedDataExplorerEnabled = ko.computed<boolean>(
|
this.isHostedDataExplorerEnabled = ko.computed<boolean>(
|
||||||
() =>
|
() =>
|
||||||
this.getPlatformType() === PlatformType.Portal &&
|
configContext.platform === Platform.Portal && !this.isRunningOnNationalCloud() && !this.isPreferredApiGraph()
|
||||||
!this.isRunningOnNationalCloud() &&
|
|
||||||
!this.isPreferredApiGraph()
|
|
||||||
);
|
);
|
||||||
this.isRightPanelV2Enabled = ko.computed<boolean>(() =>
|
this.isRightPanelV2Enabled = ko.computed<boolean>(() =>
|
||||||
this.isFeatureEnabled(Constants.Features.enableRightPanelV2)
|
this.isFeatureEnabled(Constants.Features.enableRightPanelV2)
|
||||||
@@ -918,6 +919,7 @@ export default class Explorer {
|
|||||||
|
|
||||||
this.gitHubReposPane = this.notebookManager.gitHubReposPane;
|
this.gitHubReposPane = this.notebookManager.gitHubReposPane;
|
||||||
this.isGitHubPaneEnabled(true);
|
this.isGitHubPaneEnabled(true);
|
||||||
|
this.isRecosEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.refreshCommandBarButtons();
|
this.refreshCommandBarButtons();
|
||||||
@@ -1004,6 +1006,8 @@ export default class Explorer {
|
|||||||
});
|
});
|
||||||
this.addSynapseLinkDialog = new DialogComponentAdapter();
|
this.addSynapseLinkDialog = new DialogComponentAdapter();
|
||||||
this.addSynapseLinkDialog.parameters = this._addSynapseLinkDialogProps;
|
this.addSynapseLinkDialog.parameters = this._addSynapseLinkDialogProps;
|
||||||
|
this.recommendationsAdapter = new RecommendationsAdapter(this);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public openEnableSynapseLinkDialog(): void {
|
public openEnableSynapseLinkDialog(): void {
|
||||||
@@ -1793,7 +1797,7 @@ export default class Explorer {
|
|||||||
const message: any = event.data.data;
|
const message: any = event.data.data;
|
||||||
const inputs: ViewModels.DataExplorerInputsFrame = message.inputs;
|
const inputs: ViewModels.DataExplorerInputsFrame = message.inputs;
|
||||||
|
|
||||||
const isRunningInPortal = window.dataExplorerPlatform == PlatformType.Portal;
|
const isRunningInPortal = configContext.platform === Platform.Portal;
|
||||||
const isRunningInDevMode = process.env.NODE_ENV === "development";
|
const isRunningInDevMode = process.env.NODE_ENV === "development";
|
||||||
if (inputs && configContext.BACKEND_ENDPOINT && isRunningInPortal && isRunningInDevMode) {
|
if (inputs && configContext.BACKEND_ENDPOINT && isRunningInPortal && isRunningInDevMode) {
|
||||||
inputs.extensionEndpoint = configContext.PROXY_PATH;
|
inputs.extensionEndpoint = configContext.PROXY_PATH;
|
||||||
@@ -2009,10 +2013,6 @@ export default class Explorer {
|
|||||||
this._panes.forEach((pane: ContextualPaneBase) => pane.close());
|
this._panes.forEach((pane: ContextualPaneBase) => pane.close());
|
||||||
}
|
}
|
||||||
|
|
||||||
public getPlatformType(): PlatformType {
|
|
||||||
return window.dataExplorerPlatform;
|
|
||||||
}
|
|
||||||
|
|
||||||
public isRunningOnNationalCloud(): boolean {
|
public isRunningOnNationalCloud(): boolean {
|
||||||
return (
|
return (
|
||||||
this.serverId() === Constants.ServerIds.blackforest ||
|
this.serverId() === Constants.ServerIds.blackforest ||
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||||
import { PlatformType } from "../../../PlatformType";
|
|
||||||
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
|
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
|
||||||
import { Areas } from "../../../Common/Constants";
|
import { Areas } from "../../../Common/Constants";
|
||||||
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||||
@@ -159,7 +158,7 @@ export class CommandBarComponentButtonFactory {
|
|||||||
|
|
||||||
public static createControlCommandBarButtons(container: Explorer): CommandButtonComponentProps[] {
|
public static createControlCommandBarButtons(container: Explorer): CommandButtonComponentProps[] {
|
||||||
const buttons: CommandButtonComponentProps[] = [];
|
const buttons: CommandButtonComponentProps[] = [];
|
||||||
if (window.dataExplorerPlatform === PlatformType.Hosted) {
|
if (configContext.platform === Platform.Hosted) {
|
||||||
return buttons;
|
return buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstan
|
|||||||
import { configContext, Platform } from "../../ConfigContext";
|
import { configContext, Platform } from "../../ConfigContext";
|
||||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||||
import { DynamicListItem } from "../Controls/DynamicList/DynamicListComponent";
|
import { DynamicListItem } from "../Controls/DynamicList/DynamicListComponent";
|
||||||
import { HashMap } from "../../Common/HashMap";
|
|
||||||
import { PlatformType } from "../../PlatformType";
|
|
||||||
import { refreshCachedResources } from "../../Common/DocumentClientUtilityBase";
|
import { refreshCachedResources } from "../../Common/DocumentClientUtilityBase";
|
||||||
import { createCollection } from "../../Common/dataAccess/createCollection";
|
import { createCollection } from "../../Common/dataAccess/createCollection";
|
||||||
|
|
||||||
@@ -327,7 +325,7 @@ export default class AddCollectionPane extends ContextualPaneBase {
|
|||||||
if (
|
if (
|
||||||
configContext.platform !== Platform.Emulator &&
|
configContext.platform !== Platform.Emulator &&
|
||||||
!this.container.isTryCosmosDBSubscription() &&
|
!this.container.isTryCosmosDBSubscription() &&
|
||||||
this.container.getPlatformType() !== PlatformType.Portal
|
configContext.platform !== Platform.Portal
|
||||||
) {
|
) {
|
||||||
const offerThroughput: number = this._getThroughput();
|
const offerThroughput: number = this._getThroughput();
|
||||||
return offerThroughput <= 100000;
|
return offerThroughput <= 100000;
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
|||||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||||
import { createDatabase } from "../../Common/dataAccess/createDatabase";
|
import { createDatabase } from "../../Common/dataAccess/createDatabase";
|
||||||
import { PlatformType } from "../../PlatformType";
|
|
||||||
import { configContext, Platform } from "../../ConfigContext";
|
import { configContext, Platform } from "../../ConfigContext";
|
||||||
|
|
||||||
export default class AddDatabasePane extends ContextualPaneBase {
|
export default class AddDatabasePane extends ContextualPaneBase {
|
||||||
@@ -183,7 +182,7 @@ export default class AddDatabasePane extends ContextualPaneBase {
|
|||||||
if (
|
if (
|
||||||
configContext.platform !== Platform.Emulator &&
|
configContext.platform !== Platform.Emulator &&
|
||||||
!this.container.isTryCosmosDBSubscription() &&
|
!this.container.isTryCosmosDBSubscription() &&
|
||||||
this.container.getPlatformType() !== PlatformType.Portal
|
configContext.platform !== Platform.Portal
|
||||||
) {
|
) {
|
||||||
const offerThroughput: number = this.throughput();
|
const offerThroughput: number = this.throughput();
|
||||||
return offerThroughput <= 100000;
|
return offerThroughput <= 100000;
|
||||||
|
|||||||
@@ -140,10 +140,7 @@ export class PublishNotebookPaneAdapter implements ReactAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async submit(): Promise<void> {
|
public async submit(): Promise<void> {
|
||||||
const notificationId = NotificationConsoleUtils.logConsoleMessage(
|
const clearPublishingMessage = NotificationConsoleUtils.logConsoleProgress(`Publishing ${this.name} to gallery`);
|
||||||
ConsoleDataType.InProgress,
|
|
||||||
`Publishing ${this.name} to gallery`
|
|
||||||
);
|
|
||||||
this.isExecuting = true;
|
this.isExecuting = true;
|
||||||
this.triggerRender();
|
this.triggerRender();
|
||||||
|
|
||||||
@@ -161,8 +158,16 @@ export class PublishNotebookPaneAdapter implements ReactAdapter {
|
|||||||
this.content,
|
this.content,
|
||||||
this.isLinkInjectionEnabled
|
this.isLinkInjectionEnabled
|
||||||
);
|
);
|
||||||
if (response.data) {
|
|
||||||
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Info, `Published ${name} to gallery`);
|
const data = response.data;
|
||||||
|
if (data) {
|
||||||
|
if (data.pendingScanJobIds?.length > 0) {
|
||||||
|
NotificationConsoleUtils.logConsoleInfo(
|
||||||
|
`Content of ${this.name} is currently being scanned for illegal content. It will not be available in the public gallery until the review is complete (may take a few days).`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
NotificationConsoleUtils.logConsoleInfo(`Published ${this.name} to gallery`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.formError = `Failed to publish ${this.name} to gallery`;
|
this.formError = `Failed to publish ${this.name} to gallery`;
|
||||||
@@ -170,10 +175,10 @@ export class PublishNotebookPaneAdapter implements ReactAdapter {
|
|||||||
|
|
||||||
const message = `${this.formError}: ${this.formErrorDetail}`;
|
const message = `${this.formError}: ${this.formErrorDetail}`;
|
||||||
Logger.logError(message, "PublishNotebookPaneAdapter/submit");
|
Logger.logError(message, "PublishNotebookPaneAdapter/submit");
|
||||||
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message);
|
NotificationConsoleUtils.logConsoleError(message);
|
||||||
return;
|
return;
|
||||||
} finally {
|
} finally {
|
||||||
NotificationConsoleUtils.clearInProgressMessageWithId(notificationId);
|
clearPublishingMessage();
|
||||||
this.isExecuting = false;
|
this.isExecuting = false;
|
||||||
this.triggerRender();
|
this.triggerRender();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -296,7 +296,9 @@ export class PublishNotebookPaneComponent extends React.Component<PublishNoteboo
|
|||||||
downloads: 0,
|
downloads: 0,
|
||||||
favorites: 0,
|
favorites: 0,
|
||||||
views: 0,
|
views: 0,
|
||||||
newCellId: undefined
|
newCellId: undefined,
|
||||||
|
policyViolations: undefined,
|
||||||
|
pendingScanJobIds: undefined
|
||||||
}}
|
}}
|
||||||
isFavorite={false}
|
isFavorite={false}
|
||||||
showDownload={true}
|
showDownload={true}
|
||||||
|
|||||||
@@ -103,6 +103,8 @@ exports[`PublishNotebookPaneComponent renders 1`] = `
|
|||||||
"isSample": false,
|
"isSample": false,
|
||||||
"name": "SampleNotebook.ipynb",
|
"name": "SampleNotebook.ipynb",
|
||||||
"newCellId": undefined,
|
"newCellId": undefined,
|
||||||
|
"pendingScanJobIds": undefined,
|
||||||
|
"policyViolations": undefined,
|
||||||
"tags": Array [
|
"tags": Array [
|
||||||
"",
|
"",
|
||||||
],
|
],
|
||||||
|
|||||||
50
src/Explorer/Recommendations/RecommendationsAdapter.tsx
Normal file
50
src/Explorer/Recommendations/RecommendationsAdapter.tsx
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* This adapter is responsible to render the React component
|
||||||
|
* If the component signals a change through the callback passed in the properties, it must render the React component when appropriate
|
||||||
|
* and update any knockout observables passed from the parent.
|
||||||
|
*/
|
||||||
|
import * as ko from "knockout";
|
||||||
|
import * as React from "react";
|
||||||
|
import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
|
||||||
|
import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
|
import { MessageBar, MessageBarType, Text} from "office-ui-fabric-react";
|
||||||
|
import { StyleConstants } from "../../Common/Constants";
|
||||||
|
import Explorer from "../Explorer";
|
||||||
|
// import {getRecommendations} from "./api";
|
||||||
|
import { configContext } from "../../ConfigContext";
|
||||||
|
import { JunoClient } from "../../Juno/JunoClient";
|
||||||
|
import { ICardTokens, Card } from "@uifabric/react-cards";
|
||||||
|
import {Recommendations, RecommendationProps} from "./RecommendationsComponent";
|
||||||
|
// import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
|
||||||
|
|
||||||
|
export class RecommendationsAdapter implements ReactAdapter {
|
||||||
|
public parameters: ko.Observable<number>;
|
||||||
|
public container: Explorer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
constructor(container: Explorer) {
|
||||||
|
this.container = container;
|
||||||
|
this.parameters = ko.observable<number>(Date.now());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public forceRender(): void {
|
||||||
|
window.requestAnimationFrame(() => this.parameters(Date.now()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public renderComponent(): JSX.Element {
|
||||||
|
//const backgroundColor = StyleConstants.BaseLight;
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Recommendations explorer={this.container}/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public triggerRender(): void {
|
||||||
|
window.requestAnimationFrame(() => this.parameters(Date.now()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
89
src/Explorer/Recommendations/RecommendationsComponent.tsx
Normal file
89
src/Explorer/Recommendations/RecommendationsComponent.tsx
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
import { ICardTokens, Card } from "@uifabric/react-cards";
|
||||||
|
import React from "react";
|
||||||
|
import { JunoClient } from "../../Juno/JunoClient";
|
||||||
|
import Explorer from "../Explorer";
|
||||||
|
import { MessageBar, MessageBarButton, MessageBarType, IMessageBarStyles, Spinner } from "office-ui-fabric-react";
|
||||||
|
import { FontSize } from "../Controls/GitHub/GitHubStyleConstants";
|
||||||
|
|
||||||
|
export interface RecommendationProps {
|
||||||
|
explorer: Explorer;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export const recoStyles: Partial<IMessageBarStyles> = { root: { backgroundColor: "#0078d4" ,
|
||||||
|
color:"white", fontSize: "16px"}, text: {fontSize: "16px"}, icon: {display: "none"}};
|
||||||
|
|
||||||
|
export const recoButtonStyles = {root: {fontSize: "10px"}};
|
||||||
|
|
||||||
|
export class Recommendations extends React.Component<RecommendationProps> {
|
||||||
|
|
||||||
|
public state: { recoMessage: string; loadingInfo: boolean;};
|
||||||
|
container: Explorer;
|
||||||
|
|
||||||
|
|
||||||
|
constructor(props: RecommendationProps) {
|
||||||
|
super(props);
|
||||||
|
//this.container = this.container;
|
||||||
|
this.state = {
|
||||||
|
recoMessage:"",
|
||||||
|
loadingInfo: false
|
||||||
|
}
|
||||||
|
this.loadInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async loadInfo(){
|
||||||
|
this.setState({loadingInfo: true});
|
||||||
|
let junoClient = new JunoClient(this.props.explorer.databaseAccount);
|
||||||
|
|
||||||
|
let resp = await junoClient.getRecos();
|
||||||
|
// this.state.recoMessage = resp.description;
|
||||||
|
|
||||||
|
this.setState({recoMessage: resp.description});
|
||||||
|
this.setState({loadingInfo: false});
|
||||||
|
}
|
||||||
|
|
||||||
|
private clear = () => {
|
||||||
|
this.setState({recoMessage: null})
|
||||||
|
};
|
||||||
|
|
||||||
|
private clear1()
|
||||||
|
{
|
||||||
|
this.setState({recoMessage: null})
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
if (this.state.loadingInfo)
|
||||||
|
{
|
||||||
|
return (<React.Fragment> <Spinner/> Loading your Recommendation </React.Fragment>);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (this.state.recoMessage)
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<MessageBar
|
||||||
|
dismissButtonAriaLabel="Close"
|
||||||
|
messageBarType={MessageBarType.warning}
|
||||||
|
actions={
|
||||||
|
<div>
|
||||||
|
<MessageBarButton onClick={this.clear} styles={recoButtonStyles}>Remind me later</MessageBarButton>
|
||||||
|
<MessageBarButton onClick={this.clear} styles={recoButtonStyles}>Got it</MessageBarButton>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
styles={recoStyles}
|
||||||
|
>
|
||||||
|
{this.state.recoMessage}
|
||||||
|
</MessageBar>
|
||||||
|
|
||||||
|
</React.Fragment>);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/Explorer/Recommendations/api.ts
Normal file
10
src/Explorer/Recommendations/api.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { JunoClient } from "../../Juno/JunoClient";
|
||||||
|
|
||||||
|
export const getRecommendations(endpoint: string): string {
|
||||||
|
let url = `${endpoint}/api/notebooks/recos`;
|
||||||
|
const response = await window.fetch(url, {
|
||||||
|
method: "GET",
|
||||||
|
headers: JunoClient.getHeaders()
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,7 +13,6 @@ import SaveIcon from "../../../images/save-cosmos.svg";
|
|||||||
import TabsBase from "./TabsBase";
|
import TabsBase from "./TabsBase";
|
||||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
|
||||||
import { PlatformType } from "../../PlatformType";
|
|
||||||
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
import { updateOffer } from "../../Common/dataAccess/updateOffer";
|
import { updateOffer } from "../../Common/dataAccess/updateOffer";
|
||||||
@@ -200,16 +199,14 @@ export default class DatabaseSettingsTab extends TabsBase implements ViewModels.
|
|||||||
return configContext.platform !== Platform.Emulator;
|
return configContext.platform !== Platform.Emulator;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.shouldDisplayPortalUsePrompt = ko.pureComputed<boolean>(
|
this.shouldDisplayPortalUsePrompt = ko.pureComputed<boolean>(() => configContext.platform === Platform.Hosted);
|
||||||
() => this.container.getPlatformType() === PlatformType.Hosted
|
|
||||||
);
|
|
||||||
this.canThroughputExceedMaximumValue = ko.pureComputed<boolean>(
|
this.canThroughputExceedMaximumValue = ko.pureComputed<boolean>(
|
||||||
() => this.container.getPlatformType() === PlatformType.Portal && !this.container.isRunningOnNationalCloud()
|
() => configContext.platform === Platform.Portal && !this.container.isRunningOnNationalCloud()
|
||||||
);
|
);
|
||||||
this.canRequestSupport = ko.pureComputed(() => {
|
this.canRequestSupport = ko.pureComputed(() => {
|
||||||
if (
|
if (
|
||||||
configContext.platform === Platform.Emulator ||
|
configContext.platform === Platform.Emulator ||
|
||||||
this.container.getPlatformType() === PlatformType.Hosted ||
|
configContext.platform === Platform.Hosted ||
|
||||||
this.canThroughputExceedMaximumValue()
|
this.canThroughputExceedMaximumValue()
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
@@ -273,7 +270,7 @@ export default class DatabaseSettingsTab extends TabsBase implements ViewModels.
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.maxRUThroughputInputLimit = ko.pureComputed<number>(() => {
|
this.maxRUThroughputInputLimit = ko.pureComputed<number>(() => {
|
||||||
if (this.container && this.container.getPlatformType() === PlatformType.Hosted) {
|
if (configContext.platform === Platform.Hosted) {
|
||||||
return SharedConstants.CollectionCreation.DefaultCollectionRUs1Million;
|
return SharedConstants.CollectionCreation.DefaultCollectionRUs1Million;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,9 @@ import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstan
|
|||||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||||
import { HashMap } from "../../Common/HashMap";
|
import { HashMap } from "../../Common/HashMap";
|
||||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
||||||
import { PlatformType } from "../../PlatformType";
|
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
import { userContext } from "../../UserContext";
|
import { userContext } from "../../UserContext";
|
||||||
import { configContext } from "../../ConfigContext";
|
import { configContext, Platform } from "../../ConfigContext";
|
||||||
|
|
||||||
export default class MongoShellTab extends TabsBase {
|
export default class MongoShellTab extends TabsBase {
|
||||||
public url: ko.Computed<string>;
|
public url: ko.Computed<string>;
|
||||||
@@ -31,7 +30,7 @@ export default class MongoShellTab extends TabsBase {
|
|||||||
const accountName = account && account.name;
|
const accountName = account && account.name;
|
||||||
const mongoEndpoint = account && (account.properties.mongoEndpoint || account.properties.documentEndpoint);
|
const mongoEndpoint = account && (account.properties.mongoEndpoint || account.properties.documentEndpoint);
|
||||||
|
|
||||||
this._runtimeEndpoint = window.dataExplorerPlatform === PlatformType.Hosted ? configContext.BACKEND_ENDPOINT : "";
|
this._runtimeEndpoint = configContext.platform === Platform.Hosted ? configContext.BACKEND_ENDPOINT : "";
|
||||||
const extensionEndpoint: string = configContext.BACKEND_ENDPOINT || this._runtimeEndpoint || "";
|
const extensionEndpoint: string = configContext.BACKEND_ENDPOINT || this._runtimeEndpoint || "";
|
||||||
let baseUrl = "/content/mongoshell/dist/";
|
let baseUrl = "/content/mongoshell/dist/";
|
||||||
if (this._container.serverId() === "localhost") {
|
if (this._container.serverId() === "localhost") {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import SaveIcon from "../../../images/save-cosmos.svg";
|
|||||||
import TabsBase from "./TabsBase";
|
import TabsBase from "./TabsBase";
|
||||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||||
import { PlatformType } from "../../PlatformType";
|
|
||||||
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
import { RequestOptions } from "@azure/cosmos/dist-esm";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
import { updateOffer } from "../../Common/dataAccess/updateOffer";
|
import { updateOffer } from "../../Common/dataAccess/updateOffer";
|
||||||
@@ -494,7 +493,7 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor
|
|||||||
|
|
||||||
this.canThroughputExceedMaximumValue = ko.pureComputed<boolean>(() => {
|
this.canThroughputExceedMaximumValue = ko.pureComputed<boolean>(() => {
|
||||||
const isPublicAzurePortal: boolean =
|
const isPublicAzurePortal: boolean =
|
||||||
this.container.getPlatformType() === PlatformType.Portal && !this.container.isRunningOnNationalCloud();
|
configContext.platform === Platform.Portal && !this.container.isRunningOnNationalCloud();
|
||||||
const hasPartitionKey = !!this.collection.partitionKey;
|
const hasPartitionKey = !!this.collection.partitionKey;
|
||||||
|
|
||||||
return isPublicAzurePortal && hasPartitionKey;
|
return isPublicAzurePortal && hasPartitionKey;
|
||||||
@@ -513,7 +512,7 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.container.getPlatformType() === PlatformType.Hosted) {
|
if (configContext.platform === Platform.Hosted) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,7 +525,7 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.shouldDisplayPortalUsePrompt = ko.pureComputed<boolean>(
|
this.shouldDisplayPortalUsePrompt = ko.pureComputed<boolean>(
|
||||||
() => this.container.getPlatformType() === PlatformType.Hosted && !!this.collection.partitionKey
|
() => configContext.platform === Platform.Hosted && !!this.collection.partitionKey
|
||||||
);
|
);
|
||||||
|
|
||||||
this.minRUs = ko.computed<number>(() => {
|
this.minRUs = ko.computed<number>(() => {
|
||||||
@@ -597,7 +596,7 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.maxRUThroughputInputLimit = ko.pureComputed<number>(() => {
|
this.maxRUThroughputInputLimit = ko.pureComputed<number>(() => {
|
||||||
if (this.container && this.container.getPlatformType() === PlatformType.Hosted && this.collection.partitionKey) {
|
if (configContext.platform === Platform.Hosted && this.collection.partitionKey) {
|
||||||
return SharedConstants.CollectionCreation.DefaultCollectionRUs1Million;
|
return SharedConstants.CollectionCreation.DefaultCollectionRUs1Million;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import { readCollectionQuotaInfo } from "../../Common/dataAccess/readCollectionQ
|
|||||||
import * as Logger from "../../Common/Logger";
|
import * as Logger from "../../Common/Logger";
|
||||||
import * as DataModels from "../../Contracts/DataModels";
|
import * as DataModels from "../../Contracts/DataModels";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
import * as ViewModels from "../../Contracts/ViewModels";
|
||||||
import { PlatformType } from "../../PlatformType";
|
|
||||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||||
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
import * as NotificationConsoleUtils from "../../Utils/NotificationConsoleUtils";
|
||||||
@@ -36,7 +35,7 @@ import DocumentId from "./DocumentId";
|
|||||||
import StoredProcedure from "./StoredProcedure";
|
import StoredProcedure from "./StoredProcedure";
|
||||||
import Trigger from "./Trigger";
|
import Trigger from "./Trigger";
|
||||||
import UserDefinedFunction from "./UserDefinedFunction";
|
import UserDefinedFunction from "./UserDefinedFunction";
|
||||||
import { configContext } from "../../ConfigContext";
|
import { configContext, Platform } from "../../ConfigContext";
|
||||||
import Explorer from "../Explorer";
|
import Explorer from "../Explorer";
|
||||||
import { userContext } from "../../UserContext";
|
import { userContext } from "../../UserContext";
|
||||||
import TabsBase from "../Tabs/TabsBase";
|
import TabsBase from "../Tabs/TabsBase";
|
||||||
@@ -1030,9 +1029,8 @@ export default class Collection implements ViewModels.Collection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public uploadFiles = (fileList: FileList): Q.Promise<UploadDetails> => {
|
public uploadFiles = (fileList: FileList): Q.Promise<UploadDetails> => {
|
||||||
const platformType: string = PlatformType[(<any>window).dataExplorerPlatform];
|
|
||||||
// TODO: right now web worker is not working with AAD flow. Use main thread for upload for now until we have backend upload capability
|
// TODO: right now web worker is not working with AAD flow. Use main thread for upload for now until we have backend upload capability
|
||||||
if (platformType === PlatformType[PlatformType.Hosted] && window.authType === AuthType.AAD) {
|
if (configContext.platform === Platform.Hosted && window.authType === AuthType.AAD) {
|
||||||
return this._uploadFilesCors(fileList);
|
return this._uploadFilesCors(fileList);
|
||||||
}
|
}
|
||||||
const documentUploader: Worker = new UploadWorker();
|
const documentUploader: Worker = new UploadWorker();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import ko from "knockout";
|
import ko from "knockout";
|
||||||
import { HttpHeaders, HttpStatusCodes } from "../Common/Constants";
|
import { HttpHeaders, HttpStatusCodes } from "../Common/Constants";
|
||||||
import { IPinnedRepo, JunoClient, IGalleryItem } from "./JunoClient";
|
import { IPinnedRepo, JunoClient } from "./JunoClient";
|
||||||
import { configContext } from "../ConfigContext";
|
import { configContext } from "../ConfigContext";
|
||||||
import { getAuthorizationHeader } from "../Utils/AuthorizationUtils";
|
import { getAuthorizationHeader } from "../Utils/AuthorizationUtils";
|
||||||
import { DatabaseAccount } from "../Contracts/DataModels";
|
import { DatabaseAccount } from "../Contracts/DataModels";
|
||||||
@@ -33,24 +33,6 @@ const samplePinnedRepos: IPinnedRepo[] = [
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const sampleGalleryItems: IGalleryItem[] = [
|
|
||||||
{
|
|
||||||
id: "id",
|
|
||||||
name: "name",
|
|
||||||
description: "description",
|
|
||||||
gitSha: "gitSha",
|
|
||||||
tags: ["tag1"],
|
|
||||||
author: "author",
|
|
||||||
thumbnailUrl: "thumbnailUrl",
|
|
||||||
created: "created",
|
|
||||||
isSample: false,
|
|
||||||
downloads: 0,
|
|
||||||
favorites: 0,
|
|
||||||
views: 0,
|
|
||||||
newCellId: undefined
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
describe("Pinned repos", () => {
|
describe("Pinned repos", () => {
|
||||||
const junoClient = new JunoClient(ko.observable<DatabaseAccount>(sampleDatabaseAccount));
|
const junoClient = new JunoClient(ko.observable<DatabaseAccount>(sampleDatabaseAccount));
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,13 @@ export interface IGalleryItem {
|
|||||||
favorites: number;
|
favorites: number;
|
||||||
views: number;
|
views: number;
|
||||||
newCellId: string;
|
newCellId: string;
|
||||||
|
policyViolations: string[];
|
||||||
|
pendingScanJobIds: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRecommendationData {
|
||||||
|
id: number;
|
||||||
|
description: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPublicGalleryData {
|
export interface IPublicGalleryData {
|
||||||
@@ -125,6 +132,20 @@ export class JunoClient {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getRecos(): Promise<IRecommendationData> {
|
||||||
|
var db = this.databaseAccount().id.split("/");
|
||||||
|
var subId = db[2];
|
||||||
|
var rg = db[4];
|
||||||
|
var acc = db[8];
|
||||||
|
const url = `https://localhost/api/recommendations?subId=${subId}&rg=${rg}&account=${acc}`;
|
||||||
|
const response = await window.fetch(url, {
|
||||||
|
method: "GET",
|
||||||
|
headers: JunoClient.getHeaders()
|
||||||
|
});
|
||||||
|
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
public async getGitHubToken(code: string): Promise<IGitHubResponse<IGitHubOAuthToken>> {
|
public async getGitHubToken(code: string): Promise<IGitHubResponse<IGitHubOAuthToken>> {
|
||||||
const githubParams = JunoClient.getGitHubClientParams();
|
const githubParams = JunoClient.getGitHubClientParams();
|
||||||
githubParams.append("code", code);
|
githubParams.append("code", code);
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ import { BindingHandlersRegisterer } from "./Bindings/BindingHandlersRegisterer"
|
|||||||
import * as Emulator from "./Platform/Emulator/Main";
|
import * as Emulator from "./Platform/Emulator/Main";
|
||||||
import Hosted from "./Platform/Hosted/Main";
|
import Hosted from "./Platform/Hosted/Main";
|
||||||
import * as Portal from "./Platform/Portal/Main";
|
import * as Portal from "./Platform/Portal/Main";
|
||||||
import { PlatformType } from "./PlatformType";
|
|
||||||
import { AuthType } from "./AuthType";
|
import { AuthType } from "./AuthType";
|
||||||
|
|
||||||
import { initializeIcons } from "office-ui-fabric-react/lib/Icons";
|
import { initializeIcons } from "office-ui-fabric-react/lib/Icons";
|
||||||
@@ -81,8 +80,6 @@ window.authType = AuthType.AAD;
|
|||||||
initializeConfiguration().then(config => {
|
initializeConfiguration().then(config => {
|
||||||
if (config.platform === Platform.Hosted) {
|
if (config.platform === Platform.Hosted) {
|
||||||
try {
|
try {
|
||||||
// TODO Remove. All window variables should move to src/Config file
|
|
||||||
window.dataExplorerPlatform = PlatformType.Hosted;
|
|
||||||
Hosted.initializeExplorer().then(
|
Hosted.initializeExplorer().then(
|
||||||
(explorer: Explorer) => {
|
(explorer: Explorer) => {
|
||||||
applyExplorerBindings(explorer);
|
applyExplorerBindings(explorer);
|
||||||
@@ -108,14 +105,10 @@ initializeConfiguration().then(config => {
|
|||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
} else if (config.platform === Platform.Emulator) {
|
} else if (config.platform === Platform.Emulator) {
|
||||||
// TODO Remove. All window variables should move to src/Config file
|
|
||||||
window.dataExplorerPlatform = PlatformType.Emulator;
|
|
||||||
window.authType = AuthType.MasterKey;
|
window.authType = AuthType.MasterKey;
|
||||||
const explorer = Emulator.initializeExplorer();
|
const explorer = Emulator.initializeExplorer();
|
||||||
applyExplorerBindings(explorer);
|
applyExplorerBindings(explorer);
|
||||||
} else if (config.platform === Platform.Portal) {
|
} else if (config.platform === Platform.Portal) {
|
||||||
// TODO Remove. All window variables should move to src/Config file
|
|
||||||
window.dataExplorerPlatform = PlatformType.Portal;
|
|
||||||
TelemetryProcessor.trace(Action.InitializeDataExplorer, ActionModifiers.Open, {});
|
TelemetryProcessor.trace(Action.InitializeDataExplorer, ActionModifiers.Open, {});
|
||||||
const explorer = Portal.initializeExplorer();
|
const explorer = Portal.initializeExplorer();
|
||||||
TelemetryProcessor.trace(Action.InitializeDataExplorer, ActionModifiers.IFrameReady, {});
|
TelemetryProcessor.trace(Action.InitializeDataExplorer, ActionModifiers.IFrameReady, {});
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
import { AccountKind, TagNames, DefaultAccountExperience } from "../../Common/Constants";
|
|
||||||
|
|
||||||
import Explorer from "../../Explorer/Explorer";
|
|
||||||
|
|
||||||
export default class EmulatorExplorerFactory {
|
|
||||||
public static createExplorer(): Explorer {
|
|
||||||
const explorer: Explorer = new Explorer();
|
|
||||||
explorer.databaseAccount({
|
|
||||||
name: "",
|
|
||||||
id: "",
|
|
||||||
location: "",
|
|
||||||
type: "",
|
|
||||||
kind: AccountKind.DocumentDB,
|
|
||||||
tags: {
|
|
||||||
[TagNames.defaultExperience]: DefaultAccountExperience.DocumentDB
|
|
||||||
},
|
|
||||||
properties: {
|
|
||||||
documentEndpoint: "",
|
|
||||||
tableEndpoint: "",
|
|
||||||
gremlinEndpoint: "",
|
|
||||||
cassandraEndpoint: ""
|
|
||||||
}
|
|
||||||
});
|
|
||||||
explorer.isAccountReady(true);
|
|
||||||
return explorer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,24 @@
|
|||||||
import EmulatorExplorerFactory from "./ExplorerFactory";
|
|
||||||
import Explorer from "../../Explorer/Explorer";
|
import Explorer from "../../Explorer/Explorer";
|
||||||
|
import { AccountKind, DefaultAccountExperience, TagNames } from "../../Common/Constants";
|
||||||
|
|
||||||
export function initializeExplorer(): Explorer {
|
export function initializeExplorer(): Explorer {
|
||||||
return EmulatorExplorerFactory.createExplorer();
|
const explorer = new Explorer();
|
||||||
|
explorer.databaseAccount({
|
||||||
|
name: "",
|
||||||
|
id: "",
|
||||||
|
location: "",
|
||||||
|
type: "",
|
||||||
|
kind: AccountKind.DocumentDB,
|
||||||
|
tags: {
|
||||||
|
[TagNames.defaultExperience]: DefaultAccountExperience.DocumentDB
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
documentEndpoint: "",
|
||||||
|
tableEndpoint: "",
|
||||||
|
gremlinEndpoint: "",
|
||||||
|
cassandraEndpoint: ""
|
||||||
|
}
|
||||||
|
});
|
||||||
|
explorer.isAccountReady(true);
|
||||||
|
return explorer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
import Explorer from "../../Explorer/Explorer";
|
|
||||||
|
|
||||||
export default class HostedExplorerFactory {
|
|
||||||
public createExplorer(): Explorer {
|
|
||||||
const explorer = new Explorer();
|
|
||||||
|
|
||||||
return explorer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static reInitializeDocumentClientUtilityForExplorer(explorer: Explorer): void {
|
|
||||||
if (!!explorer) {
|
|
||||||
explorer.notificationConsoleData([]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
import * as Constants from "../../Common/Constants";
|
import * as Constants from "../../Common/Constants";
|
||||||
import * as ViewModels from "../../Contracts/ViewModels";
|
|
||||||
import AuthHeadersUtil from "./Authorization";
|
import AuthHeadersUtil from "./Authorization";
|
||||||
import HostedExplorerFactory from "./ExplorerFactory";
|
|
||||||
import Q from "q";
|
import Q from "q";
|
||||||
import {
|
import {
|
||||||
AccessInputMetadata,
|
AccessInputMetadata,
|
||||||
@@ -211,7 +209,7 @@ export default class Main {
|
|||||||
Main._getAccessInputMetadata(Main._encryptedToken).then(
|
Main._getAccessInputMetadata(Main._encryptedToken).then(
|
||||||
() => {
|
() => {
|
||||||
if (explorer.isConnectExplorerVisible()) {
|
if (explorer.isConnectExplorerVisible()) {
|
||||||
HostedExplorerFactory.reInitializeDocumentClientUtilityForExplorer(explorer);
|
explorer.notificationConsoleData([]);
|
||||||
explorer.hideConnectExplorerForm();
|
explorer.hideConnectExplorerForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,8 +376,7 @@ export default class Main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static _instantiateExplorer(): Explorer {
|
private static _instantiateExplorer(): Explorer {
|
||||||
const hostedExplorerFactory = new HostedExplorerFactory();
|
const explorer = new Explorer();
|
||||||
const explorer = hostedExplorerFactory.createExplorer();
|
|
||||||
// workaround to resolve cyclic refs with view
|
// workaround to resolve cyclic refs with view
|
||||||
explorer.renewExplorerShareAccess = Main.renewExplorerAccess;
|
explorer.renewExplorerShareAccess = Main.renewExplorerAccess;
|
||||||
window.addEventListener("message", explorer.handleMessage.bind(explorer), false);
|
window.addEventListener("message", explorer.handleMessage.bind(explorer), false);
|
||||||
@@ -483,7 +480,7 @@ export default class Main {
|
|||||||
Main._accessInputMetadata = Main._getAccessInputMetadataFromAccountEndpoint(properties.accountEndpoint);
|
Main._accessInputMetadata = Main._getAccessInputMetadataFromAccountEndpoint(properties.accountEndpoint);
|
||||||
|
|
||||||
if (explorer.isConnectExplorerVisible()) {
|
if (explorer.isConnectExplorerVisible()) {
|
||||||
HostedExplorerFactory.reInitializeDocumentClientUtilityForExplorer(explorer);
|
explorer.notificationConsoleData([]);
|
||||||
explorer.hideConnectExplorerForm();
|
explorer.hideConnectExplorerForm();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,7 +567,7 @@ export default class Main {
|
|||||||
this._explorer.hideConnectExplorerForm();
|
this._explorer.hideConnectExplorerForm();
|
||||||
|
|
||||||
const masterKey = Main._getMasterKey(keys);
|
const masterKey = Main._getMasterKey(keys);
|
||||||
HostedExplorerFactory.reInitializeDocumentClientUtilityForExplorer(this._explorer);
|
this._explorer.notificationConsoleData([]);
|
||||||
Main._setExplorerReady(this._explorer, masterKey, account, authorizationToken);
|
Main._setExplorerReady(this._explorer, masterKey, account, authorizationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
import Explorer from "../../Explorer/Explorer";
|
|
||||||
|
|
||||||
export default class PortalExplorerFactory {
|
|
||||||
public createExplorer(): Explorer {
|
|
||||||
var explorer = new Explorer();
|
|
||||||
|
|
||||||
return explorer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
import PortalExplorerFactory from "./ExplorerFactory";
|
|
||||||
import "../../Explorer/Tables/DataTable/DataTableBindingManager";
|
import "../../Explorer/Tables/DataTable/DataTableBindingManager";
|
||||||
import Explorer from "../../Explorer/Explorer";
|
import Explorer from "../../Explorer/Explorer";
|
||||||
|
|
||||||
export function initializeExplorer(): Explorer {
|
export function initializeExplorer(): Explorer {
|
||||||
const portalExplorerFactory = new PortalExplorerFactory();
|
const explorer = new Explorer();
|
||||||
const explorer = portalExplorerFactory.createExplorer();
|
|
||||||
|
|
||||||
window.addEventListener("message", explorer.handleMessage.bind(explorer), false);
|
window.addEventListener("message", explorer.handleMessage.bind(explorer), false);
|
||||||
return explorer;
|
return explorer;
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
// TODO: Should be owned by parent iframe
|
|
||||||
export enum PlatformType {
|
|
||||||
// RuntimeProxy and MongoEmulator no longer used, but kept here to preserve enum structure
|
|
||||||
RuntimeProxy,
|
|
||||||
MongoEmulator,
|
|
||||||
|
|
||||||
Hosted,
|
|
||||||
Emulator,
|
|
||||||
Portal
|
|
||||||
}
|
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
|
import { configContext, Platform } from "../ConfigContext";
|
||||||
import * as ViewModels from "../Contracts/ViewModels";
|
import * as ViewModels from "../Contracts/ViewModels";
|
||||||
import { PlatformType } from "../PlatformType";
|
|
||||||
import { PortalTokenProvider } from "./PortalTokenProvider";
|
import { PortalTokenProvider } from "./PortalTokenProvider";
|
||||||
|
|
||||||
export class TokenProviderFactory {
|
export class TokenProviderFactory {
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
|
||||||
public static create(): ViewModels.TokenProvider {
|
public static create(): ViewModels.TokenProvider {
|
||||||
const platformType = window.dataExplorerPlatform;
|
const platformType = configContext.platform;
|
||||||
switch (platformType) {
|
switch (platformType) {
|
||||||
case PlatformType.Portal:
|
case Platform.Portal:
|
||||||
case PlatformType.Hosted:
|
case Platform.Hosted:
|
||||||
return new PortalTokenProvider();
|
return new PortalTokenProvider();
|
||||||
case PlatformType.Emulator:
|
case Platform.Emulator:
|
||||||
default:
|
default:
|
||||||
// should never get into this state
|
// should never get into this state
|
||||||
throw new Error(`Unknown platform ${platformType}`);
|
throw new Error(`Unknown platform ${platformType}`);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import * as Constants from "../Common/Constants";
|
import * as Constants from "../Common/Constants";
|
||||||
import * as AuthorizationUtils from "./AuthorizationUtils";
|
import * as AuthorizationUtils from "./AuthorizationUtils";
|
||||||
import { AuthType } from "../AuthType";
|
import { AuthType } from "../AuthType";
|
||||||
import { PlatformType } from "../PlatformType";
|
|
||||||
import Explorer from "../Explorer/Explorer";
|
import Explorer from "../Explorer/Explorer";
|
||||||
import { updateUserContext } from "../UserContext";
|
import { updateUserContext } from "../UserContext";
|
||||||
|
import { Platform, updateConfigContext } from "../ConfigContext";
|
||||||
jest.mock("../Explorer/Explorer");
|
jest.mock("../Explorer/Explorer");
|
||||||
|
|
||||||
describe("AuthorizationUtils", () => {
|
describe("AuthorizationUtils", () => {
|
||||||
@@ -65,12 +65,13 @@ describe("AuthorizationUtils", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
window.dataExplorer = explorer;
|
window.dataExplorer = explorer;
|
||||||
window.dataExplorerPlatform = PlatformType.Hosted;
|
updateConfigContext({
|
||||||
|
platform: Platform.Hosted
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
window.dataExplorer = undefined;
|
window.dataExplorer = undefined;
|
||||||
window.dataExplorerPlatform = undefined;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not open token renewal prompt if status code is undefined", () => {
|
it("should not open token renewal prompt if status code is undefined", () => {
|
||||||
@@ -89,7 +90,9 @@ describe("AuthorizationUtils", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should not open token renewal prompt if running on a different platform", () => {
|
it("should not open token renewal prompt if running on a different platform", () => {
|
||||||
window.dataExplorerPlatform = PlatformType.Portal;
|
updateConfigContext({
|
||||||
|
platform: Platform.Portal
|
||||||
|
});
|
||||||
AuthorizationUtils.displayTokenRenewalPromptForStatus(Constants.HttpStatusCodes.Unauthorized);
|
AuthorizationUtils.displayTokenRenewalPromptForStatus(Constants.HttpStatusCodes.Unauthorized);
|
||||||
expect(explorer.displayGuestAccessTokenRenewalPrompt).not.toHaveBeenCalled();
|
expect(explorer.displayGuestAccessTokenRenewalPrompt).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ import * as ViewModels from "../Contracts/ViewModels";
|
|||||||
import AuthHeadersUtil from "../Platform/Hosted/Authorization";
|
import AuthHeadersUtil from "../Platform/Hosted/Authorization";
|
||||||
import { AuthType } from "../AuthType";
|
import { AuthType } from "../AuthType";
|
||||||
import * as Logger from "../Common/Logger";
|
import * as Logger from "../Common/Logger";
|
||||||
import { PlatformType } from "../PlatformType";
|
import { configContext, Platform } from "../ConfigContext";
|
||||||
import { configContext } from "../ConfigContext";
|
|
||||||
import { userContext } from "../UserContext";
|
import { userContext } from "../UserContext";
|
||||||
|
|
||||||
export function getAuthorizationHeader(): ViewModels.AuthorizationTokenHeaderMetadata {
|
export function getAuthorizationHeader(): ViewModels.AuthorizationTokenHeaderMetadata {
|
||||||
@@ -57,13 +56,12 @@ export function decryptJWTToken(token: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function displayTokenRenewalPromptForStatus(httpStatusCode: number): void {
|
export function displayTokenRenewalPromptForStatus(httpStatusCode: number): void {
|
||||||
const platformType = window.dataExplorerPlatform;
|
|
||||||
const explorer = window.dataExplorer;
|
const explorer = window.dataExplorer;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
httpStatusCode == null ||
|
httpStatusCode == null ||
|
||||||
httpStatusCode != Constants.HttpStatusCodes.Unauthorized ||
|
httpStatusCode != Constants.HttpStatusCodes.Unauthorized ||
|
||||||
platformType !== PlatformType.Hosted
|
configContext.platform !== Platform.Hosted
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ const galleryItem: IGalleryItem = {
|
|||||||
downloads: 0,
|
downloads: 0,
|
||||||
favorites: 0,
|
favorites: 0,
|
||||||
views: 0,
|
views: 0,
|
||||||
newCellId: undefined
|
newCellId: undefined,
|
||||||
|
policyViolations: undefined,
|
||||||
|
pendingScanJobIds: undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
describe("GalleryUtils", () => {
|
describe("GalleryUtils", () => {
|
||||||
|
|||||||
@@ -323,3 +323,27 @@ export function getTabTitle(tab: GalleryTab): string {
|
|||||||
throw new Error(`Unknown tab ${tab}`);
|
throw new Error(`Unknown tab ${tab}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function filterPublishedNotebooks(
|
||||||
|
items: IGalleryItem[]
|
||||||
|
): {
|
||||||
|
published: IGalleryItem[];
|
||||||
|
underReview: IGalleryItem[];
|
||||||
|
removed: IGalleryItem[];
|
||||||
|
} {
|
||||||
|
const underReview: IGalleryItem[] = [];
|
||||||
|
const removed: IGalleryItem[] = [];
|
||||||
|
const published: IGalleryItem[] = [];
|
||||||
|
|
||||||
|
items?.forEach(item => {
|
||||||
|
if (item.policyViolations?.length > 0) {
|
||||||
|
removed.push(item);
|
||||||
|
} else if (item.pendingScanJobIds?.length > 0) {
|
||||||
|
underReview.push(item);
|
||||||
|
} else {
|
||||||
|
published.push(item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return { published, underReview, removed };
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,6 +11,11 @@
|
|||||||
<body>
|
<body>
|
||||||
<div class="flexContainer">
|
<div class="flexContainer">
|
||||||
<div id="divExplorer" class="flexContainer hideOverflows" style="display: none">
|
<div id="divExplorer" class="flexContainer hideOverflows" style="display: none">
|
||||||
|
<!-- ko if: isRecosEnabled -->
|
||||||
|
<div>
|
||||||
|
<div data-bind="react: recommendationsAdapter"></div>
|
||||||
|
</div>
|
||||||
|
<!-- /ko -->
|
||||||
<!-- Main Command Bar - Start -->
|
<!-- Main Command Bar - Start -->
|
||||||
<div data-bind="react: commandBarComponentAdapter"></div>
|
<div data-bind="react: commandBarComponentAdapter"></div>
|
||||||
<!-- Main Command Bar - End -->
|
<!-- Main Command Bar - End -->
|
||||||
|
|||||||
2
src/global.d.ts
vendored
2
src/global.d.ts
vendored
@@ -1,11 +1,9 @@
|
|||||||
import { AuthType } from "./AuthType";
|
import { AuthType } from "./AuthType";
|
||||||
import { PlatformType } from "./PlatformType";
|
|
||||||
import Explorer from "./Explorer/Explorer";
|
import Explorer from "./Explorer/Explorer";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
authType: AuthType;
|
authType: AuthType;
|
||||||
dataExplorerPlatform: PlatformType;
|
|
||||||
dataExplorer: Explorer;
|
dataExplorer: Explorer;
|
||||||
__REACT_DEVTOOLS_GLOBAL_HOOK__: any;
|
__REACT_DEVTOOLS_GLOBAL_HOOK__: any;
|
||||||
$: any;
|
$: any;
|
||||||
|
|||||||
@@ -56,7 +56,6 @@
|
|||||||
"./src/GitHub/GitHubConnector.ts",
|
"./src/GitHub/GitHubConnector.ts",
|
||||||
"./src/Index.ts",
|
"./src/Index.ts",
|
||||||
"./src/NotebookWorkspaceManager/NotebookWorkspaceResourceProviderMockClients.ts",
|
"./src/NotebookWorkspaceManager/NotebookWorkspaceResourceProviderMockClients.ts",
|
||||||
"./src/PlatformType.ts",
|
|
||||||
"./src/ReactDevTools.ts",
|
"./src/ReactDevTools.ts",
|
||||||
"./src/ResourceProvider/IResourceProviderClient.ts",
|
"./src/ResourceProvider/IResourceProviderClient.ts",
|
||||||
"./src/Shared/ExplorerSettings.ts",
|
"./src/Shared/ExplorerSettings.ts",
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ module.exports = function(env = {}, argv = {}) {
|
|||||||
const rules = [fontRule, lessRule, imagesRule, cssRule, htmlRule, typescriptRule];
|
const rules = [fontRule, lessRule, imagesRule, cssRule, htmlRule, typescriptRule];
|
||||||
const envVars = {
|
const envVars = {
|
||||||
GIT_SHA: gitSha,
|
GIT_SHA: gitSha,
|
||||||
PORT: process.env.PORT || "1234"
|
PORT: process.env.PORT || "2223"
|
||||||
};
|
};
|
||||||
|
|
||||||
if (mode === "production") {
|
if (mode === "production") {
|
||||||
|
|||||||
Reference in New Issue
Block a user