From fde5caa9a4d923b78f18cd920d3a80f55d92b89f Mon Sep 17 00:00:00 2001 From: Barbara Valdez <34872381+barbaravaldez@users.noreply.github.com> Date: Fri, 2 Apr 2021 15:44:25 -0700 Subject: [PATCH] Add documentation and fix paths (#14948) * use posix relative path * add doc link in dialog * rename book to Jupyter book --- extensions/notebook/package.nls.json | 16 +++--- .../notebook/src/book/tocEntryPathHandler.ts | 12 +++- .../notebook/src/common/localizedConstants.ts | 57 ++++++++++--------- .../notebook/src/dialog/addFileDialog.ts | 4 +- .../notebook/src/dialog/createBookDialog.ts | 17 ++++-- 5 files changed, 60 insertions(+), 46 deletions(-) diff --git a/extensions/notebook/package.nls.json b/extensions/notebook/package.nls.json index 6ddcd4923e..55419854f7 100644 --- a/extensions/notebook/package.nls.json +++ b/extensions/notebook/package.nls.json @@ -33,23 +33,23 @@ "title.managePackages": "Manage Packages", "title.SQL19PreviewBook": "SQL Server 2019 Guide", "books-preview-category": "Jupyter Books", - "title.saveJupyterBook": "Save Book", - "title.trustBook": "Trust Book", - "title.searchJupyterBook": "Search Book", + "title.saveJupyterBook": "Save Jupyter Book", + "title.trustBook": "Trust Jupyter Book", + "title.searchJupyterBook": "Search Jupyter Book", "title.SavedBooks": "Notebooks", - "title.ProvidedBooks": "Provided Books", + "title.ProvidedBooks": "Provided Jupyter Books", "title.PinnedBooks": "Pinned notebooks", "title.PreviewLocalizedBook": "Get localized SQL Server 2019 guide", - "title.openJupyterBook": "Open Book", - "title.closeJupyterBook": "Close Book", + "title.openJupyterBook": "Open Jupyter Book", + "title.closeJupyterBook": "Close Jupyter Book", "title.closeNotebook": "Close Notebook", "title.removeNotebook": "Remove Notebook", "title.addNotebook": "Add Notebook", "title.addMarkdown": "Add Markdown File", "title.revealInBooksViewlet": "Reveal in Books", - "title.createJupyterBook": "Create Book (Preview)", + "title.createJupyterBook": "Create Jupyter Book", "title.openNotebookFolder": "Open Notebooks in Folder", - "title.openRemoteJupyterBook": "Add Remote Book", + "title.openRemoteJupyterBook": "Add Remote Jupyter Book", "title.pinNotebook": "Pin Notebook", "title.unpinNotebook": "Unpin Notebook", "title.moveTo": "Move to ..." diff --git a/extensions/notebook/src/book/tocEntryPathHandler.ts b/extensions/notebook/src/book/tocEntryPathHandler.ts index a91432bb16..446094dce4 100644 --- a/extensions/notebook/src/book/tocEntryPathHandler.ts +++ b/extensions/notebook/src/book/tocEntryPathHandler.ts @@ -10,10 +10,16 @@ export class TocEntryPathHandler { public readonly fileInTocEntry: string; public readonly titleInTocEntry: string; public readonly fileExtension: FileExtension; + + /** + * Creates an object that contains the specific format for title and file entries in a Jupyter Book table of contents + * that is compatible on Windows and Mac. + */ constructor(public readonly filePath: string, public readonly bookRoot: string, title?: string) { - const relativePath = path.relative(bookRoot, filePath); - const pathDetails = path.parse(relativePath); - this.fileInTocEntry = relativePath.replace(pathDetails.ext, ''); + //To keep consistency how the file entries are in Jupyter Book toc on Windows and Mac. + const tocRelativePath = path.posix.join(path.posix.sep, path.posix.relative(bookRoot, filePath)); + const pathDetails = path.parse(tocRelativePath); + this.fileInTocEntry = tocRelativePath.replace(pathDetails.ext, ''); this.titleInTocEntry = title ?? pathDetails.name; this.fileExtension = pathDetails.ext === FileExtension.Notebook ? FileExtension.Notebook : FileExtension.Markdown; } diff --git a/extensions/notebook/src/common/localizedConstants.ts b/extensions/notebook/src/common/localizedConstants.ts index bbb1b02581..eca4205758 100644 --- a/extensions/notebook/src/common/localizedConstants.ts +++ b/extensions/notebook/src/common/localizedConstants.ts @@ -18,20 +18,20 @@ export const providerNotValidError = localize('providerNotValidError', "Non-MSSQ // Book view-let constants export const allFiles = localize('allFiles', "All Files"); export const labelSelectFolder = localize('labelSelectFolder', "Select Folder"); -export const labelBookFolder = localize('labelBookFolder', "Select Book"); +export const labelBookFolder = localize('labelBookFolder', "Select Jupyter Book"); export const confirmReplace = localize('confirmReplace', "Folder already exists. Are you sure you want to delete and replace this folder?"); export const openNotebookCommand = localize('openNotebookCommand', "Open Notebook"); export const openMarkdownCommand = localize('openMarkdownCommand', "Open Markdown"); export const openExternalLinkCommand = localize('openExternalLinkCommand', "Open External Link"); -export const msgBookTrusted = localize('msgBookTrusted', "Book is now trusted in the workspace."); -export const msgBookAlreadyTrusted = localize('msgBookAlreadyTrusted', "Book is already trusted in this workspace."); -export const msgBookUntrusted = localize('msgBookUntrusted', "Book is no longer trusted in this workspace"); -export const msgBookAlreadyUntrusted = localize('msgBookAlreadyUntrusted', "Book is already untrusted in this workspace."); -export function msgBookPinned(book: string): string { return localize('msgBookPinned', "Book {0} is now pinned in the workspace.", book); } -export function msgBookUnpinned(book: string): string { return localize('msgBookUnpinned', "Book {0} is no longer pinned in this workspace", book); } -export const missingTocError = localize('bookInitializeFailed', "Failed to find a Table of Contents file in the specified book."); -export const noBooksSelectedError = localize('noBooksSelected', "No books are currently selected in the viewlet."); -export const labelBookSection = localize('labelBookSection', "Select Book Section"); +export const msgBookTrusted = localize('msgBookTrusted', "Jupyter Book is now trusted in the workspace."); +export const msgBookAlreadyTrusted = localize('msgBookAlreadyTrusted', "Jupyter Book is already trusted in this workspace."); +export const msgBookUntrusted = localize('msgBookUntrusted', "Jupyter Book is no longer trusted in this workspace"); +export const msgBookAlreadyUntrusted = localize('msgBookAlreadyUntrusted', "Jupyter Book is already untrusted in this workspace."); +export function msgBookPinned(book: string): string { return localize('msgBookPinned', "Jupyter Book {0} is now pinned in the workspace.", book); } +export function msgBookUnpinned(book: string): string { return localize('msgBookUnpinned', "Jupyter Book {0} is no longer pinned in this workspace", book); } +export const missingTocError = localize('bookInitializeFailed', "Failed to find a Table of Contents file in the specified Jupyter Book."); +export const noBooksSelectedError = localize('noBooksSelected', "No Jupyter Books are currently selected in the viewlet."); +export const labelBookSection = localize('labelBookSection', "Select Jupyter Book Section"); export const labelAddToLevel = localize('labelAddToLevel', "Add to this level"); export function missingFileError(title: string, path: string): string { return localize('missingFileError', "Missing file : {0} from {1}", title, path); } @@ -39,30 +39,30 @@ export function invalidTocFileError(): string { return localize('InvalidError.to export function invalidTocError(title: string): string { return localize('Invalid toc.yml', "Error: {0} has an incorrect toc.yml file", title); } export function configFileError(): string { return localize('configFileError', "Configuration file missing"); } -export function openFileError(path: string, error: string): string { return localize('openBookError', "Open book {0} failed: {1}", path, error); } -export function readBookError(path: string, error: string): string { return localize('readBookError', "Failed to read book {0}: {1}", path, error); } +export function openFileError(path: string, error: string): string { return localize('openBookError', "Open Jupyter Book {0} failed: {1}", path, error); } +export function readBookError(path: string, error: string): string { return localize('readBookError', "Failed to read Jupyter Book {0}: {1}", path, error); } export function openNotebookError(resource: string, error: string): string { return localize('openNotebookError', "Open notebook {0} failed: {1}", resource, error); } export function openMarkdownError(resource: string, error: string): string { return localize('openMarkdownError', "Open markdown {0} failed: {1}", resource, error); } export function openUntitledNotebookError(resource: string, error: string): string { return localize('openUntitledNotebookError', "Open untitled notebook {0} as untitled failed: {1}", resource, error); } export function openExternalLinkError(resource: string, error: string): string { return localize('openExternalLinkError', "Open link {0} failed: {1}", resource, error); } -export function closeBookError(resource: string, error: string): string { return localize('closeBookError', "Close book {0} failed: {1}", resource, error); } +export function closeBookError(resource: string, error: string): string { return localize('closeBookError', "Close Jupyter Book {0} failed: {1}", resource, error); } export function duplicateFileError(title: string, path: string, newPath: string): string { return localize('duplicateFileError', "File {0} already exists in the destination folder {1} \n The file has been renamed to {2} to prevent data loss.", title, path, newPath); } -export function editBookError(path: string, error: string): string { return localize('editBookError', "Error while editing book {0}: {1}", path, error); } -export function selectBookError(error: string): string { return localize('selectBookError', "Error while selecting a book or a section to edit: {0}", error); } +export function editBookError(path: string, error: string): string { return localize('editBookError', "Error while editing Jupyter Book {0}: {1}", path, error); } +export function selectBookError(error: string): string { return localize('selectBookError', "Error while selecting a Jupyter Book or a section to edit: {0}", error); } export function sectionNotFound(section: string, tocPath: string): string { return localize('sectionNotFound', "Failed to find section {0} in {1}.", section, tocPath); } // Remote Book dialog constants export const url = localize('url', "URL"); export const repoUrl = localize('repoUrl', "Repository URL"); export const location = localize('location', "Location"); -export const addRemoteBook = localize('addRemoteBook', "Add Remote Book"); +export const addRemoteBook = localize('addRemoteBook', "Add Remote Jupyter Book"); export const onGitHub = localize('onGitHub', "GitHub"); export const onSharedFile = localize('onsharedFile', "Shared File"); export const releases = localize('releases', "Releases"); -export const book = localize('book', "Book"); +export const book = localize('book', "Jupyter Book"); export const version = localize('version', "Version"); export const language = localize('language', "Language"); -export const booksNotFound = localize('booksNotFound', "No books are currently available on the provided link"); +export const booksNotFound = localize('booksNotFound', "No Jupyter Books are currently available on the provided link"); export const urlGithubError = localize('urlGithubError', "The url provided is not a Github release url"); export const search = localize('search', "Search"); export const add = localize('add', "Add"); @@ -70,22 +70,23 @@ export const close = localize('close', "Close"); export const invalidTextPlaceholder = localize('invalidTextPlaceholder', "-"); // Remote Book Controller constants -export const msgRemoteBookDownloadProgress = localize('msgRemoteBookDownloadProgress', "Remote Book download is in progress"); -export const msgRemoteBookDownloadComplete = localize('msgRemoteBookDownloadComplete', "Remote Book download is complete"); -export const msgRemoteBookDownloadError = localize('msgRemoteBookDownloadError', "Error while downloading remote Book"); -export const msgRemoteBookUnpackingError = localize('msgRemoteBookUnpackingError', "Error while decompressing remote Book"); -export const msgRemoteBookDirectoryError = localize('msgRemoteBookDirectoryError', "Error while creating remote Book directory"); -export const msgTaskName = localize('msgTaskName', "Downloading Remote Book"); +export const msgRemoteBookDownloadProgress = localize('msgRemoteBookDownloadProgress', "Remote Jupyter Book download is in progress"); +export const msgRemoteBookDownloadComplete = localize('msgRemoteBookDownloadComplete', "Remote Jupyter Book download is complete"); +export const msgRemoteBookDownloadError = localize('msgRemoteBookDownloadError', "Error while downloading remote Jupyter Book"); +export const msgRemoteBookUnpackingError = localize('msgRemoteBookUnpackingError', "Error while decompressing remote Jupyter Book"); +export const msgRemoteBookDirectoryError = localize('msgRemoteBookDirectoryError', "Error while creating remote Jupyter Book directory"); +export const msgTaskName = localize('msgTaskName', "Downloading Remote Jupyter Book"); export const msgResourceNotFound = localize('msgResourceNotFound', "Resource not Found"); -export const msgBookNotFound = localize('msgBookNotFound', "Books not Found"); +export const msgBookNotFound = localize('msgBookNotFound', "Jupyter Books not Found"); export const msgReleaseNotFound = localize('msgReleaseNotFound', "Releases not Found"); -export const msgUndefinedAssetError = localize('msgUndefinedAssetError', "The selected book is not valid"); +export const msgUndefinedAssetError = localize('msgUndefinedAssetError', "The selected Jupyter Book is not valid"); export function httpRequestError(code: number, message: string): string { return localize('httpRequestError', "Http Request failed with error: {0} {1}", code, message); } export function msgDownloadLocation(downloadLocation: string): string { return localize('msgDownloadLocation', "Downloading to {0}", downloadLocation); } // Create Book dialog constants -export const newGroup = localize('newGroup', "New Book"); -export const groupDescription = localize('groupDescription', "Books are used to organize Notebooks."); +export const newBook = localize('newBook', "New Jupyter Book (Preview)"); +export const bookDescription = localize('bookDescription', "Jupyter Books are used to organize Notebooks."); +export const learnMore = localize('learnMore', "Learn more."); export const locationBrowser = localize('locationBrowser', "Browse locations..."); export const selectContentFolder = localize('selectContentFolder', "Select content folder"); export const browse = localize('browse', "Browse"); diff --git a/extensions/notebook/src/dialog/addFileDialog.ts b/extensions/notebook/src/dialog/addFileDialog.ts index 872e730ccf..68ad285014 100644 --- a/extensions/notebook/src/dialog/addFileDialog.ts +++ b/extensions/notebook/src/dialog/addFileDialog.ts @@ -94,8 +94,8 @@ export class AddFileDialog { private async createFile(): Promise { try { - const dirPath = this._bookItem.contextValue === BookTreeItemType.savedBook ? this._bookItem.rootContentPath : path.dirname(this._bookItem.resourceUri.fsPath); - const filePath = path.join(dirPath, this._fileNameInputBox.value).concat(this._extension); + const dirPath = this._bookItem.contextValue === BookTreeItemType.savedBook ? this._bookItem.rootContentPath : path.dirname(this._bookItem.book.contentPath); + const filePath = path.posix.join(dirPath, this._fileNameInputBox.value).concat(this._extension); await this.validatePath(dirPath, this._fileNameInputBox.value.concat(this._extension)); const pathDetails = new TocEntryPathHandler(filePath, this._bookItem.rootContentPath, this._titleInputBox.value); await this._tocManager.addNewFile(pathDetails, this._bookItem); diff --git a/extensions/notebook/src/dialog/createBookDialog.ts b/extensions/notebook/src/dialog/createBookDialog.ts index bfea20d317..7621d01a6c 100644 --- a/extensions/notebook/src/dialog/createBookDialog.ts +++ b/extensions/notebook/src/dialog/createBookDialog.ts @@ -63,13 +63,20 @@ export class CreateBookDialog { } public async createDialog(): Promise { - this.dialog = azdata.window.createModelViewDialog(loc.newGroup); + this.dialog = azdata.window.createModelViewDialog(loc.newBook); this.dialog.registerContent(async view => { this.view = view; - const groupLabel = this.view.modelBuilder.text() + const jupyterBookDocumentation = this.view.modelBuilder.hyperlink() + .withProperties({ + label: loc.learnMore, + url: 'https://jupyterbook.org/intro.html', + CSSStyles: { 'margin-bottom': '0px', 'margin-top': '0px', 'font-size': 'small' } + }).component(); + + const bookLabel = this.view.modelBuilder.text() .withProperties({ - value: loc.groupDescription, + value: loc.bookDescription, CSSStyles: { 'margin-bottom': '0px', 'margin-top': '0px', 'font-size': 'small' } }).component(); @@ -120,8 +127,8 @@ export class CreateBookDialog { .withFormItems([{ components: [ { - component: groupLabel, - required: false + required: false, + component: this.createHorizontalContainer(view, [bookLabel, jupyterBookDocumentation]) }, { component: this.bookNameInputBox,