Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd53e685d0 | ||
|
|
410bb62906 | ||
|
|
cbb4ac3e20 | ||
|
|
61746b7ff7 | ||
|
|
e6066c2cb5 | ||
|
|
633a918590 | ||
|
|
9bbed2c275 | ||
|
|
d9ba4d9130 | ||
|
|
e2bd6c06ec | ||
|
|
a26be76d79 | ||
|
|
3b68c1eb69 | ||
|
|
f7879bdbf9 | ||
|
|
dbb0fc519f |
23
CHANGELOG.md
@@ -1,5 +1,28 @@
|
||||
# Change Log
|
||||
|
||||
## Version 1.2.4
|
||||
* Release date: November 6, 2018
|
||||
* Release status: General Availability
|
||||
|
||||
## What's new in this version
|
||||
* Update to the SQL Server 2019 Preview extension
|
||||
* Introducing Paste the Plan extension
|
||||
* Introducing High Color queries extension, including SSMS editor theme
|
||||
* Fixes in SQL Server Agent, Profiler, and Import extensions
|
||||
* Fix .Net Core Socket KeepAlive issue causing dropped inactive connections on macOS
|
||||
* Upgrade SQL Tools Service to .Net Core 2.2 Preview 3 (for eventual AAD support)
|
||||
* Fix customer reported GitHub issues
|
||||
|
||||
## Contributions and "thank you"
|
||||
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
|
||||
|
||||
* rdaniels6813 for `Add query plan theme support #3031`
|
||||
* Ruturaj123 for `Fixed some typos and grammatical errors #3027`
|
||||
* PromoFaux for `Use emoji shortcodes in CONTRIBUTING.md instead of <20> #3009`
|
||||
* ckaczor for `Fix: DATETIMEOFFSET data types should be ISO formatted #714`
|
||||
* hi-im-T0dd for `Fixed sync issue with my forked master so this commit is correct #2948`
|
||||
* hi-im-T0dd for `Fixed when right clicking and selecting Manage-correct name displays #2794`
|
||||
|
||||
## Version 1.1.3
|
||||
* Release date: October 18, 2018
|
||||
* Release status: General Availability
|
||||
|
||||
19
README.md
@@ -8,12 +8,12 @@ Azure Data Studio is a data management tool that enables you to work with SQL Se
|
||||
|
||||
Platform | Link
|
||||
-- | --
|
||||
Windows Setup Installer | https://go.microsoft.com/fwlink/?linkid=2030731
|
||||
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=2030736
|
||||
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=2030738
|
||||
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=2030741
|
||||
Linux RPM | https://go.microsoft.com/fwlink/?linkid=2030746
|
||||
Linux DEB | https://go.microsoft.com/fwlink/?linkid=2030750
|
||||
Windows Setup Installer | https://go.microsoft.com/fwlink/?linkid=2038320
|
||||
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=2038323
|
||||
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=2038327
|
||||
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=2038332
|
||||
Linux RPM | https://go.microsoft.com/fwlink/?linkid=2038401
|
||||
Linux DEB | https://go.microsoft.com/fwlink/?linkid=2038405
|
||||
|
||||
Go to our [download page](https://aka.ms/azuredatastudio) for more specific instructions.
|
||||
|
||||
@@ -61,6 +61,12 @@ The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.micro
|
||||
## Contributions and "Thank You"
|
||||
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
|
||||
|
||||
* rdaniels6813 for `Add query plan theme support #3031`
|
||||
* Ruturaj123 for `Fixed some typos and grammatical errors #3027`
|
||||
* PromoFaux for `Use emoji shortcodes in CONTRIBUTING.md instead of <20> #3009`
|
||||
* ckaczor for `Fix: DATETIMEOFFSET data types should be ISO formatted #714`
|
||||
* hi-im-T0dd for `Fixed sync issue with my forked master so this commit is correct #2948`
|
||||
* hi-im-T0dd for `Fixed when right clicking and selecting Manage-correct name displays #2794`
|
||||
* philoushka for `center the icon #2760`
|
||||
* anthonypants for `Typo #2775`
|
||||
* kstolte for `Fix Invalid Configuration in Launch.json #2789`
|
||||
@@ -103,7 +109,6 @@ We would like to thank all our users who raised issues, and in particular the fo
|
||||
* Russian: Andrey Veselov, Anton Fontanov, Anton Savin, Elena Ostrovskaia, Igor Babichev, Maxim Zelensky, Rodion Fedechkin, Tasha T, Vladimir Zyryanov
|
||||
* Portuguese Brazil: Daniel de Sousa, Diogo Duarte, Douglas Correa, Douglas Eccker, José Emanuel Mendes, Marcelo Fernandes, Marcondes Alexandre, Roberto Fonseca, Rodrigo Crespi
|
||||
|
||||
|
||||
And of course, we'd like to thank the authors of all upstream dependencies. Please see a full list in the [ThirdPartyNotices.txt](https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/ThirdPartyNotices.txt)
|
||||
|
||||
## License
|
||||
|
||||
38
azure-pipelines-linux-mac.yml
Normal file
@@ -0,0 +1,38 @@
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: '8.x'
|
||||
displayName: 'Install Node.js'
|
||||
|
||||
- script: |
|
||||
git submodule update --init --recursive
|
||||
nvm install 8.9.1
|
||||
nvm use 8.9.1
|
||||
npm i -g yarn
|
||||
displayName: 'preinstall'
|
||||
|
||||
- script: |
|
||||
export CXX="g++-4.9" CC="gcc-4.9" DISPLAY=:99.0
|
||||
sh -e /etc/init.d/xvfb start
|
||||
sleep 3
|
||||
displayName: 'Linux preinstall'
|
||||
condition: eq(variables['Agent.OS'], 'Linux')
|
||||
|
||||
- script: |
|
||||
yarn
|
||||
displayName: 'Install'
|
||||
|
||||
- script: |
|
||||
node_modules/.bin/gulp electron --silent
|
||||
node_modules/.bin/gulp compile --silent --max_old_space_size=4096
|
||||
node_modules/.bin/gulp optimize-vscode --silent --max_old_space_size=4096
|
||||
displayName: 'Scripts'
|
||||
|
||||
- script: |
|
||||
./scripts/test.sh --reporter mocha-junit-reporter
|
||||
displayName: 'Tests'
|
||||
|
||||
- task: PublishTestResults@2
|
||||
inputs:
|
||||
testResultsFiles: '**/test-results.xml'
|
||||
condition: succeededOrFailed()
|
||||
27
azure-pipelines-windows.yml
Normal file
@@ -0,0 +1,27 @@
|
||||
steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: '8.9'
|
||||
displayName: 'Install Node.js'
|
||||
|
||||
- script: |
|
||||
yarn
|
||||
displayName: 'Yarn Install'
|
||||
|
||||
- script: |
|
||||
.\node_modules\.bin\gulp electron
|
||||
displayName: 'Electron'
|
||||
|
||||
- script: |
|
||||
npm run compile
|
||||
displayName: 'Compile'
|
||||
|
||||
- script: |
|
||||
.\scripts\test.bat
|
||||
.\scripts\test-integration.bat
|
||||
displayName: 'Test'
|
||||
|
||||
- task: PublishTestResults@2
|
||||
inputs:
|
||||
testResultsFiles: '**/test-results.xml'
|
||||
condition: succeededOrFailed()
|
||||
29
azure-pipelines.yml
Normal file
@@ -0,0 +1,29 @@
|
||||
trigger:
|
||||
- master
|
||||
- releases/*
|
||||
|
||||
jobs:
|
||||
|
||||
# All tasks on Windows
|
||||
- job: build_all_windows
|
||||
displayName: Build all tasks (Windows)
|
||||
pool:
|
||||
vmImage: vs2017-win2016
|
||||
steps:
|
||||
- template: azure-pipelines-windows.yml
|
||||
|
||||
# All tasks on Linux
|
||||
- job: build_all_linux
|
||||
displayName: Build all tasks (Linux)
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
steps:
|
||||
- template: azure-pipelines-linux-mac.yml
|
||||
|
||||
# All tasks on macOS
|
||||
- job: build_all_darwin
|
||||
displayName: Build all tasks (macOS)
|
||||
pool:
|
||||
vmImage: macos-10.13
|
||||
steps:
|
||||
- template: azure-pipelines-linux-mac.yml
|
||||
1
docs/UX-Design-Guidelines.md
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
||||
"version": "1.5.0-alpha.52",
|
||||
"version": "1.5.0-alpha.53",
|
||||
"downloadFileNames": {
|
||||
"Windows_86": "win-x86-netcoreapp2.2.zip",
|
||||
"Windows_64": "win-x64-netcoreapp2.2.zip",
|
||||
|
||||
@@ -12,10 +12,7 @@ import { CreateSessionData } from '../data/createSessionData';
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class CreateSessionDialog {
|
||||
private readonly _providerType: string;
|
||||
|
||||
// Top level
|
||||
private readonly DialogTitle: string = localize('createSessionDialog.newSession', 'New Session');
|
||||
private readonly CancelButtonText: string = localize('createSessionDialog.cancel', 'Cancel');
|
||||
private readonly CreateButtonText: string = localize('createSessionDialog.create', 'Create');
|
||||
private readonly DialogTitleText: string = localize('createSessionDialog.title', 'Create New Profiler Session');
|
||||
@@ -26,6 +23,7 @@ export class CreateSessionDialog {
|
||||
private sessionNameBox: sqlops.InputBoxComponent;
|
||||
|
||||
private model: CreateSessionData;
|
||||
private readonly _providerType: string;
|
||||
|
||||
private _onSuccess: vscode.EventEmitter<CreateSessionData> = new vscode.EventEmitter<CreateSessionData>();
|
||||
public readonly onSuccess: vscode.Event<CreateSessionData> = this._onSuccess.event;
|
||||
@@ -46,7 +44,7 @@ export class CreateSessionDialog {
|
||||
}
|
||||
|
||||
public async showDialog(): Promise<void> {
|
||||
this.dialog = sqlops.window.modelviewdialog.createDialog(this.DialogTitle);
|
||||
this.dialog = sqlops.window.modelviewdialog.createDialog(this.DialogTitleText);
|
||||
this.initializeContent();
|
||||
this.dialog.okButton.onClick(() => this.execute());
|
||||
this.dialog.cancelButton.onClick(() => { });
|
||||
@@ -81,7 +79,7 @@ export class CreateSessionDialog {
|
||||
|
||||
title: localize('createSessionDialog.enterSessionName', "Enter session name:")
|
||||
}],
|
||||
title: this.DialogTitleText
|
||||
title: ''
|
||||
}]).withLayout({ width: '100%' }).component();
|
||||
|
||||
await view.initializeModel(formModel);
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"commands": [
|
||||
{
|
||||
"command": "profiler.newProfiler",
|
||||
"title": "New Profiler",
|
||||
"title": "Launch Profiler",
|
||||
"category": "Profiler"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "azuredatastudio",
|
||||
"version": "1.2.4",
|
||||
"version": "1.3.1",
|
||||
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
|
||||
@@ -1520,9 +1520,6 @@
|
||||
</trans-unit>
|
||||
</body></file>
|
||||
<file original="src/sql/parts/profiler/contrib/profilerActions" source-language="en" datatype="plaintext"><body>
|
||||
<trans-unit id="profiler.connect">
|
||||
<source xml:lang="en">Connect</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="profilerAction.disconnect">
|
||||
<source xml:lang="en">Disconnect</source>
|
||||
</trans-unit>
|
||||
@@ -1533,16 +1530,13 @@
|
||||
<source xml:lang="en">Start</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="create">
|
||||
<source xml:lang="en">Create</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="profiler.capture">
|
||||
<source xml:lang="en">Pause Capture</source>
|
||||
<source xml:lang="en">New Session</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="profilerAction.resumeCapture">
|
||||
<source xml:lang="en">Resume Capture</source>
|
||||
<source xml:lang="en">Resume</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="profilerAction.pauseCapture">
|
||||
<source xml:lang="en">Pause Capture</source>
|
||||
<source xml:lang="en">Pause</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="profilerStop.stop">
|
||||
<source xml:lang="en">Stop</source>
|
||||
@@ -1550,9 +1544,6 @@
|
||||
<trans-unit id="profiler.clear">
|
||||
<source xml:lang="en">Clear Data</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="profiler.autoscrollOn">
|
||||
<source xml:lang="en">Auto Scroll: On</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="profilerAction.autoscrollOn">
|
||||
<source xml:lang="en">Auto Scroll: On</source>
|
||||
</trans-unit>
|
||||
@@ -1572,7 +1563,7 @@
|
||||
<source xml:lang="en">Find Previous String</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="profilerAction.newProfiler">
|
||||
<source xml:lang="en">New Profiler</source>
|
||||
<source xml:lang="en">Launch Profiler</source>
|
||||
</trans-unit>
|
||||
</body></file>
|
||||
<file original="src/sql/base/browser/ui/selectBox/selectBox" source-language="en" datatype="plaintext"><body>
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
||||
<file original="extensions/profiler/client\out/dialogs/profilerCreateSessionDialog" source-language="en" datatype="plaintext"><body>
|
||||
<trans-unit id="createSessionDialog.newSession">
|
||||
<source xml:lang="en">New Session</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="createSessionDialog.cancel">
|
||||
<source xml:lang="en">Cancel</source>
|
||||
</trans-unit>
|
||||
|
||||
@@ -12,12 +12,18 @@ set CODE=".build\electron\%NAMESHORT%"
|
||||
|
||||
rem TFS Builds
|
||||
if not "%BUILD_BUILDID%" == "" (
|
||||
%CODE% .\node_modules\mocha\bin\_mocha %*
|
||||
if not "%ADD_REPORTER%" == "" (
|
||||
%CODE% .\node_modules\mocha\bin\_mocha --reporter mocha-junit-reporter %*
|
||||
)
|
||||
|
||||
if "%ADD_REPORTER%" == "" (
|
||||
%CODE% .\node_modules\mocha\bin\_mocha %*
|
||||
)
|
||||
)
|
||||
|
||||
rem Otherwise
|
||||
if "%BUILD_BUILDID%" == "" (
|
||||
%CODE% .\node_modules\mocha\bin\_mocha --reporter dot %*
|
||||
%CODE% .\node_modules\mocha\bin\_mocha --reporter mocha-junit-reporter %*
|
||||
)
|
||||
popd
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
if [[ "$OSTYPE" == "darwin"* ]] || [[ "$AGENT_OS" == "Darwin"* ]]; then
|
||||
realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; }
|
||||
ROOT=$(dirname $(dirname $(realpath "$0")))
|
||||
|
||||
@@ -14,7 +14,7 @@ fi
|
||||
|
||||
cd $ROOT
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
if [[ "$OSTYPE" == "darwin"* ]] || [[ "$AGENT_OS" == "Darwin"* ]]; then
|
||||
NAME=`node -p "require('./product.json').nameLong"`
|
||||
CODE="./.build/electron/$NAME.app/Contents/MacOS/Electron"
|
||||
else
|
||||
@@ -30,7 +30,7 @@ node build/lib/electron.js || ./node_modules/.bin/gulp electron
|
||||
|
||||
# Unit Tests
|
||||
export ELECTRON_RUN_AS_NODE=1
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
if [[ "$OSTYPE" == "darwin"* ]] || [[ "$AGENT_OS" == "Darwin"* ]]; then
|
||||
cd $ROOT ; ulimit -n 4096 ; \
|
||||
"$CODE" \
|
||||
node_modules/mocha/bin/_mocha "$@"
|
||||
|
||||
@@ -236,8 +236,8 @@
|
||||
|
||||
.modal.flyout-dialog .dialog-message-detail {
|
||||
margin-top: 5px;
|
||||
white-space: normal;
|
||||
-webkit-user-select: text;
|
||||
white-space: pre-wrap;
|
||||
user-select: text;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,8 +72,8 @@ const defaultOptions: IModalOptions = {
|
||||
};
|
||||
|
||||
export abstract class Modal extends Disposable implements IThemable {
|
||||
|
||||
private _messageElement: HTMLElement;
|
||||
protected _useDefaultMessageBoxLocation: boolean = true;
|
||||
protected _messageElement: HTMLElement;
|
||||
private _messageIcon: HTMLElement;
|
||||
private _messageSeverity: Builder;
|
||||
private _messageSummary: Builder;
|
||||
@@ -253,7 +253,9 @@ export abstract class Modal extends Disposable implements IThemable {
|
||||
this._messageElement = this._modalMessageSection.getHTMLElement();
|
||||
this.updateElementVisibility(this._messageElement, false);
|
||||
|
||||
parts.push(this._messageElement);
|
||||
if (this._useDefaultMessageBoxLocation) {
|
||||
parts.push(this._messageElement);
|
||||
}
|
||||
}
|
||||
|
||||
// This modal body section refers to the body of of the dialog
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
.carbon-taskbar.monaco-toolbar .monaco-action-bar.animated .actions-container {
|
||||
justify-content: flex-start;
|
||||
padding-left: 15px;
|
||||
padding: 5px 5px 5px 15px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
|
||||
1
src/sql/media/icons/check.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-2 -2 16 16" enable-background="new -2 -2 16 16"><polygon fill="#424242" points="9,0 4.5,9 3,6 0,6 3,12 6,12 12,0"/></svg>
|
||||
|
After Width: | Height: | Size: 194 B |
1
src/sql/media/icons/check_inverse.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="-2 -2 16 16" enable-background="new -2 -2 16 16"><polygon fill="#C5C5C5" points="9,0 4.5,9 3,6 0,6 3,12 6,12 12,0"/></svg>
|
||||
|
After Width: | Height: | Size: 194 B |
@@ -227,6 +227,51 @@
|
||||
background: url('unpin.svg') center center no-repeat;
|
||||
}
|
||||
|
||||
.vs .sql.icon.pause {
|
||||
background-image: url('pause.svg')
|
||||
}
|
||||
|
||||
.vs-dark .sql.icon.pause,
|
||||
.hc-black .sql.icon.pause {
|
||||
background-image: url('pause_inverse.svg')
|
||||
}
|
||||
|
||||
.vs .sql.icon.continue {
|
||||
background-image: url('continue.svg')
|
||||
}
|
||||
|
||||
.vs-dark .sql.icon.continue,
|
||||
.hc-black .sql.icon.continue {
|
||||
background-image: url('continue_inverse.svg')
|
||||
}
|
||||
|
||||
.vs .sql.icon.checked {
|
||||
background-image: url('check.svg')
|
||||
}
|
||||
|
||||
.vs-dark .sql.icon.checked,
|
||||
.hc-black .sql.icon.checked {
|
||||
background-image: url('check_inverse.svg')
|
||||
}
|
||||
|
||||
.vs .sql.icon.start {
|
||||
background-image: url('start.svg')
|
||||
}
|
||||
|
||||
.vs-dark .sql.icon.start,
|
||||
.hc-black .sql.icon.start {
|
||||
background-image: url('start_inverse.svg')
|
||||
}
|
||||
|
||||
.vs .sql.icon.stop {
|
||||
background-image: url('stop.svg')
|
||||
}
|
||||
|
||||
.vs-dark .sql.icon.stop,
|
||||
.hc-black .sql.icon.stop {
|
||||
background-image: url('stop_inverse.svg')
|
||||
}
|
||||
|
||||
.small {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
||||
1
src/sql/media/icons/continue.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#f6f6f6;}.icon-canvas-transparent{opacity:0;}.icon-vs-action-blue{fill:#00539c;}</style></defs><title>continue</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M15.64,8l-7.8,6H2V2H7.84Z"/></g><g id="iconBg"><path class="icon-vs-action-blue" d="M3,3H5V13H3ZM7.5,3V13L14,8Z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 502 B |
1
src/sql/media/icons/continue_inverse.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#252526;}.icon-canvas-transparent{opacity:0;}.icon-vs-action-blue{fill:#75beff;}</style></defs><title>continue</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M15.64,8l-7.8,6H2V2H7.84Z"/></g><g id="iconBg"><path class="icon-vs-action-blue" d="M3,3H5V13H3ZM7.5,3V13L14,8Z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 502 B |
1
src/sql/media/icons/pause.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#f6f6f6;}.icon-canvas-transparent{opacity:0;}.icon-vs-action-blue{fill:#00539c;}</style></defs><title>pause</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M13,2V14H8.5V2ZM3,14H7.5V2H3Z"/></g><g id="iconBg"><path class="icon-vs-action-blue" d="M4,3H6.5V13H4ZM9.5,3V13H12V3Z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 505 B |
1
src/sql/media/icons/pause_inverse.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#252526;}.icon-canvas-transparent{opacity:0;}.icon-vs-action-blue{fill:#75beff;}</style></defs><title>pause</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M13,2V14H8.5V2ZM3,14H7.5V2H3Z"/></g><g id="iconBg"><path class="icon-vs-action-blue" d="M4,3H6.5V13H4ZM9.5,3V13H12V3Z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 505 B |
1
src/sql/media/icons/start.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#f6f6f6;}.icon-canvas-transparent{opacity:0;}.icon-vs-action-green{fill:#388a34;}</style></defs><title>continue</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M14.334,8,3.667,16H3V0h.667Z"/></g><g id="iconBg"><path class="icon-vs-action-green" d="M4,1.5v13L12.667,8,4,1.5Z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 505 B |
1
src/sql/media/icons/start_inverse.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#252526;}.icon-canvas-transparent{opacity:0;}.icon-vs-action-green{fill:#89d185;}</style></defs><title>continue</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M14.334,8,3.667,16H3V0h.667Z"/></g><g id="iconBg"><path class="icon-vs-action-green" d="M4,1.5v13L12.667,8,4,1.5Z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 505 B |
1
src/sql/media/icons/stop.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#f6f6f6;}.icon-canvas-transparent{opacity:0;}.icon-vs-action-red{fill:#a1260d;}</style></defs><title>stop</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M14,2V14H2V2Z"/></g><g id="iconBg"><path class="icon-vs-action-red" d="M13,3V13H3V3Z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 470 B |
1
src/sql/media/icons/stop_inverse.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#252526;}.icon-canvas-transparent{opacity:0;}.icon-vs-action-red{fill:#f48771;}</style></defs><title>stop</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M14,2V14H2V2Z"/></g><g id="iconBg"><path class="icon-vs-action-red" d="M13,3V13H3V3Z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 470 B |
@@ -24,7 +24,6 @@ import { TreeNode } from 'sql/parts/objectExplorer/common/treeNode';
|
||||
import { NodeType } from 'sql/parts/objectExplorer/common/nodeType';
|
||||
import { ConnectionProfileGroup } from 'sql/parts/connection/common/connectionProfileGroup';
|
||||
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||
import { NewProfilerAction } from 'sql/parts/profiler/contrib/profilerActions';
|
||||
import { TreeUpdateUtils } from 'sql/parts/objectExplorer/viewlet/treeUpdateUtils';
|
||||
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
||||
import { MenuId, IMenuService } from 'vs/platform/actions/common/actions';
|
||||
|
||||
@@ -10,7 +10,6 @@ import { IProfilerController } from 'sql/parts/profiler/editor/controller/interf
|
||||
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
||||
import { BaseActionContext } from 'sql/workbench/common/actions';
|
||||
import { Task } from 'sql/platform/tasks/common/tasks';
|
||||
import { ObjectExplorerActionsContext } from 'sql/parts/objectExplorer/viewlet/objectExplorerActions';
|
||||
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||
import { IConnectionManagementService, IConnectionCompletionOptions, ConnectionType } from 'sql/parts/connection/common/connectionManagement';
|
||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||
@@ -25,8 +24,11 @@ import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiati
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
|
||||
export class ProfilerConnect extends Action {
|
||||
private static readonly ConnectText = nls.localize('profilerAction.connect', 'Connect');
|
||||
private static readonly DisconnectText = nls.localize('profilerAction.disconnect', 'Disconnect');
|
||||
|
||||
public static ID = 'profiler.connect';
|
||||
public static LABEL = nls.localize('profiler.connect', "Connect");
|
||||
public static LABEL = ProfilerConnect.ConnectText;
|
||||
|
||||
private _connected: boolean = false;
|
||||
|
||||
@@ -59,7 +61,7 @@ export class ProfilerConnect extends Action {
|
||||
public set connected(value: boolean) {
|
||||
this._connected = value;
|
||||
this._setClass(value ? 'disconnect' : 'connect');
|
||||
this._setLabel(value ? nls.localize('profilerAction.disconnect', 'Disconnect') : nls.localize('profilerAction.connect', "Connect"));
|
||||
this._setLabel(value ? ProfilerConnect.DisconnectText : ProfilerConnect.ConnectText);
|
||||
}
|
||||
|
||||
public get connected(): boolean {
|
||||
@@ -75,7 +77,7 @@ export class ProfilerStart extends Action {
|
||||
id: string, label: string,
|
||||
@IProfilerService private _profilerService: IProfilerService
|
||||
) {
|
||||
super(id, label, 'start');
|
||||
super(id, label, 'sql start');
|
||||
}
|
||||
|
||||
public run(input: ProfilerInput): TPromise<boolean> {
|
||||
@@ -86,7 +88,7 @@ export class ProfilerStart extends Action {
|
||||
|
||||
export class ProfilerCreate extends Action {
|
||||
public static ID = 'profiler.create';
|
||||
public static LABEL = nls.localize('create', "Create");
|
||||
public static LABEL = nls.localize('create', "New Session");
|
||||
|
||||
constructor(
|
||||
id: string, label: string,
|
||||
@@ -105,8 +107,13 @@ export class ProfilerCreate extends Action {
|
||||
}
|
||||
|
||||
export class ProfilerPause extends Action {
|
||||
private static readonly PauseText = nls.localize('profilerAction.pauseCapture', 'Pause');
|
||||
private static readonly ResumeText = nls.localize('profilerAction.resumeCapture', 'Resume');
|
||||
private static readonly PauseCssClass = 'sql pause';
|
||||
private static readonly ResumeCssClass = 'sql continue';
|
||||
|
||||
public static ID = 'profiler.pause';
|
||||
public static LABEL = nls.localize('profiler.capture', "Pause Capture");
|
||||
public static LABEL = ProfilerPause.PauseText;
|
||||
|
||||
private _paused: boolean = false;
|
||||
|
||||
@@ -114,7 +121,7 @@ export class ProfilerPause extends Action {
|
||||
id: string, label: string,
|
||||
@IProfilerService private _profilerService: IProfilerService
|
||||
) {
|
||||
super(id, label, 'stop');
|
||||
super(id, label, ProfilerPause.PauseCssClass);
|
||||
}
|
||||
|
||||
public run(input: ProfilerInput): TPromise<boolean> {
|
||||
@@ -127,8 +134,8 @@ export class ProfilerPause extends Action {
|
||||
|
||||
public set paused(value: boolean) {
|
||||
this._paused = value;
|
||||
this._setClass(value ? 'start' : 'stop');
|
||||
this._setLabel(value ? nls.localize('profilerAction.resumeCapture', "Resume Capture") : nls.localize('profilerAction.pauseCapture', "Pause Capture"));
|
||||
this._setClass(value ? ProfilerPause.ResumeCssClass : ProfilerPause.PauseCssClass);
|
||||
this._setLabel(value ? ProfilerPause.ResumeText : ProfilerPause.PauseText);
|
||||
}
|
||||
|
||||
public get paused(): boolean {
|
||||
@@ -144,7 +151,7 @@ export class ProfilerStop extends Action {
|
||||
id: string, label: string,
|
||||
@IProfilerService private _profilerService: IProfilerService
|
||||
) {
|
||||
super(id, label, 'stop');
|
||||
super(id, label, 'sql stop');
|
||||
}
|
||||
|
||||
public run(input: ProfilerInput): TPromise<boolean> {
|
||||
@@ -167,16 +174,21 @@ export class ProfilerClear extends Action {
|
||||
}
|
||||
|
||||
export class ProfilerAutoScroll extends Action {
|
||||
private static readonly AutoScrollOnText = nls.localize('profilerAction.autoscrollOn', 'Auto Scroll: On');
|
||||
private static readonly AutoScrollOffText = nls.localize('profilerAction.autoscrollOff', 'Auto Scroll: Off');
|
||||
private static readonly CheckedCssClass = 'sql checked';
|
||||
|
||||
public static ID = 'profiler.autoscroll';
|
||||
public static LABEL = nls.localize('profiler.autoscrollOn', "Auto Scroll: On");
|
||||
public static LABEL = ProfilerAutoScroll.AutoScrollOnText;
|
||||
|
||||
constructor(id: string, label: string) {
|
||||
super(id, label);
|
||||
super(id, label, ProfilerAutoScroll.CheckedCssClass);
|
||||
}
|
||||
|
||||
run(input: ProfilerInput): TPromise<boolean> {
|
||||
this.checked = !this.checked;
|
||||
this._setLabel(this.checked ? nls.localize('profilerAction.autoscrollOn', "Auto Scroll: On") : nls.localize('profilerAction.autoscrollOff', "Auto Scroll: Off"));
|
||||
this._setLabel(this.checked ? ProfilerAutoScroll.AutoScrollOnText : ProfilerAutoScroll.AutoScrollOffText);
|
||||
this._setClass(this.checked ? ProfilerAutoScroll.CheckedCssClass : '');
|
||||
input.state.change({ autoscroll: this.checked });
|
||||
return TPromise.as(true);
|
||||
}
|
||||
@@ -256,7 +268,7 @@ export class ProfilerFindPrevious implements IEditorAction {
|
||||
|
||||
export class NewProfilerAction extends Task {
|
||||
public static readonly ID = 'profiler.newProfiler';
|
||||
public static readonly LABEL = nls.localize('profilerAction.newProfiler', 'New Profiler');
|
||||
public static readonly LABEL = nls.localize('profilerAction.newProfiler', 'Launch Profiler');
|
||||
public static readonly ICON = 'profile';
|
||||
|
||||
private _connectionProfile: ConnectionProfile;
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import * as nls from 'vs/nls';
|
||||
|
||||
import { IEditorService, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||
|
||||
export class GlobalNewProfilerAction extends Action {
|
||||
public static ID = 'explorer.newProfiler';
|
||||
public static LABEL = nls.localize('profilerWorkbenchAction.newProfiler', "New Profiler");
|
||||
|
||||
constructor(
|
||||
id: string, label: string,
|
||||
@IEditorService private _editorService: IEditorService,
|
||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||
@IConnectionManagementService private _connectionService: IConnectionManagementService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(context?: any): TPromise<boolean> {
|
||||
// TODO: for test-only, grab the first MSSQL active connection for the profiler session
|
||||
// TODO: when finishing the feature the connection should come from the launch context
|
||||
let connectionProfile: IConnectionProfile;
|
||||
if (context && context.connectionProfile) {
|
||||
connectionProfile = context.connectionProfile;
|
||||
} else {
|
||||
let activeConnections = this._connectionService.getActiveConnections();
|
||||
if (activeConnections) {
|
||||
for (let i = 0; i < activeConnections.length; ++i) {
|
||||
if (activeConnections[i].providerName === 'MSSQL') {
|
||||
connectionProfile = activeConnections[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let profilerInput = this._instantiationService.createInstance(ProfilerInput, connectionProfile);
|
||||
return this._editorService.openEditor(profilerInput, { pinned: true }, ACTIVE_GROUP).then(() => TPromise.as(true));
|
||||
}
|
||||
}
|
||||
@@ -122,7 +122,6 @@ export class ProfilerEditor extends BaseEditor {
|
||||
private _viewTemplates: Array<IProfilerViewTemplate>;
|
||||
private _sessionSelector: SelectBox;
|
||||
private _sessionsList: Array<string>;
|
||||
private _connectionInfoText: HTMLElement;
|
||||
|
||||
// Actions
|
||||
private _connectAction: Actions.ProfilerConnect;
|
||||
@@ -211,6 +210,7 @@ export class ProfilerEditor extends BaseEditor {
|
||||
|
||||
this._viewTemplates = this._profilerService.getViewTemplates();
|
||||
this._viewTemplateSelector = new SelectBox(this._viewTemplates.map(i => i.name), 'Standard View', this._contextViewService);
|
||||
this._viewTemplateSelector.setAriaLabel(nls.localize('profiler.viewSelectAccessibleName', 'Select View'));
|
||||
this._register(this._viewTemplateSelector.onDidSelect(e => {
|
||||
if (this.input) {
|
||||
this.input.viewTemplate = this._viewTemplates.find(i => i.name === e.selected);
|
||||
@@ -223,6 +223,7 @@ export class ProfilerEditor extends BaseEditor {
|
||||
|
||||
this._sessionsList = [''];
|
||||
this._sessionSelector = new SelectBox(this._sessionsList, '', this._contextViewService);
|
||||
this._sessionSelector.setAriaLabel(nls.localize('profiler.sessionSelectAccessibleName', 'Select Session'));
|
||||
this._register(this._sessionSelector.onDidSelect(e => {
|
||||
if (this.input) {
|
||||
this.input.sessionName = e.selected;
|
||||
@@ -233,32 +234,36 @@ export class ProfilerEditor extends BaseEditor {
|
||||
sessionsContainer.style.paddingRight = '5px';
|
||||
this._sessionSelector.render(sessionsContainer);
|
||||
|
||||
this._connectionInfoText = document.createElement('div');
|
||||
this._connectionInfoText.style.paddingRight = '5px';
|
||||
this._connectionInfoText.innerText = '';
|
||||
this._connectionInfoText.style.textAlign = 'center';
|
||||
this._connectionInfoText.style.display = 'flex';
|
||||
this._connectionInfoText.style.alignItems = 'center';
|
||||
|
||||
this._register(attachSelectBoxStyler(this._viewTemplateSelector, this.themeService));
|
||||
this._register(attachSelectBoxStyler(this._sessionSelector, this.themeService));
|
||||
|
||||
this._actionBar.setContent([
|
||||
{ action: this._startAction },
|
||||
{ action: this._stopAction },
|
||||
{ element: sessionsContainer },
|
||||
{ action: this._createAction },
|
||||
{ element: Taskbar.createTaskbarSeparator() },
|
||||
{ element: this._createTextElement(nls.localize('profiler.sessionSelectLabel', 'Select Session:')) },
|
||||
{ element: sessionsContainer },
|
||||
{ action: this._startAction },
|
||||
{ action: this._stopAction },
|
||||
{ action: this._pauseAction },
|
||||
{ action: this._autoscrollAction },
|
||||
{ action: this._instantiationService.createInstance(Actions.ProfilerClear, Actions.ProfilerClear.ID, Actions.ProfilerClear.LABEL) },
|
||||
{ element: Taskbar.createTaskbarSeparator() },
|
||||
{ element: this._createTextElement(nls.localize('profiler.viewSelectLabel', 'Select View:')) },
|
||||
{ element: viewTemplateContainer },
|
||||
{ element: Taskbar.createTaskbarSeparator() },
|
||||
{ element: this._connectionInfoText }
|
||||
{ action: this._autoscrollAction },
|
||||
{ action: this._instantiationService.createInstance(Actions.ProfilerClear, Actions.ProfilerClear.ID, Actions.ProfilerClear.LABEL) }
|
||||
]);
|
||||
}
|
||||
|
||||
private _createTextElement(text: string): HTMLDivElement {
|
||||
let textElement = document.createElement('div');
|
||||
textElement.style.paddingRight = '10px';
|
||||
textElement.innerText = text;
|
||||
textElement.style.textAlign = 'center';
|
||||
textElement.style.display = 'flex';
|
||||
textElement.style.alignItems = 'center';
|
||||
return textElement;
|
||||
}
|
||||
|
||||
private _createProfilerTable(): HTMLElement {
|
||||
let profilerTableContainer = document.createElement('div');
|
||||
profilerTableContainer.className = 'profiler-table monaco-editor';
|
||||
@@ -417,7 +422,6 @@ export class ProfilerEditor extends BaseEditor {
|
||||
autoscroll: true,
|
||||
isPanelCollapsed: true
|
||||
});
|
||||
this._connectionInfoText.innerText = input.connectionName;
|
||||
this._profilerTableEditor.updateState();
|
||||
this._splitView.layout();
|
||||
this._profilerTableEditor.focus();
|
||||
@@ -464,34 +468,16 @@ export class ProfilerEditor extends BaseEditor {
|
||||
this._connectAction.connected = this.input.state.isConnected;
|
||||
|
||||
if (this.input.state.isConnected) {
|
||||
|
||||
this._updateToolbar();
|
||||
this._sessionSelector.enable();
|
||||
this._profilerService.getXEventSessions(this.input.id).then((r) => {
|
||||
// set undefined result to empty list
|
||||
if (!r) {
|
||||
r = [];
|
||||
}
|
||||
|
||||
this._sessionSelector.setOptions(r);
|
||||
this._sessionsList = r;
|
||||
if ((this.input.sessionName === undefined || this.input.sessionName === '') && this._sessionsList.length > 0) {
|
||||
let sessionIndex: number = 0;
|
||||
let uiState = this._profilerService.getSessionViewState(this.input.id);
|
||||
if (uiState && uiState.previousSessionName) {
|
||||
sessionIndex = this._sessionsList.indexOf(uiState.previousSessionName);
|
||||
} else {
|
||||
this._profilerService.launchCreateSessionDialog(this.input);
|
||||
}
|
||||
// Launch the create session dialog if openning a new window.
|
||||
let uiState = this._profilerService.getSessionViewState(this.input.id);
|
||||
let previousSessionName = uiState && uiState.previousSessionName;
|
||||
if (!this.input.sessionName && !previousSessionName) {
|
||||
this._profilerService.launchCreateSessionDialog(this.input);
|
||||
}
|
||||
|
||||
if (sessionIndex < 0) {
|
||||
sessionIndex = 0;
|
||||
}
|
||||
|
||||
this.input.sessionName = this._sessionsList[sessionIndex];
|
||||
this._sessionSelector.selectWithOptionName(this.input.sessionName);
|
||||
}
|
||||
});
|
||||
this._updateSessionSelector(previousSessionName);
|
||||
} else {
|
||||
this._startAction.enabled = false;
|
||||
this._stopAction.enabled = false;
|
||||
@@ -517,23 +503,35 @@ export class ProfilerEditor extends BaseEditor {
|
||||
}
|
||||
if (this.input.state.isStopped) {
|
||||
this._updateToolbar();
|
||||
this._sessionSelector.enable();
|
||||
this._profilerService.getXEventSessions(this.input.id).then((r) => {
|
||||
// set undefined result to empty list
|
||||
if (!r) {
|
||||
r = [];
|
||||
}
|
||||
|
||||
this._sessionsList = r;
|
||||
this._sessionSelector.setOptions(r);
|
||||
if ((this.input.sessionName === undefined || this.input.sessionName === '') && this._sessionsList.length > 0) {
|
||||
this.input.sessionName = this._sessionsList[0];
|
||||
}
|
||||
});
|
||||
this._updateSessionSelector();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _updateSessionSelector(previousSessionName: string = undefined) {
|
||||
this._sessionSelector.enable();
|
||||
this._profilerService.getXEventSessions(this.input.id).then((r) => {
|
||||
if (!r) {
|
||||
r = [];
|
||||
}
|
||||
|
||||
this._sessionSelector.setOptions(r);
|
||||
this._sessionsList = r;
|
||||
if (this._sessionsList.length > 0) {
|
||||
if (!this.input.sessionName) {
|
||||
this.input.sessionName = previousSessionName;
|
||||
}
|
||||
|
||||
if (this._sessionsList.indexOf(this.input.sessionName) === -1) {
|
||||
this.input.sessionName = this._sessionsList[0];
|
||||
}
|
||||
|
||||
this._sessionSelector.selectWithOptionName(this.input.sessionName);
|
||||
};
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private _updateToolbar(): void {
|
||||
this._startAction.enabled = !this.input.state.isRunning && !this.input.state.isPaused && this.input.state.isConnected;
|
||||
this._createAction.enabled = !this.input.state.isRunning && !this.input.state.isPaused && this.input.state.isConnected;
|
||||
|
||||
@@ -12,7 +12,7 @@ import * as sqlops from 'sqlops';
|
||||
import * as nls from 'vs/nls';
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { EditorInput } from 'vs/workbench/common/editor';
|
||||
import { EditorInput, ConfirmResult } from 'vs/workbench/common/editor';
|
||||
import { IEditorModel } from 'vs/platform/editor/common/editor';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
@@ -22,6 +22,7 @@ import { IDialogService, IConfirmation, IConfirmationResult } from 'vs/platform/
|
||||
import { escape } from 'sql/base/common/strings';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import Severity from 'vs/base/common/severity';
|
||||
|
||||
export class ProfilerInput extends EditorInput implements IProfilerSession {
|
||||
|
||||
@@ -41,7 +42,7 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
||||
public onColumnsChanged: Event<Slick.Column<Slick.SlickData>[]> = this._onColumnsChanged.event;
|
||||
|
||||
constructor(
|
||||
private _connection: IConnectionProfile,
|
||||
public connection: IConnectionProfile,
|
||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||
@IProfilerService private _profilerService: IProfilerService,
|
||||
@INotificationService private _notificationService: INotificationService,
|
||||
@@ -58,7 +59,7 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
||||
autoscroll: true
|
||||
});
|
||||
|
||||
this._profilerService.registerSession(generateUuid(), _connection, this).then((id) => {
|
||||
this._profilerService.registerSession(generateUuid(), connection, this).then((id) => {
|
||||
this._id = id;
|
||||
this.state.change({ isConnected: true });
|
||||
});
|
||||
@@ -72,27 +73,10 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
||||
return ret;
|
||||
};
|
||||
this._data = new TableDataView<Slick.SlickData>(undefined, searchFn);
|
||||
|
||||
this.onDispose(() => {
|
||||
if (this._state.isRunning || this.state.isPaused) {
|
||||
let confirm: IConfirmation = {
|
||||
message: nls.localize('confirmStopProfilerSession', "Would you like to stop the running XEvent session?"),
|
||||
primaryButton: nls.localize('profilerClosingActions.yes', 'Yes'),
|
||||
secondaryButton: nls.localize('profilerClosingActions.no', 'No'),
|
||||
type: 'question'
|
||||
};
|
||||
|
||||
this._dialogService.confirm(confirm).then(result => {
|
||||
if (result.confirmed) {
|
||||
this._profilerService.stopSession(this.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public get providerType(): string {
|
||||
return this._connection ? this._connection.providerName : undefined;
|
||||
return this.connection ? this.connection.providerName : undefined;
|
||||
}
|
||||
|
||||
public set viewTemplate(template: IProfilerViewTemplate) {
|
||||
@@ -118,7 +102,7 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
||||
}
|
||||
|
||||
public set sessionName(name: string) {
|
||||
if (!this._state.isRunning || !this.state.isPaused) {
|
||||
if (!this.state.isRunning || !this.state.isPaused) {
|
||||
this._sessionName = name;
|
||||
}
|
||||
}
|
||||
@@ -137,10 +121,10 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
||||
|
||||
public getName(): string {
|
||||
let name: string = nls.localize('profilerInput.profiler', 'Profiler');
|
||||
if (!this._connection) {
|
||||
if (!this.connection) {
|
||||
return name;
|
||||
}
|
||||
name += ': ' + this._connection.serverName.substring(0, 20);
|
||||
name += ': ' + this.connection.serverName.substring(0, 20);
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -182,11 +166,11 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
||||
}
|
||||
|
||||
public get connectionName(): string {
|
||||
if (!types.isUndefinedOrNull(this._connection)) {
|
||||
if (this._connection.databaseName) {
|
||||
return `${this._connection.serverName} ${this._connection.databaseName}`;
|
||||
if (!types.isUndefinedOrNull(this.connection)) {
|
||||
if (this.connection.databaseName) {
|
||||
return `${this.connection.serverName} ${this.connection.databaseName}`;
|
||||
} else {
|
||||
return `${this._connection.serverName}`;
|
||||
return `${this.connection.serverName}`;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -203,7 +187,7 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
||||
}
|
||||
|
||||
public onSessionStopped(notification: sqlops.ProfilerSessionStoppedParams) {
|
||||
this._notificationService.error(nls.localize("profiler.sessionStopped", "XEvent Profiler Session stopped unexpectedly on the server {0}.", this._connection.serverName));
|
||||
this._notificationService.error(nls.localize("profiler.sessionStopped", "XEvent Profiler Session stopped unexpectedly on the server {0}.", this.connection.serverName));
|
||||
|
||||
this.state.change({
|
||||
isStopped: true,
|
||||
@@ -244,7 +228,7 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
||||
|
||||
public onMoreRows(eventMessage: sqlops.ProfilerSessionEvents) {
|
||||
if (eventMessage.eventsLost) {
|
||||
this._notificationService.warn(nls.localize("profiler.eventsLost", "The XEvent Profiler session for {0} has lost events.", this._connection.serverName));
|
||||
this._notificationService.warn(nls.localize("profiler.eventsLost", "The XEvent Profiler session for {0} has lost events.", this.connection.serverName));
|
||||
}
|
||||
|
||||
for (let i: number = 0; i < eventMessage.events.length && i < 500; ++i) {
|
||||
@@ -268,4 +252,31 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
confirmSave(): TPromise<ConfirmResult> {
|
||||
if (this.state.isRunning || this.state.isPaused) {
|
||||
return this._dialogService.show(Severity.Warning,
|
||||
nls.localize('confirmStopProfilerSession', "Would you like to stop the running XEvent session?"),
|
||||
[
|
||||
nls.localize('profilerClosingActions.yes', 'Yes'),
|
||||
nls.localize('profilerClosingActions.no', 'No'),
|
||||
nls.localize('profilerClosingActions.cancel', 'Cancel')
|
||||
]).then((selection: number) => {
|
||||
if (selection === 0) {
|
||||
this._profilerService.stopSession(this.id);
|
||||
return ConfirmResult.DONT_SAVE;
|
||||
} else if (selection === 1) {
|
||||
return ConfirmResult.DONT_SAVE;
|
||||
} else {
|
||||
return ConfirmResult.CANCEL;
|
||||
}
|
||||
});;
|
||||
} else {
|
||||
return TPromise.wrap(ConfirmResult.DONT_SAVE);
|
||||
}
|
||||
}
|
||||
|
||||
isDirty(): boolean {
|
||||
return this.state.isRunning || this.state.isPaused;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +141,10 @@ export class ProfilerService implements IProfilerService {
|
||||
this._sessionMap.get(this._idMap.reverseGet(id)).onSessionStateChanged({ isStopped: true, isPaused: false, isRunning: false });
|
||||
return true;
|
||||
}, (reason) => {
|
||||
this._notificationService.error(reason.message);
|
||||
// The error won't be actionable to the user, so only log it to console.
|
||||
// In case of error, the state of the UI is not usable, makes more sense to
|
||||
// set it to stopped so that user can restart it or pick a different session
|
||||
this._sessionMap.get(this._idMap.reverseGet(id)).onSessionStateChanged({ isStopped: true, isPaused: false, isRunning: false });
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,18 @@
|
||||
min-width: 800px;
|
||||
}
|
||||
|
||||
.dialog-message-and-page-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.dialogModal-page-container {
|
||||
flex: 1 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.dialogModal-pane {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -34,6 +34,9 @@ export class WizardModal extends Modal {
|
||||
// Wizard HTML elements
|
||||
private _body: HTMLElement;
|
||||
|
||||
private _messageAndPageContainer: HTMLElement;
|
||||
private _pageContainer: HTMLElement;
|
||||
|
||||
// Buttons
|
||||
private _previousButton: Button;
|
||||
private _nextButton: Button;
|
||||
@@ -53,6 +56,7 @@ export class WizardModal extends Modal {
|
||||
@IClipboardService clipboardService: IClipboardService
|
||||
) {
|
||||
super(_wizard.title, name, partService, telemetryService, clipboardService, themeService, contextKeyService, options);
|
||||
this._useDefaultMessageBoxLocation = false;
|
||||
}
|
||||
|
||||
public layout(): void {
|
||||
@@ -126,12 +130,21 @@ export class WizardModal extends Modal {
|
||||
}
|
||||
|
||||
protected renderBody(container: HTMLElement): void {
|
||||
let bodyBuilderObj;
|
||||
new Builder(container).div({ class: 'dialogModal-body' }, (bodyBuilder) => {
|
||||
bodyBuilderObj = bodyBuilder;
|
||||
this._body = bodyBuilder.getHTMLElement();
|
||||
});
|
||||
|
||||
this.initializeNavigation(this._body);
|
||||
|
||||
bodyBuilderObj.div({ class: 'dialog-message-and-page-container' }, (mpContainer) => {
|
||||
this._messageAndPageContainer = mpContainer.getHTMLElement();
|
||||
mpContainer.append(this._messageElement);
|
||||
this._pageContainer = mpContainer.div({ class: 'dialogModal-page-container' }).getHTMLElement();
|
||||
});
|
||||
|
||||
|
||||
this._wizard.pages.forEach(page => {
|
||||
this.registerPage(page);
|
||||
});
|
||||
@@ -159,7 +172,7 @@ export class WizardModal extends Modal {
|
||||
|
||||
private registerPage(page: WizardPage): void {
|
||||
let dialogPane = new DialogPane(page.title, page.content, valid => page.notifyValidityChanged(valid), this._instantiationService, this._wizard.displayPageTitles, page.description);
|
||||
dialogPane.createBody(this._body);
|
||||
dialogPane.createBody(this._pageContainer);
|
||||
this._dialogPanes.set(page, dialogPane);
|
||||
page.onUpdate(() => this.setButtonsForPage(this._wizard.currentPage));
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import { IObjectExplorerService } from 'sql/parts/objectExplorer/common/objectEx
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { QueryInput } from 'sql/parts/query/common/queryInput';
|
||||
import { DashboardInput } from 'sql/parts/dashboard/dashboardInput';
|
||||
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
||||
|
||||
// map for the version of SQL Server (default is 140)
|
||||
const scriptCompatibilityOptionMap = {
|
||||
@@ -400,6 +401,9 @@ export function getCurrentGlobalConnection(objectExplorerService: IObjectExplore
|
||||
if (activeInput instanceof QueryInput || activeInput instanceof EditDataInput || activeInput instanceof DashboardInput) {
|
||||
connection = connectionManagementService.getConnectionProfile(activeInput.uri);
|
||||
}
|
||||
else if (activeInput instanceof ProfilerInput) {
|
||||
connection = activeInput.connection;
|
||||
}
|
||||
}
|
||||
|
||||
return connection;
|
||||
|
||||
@@ -199,7 +199,7 @@ suite('Keybindings Editor Model test', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('convert with title and wihtout binding to entry', () => {
|
||||
test('convert with title and without binding to entry', () => {
|
||||
const id = 'a' + uuid.generateUuid();
|
||||
registerCommandWithTitle(id, 'some title');
|
||||
prepareKeybindingService();
|
||||
|
||||