Remove circular reference from book tree item (#16579)

* Enable drag and drop and multiple selection in Book Tree View

* replace children for hasChildren to remove circular reference
This commit is contained in:
Barbara Valdez
2021-08-18 10:37:54 -07:00
committed by GitHub
parent 7b3aae7c88
commit 8aa0dffccf
3 changed files with 39 additions and 56 deletions

View File

@@ -186,12 +186,13 @@ export class BookModel {
const config = yaml.safeLoad(fileContents.toString());
fileContents = await fsPromises.readFile(this._tableOfContentsPath, 'utf-8');
let tableOfContents: any = yaml.safeLoad(fileContents.toString());
const parsedTOC: IJupyterBookToc = { sections: this.parseJupyterSections(this._bookVersion, tableOfContents) };
let book: BookTreeItem = new BookTreeItem({
version: this._bookVersion,
title: config.title,
contentPath: this._tableOfContentsPath,
root: this.bookPath,
tableOfContents: { sections: this.parseJupyterSections(this._bookVersion, tableOfContents) },
tableOfContents: parsedTOC,
page: tableOfContents,
type: BookTreeItemType.Book,
treeItemCollapsibleState: collapsibleState,
@@ -226,7 +227,6 @@ export class BookModel {
}
public async getSections(element: BookTreeItem): Promise<BookTreeItem[]> {
let tableOfContents: IJupyterBookToc = element.tableOfContents;
let sections: JupyterBookSection[] = element.sections;
let root: string = element.root;
let book: BookTreeItemFormat = element.book;
@@ -237,7 +237,7 @@ export class BookModel {
title: sections[i].title,
contentPath: undefined,
root: root,
tableOfContents: tableOfContents,
tableOfContents: element.tableOfContents,
page: sections[i],
type: BookTreeItemType.ExternalLink,
treeItemCollapsibleState: vscode.TreeItemCollapsibleState.Collapsed,
@@ -263,7 +263,7 @@ export class BookModel {
title: sections[i].title ? sections[i].title : sections[i].file,
contentPath: pathToNotebook,
root: root,
tableOfContents: tableOfContents,
tableOfContents: element.tableOfContents,
page: sections[i],
type: BookTreeItemType.Notebook,
treeItemCollapsibleState: vscode.TreeItemCollapsibleState.Collapsed,
@@ -295,7 +295,7 @@ export class BookModel {
title: sections[i].title ? sections[i].title : sections[i].file,
contentPath: pathToMarkdown,
root: root,
tableOfContents: tableOfContents,
tableOfContents: element.tableOfContents,
page: sections[i],
type: BookTreeItemType.Markdown,
treeItemCollapsibleState: vscode.TreeItemCollapsibleState.Collapsed,
@@ -326,7 +326,7 @@ export class BookModel {
}
}
}
element.children = treeItems;
element.hasChildren = treeItems.length > 0;
this.bookItems = treeItems;
return treeItems;
}

View File

@@ -35,24 +35,24 @@ export interface BookTreeItemFormat {
isUntitled: boolean;
version?: BookVersion;
parent?: BookTreeItem;
children?: BookTreeItem[];
hasChildren?: boolean;
}
export class BookTreeItem extends vscode.TreeItem {
private _sections: JupyterBookSection[] | undefined;
private _uri: string | undefined;
public sections: JupyterBookSection[] | undefined;
public uri: string | undefined;
private _previousUri: string;
private _nextUri: string;
public override command: vscode.Command;
public override resourceUri: vscode.Uri;
private _rootContentPath: string;
private _tableOfContentsPath: string;
public rootContentPath: string;
public tableOfContentsPath: string;
constructor(public book: BookTreeItemFormat, icons: any) {
super(book.title, book.treeItemCollapsibleState);
if (book.type === BookTreeItemType.Book) {
this.collapsibleState = book.treeItemCollapsibleState;
this._sections = book.page;
this.sections = book.page;
if (book.isUntitled) {
this.contextValue = BookTreeItemType.providedBook;
} else {
@@ -77,18 +77,18 @@ export class BookTreeItem extends vscode.TreeItem {
this.setCommand();
}
this.iconPath = icons;
this._tableOfContentsPath = undefined;
this.tableOfContentsPath = undefined;
if (this.book.type === BookTreeItemType.ExternalLink) {
this.tooltip = `${this._uri}`;
this.tooltip = `${this.uri}`;
}
else {
// if it's a section, book or a notebook's book then we set the table of contents path.
if (this.book.type === BookTreeItemType.Book || this.contextValue === BookTreeItemType.section || this.contextValue === BookTreeItemType.savedBookNotebook || book.tableOfContents.sections && book.type === BookTreeItemType.Markdown) {
this._tableOfContentsPath = getTocPath(this.book.version, this.book.root);
if (this.book.type === BookTreeItemType.Book || this.contextValue === BookTreeItemType.section || this.contextValue === BookTreeItemType.savedBookNotebook || this.book.tableOfContents.sections && book.type === BookTreeItemType.Markdown) {
this.tableOfContentsPath = getTocPath(this.book.version, this.book.root);
}
this._rootContentPath = getContentPath(this.book.version, this.book.root, '');
this.tooltip = this.book.type === BookTreeItemType.Book ? this._rootContentPath : this.book.contentPath;
this.rootContentPath = getContentPath(this.book.version, this.book.root, '');
this.tooltip = this.book.type === BookTreeItemType.Book ? this.rootContentPath : this.book.contentPath;
this.resourceUri = this.book.type === BookTreeItemType.Book ? vscode.Uri.file(this.book.root) : vscode.Uri.file(this.book.contentPath);
}
}
@@ -99,8 +99,8 @@ export class BookTreeItem extends vscode.TreeItem {
this.book.page.sections || this.book.page.subsections ?
vscode.TreeItemCollapsibleState.Collapsed :
vscode.TreeItemCollapsibleState.None;
this._sections = this.book.page.sections || this.book.page.subsections;
this._uri = this.book.page.file ? this.book.page.file?.replace(/\\/g, '/') : this.book.page.url?.replace(/\\/g, '/');
this.sections = this.book.page.sections || this.book.page.subsections;
this.uri = this.book.page.file ? this.book.page.file?.replace(/\\/g, '/') : this.book.page.url?.replace(/\\/g, '/');
if (this.book.tableOfContents.sections) {
let index = (this.book.tableOfContents.sections.indexOf(this.book.page));
@@ -116,7 +116,7 @@ export class BookTreeItem extends vscode.TreeItem {
} else if (this.book.type === BookTreeItemType.Markdown) {
this.command = { command: 'bookTreeView.openMarkdown', title: loc.openMarkdownCommand, arguments: [this.book.contentPath], };
} else if (this.book.type === BookTreeItemType.ExternalLink) {
this.command = { command: 'bookTreeView.openExternalLink', title: loc.openExternalLinkCommand, arguments: [this._uri], };
this.command = { command: 'bookTreeView.openExternalLink', title: loc.openExternalLinkCommand, arguments: [this.uri], };
}
}
@@ -160,30 +160,14 @@ export class BookTreeItem extends vscode.TreeItem {
return this.book.title;
}
public get uri(): string | undefined {
return this._uri;
}
public get root(): string {
return this.book.root;
}
public get rootContentPath(): string {
return this._rootContentPath;
}
public get tableOfContentsPath(): string {
return this._tableOfContentsPath;
}
public get tableOfContents(): IJupyterBookToc {
return this.book.tableOfContents;
}
public get sections(): JupyterBookSection[] {
return this._sections;
}
public get previousUri(): string {
return this._previousUri;
}
@@ -194,24 +178,13 @@ export class BookTreeItem extends vscode.TreeItem {
public override readonly tooltip: string;
public set uri(uri: string) {
this._uri = uri;
public get hasChildren(): boolean | undefined {
return this.book.hasChildren;
}
public set sections(sections: JupyterBookSection[]) {
this._sections = sections;
}
public set tableOfContentsPath(tocPath: string) {
this._tableOfContentsPath = tocPath;
}
public get children(): BookTreeItem[] | undefined {
return this.book.children;
}
public set children(children: BookTreeItem[] | undefined) {
this.book.children = children;
public set hasChildren(hasChildren: boolean | undefined) {
this.book.hasChildren = hasChildren;
}
public get parent(): BookTreeItem {

View File

@@ -29,7 +29,7 @@ interface BookSearchResults {
bookPaths: string[];
}
export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeItem>, azdata.nb.NavigationProvider {
export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeItem>, azdata.nb.NavigationProvider, vscode.DragAndDropController<BookTreeItem> {
private _onDidChangeTreeData: vscode.EventEmitter<BookTreeItem | undefined> = new vscode.EventEmitter<BookTreeItem | undefined>();
readonly onDidChangeTreeData: vscode.Event<BookTreeItem | undefined> = this._onDidChangeTreeData.event;
private _extensionContext: vscode.ExtensionContext;
@@ -44,6 +44,7 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
public viewId: string;
public books: BookModel[] = [];
public currentBook: BookModel;
supportedTypes = ['text/treeitems'];
constructor(workspaceFolders: vscode.WorkspaceFolder[], extensionContext: vscode.ExtensionContext, openAsUntitled: boolean, view: string, public providerId: string) {
this._openAsUntitled = openAsUntitled;
@@ -54,7 +55,7 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
this.prompter = new CodeAdapter();
this._bookTrustManager = new BookTrustManager(this.books);
this.bookTocManager = new BookTocManager();
this._bookViewer = vscode.window.createTreeView(this.viewId, { showCollapseAll: true, treeDataProvider: this });
this._bookViewer = vscode.window.createTreeView(this.viewId, { showCollapseAll: true, canSelectMany: true, treeDataProvider: this, dragAndDropController: this });
this._bookViewer.onDidChangeVisibility(async e => {
await this.initialized;
// Whenever the viewer changes visibility then try and reveal the currently active document
@@ -470,7 +471,7 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
// increment to reset the depth since parent is in the same level
depthOfNotebookInBook++;
}
if (!bookItemToExpand.children) {
if (!bookItemToExpand.hasChildren) {
// We haven't loaded children of this node yet so do that now so we can
// continue expanding and search its children
await this.getChildren(bookItemToExpand);
@@ -715,4 +716,13 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
}
return Promise.resolve(result);
}
async onDrop(sources: vscode.TreeDataTransfer, target: BookTreeItem): Promise<void> {
let treeItems = JSON.parse(await sources.items.get('text/treeitems')!.asString());
if (treeItems) {
}
}
dispose(): void { }
}