mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-20 01:11:25 +00:00
Use graphql in GitHubClient and misc fixes (#8)
* Use graphql in GitHubClient * Replace usage of Array.find with _.find
This commit is contained in:
@@ -54,7 +54,8 @@ export class DialogComponent extends React.Component<DialogProps, {}> {
|
||||
styles: {
|
||||
title: { fontSize: DIALOG_TITLE_FONT_SIZE, fontWeight: DIALOG_TITLE_FONT_WEIGHT },
|
||||
subText: { fontSize: DIALOG_SUBTEXT_FONT_SIZE }
|
||||
}
|
||||
},
|
||||
showCloseButton: false
|
||||
},
|
||||
modalProps: { isBlocking: this.props.isModal },
|
||||
minWidth: DIALOG_MIN_WIDTH,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* React component for Switch Directory
|
||||
*/
|
||||
|
||||
import _ from "underscore";
|
||||
import * as React from "react";
|
||||
import { Dropdown, IDropdownOption, IDropdownProps } from "office-ui-fabric-react/lib/Dropdown";
|
||||
import { Tenant } from "../../../Contracts/DataModels";
|
||||
@@ -60,7 +61,7 @@ export class DefaultDirectoryDropdownComponent extends React.Component<DefaultDi
|
||||
return;
|
||||
}
|
||||
|
||||
const selectedDirectory = this.props.directories.find(d => d.tenantId === option.key);
|
||||
const selectedDirectory = _.find(this.props.directories, d => d.tenantId === option.key);
|
||||
if (!selectedDirectory) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import _ from "underscore";
|
||||
import * as React from "react";
|
||||
|
||||
import { DefaultButton, IButtonProps } from "office-ui-fabric-react/lib/Button";
|
||||
@@ -114,7 +115,7 @@ export class DirectoryListComponent extends React.Component<DirectoryListProps,
|
||||
}
|
||||
const buttonElement = e.currentTarget;
|
||||
const selectedDirectoryId = buttonElement.getElementsByClassName("directoryListItemId")[0].textContent;
|
||||
const selectedDirectory = this.props.directories.find(d => d.tenantId === selectedDirectoryId);
|
||||
const selectedDirectory = _.find(this.props.directories, d => d.tenantId === selectedDirectoryId);
|
||||
|
||||
this.props.onNewDirectorySelected(selectedDirectory);
|
||||
};
|
||||
|
||||
@@ -93,7 +93,7 @@ export class AddRepoComponent extends React.Component<AddRepoComponentProps, Add
|
||||
const repo = await this.props.getRepo(repoInfo.owner, repoInfo.repo);
|
||||
if (repo) {
|
||||
const item: RepoListItem = {
|
||||
key: GitHubUtils.toRepoFullName(repo.owner.login, repo.name),
|
||||
key: GitHubUtils.toRepoFullName(repo.owner, repo.name),
|
||||
repo,
|
||||
branches: [
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
Text
|
||||
} from "office-ui-fabric-react";
|
||||
import * as React from "react";
|
||||
import { IGitHubBranch } from "../../../GitHub/GitHubClient";
|
||||
import { IGitHubBranch, IGitHubPageInfo } from "../../../GitHub/GitHubClient";
|
||||
import { GitHubUtils } from "../../../Utils/GitHubUtils";
|
||||
import { RepoListItem } from "./GitHubReposComponent";
|
||||
import {
|
||||
@@ -41,6 +41,7 @@ export interface ReposListComponentProps {
|
||||
|
||||
export interface BranchesProps {
|
||||
branches: IGitHubBranch[];
|
||||
lastPageInfo?: IGitHubPageInfo;
|
||||
hasMore: boolean;
|
||||
isLoading: boolean;
|
||||
loadMore: () => void;
|
||||
@@ -139,7 +140,7 @@ export class ReposListComponent extends React.Component<ReposListComponentProps>
|
||||
}
|
||||
|
||||
const checkboxProps: ICheckboxProps = {
|
||||
...ReposListComponent.getCheckboxPropsForLabel(GitHubUtils.toRepoFullName(item.repo.owner.login, item.repo.name)),
|
||||
...ReposListComponent.getCheckboxPropsForLabel(GitHubUtils.toRepoFullName(item.repo.owner, item.repo.name)),
|
||||
styles: ReposListCheckboxStyles,
|
||||
defaultChecked: true,
|
||||
onChange: () => this.props.unpinRepo(item)
|
||||
@@ -153,7 +154,7 @@ export class ReposListComponent extends React.Component<ReposListComponentProps>
|
||||
return <></>;
|
||||
}
|
||||
|
||||
const branchesProps = this.props.branchesProps[GitHubUtils.toRepoFullName(item.repo.owner.login, item.repo.name)];
|
||||
const branchesProps = this.props.branchesProps[GitHubUtils.toRepoFullName(item.repo.owner, item.repo.name)];
|
||||
const options: IDropdownOption[] = branchesProps.branches.map(branch => ({
|
||||
key: branch.name,
|
||||
text: branch.name,
|
||||
@@ -222,7 +223,7 @@ export class ReposListComponent extends React.Component<ReposListComponentProps>
|
||||
|
||||
private onRenderPinnedReposBranchesDropdownOption(option: IDropdownOption): JSX.Element {
|
||||
const item: RepoListItem = option.data;
|
||||
const branchesProps = this.props.branchesProps[GitHubUtils.toRepoFullName(item.repo.owner.login, item.repo.name)];
|
||||
const branchesProps = this.props.branchesProps[GitHubUtils.toRepoFullName(item.repo.owner, item.repo.name)];
|
||||
|
||||
if (option.index === ReposListComponent.FooterIndex) {
|
||||
const linkProps: ILinkProps = {
|
||||
@@ -267,7 +268,7 @@ export class ReposListComponent extends React.Component<ReposListComponentProps>
|
||||
}
|
||||
|
||||
const checkboxProps: ICheckboxProps = {
|
||||
...ReposListComponent.getCheckboxPropsForLabel(GitHubUtils.toRepoFullName(item.repo.owner.login, item.repo.name)),
|
||||
...ReposListComponent.getCheckboxPropsForLabel(GitHubUtils.toRepoFullName(item.repo.owner, item.repo.name)),
|
||||
styles: ReposListCheckboxStyles,
|
||||
onChange: () => {
|
||||
const repoListItem = { ...item };
|
||||
|
||||
@@ -2583,7 +2583,7 @@ export default class Explorer implements ViewModels.Explorer {
|
||||
const item = NotebookUtil.createNotebookContentItem(name, path, "file");
|
||||
const parent = this.resourceTree.myNotebooksContentRoot;
|
||||
|
||||
if (parent && this.isNotebookEnabled() && this.notebookClient) {
|
||||
if (parent && parent.children && this.isNotebookEnabled() && this.notebookClient) {
|
||||
if (this._filePathToImportAndOpen === path) {
|
||||
this._filePathToImportAndOpen = null; // we don't want to try opening this path again
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import _ from "underscore";
|
||||
import * as React from "react";
|
||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||
import { Observable } from "knockout";
|
||||
@@ -46,7 +47,7 @@ export class CommandBarUtil {
|
||||
text: btn.commandButtonLabel || btn.tooltipText,
|
||||
"data-test": btn.commandButtonLabel || btn.tooltipText,
|
||||
title: btn.tooltipText,
|
||||
name: "menuitem",
|
||||
name: btn.commandButtonLabel || btn.tooltipText,
|
||||
disabled: btn.disabled,
|
||||
ariaLabel: btn.ariaLabel,
|
||||
buttonStyles: {
|
||||
@@ -126,6 +127,9 @@ export class CommandBarUtil {
|
||||
}
|
||||
|
||||
if (btn.isDropdown) {
|
||||
const selectedChild = _.find(btn.children, child => child.dropdownItemKey === btn.dropdownSelectedKey);
|
||||
result.name = selectedChild?.commandButtonLabel || btn.dropdownPlaceholder;
|
||||
|
||||
const dropdownStyles: Partial<IDropdownStyles> = {
|
||||
root: { margin: 5 },
|
||||
dropdown: { width: btn.dropdownWidth },
|
||||
|
||||
@@ -17,25 +17,6 @@ export const closeNotebook = (payload: { contentRef: ContentRef }): CloseNoteboo
|
||||
};
|
||||
};
|
||||
|
||||
export const UPDATE_LAST_MODIFIED = "UPDATE_LAST_MODIFIED";
|
||||
export interface UpdateLastModifiedAction {
|
||||
type: "UPDATE_LAST_MODIFIED";
|
||||
payload: {
|
||||
contentRef: ContentRef;
|
||||
lastModified: string;
|
||||
};
|
||||
}
|
||||
|
||||
export const updateLastModified = (payload: {
|
||||
contentRef: ContentRef;
|
||||
lastModified: string;
|
||||
}): UpdateLastModifiedAction => {
|
||||
return {
|
||||
type: UPDATE_LAST_MODIFIED,
|
||||
payload
|
||||
};
|
||||
};
|
||||
|
||||
export const EXECUTE_FOCUSED_CELL_AND_FOCUS_NEXT = "EXECUTE_FOCUSED_CELL_AND_FOCUS_NEXT";
|
||||
export interface ExecuteFocusedCellAndFocusNextAction {
|
||||
type: "EXECUTE_FOCUSED_CELL_AND_FOCUS_NEXT";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { empty, merge, of, timer, interval, concat, Subject, Subscriber, Observable, Observer } from "rxjs";
|
||||
import { empty, merge, of, timer, concat, Subject, Subscriber, Observable, Observer } from "rxjs";
|
||||
import { webSocket } from "rxjs/webSocket";
|
||||
import { ActionsObservable, StateObservable } from "redux-observable";
|
||||
import { ofType } from "redux-observable";
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
map,
|
||||
switchMap,
|
||||
take,
|
||||
distinctUntilChanged,
|
||||
filter,
|
||||
catchError,
|
||||
first,
|
||||
@@ -21,7 +20,6 @@ import {
|
||||
AppState,
|
||||
ServerConfig as JupyterServerConfig,
|
||||
JupyterHostRecordProps,
|
||||
JupyterHostRecord,
|
||||
RemoteKernelProps,
|
||||
castToSessionId,
|
||||
createKernelRef,
|
||||
@@ -29,8 +27,7 @@ import {
|
||||
ContentRef,
|
||||
KernelInfo,
|
||||
actions,
|
||||
selectors,
|
||||
IContentProvider
|
||||
selectors
|
||||
} from "@nteract/core";
|
||||
import { message, JupyterMessage, Channels, createMessage, childOf, ofMessageType } from "@nteract/messaging";
|
||||
import { sessions, kernels } from "rx-jupyter";
|
||||
@@ -752,69 +749,6 @@ export const cleanKernelOnConnectionLostEpic = (
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Workaround for issue: https://github.com/nteract/nteract/issues/4583
|
||||
* We reajust the property
|
||||
* @param action$
|
||||
* @param state$
|
||||
*/
|
||||
const adjustLastModifiedOnSaveEpic = (
|
||||
action$: ActionsObservable<actions.SaveFulfilled>,
|
||||
state$: StateObservable<AppState>,
|
||||
dependencies: { contentProvider: IContentProvider }
|
||||
): Observable<{} | CdbActions.UpdateLastModifiedAction> => {
|
||||
return action$.pipe(
|
||||
ofType(actions.SAVE_FULFILLED),
|
||||
mergeMap(action => {
|
||||
const pollDelayMs = 500;
|
||||
const nbAttempts = 4;
|
||||
|
||||
// Retry updating last modified
|
||||
const currentHost = selectors.currentHost(state$.value);
|
||||
const serverConfig = selectors.serverConfig(currentHost as JupyterHostRecord);
|
||||
const filepath = selectors.filepath(state$.value, { contentRef: action.payload.contentRef });
|
||||
const content = selectors.content(state$.value, { contentRef: action.payload.contentRef });
|
||||
const lastSaved = (content.lastSaved as any) as string;
|
||||
const contentProvider = dependencies.contentProvider;
|
||||
|
||||
// Query until value is stable
|
||||
return interval(pollDelayMs)
|
||||
.pipe(take(nbAttempts))
|
||||
.pipe(
|
||||
mergeMap(x =>
|
||||
contentProvider.get(serverConfig, filepath, { content: 0 }).pipe(
|
||||
map(xhr => {
|
||||
if (xhr.status !== 200 || typeof xhr.response === "string") {
|
||||
return undefined;
|
||||
}
|
||||
const model = xhr.response;
|
||||
const lastModified = model.last_modified;
|
||||
if (lastModified === lastSaved) {
|
||||
return undefined;
|
||||
}
|
||||
// Return last modified
|
||||
return lastModified;
|
||||
})
|
||||
)
|
||||
),
|
||||
distinctUntilChanged(),
|
||||
mergeMap(lastModified => {
|
||||
if (!lastModified) {
|
||||
return empty();
|
||||
}
|
||||
|
||||
return of(
|
||||
CdbActions.updateLastModified({
|
||||
contentRef: action.payload.contentRef,
|
||||
lastModified
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute focused cell and focus next cell
|
||||
* @param action$
|
||||
@@ -917,7 +851,6 @@ export const allEpics = [
|
||||
acquireKernelInfoEpic,
|
||||
handleKernelConnectionLostEpic,
|
||||
cleanKernelOnConnectionLostEpic,
|
||||
adjustLastModifiedOnSaveEpic,
|
||||
executeFocusedCellAndFocusNextEpic,
|
||||
closeUnsupportedMimetypesEpic,
|
||||
closeContentFailedToFetchEpic,
|
||||
|
||||
@@ -51,11 +51,6 @@ export const coreReducer = (state: CoreRecord, action: Action) => {
|
||||
.setIn(path.concat("displayName"), kernelspecs.displayName)
|
||||
.setIn(path.concat("language"), kernelspecs.language);
|
||||
}
|
||||
case cdbActions.UPDATE_LAST_MODIFIED: {
|
||||
typedAction = action as cdbActions.UpdateLastModifiedAction;
|
||||
const path = ["entities", "contents", "byRef", typedAction.payload.contentRef, "lastSaved"];
|
||||
return state.setIn(path, typedAction.payload.lastModified);
|
||||
}
|
||||
default:
|
||||
return nteractReducers.core(state as any, action as any);
|
||||
}
|
||||
|
||||
127
src/Explorer/Notebook/NotebookSamples.ts
Normal file
127
src/Explorer/Notebook/NotebookSamples.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
import { IGitHubRepo, IGitHubBranch } from "../../GitHub/GitHubClient";
|
||||
|
||||
export const SamplesRepo: IGitHubRepo = {
|
||||
name: "cosmos-notebooks",
|
||||
owner: "Azure-Samples",
|
||||
private: false
|
||||
};
|
||||
|
||||
export const SamplesBranch: IGitHubBranch = {
|
||||
name: "master"
|
||||
};
|
||||
|
||||
export const isSamplesCall = (owner: string, repo: string, branch?: string): boolean => {
|
||||
return owner === SamplesRepo.owner && repo === SamplesRepo.name && (!branch || branch === SamplesBranch.name);
|
||||
};
|
||||
|
||||
// GitHub API calls have a rate limit of 5000 requests per hour. So if we get high traffic on Data Explorer
|
||||
// loading samples exceed that limit. Using this hard coded response for samples until we fix that.
|
||||
export const SamplesContentsQueryResponse = {
|
||||
repository: {
|
||||
owner: {
|
||||
login: "Azure-Samples"
|
||||
},
|
||||
name: "cosmos-notebooks",
|
||||
isPrivate: false,
|
||||
ref: {
|
||||
name: "master",
|
||||
target: {
|
||||
history: {
|
||||
nodes: [
|
||||
{
|
||||
oid: "cda7facb9e039b173f3376200c26c859896e7974",
|
||||
message:
|
||||
"Merge pull request #45 from Azure-Samples/users/deborahc/pythonSampleUpdates\n\nAdd bokeh version to notebook",
|
||||
committer: {
|
||||
date: "2020-05-28T11:28:01-07:00"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
object: {
|
||||
entries: [
|
||||
{
|
||||
name: ".github",
|
||||
type: "tree",
|
||||
object: {}
|
||||
},
|
||||
{
|
||||
name: ".gitignore",
|
||||
type: "blob",
|
||||
object: {
|
||||
oid: "3e759b75bf455ac809d0987d369aab89137b5689",
|
||||
byteSize: 5582
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "1. GettingStarted.ipynb",
|
||||
type: "blob",
|
||||
object: {
|
||||
oid: "0732ff5366e4aefdc4c378c61cbd968664f0acec",
|
||||
byteSize: 3933
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "2. Visualization.ipynb",
|
||||
type: "blob",
|
||||
object: {
|
||||
oid: "6b16b0740a77afdd38a95bc6c3ebd0f2f17d9465",
|
||||
byteSize: 820317
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "3. RequestUnits.ipynb",
|
||||
type: "blob",
|
||||
object: {
|
||||
oid: "252b79a4adc81e9f2ffde453231b695d75e270e8",
|
||||
byteSize: 9490
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "4. Indexing.ipynb",
|
||||
type: "blob",
|
||||
object: {
|
||||
oid: "e10dd67bd1c55c345226769e4f80e43659ef9cd5",
|
||||
byteSize: 10394
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "5. StoredProcedures.ipynb",
|
||||
type: "blob",
|
||||
object: {
|
||||
oid: "949941949920de4d2d111149e2182e9657cc8134",
|
||||
byteSize: 11818
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "6. GlobalDistribution.ipynb",
|
||||
type: "blob",
|
||||
object: {
|
||||
oid: "b91c31dacacbc9e35750d9054063dda4a5309f3b",
|
||||
byteSize: 11375
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "7. IoTAnomalyDetection.ipynb",
|
||||
type: "blob",
|
||||
object: {
|
||||
oid: "82057ae52a67721a5966e2361317f5dfbd0ee595",
|
||||
byteSize: 377939
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "All_API_quickstarts",
|
||||
type: "tree",
|
||||
object: {}
|
||||
},
|
||||
{
|
||||
name: "CSharp_quickstarts",
|
||||
type: "tree",
|
||||
object: {}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -155,19 +155,7 @@ function openPane(action: ActionContracts.OpenPane, explorer: ViewModels.Explore
|
||||
}
|
||||
|
||||
function openFile(action: ActionContracts.OpenSampleNotebook, explorer: ViewModels.Explorer) {
|
||||
let path: string;
|
||||
if (action.hasOwnProperty("file")) {
|
||||
// This is deprecated
|
||||
const downloadUrl: string = (action as any).file.download_url;
|
||||
path = downloadUrl.replace(
|
||||
"raw.githubusercontent.com/Azure-Samples/cosmos-notebooks",
|
||||
"github.com/Azure-Samples/cosmos-notebooks/blob"
|
||||
); // convert raw download url to something which GitHubContentProvider understands
|
||||
} else {
|
||||
path = action.path;
|
||||
}
|
||||
|
||||
explorer.handleOpenFileAction(path);
|
||||
explorer.handleOpenFileAction(decodeURIComponent(action.path));
|
||||
}
|
||||
|
||||
function generateQueryText(action: ActionContracts.OpenQueryTab, partitionKeyProperty: string): string {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import _ from "underscore";
|
||||
import * as ko from "knockout";
|
||||
import * as Constants from "../../Common/Constants";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
@@ -81,7 +82,7 @@ export class ClusterLibraryPane extends ContextualPaneBase {
|
||||
|
||||
private _onInstalledChanged = (libraryName: string, installed: boolean): void => {
|
||||
const items = this._clusterLibraryProps().libraryItems;
|
||||
const library = items.find(item => item.name === libraryName);
|
||||
const library = _.find(items, item => item.name === libraryName);
|
||||
library.installed = installed;
|
||||
this._clusterLibraryProps.valueHasMutated();
|
||||
};
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
import _ from "underscore";
|
||||
import { Areas, HttpStatusCodes } from "../../Common/Constants";
|
||||
import { Logger } from "../../Common/Logger";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import { GitHubClient, IGitHubRepo } from "../../GitHub/GitHubClient";
|
||||
import { GitHubClient, IGitHubPageInfo, IGitHubRepo } from "../../GitHub/GitHubClient";
|
||||
import { IPinnedRepo, JunoClient } from "../../Juno/JunoClient";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { GitHubUtils } from "../../Utils/GitHubUtils";
|
||||
import { JunoUtils } from "../../Utils/JunoUtils";
|
||||
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
|
||||
import { AuthorizeAccessComponent } from "../Controls/GitHub/AuthorizeAccessComponent";
|
||||
import { GitHubReposComponentProps, RepoListItem, GitHubReposComponent } from "../Controls/GitHub/GitHubReposComponent";
|
||||
import { GitHubReposComponent, GitHubReposComponentProps, RepoListItem } from "../Controls/GitHub/GitHubReposComponent";
|
||||
import { GitHubReposComponentAdapter } from "../Controls/GitHub/GitHubReposComponentAdapter";
|
||||
import { BranchesProps, PinnedReposProps, UnpinnedReposProps } from "../Controls/GitHub/ReposListComponent";
|
||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||
import { JunoUtils } from "../../Utils/JunoUtils";
|
||||
|
||||
export class GitHubReposPane extends ContextualPaneBase {
|
||||
private static readonly PageSize = 30;
|
||||
@@ -29,6 +30,7 @@ export class GitHubReposPane extends ContextualPaneBase {
|
||||
private gitHubReposAdapter: GitHubReposComponentAdapter;
|
||||
|
||||
private allGitHubRepos: IGitHubRepo[];
|
||||
private allGitHubReposLastPageInfo?: IGitHubPageInfo;
|
||||
private pinnedReposUpdated: boolean;
|
||||
|
||||
constructor(options: ViewModels.GitHubReposPaneOptions) {
|
||||
@@ -73,6 +75,7 @@ export class GitHubReposPane extends ContextualPaneBase {
|
||||
this.gitHubReposAdapter = new GitHubReposComponentAdapter(this.gitHubReposProps);
|
||||
|
||||
this.allGitHubRepos = [];
|
||||
this.allGitHubReposLastPageInfo = undefined;
|
||||
this.pinnedReposUpdated = false;
|
||||
}
|
||||
|
||||
@@ -115,6 +118,7 @@ export class GitHubReposPane extends ContextualPaneBase {
|
||||
|
||||
// Reset cached repos
|
||||
this.allGitHubRepos = [];
|
||||
this.allGitHubReposLastPageInfo = undefined;
|
||||
|
||||
// Reset flags
|
||||
this.pinnedReposUpdated = false;
|
||||
@@ -164,29 +168,28 @@ export class GitHubReposPane extends ContextualPaneBase {
|
||||
const unpinnedGitHubRepos = this.allGitHubRepos.filter(
|
||||
gitHubRepo =>
|
||||
this.pinnedReposProps.repos.findIndex(
|
||||
pinnedRepo => pinnedRepo.key === GitHubUtils.toRepoFullName(gitHubRepo.owner.login, gitHubRepo.name)
|
||||
pinnedRepo => pinnedRepo.key === GitHubUtils.toRepoFullName(gitHubRepo.owner, gitHubRepo.name)
|
||||
) === -1
|
||||
);
|
||||
return unpinnedGitHubRepos.map(gitHubRepo => ({
|
||||
key: GitHubUtils.toRepoFullName(gitHubRepo.owner.login, gitHubRepo.name),
|
||||
key: GitHubUtils.toRepoFullName(gitHubRepo.owner, gitHubRepo.name),
|
||||
repo: gitHubRepo,
|
||||
branches: []
|
||||
}));
|
||||
}
|
||||
|
||||
private async loadMoreBranches(repo: IGitHubRepo): Promise<void> {
|
||||
const branchesProps = this.branchesProps[GitHubUtils.toRepoFullName(repo.owner.login, repo.name)];
|
||||
const branchesProps = this.branchesProps[GitHubUtils.toRepoFullName(repo.owner, repo.name)];
|
||||
branchesProps.hasMore = true;
|
||||
branchesProps.isLoading = true;
|
||||
this.triggerRender();
|
||||
|
||||
const nextPage = Math.floor(branchesProps.branches.length / GitHubReposPane.PageSize) + 1;
|
||||
try {
|
||||
const response = await this.gitHubClient.getBranchesAsync(
|
||||
repo.owner.login,
|
||||
repo.owner,
|
||||
repo.name,
|
||||
nextPage,
|
||||
GitHubReposPane.PageSize
|
||||
GitHubReposPane.PageSize,
|
||||
branchesProps.lastPageInfo?.endCursor
|
||||
);
|
||||
if (response.status !== HttpStatusCodes.OK) {
|
||||
throw new Error(`Received HTTP ${response.status} when fetching branches`);
|
||||
@@ -194,6 +197,7 @@ export class GitHubReposPane extends ContextualPaneBase {
|
||||
|
||||
if (response.data) {
|
||||
branchesProps.branches = branchesProps.branches.concat(response.data);
|
||||
branchesProps.lastPageInfo = response.pageInfo;
|
||||
}
|
||||
} catch (error) {
|
||||
const message = `Failed to fetch branches: ${error}`;
|
||||
@@ -202,7 +206,7 @@ export class GitHubReposPane extends ContextualPaneBase {
|
||||
}
|
||||
|
||||
branchesProps.isLoading = false;
|
||||
branchesProps.hasMore = branchesProps.branches.length === GitHubReposPane.PageSize * nextPage;
|
||||
branchesProps.hasMore = branchesProps.lastPageInfo?.hasNextPage;
|
||||
this.triggerRender();
|
||||
}
|
||||
|
||||
@@ -211,15 +215,18 @@ export class GitHubReposPane extends ContextualPaneBase {
|
||||
this.unpinnedReposProps.hasMore = true;
|
||||
this.triggerRender();
|
||||
|
||||
const nextPage = Math.floor(this.allGitHubRepos.length / GitHubReposPane.PageSize) + 1;
|
||||
try {
|
||||
const response = await this.gitHubClient.getReposAsync(nextPage, GitHubReposPane.PageSize);
|
||||
const response = await this.gitHubClient.getReposAsync(
|
||||
GitHubReposPane.PageSize,
|
||||
this.allGitHubReposLastPageInfo?.endCursor
|
||||
);
|
||||
if (response.status !== HttpStatusCodes.OK) {
|
||||
throw new Error(`Received HTTP ${response.status} when fetching unpinned repos`);
|
||||
}
|
||||
|
||||
if (response.data) {
|
||||
this.allGitHubRepos = this.allGitHubRepos.concat(response.data);
|
||||
this.allGitHubReposLastPageInfo = response.pageInfo;
|
||||
this.unpinnedReposProps.repos = this.calculateUnpinnedRepos();
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -229,7 +236,7 @@ export class GitHubReposPane extends ContextualPaneBase {
|
||||
}
|
||||
|
||||
this.unpinnedReposProps.isLoading = false;
|
||||
this.unpinnedReposProps.hasMore = this.allGitHubRepos.length === GitHubReposPane.PageSize * nextPage;
|
||||
this.unpinnedReposProps.hasMore = this.allGitHubReposLastPageInfo?.hasNextPage;
|
||||
this.triggerRender();
|
||||
}
|
||||
|
||||
@@ -253,7 +260,7 @@ export class GitHubReposPane extends ContextualPaneBase {
|
||||
this.pinnedReposUpdated = true;
|
||||
const initialReposLength = this.pinnedReposProps.repos.length;
|
||||
|
||||
const existingRepo = this.pinnedReposProps.repos.find(repo => repo.key === item.key);
|
||||
const existingRepo = _.find(this.pinnedReposProps.repos, repo => repo.key === item.key);
|
||||
if (existingRepo) {
|
||||
existingRepo.branches = item.branches;
|
||||
} else {
|
||||
@@ -318,6 +325,7 @@ export class GitHubReposPane extends ContextualPaneBase {
|
||||
if (!this.branchesProps[item.key]) {
|
||||
this.branchesProps[item.key] = {
|
||||
branches: [],
|
||||
lastPageInfo: undefined,
|
||||
hasMore: true,
|
||||
isLoading: true,
|
||||
loadMore: (): Promise<void> => this.loadMoreBranches(item.repo)
|
||||
@@ -329,6 +337,7 @@ export class GitHubReposPane extends ContextualPaneBase {
|
||||
|
||||
private async refreshUnpinnedRepoListItems(): Promise<void> {
|
||||
this.allGitHubRepos = [];
|
||||
this.allGitHubReposLastPageInfo = undefined;
|
||||
this.unpinnedReposProps.repos = [];
|
||||
this.loadMoreUnpinnedRepos();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import CollectionIcon from "../../../images/tree-collection.svg";
|
||||
import DeleteIcon from "../../../images/delete.svg";
|
||||
import NotebookIcon from "../../../images/notebook/Notebook-resource.svg";
|
||||
import RefreshIcon from "../../../images/refresh-cosmos.svg";
|
||||
import { IGitHubRepo, IGitHubBranch } from "../../GitHub/GitHubClient";
|
||||
import NewNotebookIcon from "../../../images/notebook/Notebook-new.svg";
|
||||
import FileIcon from "../../../images/notebook/file-cosmos.svg";
|
||||
import { ArrayHashMap } from "../../Common/ArrayHashMap";
|
||||
@@ -26,21 +25,11 @@ import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import { Areas } from "../../Common/Constants";
|
||||
import { GitHubUtils } from "../../Utils/GitHubUtils";
|
||||
import { SamplesRepo, SamplesBranch } from "../Notebook/NotebookSamples";
|
||||
|
||||
export class ResourceTreeAdapter implements ReactAdapter {
|
||||
private static readonly DataTitle = "DATA";
|
||||
private static readonly NotebooksTitle = "NOTEBOOKS";
|
||||
|
||||
private static readonly SamplesRepo: IGitHubRepo = {
|
||||
name: "cosmos-notebooks",
|
||||
owner: {
|
||||
login: "Azure-Samples"
|
||||
},
|
||||
private: false
|
||||
};
|
||||
private static readonly SamplesBranch: IGitHubBranch = {
|
||||
name: "master"
|
||||
};
|
||||
private static readonly PseudoDirPath = "PsuedoDir";
|
||||
|
||||
public parameters: ko.Observable<number>;
|
||||
@@ -103,12 +92,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
||||
|
||||
this.sampleNotebooksContentRoot = {
|
||||
name: "Sample Notebooks (View Only)",
|
||||
path: GitHubUtils.toContentUri(
|
||||
ResourceTreeAdapter.SamplesRepo.owner.login,
|
||||
ResourceTreeAdapter.SamplesRepo.name,
|
||||
ResourceTreeAdapter.SamplesBranch.name,
|
||||
""
|
||||
),
|
||||
path: GitHubUtils.toContentUri(SamplesRepo.owner, SamplesRepo.name, SamplesBranch.name, ""),
|
||||
type: NotebookContentItemType.Directory
|
||||
};
|
||||
refreshTasks.push(
|
||||
|
||||
Reference in New Issue
Block a user