Compare commits

...

10 Commits

Author SHA1 Message Date
Charles Gagnon
765c7064d4 Add Product Feedback survey link to welcome page (#14705) (#14739)
* Fix welcome page

* Add link
2021-03-15 17:25:10 -07:00
Karl Burtram
dfeb80ed3e Fix script loading in sandbox windows (#14727) (#14731)
* Fix script loading in sandbox windows

* Avoid uglify error
2021-03-15 13:49:23 -07:00
Charles Gagnon
e2ce6bebac Fix filtered resource options persisting across deployments (#14702) (#14711) 2021-03-15 12:06:54 -07:00
Charles Gagnon
3368af9371 Fix welcome page (#14701) (#14706) 2021-03-14 22:27:42 -07:00
Charles Gagnon
26156b4e61 Disable auto sync service (#14677) (#14689)
* Disable auto sync service

* skip tests

(cherry picked from commit 1c671676bf)
2021-03-12 10:49:21 -08:00
Hale Rankin
cbbfdb98db Manage Packages icon position fix (#14528) (#14679)
* Added CSS to treat manage packages icon position.

* Wired up a rough concept showing how I propose to pass a masked-icon class, along with the icon name - derived from the action icon path - to the injected action prior to rendering. The end result is an injected action with an icon which behaves like the others in the notebook toolbar.

* Revert "Added CSS to treat manage packages icon position."

This reverts commit 215a67244a78224fe8fd2e6480b7e50d37a15dc0.

* Revert "Wired up a rough concept showing how I propose to pass a masked-icon class, along with the icon name - derived from the action icon path - to the injected action prior to rendering. The end result is an injected action with an icon which behaves like the others in the notebook toolbar."

This reverts commit 1e0cf116602192aa554334d564e855167b0e8bb6.

* Modified LabeledMenuItemActionItem to add masked-icon class to injected label element.

* Modified LabeledMenuItemActionItem to add masked-icon class and styles for injected label element.

* To prevent conflict with Dashboard, I duplicated the existing LabelMenuItemActionItem and odified it.

* Added comment to new method. Added non-prefixed mask-image style.

* Renamed method and modified comments.
2021-03-12 09:11:26 -08:00
Barbara Valdez
9ae254c91e Queue concurrent calls when initializing contents in BookModel (#14586) (#14619)
* Initial work for handling concurrent operations when calling initialized books

* fixes to init contents

* create a queue of deferred promises for initializing books

* resolve active promise and set to undefined

* remove duplicated variable

* address pr comments
2021-03-10 19:04:20 -08:00
Alan Ren
4772be5dcc handle query gallery with tags (#14633) (#14636)
* handle query gallery with tags

* fix typo
2021-03-10 16:10:42 -08:00
Aasim Khan
41e756b906 Fixing welcome page tour. (#14640) (#14661)
* Fixing the icon names

* Fixing settings card position

* getting icon selectors from their source

* Changing var name from dataExplorer to dataExplorerId
2021-03-10 16:09:06 -08:00
Charles Gagnon
e2bd65cdb0 Change tenant to tenant.id when passing to azdata.accounts.getAccountSecurityToken() method. (#14588) (#14605)
(cherry picked from commit 0bea923c0a)

Co-authored-by: Jeff Trimmer <jetrimme@microsoft.com>
2021-03-10 12:03:27 -08:00
20 changed files with 261 additions and 90 deletions

View File

@@ -76,7 +76,7 @@ export class AccountFeature implements StaticFeature {
window.showErrorMessage(unauthorizedMessage);
return undefined;
}
const securityToken = await azdata.accounts.getAccountSecurityToken(account, tenant, azdata.AzureResource.AzureKeyVault);
const securityToken = await azdata.accounts.getAccountSecurityToken(account, tenant.id, azdata.AzureResource.AzureKeyVault);
if (!securityToken?.token) {
window.showErrorMessage(unauthorizedMessage);

View File

@@ -14,6 +14,7 @@ import * as loc from '../common/localizedConstants';
import { IJupyterBookToc, JupyterBookSection } from '../contracts/content';
import { convertFrom, getContentPath, BookVersion } from './bookVersionHandler';
import { debounce } from '../common/utils';
import { Deferred } from '../common/promise';
const fsPromises = fileServices.promises;
const content = 'content';
@@ -26,6 +27,8 @@ export class BookModel {
private _bookVersion: BookVersion;
private _rootPath: string;
private _errorMessage: string;
private _activePromise: Deferred<void> | undefined = undefined;
private _queuedPromises: Deferred<void>[] = [];
constructor(
public readonly bookPath: string,
@@ -56,14 +59,31 @@ export class BookModel {
}
public async initializeContents(): Promise<void> {
this._bookItems = [];
this._allNotebooks = new Map<string, BookTreeItem>();
if (this.isNotebook) {
this.readNotebook();
} else {
await this.readBookStructure();
await this.loadTableOfContentFiles();
await this.readBooks();
const deferred = new Deferred<void>();
if (!this._activePromise && this._queuedPromises.length === 0) {
this._activePromise = deferred;
}
else {
// If there's an active promise, then we need to add the new promise to the queue.
this._queuedPromises.push(deferred);
await deferred.promise;
}
try {
this._bookItems = [];
this._allNotebooks = new Map<string, BookTreeItem>();
if (this.isNotebook) {
this.readNotebook();
} else {
await this.readBookStructure();
await this.loadTableOfContentFiles();
await this.readBooks();
}
}
finally {
// Resolve next promise in queue
const queuedPromise = this._queuedPromises.shift();
queuedPromise?.resolve();
this._activePromise = queuedPromise;
}
}

View File

@@ -21,6 +21,7 @@ import { DeployAzureSQLDBWizardModel } from './deployAzureSQLDBWizard/deployAzur
import { ToolsAndEulaPage } from './toolsAndEulaSettingsPage';
import { OptionValuesFilter, ResourceTypeService } from '../services/resourceTypeService';
import { PageLessDeploymentModel } from './pageLessDeploymentModel';
import { deepClone } from '../common/utils';
export class ResourceTypeWizard {
private customButtons: azdata.window.Button[] = [];
@@ -65,7 +66,7 @@ export class ResourceTypeWizard {
* Setting the first provider from the first value of the dropdowns.
* If there are no options (dropdowns) then the resource type has only one provider which is set as default here.
*/
let filteredOptions = resourceType.options;
let filteredOptions = deepClone(resourceType.options);
const optionsFilter = this._optionValuesFilter?.[this.resourceType.name];
if (optionsFilter) {
filteredOptions.forEach(option => {

View File

@@ -10,7 +10,7 @@ import { AgreementInfo, DeploymentProvider, HelpText, ITool, ResourceType, Resou
import { createFlexContainer } from './modelViewUtils';
import * as loc from '../localizedConstants';
import { IToolsService } from '../services/toolsService';
import { getErrorMessage } from '../common/utils';
import { deepClone, getErrorMessage } from '../common/utils';
import { ResourceTypePage } from './resourceTypePage';
import { ResourceTypeWizard } from './resourceTypeWizard';
import { OptionValuesFilter as OptionValuesFilter } from '../services/resourceTypeService';
@@ -200,7 +200,7 @@ export class ToolsAndEulaPage extends ResourceTypePage {
}).component();
this._optionsContainer.addItem(optionsTitle);
this._resourceType.options.forEach((option, index) => {
let optionValues = option.values;
let optionValues = deepClone(option.values);
const optionValueFilter = this.optionValuesFilter?.[this._resourceType.name]?.[option.name];
if (optionValueFilter) {
optionValues = optionValues.filter(optionValue => optionValueFilter.includes(optionValue.name));

View File

@@ -21,6 +21,7 @@
globalThis.MonacoBootstrapWindow = factory();
}
}(this, function () {
const bootstrapLib = bootstrap();
const preloadGlobals = globals();
const sandbox = preloadGlobals.context.sandbox;
const webFrame = preloadGlobals.webFrame;
@@ -56,15 +57,22 @@
developerToolsUnbind = registerDeveloperKeybindings(options && options.disallowReloadKeybinding);
}
// Enable ASAR support
globalThis.MonacoBootstrap.enableASARSupport(configuration.appRoot);
// Correctly inherit the parent's environment (TODO@sandbox non-sandboxed only)
if (!sandbox) {
Object.assign(safeProcess.env, configuration.userEnv);
}
// Enable ASAR support (TODO@sandbox non-sandboxed only)
if (!sandbox) {
globalThis.MonacoBootstrap.enableASARSupport(configuration.appRoot);
}
if (options && typeof options.canModifyDOM === 'function') {
options.canModifyDOM(configuration);
}
// Get the nls configuration into the process.env as early as possible
const nlsConfig = globalThis.MonacoBootstrap.setupNLS();
// Get the nls configuration into the process.env as early as possible (TODO@sandbox non-sandboxed only)
const nlsConfig = sandbox ? { availableLanguages: {} } : globalThis.MonacoBootstrap.setupNLS();
let locale = nlsConfig.availableLanguages['*'] || 'en';
if (locale === 'zh-tw') {
@@ -87,16 +95,27 @@
window['MonacoEnvironment'] = {};
// const baseUrl = sandbox ? // {{SQL CARBON EDIT}} Pending changes?
// `${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 baseUrl = sandbox ?
`${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 = {
baseUrl: `${uriFromPath(configuration.appRoot)}/out`,
baseUrl: baseUrl,
'vs/nls': nlsConfig,
amdModulesPattern: /^(vs|sql)\//, // {{SQL CARBON EDIT}} include sql in regex
preferScriptTags: sandbox
};
// use a trusted types policy when loading via script tags
if (loaderConfig.preferScriptTags && window && window.trustedTypes) { // {{SQL CARBON EDIT}} fix uglify error
loaderConfig.trustedTypesPolicy = window.trustedTypes.createPolicy('amdLoader', {
createScriptURL(value) {
if (value.startsWith(window.location.origin)) {
return value;
}
throw new Error(`Invalid script url: ${value}`);
}
});
}
// cached data config
if (configuration.nodeCachedDataDir) {
@@ -228,6 +247,14 @@
}
}
/**
* @return {{ fileUriFromPath: (path: string, config: { isWindows?: boolean, scheme?: string, fallbackAuthority?: string }) => string; }}
*/
function bootstrap() {
// @ts-ignore (defined in bootstrap.js)
return globalThis.MonacoBootstrap;
}
/**
* @return {typeof import('./vs/base/parts/sandbox/electron-sandbox/globals')}
*/

39
src/bootstrap.js vendored
View File

@@ -23,9 +23,9 @@
}
}
}(this, function () {
const Module = require('module');
const path = require('path');
const fs = require('fs');
const Module = typeof require === 'function' ? require('module') : undefined;
const path = typeof require === 'function' ? require('path') : undefined;
const fs = typeof require === 'function' ? require('fs') : undefined;
//#region global bootstrapping
@@ -34,9 +34,11 @@
// Workaround for Electron not installing a handler to ignore SIGPIPE
// (https://github.com/electron/electron/issues/13254)
process.on('SIGPIPE', () => {
console.error(new Error('Unexpected SIGPIPE'));
});
if (typeof process !== 'undefined') {
process.on('SIGPIPE', () => {
console.error(new Error('Unexpected SIGPIPE'));
});
}
//#endregion
@@ -89,21 +91,32 @@
//#region URI helpers
/**
* @param {string} _path
* @param {string} path
* @param {{ isWindows?: boolean, scheme?: string, fallbackAuthority?: string }} config
* @returns {string}
*/
function fileUriFromPath(_path) {
let pathName = path.resolve(_path).replace(/\\/g, '/');
function fileUriFromPath(path, config) {
// Since we are building a URI, we normalize any backlsash
// to slashes and we ensure that the path begins with a '/'.
let pathName = path.replace(/\\/g, '/');
if (pathName.length > 0 && pathName.charAt(0) !== '/') {
pathName = `/${pathName}`;
}
/** @type {string} */
let uri;
if (process.platform === 'win32' && pathName.startsWith('//')) { // specially handle Windows UNC paths
uri = encodeURI(`file:${pathName}`);
} else {
uri = encodeURI(`file://${pathName}`);
// Windows: in order to support UNC paths (which start with '//')
// that have their own authority, we do not use the provided authority
// but rather preserve it.
if (config.isWindows && pathName.startsWith('//')) {
uri = encodeURI(`${config.scheme || 'file'}:${pathName}`);
}
// Otherwise we optionally add the provided authority if specified
else {
uri = encodeURI(`${config.scheme || 'file'}://${config.fallbackAuthority || ''}${pathName}`);
}
return uri.replace(/#/g, '%23');

View File

@@ -148,6 +148,8 @@ export class DataExplorerViewPaneContainer extends ViewPaneContainer {
}
}
export const dataExplorerIconId = 'dataExplorer';
export const VIEW_CONTAINER = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({
id: VIEWLET_ID,
name: localize('dataexplorer.name', "Connections"),

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 { LabeledMenuItemActionItem, fillInActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { MaskedLabeledMenuItemActionItem, 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';
@@ -509,7 +509,7 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
action.tooltip = action.label;
action.label = '';
}
return new LabeledMenuItemActionItem(action, this.keybindingService, this.notificationService);
return new MaskedLabeledMenuItemActionItem(action, this.keybindingService, this.notificationService);
}
return undefined;
}

View File

@@ -440,11 +440,13 @@ export class NotebookExplorerViewPaneContainer extends ViewPaneContainer {
}
}
export const notebookIconId = 'book';
export const NOTEBOOK_VIEW_CONTAINER = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer({
id: VIEWLET_ID,
name: localize('notebookExplorer.name', "Notebooks"),
ctorDescriptor: new SyncDescriptor(NotebookExplorerViewPaneContainer),
icon: { id: 'book' },
icon: { id: notebookIconId },
order: 6,
storageId: `${VIEWLET_ID}.state`
}, ViewContainerLocation.Sidebar);

View File

@@ -16,7 +16,7 @@ export default () => `
<div class="content-container">
<div class="ads-homepage-section tool-tip">
<div class="tool-tip-container" id="tool-tip-container-wide">
<a role="img" tabindex=0 class="ads-welcome-page-link" aria-label="${previewImgDescription}" title="${previewImgDescription}" id="preview-link-wide" class="preview-link" tabindex="0" name="preview"><p>${escape(localize('welcomePage.preview', "Preview"))}</p><i class="icon-info themed-icon"></i></a>
<a role="img" tabindex=0 class="ads-welcome-page-link preview-link" aria-label="${previewImgDescription}" title="${previewImgDescription}" id="preview-link-wide" tabindex="0" name="preview"><p>${escape(localize('welcomePage.preview', "Preview"))}</p><i class="icon-info themed-icon"></i></a>
</div>
</div>
<div class="ads-homepage-section section header hero">
@@ -111,37 +111,42 @@ export default () => `
<div class="links">
<h2>${escape(localize('welcomePage.usefuLinks', "Useful Links"))}</h2>
<div class="link-header">
<a class="link ads-welcome-page-link"
href="https://aka.ms/get-started-azdata">${escape(localize('welcomePage.gettingStarted',
"Getting Started"))}<span class="icon-link themed-icon-alt"></a>
<a class="link ads-welcome-page-link" href="https://aka.ms/get-started-azdata">
${escape(localize('welcomePage.gettingStarted', "Getting Started"))}<span class="icon-link themed-icon-alt"></span>
</a>
</div>
<p>
${escape(localize('welcomePage.gettingStartedBody',
"Discover the capabilities offered by Azure Data Studio and learn how to make the most of them."))}
${escape(localize('welcomePage.gettingStartedBody', "Discover the capabilities offered by Azure Data Studio and learn how to make the most of them."))}
</p>
<div class="link-header">
<a class="link ads-welcome-page-link"
href="command:workbench.action.openDocumentationUrl">${escape(localize('welcomePage.documentation',
"Documentation"))}<span class="icon-link themed-icon-alt"</a></a>
<a class="link ads-welcome-page-link" href="command:workbench.action.openDocumentationUrl">
${escape(localize('welcomePage.documentation', "Documentation"))}<span class="icon-link themed-icon-alt"></span>
</a>
</div>
<p>${escape(localize('welcomePage.documentationBody',
"Visit the documentation center for quickstarts, how-to guides, and references for PowerShell, APIs, etc."))}
<p>
${escape(localize('welcomePage.documentationBody', "Visit the documentation center for quickstarts, how-to guides, and references for PowerShell, APIs, etc."))}
</p>
<div class="link-header">
<a class="link ads-welcome-page-link" href="https://aka.ms/AzureSQLSurvey">
${escape(localize('welcomePage.productFeedback', "Product Feedback"))}<span class="icon-link themed-icon-alt"></span>
</a>
</div>
<p>
${escape(localize('welcomePage.productFeedbackBody', "Shape the future of the Azure SQL products you're using by completing the feedback survey!"))}
</p>
<div class="videos-container row">
<h2>Videos</h2>
<h2>${escape(localize('welcomePage.videos', "Videos"))}</h2>
<div class="flex flex-container-video">
<div class="videos-container-video">
<a href="https://www.youtube.com/watch?v=Orv7fptVoUA" class="video overview ads-welcome-page-link">
<img src="${require.toUrl('./../../media/video_overview.png')}" class="video-overview" id="video-overview" />
<h4>${escape(localize('welcomePage.videoDescriptionOverview',
"Overview of Azure Data Studio"))}</h4>
<img src="${require.toUrl('./../../media/video_overview.png')}" class="video-overview" id="video-overview" />
<h4>${escape(localize('welcomePage.videoDescriptionOverview', "Overview of Azure Data Studio"))}</h4>
</a>
</div>
<div class="videos-container-video">
<a href="https://www.youtube.com/watch?v=Nt4kIHQ0IOc" class="video overview ads-welcome-page-link">
<img src="${require.toUrl('./../../media/video_introduction.png')}" class="video-introduction" id="video-introduction" />
<h4>${escape(localize('welcomePage.videoDescriptionIntroduction',
"Introduction to Azure Data Studio Notebooks | Data Exposed"))}</h4>
<img src="${require.toUrl('./../../media/video_introduction.png')}" class="video-introduction" id="video-introduction" />
<h4>${escape(localize('welcomePage.videoDescriptionIntroduction', "Introduction to Azure Data Studio Notebooks | Data Exposed"))}</h4>
</a>
</div>
</div>
@@ -152,26 +157,29 @@ export default () => `
<div class="ads-homepage-section content extensions content-container">
<div class="flex flex-j-between">
<h2>${escape(localize('welcomePage.extensions', "Extensions"))}</h2>
<a role="button" class="link-show-all flex ads-welcome-page-link" href="command:workbench.view.extensions">${escape(localize('welcomePage.showAll', "Show All"))} <span class="icon-arrow-right"></span></a>
<a role="button" class="link-show-all flex ads-welcome-page-link" href="command:workbench.view.extensions">
${escape(localize('welcomePage.showAll', "Show All"))}<span class="icon-arrow-right"></span>
</a>
</div>
<div class="row ads-grid grip-gap-50">
<div
class="ads-grid tile no-hover extension-pack">
<div class="ads-grid tile no-hover extension-pack">
<div class="extension-pack-description">
<h3 class="extension-pack-header"></h3>
<p class="extension-pack-body"></p>
</div>
<div class="extension-pack-extensions flex flex-d-column flex-j-evenly flex-a-start">
<div class="extension-pack-extension-list flex flex-d-column flex-j-evenly flex-a-start"></div>
<div class="flex flex-j-end extension-pack-btn-container flex flex-j-between flex-a-center"">
<div class="extensionPack" href="#"></div>
<a role="button" class="a-self-end link-learn-more flex flex-a-center ads-welcome-page-link" href="command:azdata.extension.open?%7B%22id%22%3A%22microsoft.admin-pack%22%7D">${escape(localize('welcomePage.learnMore',
"Learn more "))}<span class="icon-arrow-right"></span></a>
<div class="flex flex-j-end extension-pack-btn-container flex flex-j-between flex-a-center">
<div class="extensionPack"></div>
<a role="button" class="a-self-end link-learn-more flex flex-a-center ads-welcome-page-link" href="command:azdata.extension.open?%7B%22id%22%3A%22microsoft.admin-pack%22%7D">
${escape(localize('welcomePage.learnMore', "Learn more "))}<span class="icon-arrow-right"></span>
</a>
</div>
</div>
</div>
</div>
<div class="extension-list flex flex-d-column">
<!-- Dynamically populated -->
<div class="extension-list flex flex-d-column">
<!-- Dynamically populated -->
</div>
</div>
<br /><br /><br />
</div>
@@ -179,3 +187,4 @@ export default () => `
</div>
</div>
`;

View File

@@ -11,7 +11,7 @@ import { Action } from 'vs/base/common/actions';
import { Disposable } from 'vs/base/common/lifecycle';
import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { registerThemingParticipant, ThemeIcon } from 'vs/platform/theme/common/themeService';
import { buttonBackground, buttonForeground } from 'vs/platform/theme/common/colorRegistry';
import { Color } from 'vs/base/common/color';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -20,6 +20,10 @@ import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { KeyCode } from 'vs/base/common/keyCodes';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { Button } from 'sql/base/browser/ui/button/button';
import { extensionsViewIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons';
import { settingsViewBarIcon } from 'vs/workbench/browser/parts/activitybar/activitybarPart';
import { dataExplorerIconId } from 'sql/workbench/contrib/dataExplorer/browser/dataExplorerViewlet';
import { notebookIconId } from 'sql/workbench/contrib/notebook/browser/notebookExplorer/notebookExplorerViewlet';
const $ = dom.$;
interface TourData {
@@ -40,11 +44,16 @@ interface TourData {
popupImage: string;
}
const dataExplorerIconCssSelector = `.action-label.${dataExplorerIconId}`;
const notebookIconCssSelector = `.action-label.${notebookIconId}`;
const extensionsIconCssSelector = ThemeIcon.asCSSSelector(extensionsViewIcon);
const settingsGearIconCssSelector = ThemeIcon.asCSSSelector(settingsViewBarIcon);
const tourData: TourData[] = [
{ key: 'connections', order: '1', header: localize('GuidedTour.connections', "Connections"), body: localize('GuidedTour.makeConnections', "Connect, query, and manage your connections from SQL Server, Azure, and more."), step: localize('GuidedTour.one', "1"), elmClass: 'overview-tour-connections', id: 'overview-tour-connections', btnId: 'overview-tour-connections-btn', btnText: localize('GuidedTour.next', "Next"), docs: 'https://aka.ms/ads-connections-quickstart', elementToAppendTo: '.action-label.dataExplorer', arrow: 'arrow-left', popupImage: './../../gettingStarted/media/connections.png' },
{ key: 'jupyer_books', order: '2', header: localize('GuidedTour.notebooks', "Notebooks"), body: localize('GuidedTour.gettingStartedNotebooks', "Get started creating your own notebook or collection of notebooks in a single place."), step: localize('GuidedTour.two', "2"), elmClass: 'overview-tour-jupyterBooks', id: 'overview-tour-jupyterBooks', btnId: 'overview-tour-jupyter-btn', btnText: localize('GuidedTour.next', "Next"), docs: 'https://aka.ms/ads-notebooks', elementToAppendTo: '.action-label.book', arrow: 'arrow-left', popupImage: './../../gettingStarted/media/notebooks.png' },
{ key: 'extensions', order: '3', header: localize('GuidedTour.extensions', "Extensions"), body: localize('GuidedTour.addExtensions', "Extend the functionality of Azure Data Studio by installing extensions developed by us/Microsoft as well as the third-party community (you!)."), step: localize('GuidedTour.three', "3"), elmClass: 'overview-tour-extensions', id: 'overview-tour-extensions', btnId: 'overview-tour-extensions-btn', btnText: localize('GuidedTour.next', "Next"), docs: 'https://aka.ms/ads-extensions', elementToAppendTo: '.action-label.codicon-extensions', arrow: 'arrow-left', popupImage: './../../gettingStarted/media/extensions.png' },
{ key: 'settings', order: '4', header: localize('GuidedTour.settings', "Settings"), body: localize('GuidedTour.makeConnesetSettings', "Customize Azure Data Studio based on your preferences. You can configure Settings like autosave and tab size, personalize your Keyboard Shortcuts, and switch to a Color Theme of your liking."), step: localize('GuidedTour.four', "4"), elmClass: 'overview-tour-settings', id: 'overview-tour-settings', btnId: 'overview-tour-settings-btn', btnText: localize('GuidedTour.next', "Next"), elementToAppendTo: '.codicon-settings-gear', arrow: 'arrow-bottom-left', popupImage: '../../gettingStarted/media/settings.png' },
{ key: 'connections', order: '1', header: localize('GuidedTour.connections', "Connections"), body: localize('GuidedTour.makeConnections', "Connect, query, and manage your connections from SQL Server, Azure, and more."), step: localize('GuidedTour.one', "1"), elmClass: 'overview-tour-connections', id: 'overview-tour-connections', btnId: 'overview-tour-connections-btn', btnText: localize('GuidedTour.next', "Next"), docs: 'https://aka.ms/ads-connections-quickstart', elementToAppendTo: dataExplorerIconCssSelector, arrow: 'arrow-left', popupImage: './../../gettingStarted/media/connections.png' },
{ key: 'jupyer_books', order: '2', header: localize('GuidedTour.notebooks', "Notebooks"), body: localize('GuidedTour.gettingStartedNotebooks', "Get started creating your own notebook or collection of notebooks in a single place."), step: localize('GuidedTour.two', "2"), elmClass: 'overview-tour-jupyterBooks', id: 'overview-tour-jupyterBooks', btnId: 'overview-tour-jupyter-btn', btnText: localize('GuidedTour.next', "Next"), docs: 'https://aka.ms/ads-notebooks', elementToAppendTo: notebookIconCssSelector, arrow: 'arrow-left', popupImage: './../../gettingStarted/media/notebooks.png' },
{ key: 'extensions', order: '3', header: localize('GuidedTour.extensions', "Extensions"), body: localize('GuidedTour.addExtensions', "Extend the functionality of Azure Data Studio by installing extensions developed by us/Microsoft as well as the third-party community (you!)."), step: localize('GuidedTour.three', "3"), elmClass: 'overview-tour-extensions', id: 'overview-tour-extensions', btnId: 'overview-tour-extensions-btn', btnText: localize('GuidedTour.next', "Next"), docs: 'https://aka.ms/ads-extensions', elementToAppendTo: extensionsIconCssSelector, arrow: 'arrow-left', popupImage: './../../gettingStarted/media/extensions.png' },
{ key: 'settings', order: '4', header: localize('GuidedTour.settings', "Settings"), body: localize('GuidedTour.makeConnesetSettings', "Customize Azure Data Studio based on your preferences. You can configure Settings like autosave and tab size, personalize your Keyboard Shortcuts, and switch to a Color Theme of your liking."), step: localize('GuidedTour.four', "4"), elmClass: 'overview-tour-settings', id: 'overview-tour-settings', btnId: 'overview-tour-settings-btn', btnText: localize('GuidedTour.next', "Next"), elementToAppendTo: settingsGearIconCssSelector, arrow: 'arrow-bottom-left', popupImage: '../../gettingStarted/media/settings.png' },
{ key: 'welcome_page', order: '5', header: localize('GuidedTour.welcomePage', "Welcome Page"), body: localize('GuidedTour.discoverWelcomePage', "Discover top features, recently opened files, and recommended extensions on the Welcome page. For more information on how to get started in Azure Data Studio, check out our videos and documentation."), step: localize('GuidedTour.five', "5"), elmClass: 'overview-tour-home', id: 'overview-tour-home', btnId: 'overview-tour-home-btn', btnText: localize('GuidedTour.finish', "Finish"), elementToAppendTo: 'center', arrow: 'none', popupImage: '../../gettingStarted/media/welcome.png' },
];
@@ -232,7 +241,7 @@ export class GuidedTour extends Disposable {
positionVertical = Math.round((subjectElementPosition.top - 22));
subjectElement.style.pointerEvents = 'none';
}
if (elementClassToAppendTo === '.codicon-settings-gear') {
if (elementClassToAppendTo === settingsGearIconCssSelector) {
tourItem.style.top = (positionVertical - 330) + 'px';
tourItem.style.left = positionHorizontal + 'px';
}
@@ -325,7 +334,7 @@ registerThemingParticipant((theme, collector) => {
collector.addRule(`.monaco-workbench > .ads-tour .ads-tour-popup p, .monaco-workbench > .ads-tour .ads-tour-popup h1 { color: ${bodyTag}; }`);
collector.addRule(`.monaco-workbench > .ads-tour .ads-tour-popup .ads-tour-btn-container .ads-tour-docs-link { color: ${bodyTag}; }`);
collector.addRule(`.monaco-workbench > .ads-tour .ads-tour-popup .ads-tour-btn-container .ads-tour-btn-primary-inverse { background: ${bodyTag}; }`);
collector.addRule(`.monaco-workbench .activitybar>.content :not(.monaco-menu)>.monaco-action-bar .action-label.activity-workbench-view-extension-books-explorer.subject-element-focused, .monaco-workbench .activitybar>.content :not(.monaco-menu)>.monaco-action-bar .action-label.codicon.dataExplorer.subject-element-focused { background: ${bodyTag}; }`);
collector.addRule(`.monaco-workbench .activitybar>.content :not(.monaco-menu)>.monaco-action-bar .action-label.activity-workbench-view-extension-books-explorer.subject-element-focused, .monaco-workbench .activitybar>.content :not(.monaco-menu)>.monaco-action-bar ${dataExplorerIconCssSelector}.subject-element-focused { background: ${bodyTag}; }`);
collector.addRule(`.monaco-workbench .activitybar>.content :not(.monaco-menu)>.monaco-action-bar .action-label.codicon.subject-element-focused { color: ${bodyTag} !important; }`);
collector.addRule(`.monaco-workbench .welcomePage .btn-remove-tour { color: ${bodyTag} !important; }`);
collector.addRule(`.monaco-workbench .welcomePage .guided-tour-banner p { color: ${bodyTag}; }`);

View File

@@ -291,12 +291,8 @@
display: none;
}
.ads-homepage #tool-tip-container-wide .ads-welcome-page-link{
display: flex;
align-items: center;
}
.ads-homepage #tool-tip-container-narrow .ads-welcome-page-link{
.ads-homepage #tool-tip-container-wide .ads-welcome-page-link,
.ads-homepage #tool-tip-container-narrow .ads-welcome-page-link {
display: flex;
align-items: center;
}
@@ -885,18 +881,24 @@
border-top: 1px solid;
}
.ads-homepage .ads-homepage-section .history .list, .ads-homepage .ads-homepage-section .pinned .list {
.ads-homepage .ads-homepage-section .history .list,
.ads-homepage .ads-homepage-section .pinned .list {
min-height: 170px; /* 5 (max # of items displayed in list) x list item height */
list-style-type: none;
padding: 0;
margin-top: 0
}
.ads-homepage .ads-homepage-section .history .list-header, .ads-homepage .ads-homepage-section .pinned .list-header {
.ads-homepage .ads-homepage-section .history .list-header,
.ads-homepage .ads-homepage-section .pinned .list-header {
padding: 0 0 2px 11px
}
.ads-homepage .ads-homepage-section .history .list li:not(.moreRecent), .ads-homepage .ads-homepage-section .history .list-header-container, .ads-homepage .ads-homepage-section .pinned .list li:not(.moreRecent), .ads-homepage .ads-homepage-section .pinned .list-header-container {
.ads-homepage .ads-homepage-section .history .list li:not(.moreRecent),
.ads-homepage .ads-homepage-section .history .list-header-container,
.ads-homepage .ads-homepage-section .pinned .list li:not(.moreRecent),
.ads-homepage .ads-homepage-section .pinned .list-header-container {
height: 33px;
list-style: none;
border-bottom: 1px solid;

View File

@@ -186,10 +186,10 @@ const extensionPacks: ExtensionSuggestion[] = [
];
const extensionPackExtensions: ExtensionPackExtensions[] = [
{ name: 'SQL Server Agent', icon: require.toUrl('./../../media/defaultExtensionIcon.svg'), link: `command:azdata.extension.open?{"id":"microsoft.agent"}` },
{ name: 'SQL Server Profiler', icon: require.toUrl('./../../media/defaultExtensionIcon.svg'), link: `command:azdata.extension.open?{"id":"microsoft.profiler"}` },
{ name: 'SQL Server Import', icon: require.toUrl('./../../media/defaultExtensionIcon.svg'), link: `command:azdata.extension.open?{"id":"microsoft.import"}` },
{ name: 'SQL Server Dacpac', icon: require.toUrl('./../../media/defaultExtensionIcon.svg'), link: `command:azdata.extension.open?{"id":"microsoft.dacpac"}` }
{ name: localize('welcomePage.sqlServerAgent', "SQL Server Agent"), icon: require.toUrl('./../../media/defaultExtensionIcon.svg'), link: `command:azdata.extension.open?{"id":"microsoft.agent"}` },
{ name: localize('welcomePage.sqlServerProfiler', "SQL Server Profiler"), icon: require.toUrl('./../../media/defaultExtensionIcon.svg'), link: `command:azdata.extension.open?{"id":"microsoft.profiler"}` },
{ name: localize('welcomePage.sqlServerImport', "SQL Server Import"), icon: require.toUrl('./../../media/defaultExtensionIcon.svg'), link: `command:azdata.extension.open?{"id":"microsoft.import"}` },
{ name: localize('welcomePage.sqlServerDacpac', "SQL Server Dacpac"), icon: require.toUrl('./../../media/defaultExtensionIcon.svg'), link: `command:azdata.extension.open?{"id":"microsoft.dacpac"}` }
];
const extensions: ExtensionSuggestion[] = [
@@ -343,7 +343,7 @@ class WelcomePage extends Disposable {
const workspacesToShow = workspaces.slice(0, 5);
clearNode(ul);
await this.mapListEntries(workspacesToShow, container, ul);
await this.mapListEntries(workspacesToShow, container);
}).then(undefined, onUnexpectedError);
this.addExtensionList(container, '.extension-list');
this.addExtensionPack(container, '.extensionPack');
@@ -514,7 +514,7 @@ class WelcomePage extends Disposable {
return result;
}
private async mapListEntries(recents: (IRecentWorkspace | IRecentFolder)[], container: HTMLElement, ul: HTMLElement): Promise<HTMLElement[]> {
private async mapListEntries(recents: (IRecentWorkspace | IRecentFolder)[], container: HTMLElement): Promise<HTMLElement[]> {
const result: HTMLElement[] = [];
for (let i = 0; i < recents.length; i++) {
const recent = recents[i];

View File

@@ -1441,17 +1441,18 @@ const _ttpSafeInnerHtml = window.trustedTypes?.createPolicy('safeInnerHtml', {
export function safeInnerHtml(node: HTMLElement, value: string): void {
const options = _extInsaneOptions({
allowedTags: ['a', 'button', 'blockquote', 'code', 'div', 'h1', 'h2', 'h3', 'input', 'label', 'li', 'p', 'pre', 'select', 'small', 'span', 'strong', 'textarea', 'ul', 'ol'],
allowedTags: ['a', 'button', 'blockquote', 'code', 'div', 'h1', 'h2', 'h3', 'h4', 'i', 'img', 'input', 'label', 'li', 'p', 'pre', 'select', 'small', 'span', 'strong', 'textarea', 'ul', 'ol'], // {{SQL CARBON EDIT}} Add tags for welcome page support
allowedAttributes: {
'a': ['href', 'x-dispatch'],
'button': ['data-href', 'x-dispatch'],
'input': ['type', 'placeholder', 'checked', 'required'],
'img': ['src', 'alt', 'title', 'aria-label'], // {{SQL CARBON EDIT}} Add img for welcome page support
'label': ['for'],
'select': ['required'],
'span': ['data-command', 'role'],
'textarea': ['name', 'placeholder', 'required'],
},
allowedSchemes: ['http', 'https', 'command']
allowedSchemes: ['http', 'https', 'command', 'file'] // {{SQL CARBON EDIT}} Add allowed schema for welcome page support
}, ['class', 'id', 'role', 'tabindex']);
const html = _ttpSafeInnerHtml?.createHTML(value, options) ?? insane(value, options);

View File

@@ -313,4 +313,78 @@ export class LabeledMenuItemActionItem extends MenuEntryActionViewItem {
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

@@ -608,6 +608,11 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
});
}
}
// ADS doesn't support extension tags, we need to return empty array to avoid breaking some scenarios. e.g. file extension based recommendations.
const tagFilters = query.criteria.filter(x => x.filterType === FilterType.Tag);
if (tagFilters?.length > 0) {
filteredExtensions = [];
}
const searchTexts = query.criteria.filter(x => x.filterType === FilterType.SearchText).map(v => v.value ? v.value.toLocaleLowerCase() : undefined);
if (searchTexts && searchTexts.length > 0) {
searchTexts.forEach(searchText => {

View File

@@ -59,6 +59,7 @@ export class UserDataAutoSyncEnablementService extends Disposable implements _IU
}
isEnabled(defaultEnablement?: boolean): boolean {
/* {{SQL CARBON EDIT}} Disable unused sync service
switch (this.environmentService.sync) {
case 'on':
return true;
@@ -66,6 +67,8 @@ export class UserDataAutoSyncEnablementService extends Disposable implements _IU
return false;
default: return this.storageService.getBoolean(enablementKey, StorageScope.GLOBAL, !!defaultEnablement); // {{SQL CARBON EDIT}} strict-null-checks move this to a default case
}
*/
return false;
}
canToggleEnablement(): boolean {

View File

@@ -24,7 +24,7 @@ class TestUserDataAutoSyncService extends UserDataAutoSyncService {
}
}
suite('UserDataAutoSyncService', () => {
suite.skip('UserDataAutoSyncService', () => { // {{SQL CARBON EDIT}} Service is disabled so turn off tests
const disposableStore = new DisposableStore();

View File

@@ -71,7 +71,7 @@ interface ICachedViewContainer {
views?: { when?: string }[];
}
const settingsViewBarIcon = registerIcon('settings-view-bar-icon', Codicon.settingsGear, nls.localize('settingsViewBarIcon', 'Settings icon in the view bar.'));
export const settingsViewBarIcon = registerIcon('settings-view-bar-icon', Codicon.settingsGear, nls.localize('settingsViewBarIcon', 'Settings icon in the view bar.')); // {{SQL CARBON EDIT}} exporting to use it in getting started tour
const accountsViewBarIcon = registerIcon('accounts-view-bar-icon', Codicon.account, nls.localize('accountsViewBarIcon', 'Accounts icon in the view bar.'));
export class ActivitybarPart extends Part implements IActivityBarService {

View File

@@ -12,6 +12,7 @@ export class WebUserDataAutoSyncEnablementService extends UserDataAutoSyncEnable
private enabled: boolean | undefined = undefined;
isEnabled(): boolean {
/* {{SQL CARBON EDIT}} Disable unused sync service
if (this.enabled === undefined) {
this.enabled = this.workbenchEnvironmentService.options?.settingsSyncOptions?.enabled;
}
@@ -19,6 +20,8 @@ export class WebUserDataAutoSyncEnablementService extends UserDataAutoSyncEnable
this.enabled = super.isEnabled(this.workbenchEnvironmentService.options?.enableSyncByDefault);
}
return this.enabled;
*/
return false;
}
setEnablement(enabled: boolean) {