Compare commits

...

16 Commits

Author SHA1 Message Date
Chris LaFreniere
0f5cfdc2c8 Handle key_up in callout dialog (#15472) (#15485) 2021-05-14 12:04:15 -07:00
Charles Gagnon
1d6427ce89 Fix Issue Reporter (#15467) (#15475)
(cherry picked from commit d797ef433a)
2021-05-13 21:44:28 -07:00
Alan Ren
4356e49793 fix animated svg issue (#15471) (#15473) 2021-05-13 20:13:56 -07:00
Hai Cao
12662f7427 Fix link handling in viewPane (#15458) (#15468) 2021-05-13 15:26:01 -07:00
Aditya Bist
6e1f995286 fix azure context menu (#15447) (#15462)
* fix azure context menu

* fix node issue

* change to undefined

* just use interface

* set connection profile

* add save profile
2021-05-13 14:13:32 -07:00
Aditya Bist
c5508cf46a Fix cloud shell (#15452) (#15461)
* fix cloud shell

* better logic for dimensions

* fix dimension type

* change terminate to close
2021-05-13 14:12:08 -07:00
Udeesha Gautam
3f10d89db3 Doing a point fix for backup since select box has impact on other features (#15415) (#15456) 2021-05-13 12:45:24 -07:00
Barbara Valdez
419c2324c9 Notebooks View: Do not recenter view when selecting a notebook that is visible (#15442) (#15455)
* do not focus element when tree item is visible

* reset reveal behavior

* add comment
2021-05-13 10:46:46 -07:00
Benjin Dubishar
166faccf1e added missing await, removed duplicate okay button checks (#15450) (#15454) 2021-05-13 10:46:15 -07:00
Chris LaFreniere
e5f9790ed1 Notebooks: Fix Table Generation into Pure Markdown When No thead Exists (#15423) (#15448)
* works without alignment

* Alignment working

* Add comment

* Remove outdated comment
2021-05-12 17:57:02 -07:00
Charles Gagnon
e7fbedfe65 Fix dashboard icons (#15400) (#15431)
* Fix dashboard icons

* Split out custom SQL menu items

* Put on same line
2021-05-12 14:08:04 -07:00
Charles Gagnon
e291a25104 Fix event prefix (#15429) (#15433) 2021-05-12 13:50:37 -07:00
Lucy Zhang
4d3787dbc0 skip text cell smoketest (#15411) (#15417) 2021-05-12 10:23:11 -07:00
Aditya Bist
56cc1202d5 update remote yarn lock (#15419) (#15424)
* update yarn lock to use 2.9.4 when ^2.6.0 is used

* update main yarn lock

* update yarn lock for remote/web
2021-05-11 20:07:49 -07:00
Alan Ren
e3b238c017 remove the filters not applicable to ads (#15409) (#15418) 2021-05-11 16:27:21 -07:00
Aasim Khan
ed5bb14b11 Adding all the arm libraries as external dependencies in azurecore webpack (#15398) (#15399) 2021-05-11 13:41:38 -07:00
39 changed files with 366 additions and 290 deletions

View File

@@ -16,6 +16,8 @@ const externals = {
'bufferutil': 'commonjs bufferutil',
'utf-8-validate': 'commonjs utf-8-validate',
'keytar': 'commonjs keytar',
'@azure/arm-subscriptions': 'commonjs @azure/arm-subscriptions',
'@azure/arm-resourcegraph': 'commonjs @azure/arm-resourcegraph'
};
// conditionally add ws if we are going to be running in a node environment

View File

@@ -181,17 +181,22 @@ export function registerAzureResourceCommands(appContext: AppContext, azureViewT
vscode.commands.executeCommand('workbench.actions.modal.linkedAccount');
});
vscode.commands.registerCommand('azure.resource.connectsqlserver', async (node?: TreeNode) => {
vscode.commands.registerCommand('azure.resource.connectsqlserver', async (node?: TreeNode | azdata.ObjectExplorerContext) => {
if (!node) {
return;
}
const treeItem: azdata.TreeItem = await node.getTreeItem();
if (!treeItem.payload) {
return;
let connectionProfile: azdata.IConnectionProfile = undefined;
if (node instanceof TreeNode) {
const treeItem: azdata.TreeItem = await node.getTreeItem();
if (!treeItem.payload) {
return;
}
// Ensure connection is saved to the Connections list, then open connection dialog
connectionProfile = Object.assign({}, treeItem.payload, { saveProfile: true });
} else if (node.isConnectionNode) {
connectionProfile = Object.assign({}, node.connectionProfile, { saveProfile: true });
}
// Ensure connection is saved to the Connections list, then open connection dialog
let connectionProfile = Object.assign({}, treeItem.payload, { saveProfile: true });
const conn = await azdata.connection.openConnectionDialog(undefined, connectionProfile, { saveConnection: true, showDashboard: true });
if (conn) {
vscode.commands.executeCommand('workbench.view.connections');

View File

@@ -103,7 +103,7 @@ export class AzureTerminalService implements IAzureTerminalService {
}
}
const shells = [new ShellType('PowerShell', 'pwsh'), new ShellType('Bash', 'bash'),];
const shells = [new ShellType('PowerShell', 'pwsh'), new ShellType('Bash', 'bash')];
const idx = shells.findIndex(s => s.value === preferredShell);
const prefShell = shells.splice(idx, 1);
@@ -157,7 +157,7 @@ class AzureTerminal implements vscode.Pseudoterminal {
}
async open(initialDimensions: vscode.TerminalDimensions): Promise<void> {
this.setDimensions(initialDimensions);
await this.setDimensions(initialDimensions);
}
close(): void {
@@ -167,14 +167,19 @@ class AzureTerminal implements vscode.Pseudoterminal {
this.socket.removeAllListeners('message');
this.socket.removeAllListeners('close');
this.socket.terminate();
this.socket.close();
if (this.intervalTimer) {
clearInterval(this.intervalTimer);
}
}
private areSameDimensions(oldDimensions: vscode.TerminalDimensions | undefined, newDimensions: vscode.TerminalDimensions): boolean {
return oldDimensions?.columns === newDimensions.columns && oldDimensions?.rows === newDimensions.rows;
}
async setDimensions(dimensions: vscode.TerminalDimensions): Promise<void> {
if (!dimensions) {
if (!dimensions || this.areSameDimensions(this.terminalDimensions, dimensions)) {
return;
}
this.terminalDimensions = dimensions;

View File

@@ -68,7 +68,7 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
book && // The notebook is part of a book in the viewlet (otherwise nothing to reveal)
(this._openAsUntitled ? notebookPath?.scheme === 'untitled' : notebookPath?.scheme !== 'untitled')) // The notebook is of the correct type for this tree view
{
await this.revealDocumentInTreeView(notebookPath);
await this.revealDocumentInTreeView(notebookPath, true, true);
}
});
this._extensionContext.subscriptions.push(azdata.nb.registerNavigationProvider(this));
@@ -391,7 +391,13 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
}
}
async revealDocumentInTreeView(uri?: vscode.Uri, shouldReveal: boolean = true): Promise<BookTreeItem | undefined> {
/**
* Reveals the given uri in the tree view.
* @param uri The path to the notebook. If it's undefined then the current active notebook is revealed in the Tree View.
* @param shouldReveal A boolean to expand the parent node.
* @param shouldFocus A boolean to focus on the tree item.
*/
async revealDocumentInTreeView(uri: vscode.Uri | undefined, shouldReveal: boolean, shouldFocus: boolean): Promise<BookTreeItem | undefined> {
let bookItem: BookTreeItem;
let notebookPath: string;
// If no uri is passed in, try to use the current active notebook editor
@@ -405,17 +411,18 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
}
if (shouldReveal || this._bookViewer?.visible) {
bookItem = notebookPath ? await this.findAndExpandParentNode(notebookPath) : undefined;
bookItem = notebookPath ? await this.findAndExpandParentNode(notebookPath, shouldFocus) : undefined;
// Select + focus item in viewlet if books viewlet is already open, or if we pass in variable
if (bookItem?.contextValue && bookItem.contextValue !== 'pinnedNotebook') {
// Note: 3 is the maximum number of levels that the vscode APIs let you expand to
await this._bookViewer.reveal(bookItem, { select: true, focus: true, expand: true });
await this._bookViewer.reveal(bookItem, { select: true, focus: shouldFocus, expand: true });
}
}
return bookItem;
}
async findAndExpandParentNode(notebookPath: string): Promise<BookTreeItem | undefined> {
async findAndExpandParentNode(notebookPath: string, shouldFocus: boolean): Promise<BookTreeItem | undefined> {
notebookPath = notebookPath.replace(/\\/g, '/');
const parentBook = this.books.find(b => notebookPath.indexOf(b.bookPath) > -1);
if (!parentBook) {
@@ -470,7 +477,7 @@ export class BookTreeViewProvider implements vscode.TreeDataProvider<BookTreeIte
}
try {
// TO DO: Check why the reveal fails during initial load with 'TreeError [bookTreeView] Tree element not found'
await this._bookViewer.reveal(bookItemToExpand, { select: false, focus: true, expand: true });
await this._bookViewer.reveal(bookItemToExpand, { select: false, focus: shouldFocus, expand: true });
}
catch (e) {
console.error(e);

View File

@@ -150,9 +150,9 @@ export async function activate(extensionContext: vscode.ExtensionContext): Promi
azdata.nb.onDidChangeActiveNotebookEditor(e => {
if (e.document.uri.scheme === 'untitled') {
providedBookTreeViewProvider.revealDocumentInTreeView(e.document.uri, false);
providedBookTreeViewProvider.revealDocumentInTreeView(e.document.uri, false, false);
} else {
bookTreeViewProvider.revealDocumentInTreeView(e.document.uri, false);
bookTreeViewProvider.revealDocumentInTreeView(e.document.uri, false, false);
}
});

View File

@@ -244,7 +244,7 @@ describe('BooksTreeViewTests', function () {
it('revealActiveDocumentInViewlet should return correct bookItem for highlight', async () => {
let notebook1Path = path.join(rootFolderPath, 'Book', 'content', 'notebook1.ipynb').replace(/\\/g, '/');
let currentSelection = await bookTreeViewProvider.findAndExpandParentNode(notebook1Path);
let currentSelection = await bookTreeViewProvider.findAndExpandParentNode(notebook1Path, true);
should(currentSelection).not.be.undefined();
equalBookItems(currentSelection, expectedNotebook1);
});
@@ -329,7 +329,7 @@ describe('BooksTreeViewTests', function () {
it('revealActiveDocumentInViewlet should return correct bookItem for highlight', async () => {
let notebook1Path = path.join(rootFolderPath, 'Book', 'content', 'notebook1.ipynb').replace(/\\/g, '/');
let currentSelection = await providedbookTreeViewProvider.findAndExpandParentNode(notebook1Path);
let currentSelection = await providedbookTreeViewProvider.findAndExpandParentNode(notebook1Path, true);
should(currentSelection).not.be.undefined();
equalBookItems(currentSelection, expectedNotebook1);
});

View File

@@ -221,8 +221,8 @@ export class SchemaCompareDialog {
this.sourceDacpacComponent = this.createFileBrowser(false, this.schemaCompareMainWindow.sourceEndpointInfo);
this.targetDacpacComponent = this.createFileBrowser(true, this.schemaCompareMainWindow.targetEndpointInfo);
let sourceRadioButtons = this.createSourceRadiobuttons();
let targetRadioButtons = this.createTargetRadiobuttons();
let sourceRadioButtons = this.createSourceRadioButtons();
let targetRadioButtons = this.createTargetRadioButtons();
let sourceComponents = [];
let targetComponents = [];
@@ -336,7 +336,7 @@ export class SchemaCompareDialog {
};
}
private createSourceRadiobuttons(): azdata.FormComponent {
private createSourceRadioButtons(): azdata.FormComponent {
this.sourceDacpacRadioButton = this.view.modelBuilder.radioButton()
.withProperties({
name: 'source',
@@ -365,8 +365,7 @@ export class SchemaCompareDialog {
this.formBuilder.insertFormItem(this.sourceDatabaseComponent, 3, { horizontal: true, titleFontSize: titleFontSize });
this.formBuilder.removeFormItem(this.sourceDacpacComponent);
this.populateServerDropdown(false);
this.dialog.okButton.enabled = await this.shouldEnableOkayButton();
await this.populateServerDropdown(false);
});
// if source is currently a db, show it in the server and db dropdowns
@@ -389,7 +388,7 @@ export class SchemaCompareDialog {
};
}
private createTargetRadiobuttons(): azdata.FormComponent {
private createTargetRadioButtons(): azdata.FormComponent {
let dacpacRadioButton = this.view.modelBuilder.radioButton()
.withProperties({
name: 'target',
@@ -418,8 +417,7 @@ export class SchemaCompareDialog {
this.formBuilder.addFormItem(this.targetServerComponent, { horizontal: true, titleFontSize: titleFontSize });
this.formBuilder.addFormItem(this.targetDatabaseComponent, { horizontal: true, titleFontSize: titleFontSize });
this.populateServerDropdown(true);
this.dialog.okButton.enabled = await this.shouldEnableOkayButton();
await this.populateServerDropdown(true);
});
// if target is currently a db, show it in the server and db dropdowns
@@ -445,7 +443,6 @@ export class SchemaCompareDialog {
}
private async shouldEnableOkayButton(): Promise<boolean> {
let sourcefilled = (this.sourceIsDacpac && await this.existsDacpac(this.sourceTextBox.value))
|| (!this.sourceIsDacpac && !isNullOrUndefined(this.sourceDatabaseDropdown.value) && this.sourceDatabaseDropdown.values.findIndex(x => this.matchesValue(x, this.sourceDbEditable)) !== -1);
let targetfilled = (this.targetIsDacpac && await this.existsDacpac(this.targetTextBox.value))
@@ -720,6 +717,7 @@ export class SchemaCompareDialog {
});
}
this.dialog.okButton.enabled = await this.shouldEnableOkayButton();
currentDropdown.loading = false;
}

View File

@@ -73,15 +73,7 @@ chalk@^2.4.1, chalk@^2.4.2:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chart.js@^2.6.0:
version "2.9.1"
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.9.1.tgz#e98893a810d40d1c0a016e6872a13fa5faedcdf8"
integrity sha512-DA5dFt0Bz79oz56ezmrwmZqj0hXGs+i9VbCFOcHqbwrHIGv7RI4YqninJKNIAC0qa29WBI9qYTN7LzULlOeunA==
dependencies:
chartjs-color "^2.1.0"
moment "^2.10.2"
chart.js@^2.9.4:
chart.js@^2.6.0, chart.js@^2.9.4:
version "2.9.4"
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.9.4.tgz#0827f9563faffb2dc5c06562f8eb10337d5b9684"
integrity sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==

View File

@@ -140,15 +140,7 @@ chalk@^2.4.1, chalk@^2.4.2:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chart.js@^2.6.0:
version "2.9.1"
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.9.1.tgz#e98893a810d40d1c0a016e6872a13fa5faedcdf8"
integrity sha512-DA5dFt0Bz79oz56ezmrwmZqj0hXGs+i9VbCFOcHqbwrHIGv7RI4YqninJKNIAC0qa29WBI9qYTN7LzULlOeunA==
dependencies:
chartjs-color "^2.1.0"
moment "^2.10.2"
chart.js@^2.9.4:
chart.js@^2.6.0, chart.js@^2.9.4:
version "2.9.4"
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.9.4.tgz#0827f9563faffb2dc5c06562f8eb10337d5b9684"
integrity sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==

View File

@@ -97,7 +97,7 @@
window['MonacoEnvironment'] = {};
const baseUrl = useCustomProtocol ?
`${bootstrapLib.fileUriFromPath(configuration.appRoot, { isWindows: safeProcess.platform === 'win32', scheme: 'azuredatastudio-file', fallbackAuthority: 'azuredatastudio-app' })}/out` :
`${bootstrapLib.fileUriFromPath(configuration.appRoot, { isWindows: safeProcess.platform === 'win32', scheme: 'vscode-file', fallbackAuthority: 'vscode-app' })}/out` :
`${bootstrapLib.fileUriFromPath(configuration.appRoot, { isWindows: safeProcess.platform === 'win32' })}/out`;
const loaderConfig = {

View File

@@ -14,8 +14,8 @@
circle:nth-child(8) { animation-delay: 0.525s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
0% { opacity: 1; }
100% { opacity: 0.3; }
}
</style>
<g>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -14,8 +14,8 @@
circle:nth-child(8) { animation-delay: 0.525s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
0% { opacity: 1; }
100% { opacity: 0.3; }
}
</style>
<g style="fill:white;">

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,164 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { asCSSUrl, createCSSRule } from 'vs/base/browser/dom';
import { IdGenerator } from 'vs/base/common/idGenerator';
import { IDisposable, toDisposable, dispose } from 'vs/base/common/lifecycle';
import { ICommandAction, MenuItemAction } from 'vs/platform/actions/common/actions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
const ids = new IdGenerator('menu-item-action-item-icon-');
const ICON_PATH_TO_CSS_RULES = new Map<string /* path*/, string /* CSS rule */>();
/**
* Always show label for action items, instead of whether they don't have
* an icon/CSS class. Useful for some toolbar scenarios in particular with
* contributed actions from other extensions
*/
export class LabeledMenuItemActionItem extends MenuEntryActionViewItem {
private _labeledItemClassDispose?: IDisposable;
constructor(
public _action: MenuItemAction,
@IKeybindingService labeledkeybindingService: IKeybindingService,
@INotificationService protected _notificationService: INotificationService,
private readonly _defaultCSSClassToAdd: string = ''
) {
super(_action, labeledkeybindingService, _notificationService);
}
updateLabel(): void {
if (this.label) {
this.label.innerText = this._commandAction.label;
}
}
// Overwrite item class to ensure that we can pass in a CSS class that other items use
// Leverages the _defaultCSSClassToAdd property that's passed into the constructor
protected _updateItemClass(item: ICommandAction): void {
dispose(this._labeledItemClassDispose);
this._labeledItemClassDispose = undefined;
if (ThemeIcon.isThemeIcon(item.icon)) {
// TODO
} else if (item.icon) {
let iconClass: string;
if (item.icon?.dark?.scheme) {
const iconPathMapKey = item.icon.dark.toString();
if (ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) {
iconClass = ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!;
} else {
iconClass = ids.nextId();
createCSSRule(`.codicon.${iconClass}`, `background-image: ${asCSSUrl(item.icon.light || item.icon.dark)} !important`);
createCSSRule(`.vs-dark .codicon.${iconClass}, .hc-black .codicon.${iconClass}`, `background-image: ${asCSSUrl(item.icon.dark)} !important`);
ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass);
}
if (this.label) {
const iconClasses = iconClass.split(' ');
if (this._defaultCSSClassToAdd) {
iconClasses.push(this._defaultCSSClassToAdd);
}
this.label.classList.add('codicon', ...iconClasses);
this._labeledItemClassDispose = toDisposable(() => {
if (this.label) {
this.label.classList.remove('codicon', ...iconClasses);
}
});
}
}
}
}
dispose(): void {
if (this._labeledItemClassDispose) {
dispose(this._labeledItemClassDispose);
this._labeledItemClassDispose = undefined;
}
super.dispose();
}
}
/**
* This is a duplicate of LabeledMenuItemActionItem with the following exceptions:
* - Adds CSS class: `masked-icon` to contributed actions label element.
* - Adds style rule for masked-icon.
*/
export class MaskedLabeledMenuItemActionItem extends MenuEntryActionViewItem {
private _labeledItemClassDispose?: IDisposable;
constructor(
public _action: MenuItemAction,
@IKeybindingService labeledkeybindingService: IKeybindingService,
@INotificationService protected _notificationService: INotificationService,
private readonly _defaultCSSClassToAdd: string = ''
) {
super(_action, labeledkeybindingService, _notificationService);
}
updateLabel(): void {
if (this.label) {
this.label.innerText = this._commandAction.label;
}
}
// Overwrite item class to ensure that we can pass in a CSS class that other items use
// Leverages the _defaultCSSClassToAdd property that's passed into the constructor
protected _updateItemClass(item: ICommandAction): void {
dispose(this._labeledItemClassDispose);
this._labeledItemClassDispose = undefined;
if (ThemeIcon.isThemeIcon(item.icon)) {
// TODO
} else if (item.icon) {
let iconClass: string;
if (item.icon?.dark?.scheme) {
const iconPathMapKey = item.icon.dark.toString();
if (ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) {
iconClass = ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!;
} else {
iconClass = ids.nextId();
createCSSRule(`.codicon.masked-icon.${iconClass}::before`, `-webkit-mask-image: ${asCSSUrl(item.icon.light || item.icon.dark)}`);
createCSSRule(`.codicon.masked-icon.${iconClass}::before`, `mask-image: ${asCSSUrl(item.icon.light || item.icon.dark)}`);
ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass);
}
if (this.label) {
const iconClasses = iconClass.split(' ');
if (this._defaultCSSClassToAdd) {
iconClasses.push(this._defaultCSSClassToAdd);
}
this.label.classList.add('codicon', ...iconClasses);
this.label.classList.add('masked-icon', ...iconClasses);
this._labeledItemClassDispose = toDisposable(() => {
if (this.label) {
this.label.classList.remove('codicon', ...iconClasses);
}
});
}
}
}
}
dispose(): void {
if (this._labeledItemClassDispose) {
dispose(this._labeledItemClassDispose);
this._labeledItemClassDispose = undefined;
}
super.dispose();
}
}

View File

@@ -14,8 +14,8 @@
circle:nth-child(8) { animation-delay: 0.525s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
0% { opacity: 1; }
100% { opacity: 0.3; }
}
</style>
<g>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -14,8 +14,8 @@
circle:nth-child(8) { animation-delay: 0.525s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
0% { opacity: 1; }
100% { opacity: 0.3; }
}
</style>
<g style="fill:white;">

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -440,6 +440,9 @@ export class BackupComponent extends AngularDisposable {
// Set backup type
this.backupTypeSelectBox!.setOptions(this.backupTypeOptions, 0);
// The above call does not set the private variable for selectedOption variable in select box
// Doing a point fix for backup since select box changes have wider unwanted impact
this.backupTypeSelectBox!.select(0);
this.setDefaultBackupName();
this.backupNameBox!.focus();

View File

@@ -43,7 +43,7 @@ import * as DOM from 'vs/base/browser/dom';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { TaskRegistry } from 'sql/workbench/services/tasks/browser/tasksRegistry';
import { MenuRegistry, IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
import { fillInActions, LabeledMenuItemActionItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { fillInActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { NAV_SECTION } from 'sql/workbench/contrib/dashboard/browser/containers/dashboardNavSection.contribution';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
@@ -51,6 +51,7 @@ import { DASHBOARD_BORDER, EDITOR_PANE_BACKGROUND, TOOLBAR_OVERFLOW_SHADOW } fro
import { IColorTheme, registerThemingParticipant, ICssStyleCollector } from 'vs/platform/theme/common/themeService';
import { attachTabbedPanelStyler } from 'sql/workbench/common/styler';
import { focusBorder } from 'vs/platform/theme/common/colorRegistry';
import { LabeledMenuItemActionItem } from 'sql/platform/actions/browser/menuEntryActionViewItem';
const dashboardRegistry = Registry.as<IDashboardRegistry>(DashboardExtensions.DashboardContributions);
const homeTabGroupId = 'home';

View File

@@ -22,6 +22,7 @@ import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox';
import { attachCalloutDialogStyler } from 'sql/workbench/common/styler';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { escapeLabel, escapeUrl } from 'sql/workbench/contrib/notebook/browser/calloutDialog/common/utils';
import { KeyCode } from 'vs/base/common/keyCodes';
export interface ILinkCalloutDialogOptions {
insertTitle?: string,
@@ -100,6 +101,13 @@ export class LinkCalloutDialog extends Modal {
}
protected renderBody(container: HTMLElement) {
this._register(DOM.addDisposableListener(document, DOM.EventType.KEY_UP, (e: KeyboardEvent) => {
let event = new StandardKeyboardEvent(e);
if (event.equals(KeyCode.Enter)) {
DOM.EventHelper.stop(e, true);
this.hide('ok');
}
}));
let linkContentColumn = DOM.$('.column.insert-link');
DOM.append(container, linkContentColumn);
@@ -147,7 +155,8 @@ export class LinkCalloutDialog extends Modal {
protected onAccept(e?: StandardKeyboardEvent) {
// EventHelper.stop() will call preventDefault. Without it, text cell will insert an extra newline when pressing enter on dialog
DOM.EventHelper.stop(e, true);
this.insert();
const keyboardEventExists = !!e;
this.insert(keyboardEventExists);
}
protected onClose(e?: StandardKeyboardEvent) {
@@ -155,8 +164,10 @@ export class LinkCalloutDialog extends Modal {
this.cancel();
}
public insert(): void {
this.hide('ok');
public insert(willHideByKeyboardEvent = false): void {
if (!willHideByKeyboardEvent) {
this.hide('ok');
}
let escapedLabel = escapeLabel(this._linkTextInputBox.value);
let escapedUrl = escapeUrl(this._linkUrlInputBox.value);

View File

@@ -266,6 +266,15 @@ export class HTMLMarkdownConverter {
return delimiter + leadingSpace + content + trailingSpace + delimiter;
}
});
this.turndownService.addRule('p', {
filter: 'p',
replacement: function (content, node) {
// If inside of a table cell, extra newlines would break table rendering
return isInsideTable(node) ? content : '\n\n' + content + '\n\n';
}
});
this.turndownService.escape = escapeMarkdown;
}
}
@@ -281,10 +290,16 @@ function blankReplacement(content, node) {
// When outdenting a nested list, an empty list will still remain. Need to handle this case.
if (node.nodeName === 'UL' || node.nodeName === 'OL') {
return '\n';
} else if (isInsideTable(node)) {
return ' ';
}
return node.isBlock ? '\n\n' : '';
}
function isInsideTable(node): boolean {
return node.parentNode?.nodeName === 'TH' || node.parentNode?.nodeName === 'TD';
}
export function findPathRelativeToContent(notebookFolder: string, contentPath: URI | undefined): string {
if (notebookFolder) {
if (contentPath?.scheme === 'file') {

View File

@@ -41,7 +41,7 @@ import { createErrorWithActions } from 'vs/base/common/errorsWithActions';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { ILogService } from 'vs/platform/log/common/log';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { MaskedLabeledMenuItemActionItem, fillInActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { fillInActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { Button } from 'sql/base/browser/ui/button/button';
import { isUndefinedOrNull } from 'vs/base/common/types';
import { IBootstrapParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams';
@@ -52,6 +52,7 @@ import { NotebookInput } from 'sql/workbench/contrib/notebook/browser/models/not
import { IColorTheme } from 'vs/platform/theme/common/themeService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { CellToolbarComponent } from 'sql/workbench/contrib/notebook/browser/cellViews/cellToolbar.component';
import { MaskedLabeledMenuItemActionItem } from 'sql/platform/actions/browser/menuEntryActionViewItem';
export const NOTEBOOK_SELECTOR: string = 'notebook-component';

View File

@@ -68,36 +68,23 @@ rules['tableCell'] = {
rules['tableRow'] = {
filter: 'tr',
replacement: function (content, node) {
let borderCells = '';
let alignMap = { left: ':--', right: '--:', center: ':-:' };
if (isHeadingRow(node)) {
for (let i = 0; i < node.childNodes.length; i++) {
let border = '---';
let align = (
node.childNodes[i].getAttribute('align') || ''
).toLowerCase();
if (align) {
border = alignMap[align] || border;
}
borderCells += cell(border, node.childNodes[i]);
}
}
const borderCells = isHeadingRow(node) ? constructBorderCells(node) : '';
return '\n' + content + (borderCells ? '\n' + borderCells : '');
}
};
rules['table'] = {
// Only convert tables with a heading row.
// Tables with no heading row are kept using `keep` (see below).
filter: function (node) {
return node.nodeName === 'TABLE' && isHeadingRow(node.rows[0]);
return node.nodeName === 'TABLE';
},
replacement: function (content, node) {
// Ensure there are no blank lines
content = content.replace('\n\n', '\n');
// if the headings are empty, add border line and headings to keep table format
if (!isHeadingRow(node.rows[0])) {
let emptyHeader = '\n\n|' + ' |'.repeat(node.rows[0].childNodes.length) + '\n';
return emptyHeader + constructBorderCells(node.rows[0]) + content + '\n\n';
}
return '\n\n' + content + '\n\n';
}
};
@@ -148,10 +135,25 @@ function cell(content, node) {
return prefix + content + ' |';
}
function constructBorderCells(node): string {
const alignMap = { left: ':--', right: '--:', center: ':-:' };
let borderCells = '';
for (let i = 0; i < node.childNodes.length; i++) {
let border = '---';
let align = (
node.childNodes[i].getAttribute('align') || ''
).toLowerCase();
if (align) {
border = alignMap[align] || border;
}
borderCells += cell(border, node.childNodes[i]);
}
return borderCells;
}
export function tables(turndownService) {
turndownService.keep(function (node) {
return node.nodeName === 'TABLE' && !isHeadingRow(node.rows[0]);
});
for (let key in rules) {
turndownService.addRule(key, rules[key]);
}

View File

@@ -228,6 +228,38 @@ suite('HTML Markdown Converter', function (): void {
assert.equal(htmlMarkdownConverter.convert(htmlString), `| Test | Test | Test |\n| --- | --- | --- |\n| test | test | test |\n| test | test | test |\n| test | test | test |\n| test | test | test |`, 'Table with no thead failed');
});
test('Should transform table with only tbody - typical Office scenario', () => {
htmlString = '<table><tbody><tr>\n<td>test1</td>\n<td>test2</td>\n<td>test3</td>\n</tr></tbody></table>\n';
assert.equal(htmlMarkdownConverter.convert(htmlString), `| | | |\n| --- | --- | --- |\n| test1 | test2 | test3 |`, 'One row test with only tbody failed');
htmlString = '<table><tbody><tr>\n<td>test1</td>\n</tr></tbody></table>\n';
assert.equal(htmlMarkdownConverter.convert(htmlString), `| |\n| --- |\n| test1 |`, 'One row one cell test with only tbody failed');
htmlString = '<table><tbody><tr>\n<td>test1</td>\n<td>test2</td>\n<td>test3</td>\n</tr>\n<tr>\n<td>test4</td>\n<td>test5</td>\n<td>test6</td>\n</tr>\n<tr>\n<td>test7</td>\n<td>test8</td>\n<td>test9</td>\n</tr>\n<tr>\n<td>test10</td>\n<td>test11</td>\n<td>test12</td>\n</tr>\n</tbody></table>\n';
assert.equal(htmlMarkdownConverter.convert(htmlString), `| | | |\n| --- | --- | --- |\n| test1 | test2 | test3 |\n| test4 | test5 | test6 |\n| test7 | test8 | test9 |\n| test10 | test11 | test12 |`, 'Table with no thead failed');
});
test('Should transform table with paragraph cell correctly', () => {
htmlString = '<table><thead><tr><th>Test</th><th>Test2</th></tr></thead><tbody><tr><td><p>testP</p></td><td>test</td></tr></tbody></table>';
assert.equal(htmlMarkdownConverter.convert(htmlString), `| Test | Test2 |\n| --- | --- |\n| testP | test |`, 'Table with simple nested paragraph failed');
htmlString = '<table><thead><tr><th><p>Test</p></th><th><p>Test2</p></th></tr></thead><tbody><tr><td><p>testP</p></td><td><p>test</p></td></tr></tbody></table>';
assert.equal(htmlMarkdownConverter.convert(htmlString), `| Test | Test2 |\n| --- | --- |\n| testP | test |`, 'Table with every element with nested paragraph failed');
});
test('Should keep highlight and link tags in tables', () => {
htmlString = '<table><thead><tr><th><mark>Test</mark></th><th>Test2</th></tr></thead><tbody><tr><td><p>testP</p></td><td>test</td></tr></tbody></table>';
assert.equal(htmlMarkdownConverter.convert(htmlString), `| <mark>Test</mark> | Test2 |\n| --- | --- |\n| testP | test |`, 'Table with simple nested paragraph failed');
htmlString = '<table><thead><tr><th><p><a href="https://www.microsoft.com/">Test</a></p></th><th><p>Test2</p></th></tr></thead><tbody><tr><td><p>testP</p></td><td><p>test</p></td></tr></tbody></table>';
assert.equal(htmlMarkdownConverter.convert(htmlString), `| [Test](https://www.microsoft.com/) | Test2 |\n| --- | --- |\n| testP | test |`, 'Table with link in cell failed');
});
test('Should transform table with column alignment', () => {
htmlString = '<table>\n<thead>\n<tr>\n<th align=right>Test</th>\n<th>Test</th>\n<th>Test</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>test</td>\n<td>test</td>\n<td>test</td>\n</tr>\n<tr>\n<td>test</td>\n<td>test</td>\n<td>test</td>\n</tr>\n<tr>\n<td>test</td>\n<td>test</td>\n<td>test</td>\n</tr>\n<tr>\n<td>test</td>\n<td>test</td>\n<td>test</td>\n</tr>\n</tbody></table>\n';
assert.equal(htmlMarkdownConverter.convert(htmlString), `| Test | Test | Test |\n| --: | --- | --- |\n| test | test | test |\n| test | test | test |\n| test | test | test |\n| test | test | test |`, 'Table with right align column header failed');
htmlString = '<table>\n<thead>\n<tr>\n<th align=left>Test</th>\n<th>Test</th>\n<th>Test</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>test</td>\n<td>test</td>\n<td>test</td>\n</tr>\n<tr>\n<td>test</td>\n<td>test</td>\n<td>test</td>\n</tr>\n<tr>\n<td>test</td>\n<td>test</td>\n<td>test</td>\n</tr>\n<tr>\n<td>test</td>\n<td>test</td>\n<td>test</td>\n</tr>\n</tbody></table>\n';
assert.equal(htmlMarkdownConverter.convert(htmlString), `| Test | Test | Test |\n| :-- | --- | --- |\n| test | test | test |\n| test | test | test |\n| test | test | test |\n| test | test | test |`, 'Table with left align column header failed');
htmlString = '<table>\n<thead>\n<tr>\n<th align=center>Test</th>\n<th>Test</th>\n<th>Test</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>test</td>\n<td>test</td>\n<td>test</td>\n</tr>\n<tr>\n<td>test</td>\n<td>test</td>\n<td>test</td>\n</tr>\n<tr>\n<td>test</td>\n<td>test</td>\n<td>test</td>\n</tr>\n<tr>\n<td>test</td>\n<td>test</td>\n<td>test</td>\n</tr>\n</tbody></table>\n';
assert.equal(htmlMarkdownConverter.convert(htmlString), `| Test | Test | Test |\n| :-: | --- | --- |\n| test | test | test |\n| test | test | test |\n| test | test | test |\n| test | test | test |`, 'Table with center align column header failed');
});
test('Should transform <b> and <strong> tags', () => {
htmlString = '<b>test string</b>';
assert.equal(htmlMarkdownConverter.convert(htmlString), '**test string**', 'Basic bold test failed');

View File

@@ -14,8 +14,8 @@
circle:nth-child(8) { animation-delay: 0.525s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
0% { opacity: 1; }
100% { opacity: 0.3; }
}
</style>
<g>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -14,8 +14,8 @@
circle:nth-child(8) { animation-delay: 0.525s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
0% { opacity: 1; }
100% { opacity: 0.3; }
}
</style>
<g style="fill:white;">

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -14,8 +14,8 @@
circle:nth-child(8) { animation-delay: 0.525s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
0% { opacity: 1; }
100% { opacity: 0.3; }
}
</style>
<g>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -14,8 +14,8 @@
circle:nth-child(8) { animation-delay: 0.525s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
0% { opacity: 1; }
100% { opacity: 0.3; }
}
</style>
<g style="fill:white;">

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -14,8 +14,8 @@
circle:nth-child(8) { animation-delay: 0.525s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
0% { opacity: 1; }
100% { opacity: 0.3; }
}
</style>
<g>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -14,8 +14,8 @@
circle:nth-child(8) { animation-delay: 0.525s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
0% { opacity: 1; }
100% { opacity: 0.3; }
}
</style>
<g style="fill:white;">

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -14,8 +14,8 @@
circle:nth-child(8) { animation-delay: 0.525s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
0% { opacity: 1; }
100% { opacity: 0.3; }
}
</style>
<g style="fill:grey;">

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -14,8 +14,8 @@
circle:nth-child(8) { animation-delay: 0.525s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
0% { opacity: 1; }
100% { opacity: 0.3; }
}
</style>
<g style="fill:white;">

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -14,8 +14,8 @@
circle:nth-child(8) { animation-delay: 0.525s; }
@keyframes ball {
from { opacity: 1; }
to { opacity: 0.3; }
0% { opacity: 1; }
100% { opacity: 0.3; }
}
</style>
<g>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -207,7 +207,7 @@ class SharedProcessMain extends Disposable {
// Application Insights
if (product.aiConfig && product.aiConfig.asimovKey && isBuilt) {
const appInsightsAppender = new AppInsightsAppender('monacoworkbench', null, product.aiConfig.asimovKey);
const appInsightsAppender = new AppInsightsAppender('adsworkbench', null, product.aiConfig.asimovKey); // {{SQL CARBON EDIT}} Use our own event prefix
this._register(toDisposable(() => appInsightsAppender.flush())); // Ensure the AI appender is disposed so that it flushes remaining data
telemetryAppender = combinedAppender(appInsightsAppender, telemetryAppender);
}

View File

@@ -151,7 +151,7 @@ class CliMain extends Disposable {
const appenders: AppInsightsAppender[] = [];
if (isBuilt && !extensionDevelopmentLocationURI && !environmentService.disableTelemetry && product.enableTelemetry) {
if (product.aiConfig && product.aiConfig.asimovKey) {
appenders.push(new AppInsightsAppender('monacoworkbench', null, product.aiConfig.asimovKey));
appenders.push(new AppInsightsAppender('adsworkbench', null, product.aiConfig.asimovKey)); // {{SQL CARBON EDIT}} Use our own event prefix
}
const config: ITelemetryServiceConfig = {

View File

@@ -4,11 +4,10 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./menuEntryActionViewItem';
import { asCSSUrl, createCSSRule, ModifierKeyEmitter } from 'vs/base/browser/dom';
import { asCSSUrl, ModifierKeyEmitter } from 'vs/base/browser/dom';
import { domEvent } from 'vs/base/browser/event';
import { IAction, Separator } from 'vs/base/common/actions';
import { IdGenerator } from 'vs/base/common/idGenerator'; // {{SQL CARBON EDIT}}
import { IDisposable, toDisposable, MutableDisposable, DisposableStore, dispose } from 'vs/base/common/lifecycle'; // {{SQL CARBON EDIT}}
import { IDisposable, toDisposable, MutableDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { localize } from 'vs/nls';
import { ICommandAction, IMenu, IMenuActionOptions, MenuItemAction, SubmenuItemAction, Icon } from 'vs/platform/actions/common/actions';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
@@ -45,8 +44,7 @@ function asDisposable(groups: ReadonlyArray<[string, ReadonlyArray<MenuItemActio
return disposables;
}
// {{SQL CARBON EDIT}} add export modifier
export function fillInActions(groups: ReadonlyArray<[string, ReadonlyArray<MenuItemAction | SubmenuItemAction>]>, target: IAction[] | { primary: IAction[]; secondary: IAction[]; }, useAlternativeActions: boolean, isPrimaryGroup: (group: string) => boolean = group => group === 'navigation', primaryMaxCount: number = Number.MAX_SAFE_INTEGER): void {
export function fillInActions(groups: ReadonlyArray<[string, ReadonlyArray<MenuItemAction | SubmenuItemAction>]>, target: IAction[] | { primary: IAction[]; secondary: IAction[]; }, useAlternativeActions: boolean, isPrimaryGroup: (group: string) => boolean = group => group === 'navigation', primaryMaxCount: number = Number.MAX_SAFE_INTEGER): void { // {{SQL CARBON EDIT}} add export modifier
let primaryBucket: IAction[];
let secondaryBucket: IAction[];
@@ -80,10 +78,6 @@ export function fillInActions(groups: ReadonlyArray<[string, ReadonlyArray<MenuI
}
}
const ids = new IdGenerator('menu-item-action-item-icon-'); // {{SQL CARBON EDIT}} - add back since custom toolbar menu is using below
const ICON_PATH_TO_CSS_RULES = new Map<string /* path*/, string /* CSS rule */>(); // {{SQL CARBON EDIT}} - add back since custom toolbar menu is using below
export class MenuEntryActionViewItem extends ActionViewItem {
private _wantsAltCommand: boolean = false;
@@ -262,150 +256,3 @@ export function createActionViewItem(instaService: IInstantiationService, action
return undefined;
}
}
// {{SQL CARBON EDIT}} - This is here to use the 'ids' generator above
// Always show label for action items, instead of whether they don't have
// an icon/CSS class. Useful for some toolbar scenarios in particular with
// contributed actions from other extensions
export class LabeledMenuItemActionItem extends MenuEntryActionViewItem {
private _labeledItemClassDispose?: IDisposable;
constructor(
public _action: MenuItemAction,
@IKeybindingService labeledkeybindingService: IKeybindingService,
@INotificationService protected _notificationService: INotificationService,
private readonly _defaultCSSClassToAdd: string = ''
) {
super(_action, labeledkeybindingService, _notificationService);
}
updateLabel(): void {
if (this.label) {
this.label.innerText = this._commandAction.label;
}
}
// Overwrite item class to ensure that we can pass in a CSS class that other items use
// Leverages the _defaultCSSClassToAdd property that's passed into the constructor
protected _updateItemClass(item: ICommandAction): void {
dispose(this._labeledItemClassDispose);
this._labeledItemClassDispose = undefined;
if (ThemeIcon.isThemeIcon(item.icon)) {
// TODO
} else if (item.icon) {
let iconClass: string;
if (item.icon?.dark?.scheme) {
const iconPathMapKey = item.icon.dark.toString();
if (ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) {
iconClass = ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!;
} else {
iconClass = ids.nextId();
createCSSRule(`.codicon.${iconClass}`, `background-image: ${asCSSUrl(item.icon.light || item.icon.dark)}`);
createCSSRule(`.vs-dark .codicon.${iconClass}, .hc-black .codicon.${iconClass}`, `background-image: ${asCSSUrl(item.icon.dark)}`);
ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass);
}
if (this.label) {
const iconClasses = iconClass.split(' ');
if (this._defaultCSSClassToAdd) {
iconClasses.push(this._defaultCSSClassToAdd);
}
this.label.classList.add('codicon', ...iconClasses);
this._labeledItemClassDispose = toDisposable(() => {
if (this.label) {
this.label.classList.remove('codicon', ...iconClasses);
}
});
}
}
}
}
dispose(): void {
if (this._labeledItemClassDispose) {
dispose(this._labeledItemClassDispose);
this._labeledItemClassDispose = undefined;
}
super.dispose();
}
}
/**
* This is a duplicate of LabeledMenuItemActionItem with the following exceptions:
* - Adds CSS class: `masked-icon` to contributed actions label element.
* - Adds style rule for masked-icon.
*/
export class MaskedLabeledMenuItemActionItem extends MenuEntryActionViewItem {
private _labeledItemClassDispose?: IDisposable;
constructor(
public _action: MenuItemAction,
@IKeybindingService labeledkeybindingService: IKeybindingService,
@INotificationService protected _notificationService: INotificationService,
private readonly _defaultCSSClassToAdd: string = ''
) {
super(_action, labeledkeybindingService, _notificationService);
}
updateLabel(): void {
if (this.label) {
this.label.innerText = this._commandAction.label;
}
}
// Overwrite item class to ensure that we can pass in a CSS class that other items use
// Leverages the _defaultCSSClassToAdd property that's passed into the constructor
protected _updateItemClass(item: ICommandAction): void {
dispose(this._labeledItemClassDispose);
this._labeledItemClassDispose = undefined;
if (ThemeIcon.isThemeIcon(item.icon)) {
// TODO
} else if (item.icon) {
let iconClass: string;
if (item.icon?.dark?.scheme) {
const iconPathMapKey = item.icon.dark.toString();
if (ICON_PATH_TO_CSS_RULES.has(iconPathMapKey)) {
iconClass = ICON_PATH_TO_CSS_RULES.get(iconPathMapKey)!;
} else {
iconClass = ids.nextId();
createCSSRule(`.codicon.masked-icon.${iconClass}::before`, `-webkit-mask-image: ${asCSSUrl(item.icon.light || item.icon.dark)}`);
createCSSRule(`.codicon.masked-icon.${iconClass}::before`, `mask-image: ${asCSSUrl(item.icon.light || item.icon.dark)}`);
ICON_PATH_TO_CSS_RULES.set(iconPathMapKey, iconClass);
}
if (this.label) {
const iconClasses = iconClass.split(' ');
if (this._defaultCSSClassToAdd) {
iconClasses.push(this._defaultCSSClassToAdd);
}
this.label.classList.add('codicon', ...iconClasses);
this.label.classList.add('masked-icon', ...iconClasses);
this._labeledItemClassDispose = toDisposable(() => {
if (this.label) {
this.label.classList.remove('codicon', ...iconClasses);
}
});
}
}
}
}
dispose(): void {
if (this._labeledItemClassDispose) {
dispose(this._labeledItemClassDispose);
this._labeledItemClassDispose = undefined;
}
super.dispose();
}
}
// {{SQL CARBON EDIT}} - End

View File

@@ -155,24 +155,25 @@ export interface IExtensionIdentifier {
uuid?: string;
}
// {{SQL CARBON EDIT}} - ADS only implemented language pack filtering
export const EXTENSION_CATEGORIES = [
'Azure',
'Data Science',
'Debuggers',
'Extension Packs',
'Formatters',
'Keymaps',
// 'Azure',
// 'Data Science',
// 'Debuggers',
// 'Extension Packs',
// 'Formatters',
// 'Keymaps',
'Language Packs',
'Linters',
'Machine Learning',
'Notebooks',
'Programming Languages',
'SCM Providers',
'Snippets',
'Testing',
'Themes',
'Visualization',
'Other',
// 'Linters',
// 'Machine Learning',
// 'Notebooks',
// 'Programming Languages',
// 'SCM Providers',
// 'Snippets',
// 'Testing',
// 'Themes',
// 'Visualization',
// 'Other',
];
export interface IExtensionManifest {

View File

@@ -576,7 +576,7 @@ export abstract class ViewPane extends Pane implements IView {
button.label = node.label;
button.onDidClick(_ => {
this.telemetryService.publicLog2<{ viewId: string, uri: string }, WelcomeActionClassification>('views.welcomeAction', { viewId: this.id, uri: node.href });
this.openerService.open(node.href);
this.openerService.open(node.href, { allowCommands: true });
}, null, disposables);
disposables.add(button);
disposables.add(attachButtonStyler(button, this.themeService));

View File

@@ -14,7 +14,7 @@ import { IExtensionIgnoredRecommendationsService, IExtensionRecommendationsServi
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IOutputChannelRegistry, Extensions as OutputExtensions } from 'vs/workbench/services/output/common/output';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { VIEWLET_ID, IExtensionsWorkbenchService, IExtensionsViewPaneContainer, TOGGLE_IGNORE_EXTENSION_ACTION_ID, INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID, DefaultViewsContext, ExtensionsSortByContext, WORKSPACE_RECOMMENDATIONS_VIEW_ID, IWorkspaceRecommendedExtensionsView, AutoUpdateConfigurationKey, HasOutdatedExtensionsContext, SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID } from 'vs/workbench/contrib/extensions/common/extensions';
import { VIEWLET_ID, IExtensionsWorkbenchService, IExtensionsViewPaneContainer, TOGGLE_IGNORE_EXTENSION_ACTION_ID, INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID, DefaultViewsContext, WORKSPACE_RECOMMENDATIONS_VIEW_ID, IWorkspaceRecommendedExtensionsView, AutoUpdateConfigurationKey, HasOutdatedExtensionsContext, SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID } from 'vs/workbench/contrib/extensions/common/extensions'; //{{SQL CARBON EDIT}}
import { ReinstallAction, InstallSpecificVersionOfExtensionAction, ConfigureWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction, PromptExtensionInstallFailureAction, SearchExtensionsAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
import { ExtensionEditor } from 'vs/workbench/contrib/extensions/browser/extensionEditor';
@@ -67,7 +67,7 @@ import { isArray } from 'vs/base/common/types';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
import { mnemonicButtonLabel } from 'vs/base/common/labels';
import { Query } from 'vs/workbench/contrib/extensions/common/extensionQuery';
// import { Query } from 'vs/workbench/contrib/extensions/common/extensionQuery'; {{SQL CARBON EDIT}}
import { Promises } from 'vs/base/common/async';
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
@@ -762,6 +762,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
icon: filterIcon,
});
/* {{SQL CARBON EDIT}} - Remove the menu items not applicable in ADS
const showFeaturedExtensionsId = 'extensions.filter.featured';
this.registerExtensionAction({
id: showFeaturedExtensionsId,
@@ -800,6 +801,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
},
run: () => runAction(this.instantiationService.createInstance(SearchExtensionsAction, '@popular '))
});
*/
this.registerExtensionAction({
id: 'workbench.extensions.action.showRecommendedExtensions',
@@ -820,6 +822,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
run: () => runAction(this.instantiationService.createInstance(SearchExtensionsAction, '@recommended '))
});
/* {{SQL CARBON EDIT}} - Remove the menu items not applicable in ADS
this.registerExtensionAction({
id: 'workbench.extensions.action.recentlyPublishedExtensions',
title: { value: localize('recentlyPublishedExtensions', "Show Recently Published Extensions"), original: 'Show Recently Published Extensions' },
@@ -838,6 +841,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
},
run: () => runAction(this.instantiationService.createInstance(SearchExtensionsAction, '@sort:publishedDate '))
});
*/
const extensionsCategoryFilterSubMenu = new MenuId('extensionsCategoryFilterSubMenu');
MenuRegistry.appendMenuItem(extensionsFilterSubMenu, <ISubmenuItem>{
@@ -952,6 +956,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
run: () => runAction(this.instantiationService.createInstance(SearchExtensionsAction, '@outdated '))
});
/* {{SQL CARBON EDIT}} - Remove the menu items not applicable in ADS
const extensionsSortSubMenu = new MenuId('extensionsSortSubMenu');
MenuRegistry.appendMenuItem(extensionsFilterSubMenu, <ISubmenuItem>{
submenu: extensionsSortSubMenu,
@@ -986,6 +991,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
}
});
});
*/
this.registerExtensionAction({
id: 'workbench.extensions.action.clearExtensionsSearchResults',

View File

@@ -60,7 +60,7 @@ export function setup() {
await app.workbench.quickaccess.runCommand('workbench.action.closeActiveEditor');
});
it('can perform basic text cell functionality', async function () {
it.skip('can perform basic text cell functionality', async function () {
const app = this.app as Application;
await app.workbench.sqlNotebook.newUntitledNotebook();
await app.workbench.sqlNotebook.addCellFromPlaceholder('Markdown');

View File

@@ -1946,15 +1946,7 @@ charenc@~0.0.1:
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
chart.js@^2.6.0:
version "2.7.2"
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.7.2.tgz#3c9fde4dc5b95608211bdefeda7e5d33dffa5714"
integrity sha512-90wl3V9xRZ8tnMvMlpcW+0Yg13BelsGS9P9t0ClaDxv/hdypHDr/YAGf+728m11P5ljwyB0ZHfPKCapZFqSqYA==
dependencies:
chartjs-color "^2.1.0"
moment "^2.10.2"
chart.js@^2.9.4:
chart.js@^2.6.0, chart.js@^2.9.4:
version "2.9.4"
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.9.4.tgz#0827f9563faffb2dc5c06562f8eb10337d5b9684"
integrity sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==