Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd53e685d0 | ||
|
|
410bb62906 | ||
|
|
cbb4ac3e20 | ||
|
|
61746b7ff7 | ||
|
|
e6066c2cb5 | ||
|
|
633a918590 | ||
|
|
9bbed2c275 | ||
|
|
d9ba4d9130 | ||
|
|
e2bd6c06ec | ||
|
|
a26be76d79 | ||
|
|
3b68c1eb69 | ||
|
|
f7879bdbf9 | ||
|
|
dbb0fc519f | ||
|
|
b931ccfabf | ||
|
|
eeab048f46 | ||
|
|
e2b446be1c | ||
|
|
5f2e17a738 | ||
|
|
399d6d0045 | ||
|
|
f36f3ffd21 | ||
|
|
00cd772cbc | ||
|
|
b6c9a3bb89 | ||
|
|
cbf6c06e4b | ||
|
|
cff21124da | ||
|
|
ce7893c2e5 | ||
|
|
f7dcaa38ff | ||
|
|
8ce1013a26 | ||
|
|
114d67b408 | ||
|
|
56c2d16560 | ||
|
|
2238c42432 | ||
|
|
64f6cf6747 | ||
|
|
c0e9f1ca43 | ||
|
|
7f66087d8c | ||
|
|
18671b7cca | ||
|
|
233156c744 | ||
|
|
5e964d2105 | ||
|
|
59e7a5fa4b | ||
|
|
8452f577d2 | ||
|
|
726eb8d0e1 | ||
|
|
2c0d6b93ee |
23
CHANGELOG.md
@@ -1,5 +1,28 @@
|
|||||||
# Change Log
|
# 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
|
## Version 1.1.3
|
||||||
* Release date: October 18, 2018
|
* Release date: October 18, 2018
|
||||||
* Release status: General Availability
|
* Release status: General Availability
|
||||||
|
|||||||
37
README.md
@@ -8,12 +8,12 @@ Azure Data Studio is a data management tool that enables you to work with SQL Se
|
|||||||
|
|
||||||
Platform | Link
|
Platform | Link
|
||||||
-- | --
|
-- | --
|
||||||
Windows Setup Installer | https://go.microsoft.com/fwlink/?linkid=2030731
|
Windows Setup Installer | https://go.microsoft.com/fwlink/?linkid=2038320
|
||||||
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=2030736
|
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=2038323
|
||||||
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=2030738
|
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=2038327
|
||||||
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=2030741
|
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=2038332
|
||||||
Linux RPM | https://go.microsoft.com/fwlink/?linkid=2030746
|
Linux RPM | https://go.microsoft.com/fwlink/?linkid=2038401
|
||||||
Linux DEB | https://go.microsoft.com/fwlink/?linkid=2030750
|
Linux DEB | https://go.microsoft.com/fwlink/?linkid=2038405
|
||||||
|
|
||||||
Go to our [download page](https://aka.ms/azuredatastudio) for more specific instructions.
|
Go to our [download page](https://aka.ms/azuredatastudio) for more specific instructions.
|
||||||
|
|
||||||
@@ -34,9 +34,9 @@ See the [change log](https://github.com/Microsoft/azuredatastudio/blob/master/CH
|
|||||||
- Task History window to view current task execution status, completion results with error messages and task T-SQL scripting
|
- Task History window to view current task execution status, completion results with error messages and task T-SQL scripting
|
||||||
- Scripting support to generate CREATE, SELECT, ALTER and DROP statements for database objects
|
- Scripting support to generate CREATE, SELECT, ALTER and DROP statements for database objects
|
||||||
- Workspaces with full Git integration and Find In Files support to managing T-SQL script libraries
|
- Workspaces with full Git integration and Find In Files support to managing T-SQL script libraries
|
||||||
- Modern light-weight shell with theming, user settings, full screen support, integrated terminal and numerous other features
|
- Modern light-weight shell with theming, user settings, full-screen support, integrated terminal and numerous other features
|
||||||
|
|
||||||
Here's some of these features in action.
|
Here are some of these features in action.
|
||||||
|
|
||||||
<img src='https://github.com/Microsoft/azuredatastudio/blob/master/docs/overview_screen.jpg' width='800px'>
|
<img src='https://github.com/Microsoft/azuredatastudio/blob/master/docs/overview_screen.jpg' width='800px'>
|
||||||
|
|
||||||
@@ -61,6 +61,12 @@ The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.micro
|
|||||||
## Contributions and "Thank You"
|
## 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:
|
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`
|
* philoushka for `center the icon #2760`
|
||||||
* anthonypants for `Typo #2775`
|
* anthonypants for `Typo #2775`
|
||||||
* kstolte for `Fix Invalid Configuration in Launch.json #2789`
|
* kstolte for `Fix Invalid Configuration in Launch.json #2789`
|
||||||
@@ -69,25 +75,25 @@ We would like to thank all our users who raised issues, and in particular the fo
|
|||||||
* AlexFsmn `Disabled connection name input when connecting to a server. #2566`
|
* AlexFsmn `Disabled connection name input when connecting to a server. #2566`
|
||||||
* SebastianPfliegel `Added more saveAsCsv options #2099`
|
* SebastianPfliegel `Added more saveAsCsv options #2099`
|
||||||
* ianychoi `Fixes a typo: Mimunum -> Minimum #1994`
|
* ianychoi `Fixes a typo: Mimunum -> Minimum #1994`
|
||||||
* AlexFsmn `Fixed bug where proper file extension wasn't appended to filename. #2151`
|
* AlexFsmn `Fixed bug where proper file extension wasn't appended to the filename. #2151`
|
||||||
* AlexFsmn `Added functionality for adding any file to import wizard #2329`
|
* AlexFsmn `Added functionality for adding any file to import wizard #2329`
|
||||||
* AlexFsmn `Fixed background issue when copying a chart to clipboard #2215`
|
* AlexFsmn `Fixed background issue when copying a chart to clipboard #2215`
|
||||||
* AlexFsmn `Fixed problem where vertical charts didn't display labels correctly. #2263`
|
* AlexFsmn `Fixed problem where vertical charts didn't display labels correctly. #2263`
|
||||||
* AlexFsmn `Fixed Initial values for charts to match visuals #2266`
|
* AlexFsmn `Fixed Initial values for charts to match visuals #2266`
|
||||||
* AlexFsmn `Renamed chart option labels #2264`
|
* AlexFsmn `Renamed chart option labels #2264`
|
||||||
* AlexFsmn `Added feature for opening file after exporting to CSV/XLS/JSON & query files #2216`
|
* AlexFsmn `Added feature for the opening file after exporting to CSV/XLS/JSON & query files #2216`
|
||||||
* AlexFsmm `Get Connection String should copy to clipboard #2175`
|
* AlexFsmm `Get Connection String should copy to clipboard #2175`
|
||||||
* lanceklinger `Fix for double clicking column handle in results table #1504`
|
* lanceklinger `Fix for double-clicking column handle in results table #1504`
|
||||||
* westerncj for `Removed duplicate contribution from README.md (#753)`
|
* westerncj for `Removed duplicate contribution from README.md (#753)`
|
||||||
* ntovas for `Fix for duplicate extensions shown in "Save File" dialog. (#779)`
|
* ntovas for `Fix for duplicate extensions shown in "Save File" dialog. (#779)`
|
||||||
* SebastianPfliegel for `Add cursor snippet (#475)`
|
* SebastianPfliegel for `Add cursor snippet (#475)`
|
||||||
* mikaoelitiana for fix: `revert README and CONTRIBUTING after last VSCode merge (#574)`
|
* mikaoelitiana for the fix: `revert README and CONTRIBUTING after last VSCode merge (#574)`
|
||||||
* alextercete for `Reinstate menu item to install from VSIX (#682)`
|
* alextercete for `Reinstate menu item to install from VSIX (#682)`
|
||||||
* alextercete for `Fix "No extension gallery service configured" error (#427)`
|
* alextercete for `Fix "No extension gallery service configured" error (#427)`
|
||||||
* mwiedemeyer for `Fix #58: Default sort order for DB size widget (#111)`
|
* mwiedemeyer for `Fix #58: Default sort order for DB size widget (#111)`
|
||||||
* AlexTroshkin for `Show disconnect in context menu only when connectionProfile connected (#150)`
|
* AlexTroshkin for `Show disconnect in context menu only when connectionProfile connected (#150)`
|
||||||
* AlexTroshkin for `Fix #138: Invalid syntax color highlighting (identity not highlighting) (#140))`
|
* AlexTroshkin for `Fix #138: Invalid syntax color highlighting (identity not highlighting) (#140))`
|
||||||
* stebet for `Fix #153: Fixing sql snippets that failed on a DB with case-sensitive collation. (#152)`
|
* stebet for `Fix #153: Fixing sql snippets that failed on a DB with a case-sensitive collation. (#152)`
|
||||||
* SebastianPfliegel `Remove sqlExtensionHelp (#312)`
|
* SebastianPfliegel `Remove sqlExtensionHelp (#312)`
|
||||||
* olljanat for `Implemented npm version check (#314)`
|
* olljanat for `Implemented npm version check (#314)`
|
||||||
* Adam Machanic for helping with the `whoisactive` extension
|
* Adam Machanic for helping with the `whoisactive` extension
|
||||||
@@ -96,15 +102,14 @@ We would like to thank all our users who raised issues, and in particular the fo
|
|||||||
* Italian: Aldo Donetti, Alessandro Alpi, Andrea Dottor, Bruni Luca, Gianluca Hotz, Luca Nardi, Luigi Bruno, Marco Dal Pino, Mirco Vanini, Pasquale Ceglie, Riccardo Cappello, Sergio Govoni, Stefano Demiliani
|
* Italian: Aldo Donetti, Alessandro Alpi, Andrea Dottor, Bruni Luca, Gianluca Hotz, Luca Nardi, Luigi Bruno, Marco Dal Pino, Mirco Vanini, Pasquale Ceglie, Riccardo Cappello, Sergio Govoni, Stefano Demiliani
|
||||||
* German: Anna Henke-Gunvaldson, Ben Weissman, David Ullmer, J.M. ., Kai Modo, Konstantin Staschill, Kostja Klein, Lennart Trunk, Markus Ehrenmüller-Jensen, Mascha Kroenlein, Matthias Knoll, Mourad Louha, Thomas Hütter, Wolfgang Straßer
|
* German: Anna Henke-Gunvaldson, Ben Weissman, David Ullmer, J.M. ., Kai Modo, Konstantin Staschill, Kostja Klein, Lennart Trunk, Markus Ehrenmüller-Jensen, Mascha Kroenlein, Matthias Knoll, Mourad Louha, Thomas Hütter, Wolfgang Straßer
|
||||||
* Spanish: Alberto Poblacion, Andy Gonzalez, Carlos Mendible, Christian Araujo, Daniel D, Eickhel Mendoza, Ernesto Cardenas, Ivan Toledo Ivanovic, Fran Diaz, JESUS GIL, Jorge Serrano Pérez, José Saturnino Pimentel Juárez, Mauricio Hidalgo, Pablo Iglesias, Rikhardo Estrada Rdez, Thierry DEMAN, YOLANDA CUESTA ALTIERI
|
* Spanish: Alberto Poblacion, Andy Gonzalez, Carlos Mendible, Christian Araujo, Daniel D, Eickhel Mendoza, Ernesto Cardenas, Ivan Toledo Ivanovic, Fran Diaz, JESUS GIL, Jorge Serrano Pérez, José Saturnino Pimentel Juárez, Mauricio Hidalgo, Pablo Iglesias, Rikhardo Estrada Rdez, Thierry DEMAN, YOLANDA CUESTA ALTIERI
|
||||||
* Japanese: Fujio Kojima, Kazushi KAMEGAWA, Masayoshi Yamada, Masayuki Ozawa , Seiji Momoto, Takashi Kanai, Takayoshi Tanaka, Yoshihisa Ozaki, 庄垣内治
|
* Japanese: Fujio Kojima, Kazushi KAMEGAWA, Masayoshi Yamada, Masayuki Ozawa, Seiji Momoto, Takashi Kanai, Takayoshi Tanaka, Yoshihisa Ozaki, 庄垣内治
|
||||||
* Chinese (simplified): DAN YE, Joel Yang, Lynne Dong, Ryan(Yu) Zhang, Sheng Jiang, Wei Zhang, Zhiliang Xu
|
* Chinese (simplified): DAN YE, Joel Yang, Lynne Dong, Ryan(Yu) Zhang, Sheng Jiang, Wei Zhang, Zhiliang Xu
|
||||||
* Chinese (Traditional): Bruce Chen, Chiayi Yen, Kevin Yang, Winnie Lin, 保哥 Will, 謝政廷
|
* Chinese (Traditional): Bruce Chen, Chiayi Yen, Kevin Yang, Winnie Lin, 保哥 Will, 謝政廷
|
||||||
* Korean: Do-Kyun Kim, Evelyn Kim, Helen Jung, Hong Jmee, jeongwoo choi, Jun Hyoung Lee, Jungsun Kim정선, Justin Yoo, Kavrith mucha, Kiwoong Youm, MinGyu Ju, MVP_JUNO BEA, Sejun Kim, SOONMAN KWON, sung man ko, Yeongrak Choi, younggun kim, Youngjae Kim, 소영 이
|
* Korean: Do-Kyun Kim, Evelyn Kim, Helen Jung, Hong Jmee, jeongwoo choi, Jun Hyoung Lee, Jungsun Kim정선, Justin Yoo, Kavrith mucha, Kiwoong Youm, MinGyu Ju, MVP_JUNO BEA, Sejun Kim, SOONMAN KWON, sung man ko, Yeongrak Choi, younggun kim, Youngjae Kim, 소영 이
|
||||||
* Russian: Andrey Veselov, Anton Fontanov, Anton Savin, Elena Ostrovskaia, Igor Babichev, Maxim Zelensky, Rodion Fedechkin, Tasha T, Vladimir Zyryanov
|
* 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
|
* 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)
|
||||||
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
|
## 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 @@
|
|||||||
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "agent",
|
"name": "agent",
|
||||||
"displayName": "SQL Server Agent",
|
"displayName": "SQL Server Agent",
|
||||||
"description": "Manage and troubleshoot SQL Server Agent jobs",
|
"description": "Manage and troubleshoot SQL Server Agent jobs",
|
||||||
"version": "0.34.0",
|
"version": "0.35.0",
|
||||||
"publisher": "Microsoft",
|
"publisher": "Microsoft",
|
||||||
"preview": true,
|
"preview": true,
|
||||||
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
|
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import * as vscode from 'vscode';
|
|||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import { AgentUtils } from '../agentUtils';
|
import { AgentUtils } from '../agentUtils';
|
||||||
import { IAgentDialogData, AgentDialogMode } from '../interfaces';
|
import { IAgentDialogData, AgentDialogMode } from '../interfaces';
|
||||||
|
import { JobData } from './jobData';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
@@ -45,8 +46,19 @@ export class AlertData implements IAgentDialogData {
|
|||||||
wmiEventNamespace: string;
|
wmiEventNamespace: string;
|
||||||
wmiEventQuery: string;
|
wmiEventQuery: string;
|
||||||
|
|
||||||
constructor(ownerUri:string, alertInfo: sqlops.AgentAlertInfo) {
|
private viaJobDialog: boolean;
|
||||||
|
private jobModel: JobData;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
ownerUri:string,
|
||||||
|
alertInfo: sqlops.AgentAlertInfo,
|
||||||
|
jobModel?: JobData,
|
||||||
|
viaJobDialog: boolean = false
|
||||||
|
) {
|
||||||
this.ownerUri = ownerUri;
|
this.ownerUri = ownerUri;
|
||||||
|
this.viaJobDialog = viaJobDialog;
|
||||||
|
this.jobModel = jobModel;
|
||||||
|
this.jobName = this.jobName ? this.jobName : this.jobModel.name;
|
||||||
|
|
||||||
if (alertInfo) {
|
if (alertInfo) {
|
||||||
this.dialogMode = AgentDialogMode.EDIT;
|
this.dialogMode = AgentDialogMode.EDIT;
|
||||||
@@ -60,7 +72,6 @@ export class AlertData implements IAgentDialogData {
|
|||||||
this.includeEventDescription = alertInfo.includeEventDescription.toString();
|
this.includeEventDescription = alertInfo.includeEventDescription.toString();
|
||||||
this.isEnabled = alertInfo.isEnabled;
|
this.isEnabled = alertInfo.isEnabled;
|
||||||
this.jobId = alertInfo.jobId;
|
this.jobId = alertInfo.jobId;
|
||||||
this.jobName = alertInfo.jobName;
|
|
||||||
this.lastOccurrenceDate = alertInfo.lastOccurrenceDate;
|
this.lastOccurrenceDate = alertInfo.lastOccurrenceDate;
|
||||||
this.lastResponseDate = alertInfo.lastResponseDate;
|
this.lastResponseDate = alertInfo.lastResponseDate;
|
||||||
this.messageId = alertInfo.messageId;
|
this.messageId = alertInfo.messageId;
|
||||||
@@ -82,10 +93,18 @@ export class AlertData implements IAgentDialogData {
|
|||||||
|
|
||||||
public async save() {
|
public async save() {
|
||||||
let agentService = await AgentUtils.getAgentService();
|
let agentService = await AgentUtils.getAgentService();
|
||||||
let result = this.dialogMode === AgentDialogMode.CREATE
|
let result: any;
|
||||||
? await agentService.createAlert(this.ownerUri, this.toAgentAlertInfo())
|
// if it's called via the job dialog, add it to the
|
||||||
: await agentService.updateAlert(this.ownerUri, this.originalName, this.toAgentAlertInfo());
|
// job model
|
||||||
|
if (this.viaJobDialog) {
|
||||||
|
if (this.jobModel) {
|
||||||
|
Promise.resolve(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// has to be a create alert
|
||||||
|
result = await agentService.createAlert(this.ownerUri, this.toAgentAlertInfo());
|
||||||
|
}
|
||||||
if (!result || !result.success) {
|
if (!result || !result.success) {
|
||||||
vscode.window.showErrorMessage(
|
vscode.window.showErrorMessage(
|
||||||
localize('alertData.saveErrorMessage', "Alert update failed '{0}'", result.errorMessage ? result.errorMessage : 'Unknown'));
|
localize('alertData.saveErrorMessage', "Alert update failed '{0}'", result.errorMessage ? result.errorMessage : 'Unknown'));
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ export class JobData implements IAgentDialogData {
|
|||||||
public jobSteps: sqlops.AgentJobStepInfo[];
|
public jobSteps: sqlops.AgentJobStepInfo[];
|
||||||
public jobSchedules: sqlops.AgentJobScheduleInfo[];
|
public jobSchedules: sqlops.AgentJobScheduleInfo[];
|
||||||
public alerts: sqlops.AgentAlertInfo[];
|
public alerts: sqlops.AgentAlertInfo[];
|
||||||
|
public jobId: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
ownerUri: string,
|
ownerUri: string,
|
||||||
@@ -62,6 +63,7 @@ export class JobData implements IAgentDialogData {
|
|||||||
this.jobSteps = jobInfo.JobSteps;
|
this.jobSteps = jobInfo.JobSteps;
|
||||||
this.jobSchedules = jobInfo.JobSchedules;
|
this.jobSchedules = jobInfo.JobSchedules;
|
||||||
this.alerts = jobInfo.Alerts;
|
this.alerts = jobInfo.Alerts;
|
||||||
|
this.jobId = jobInfo.jobId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +117,6 @@ export class JobData implements IAgentDialogData {
|
|||||||
let result = this.dialogMode === AgentDialogMode.CREATE
|
let result = this.dialogMode === AgentDialogMode.CREATE
|
||||||
? await this._agentService.createJob(this.ownerUri, jobInfo)
|
? await this._agentService.createJob(this.ownerUri, jobInfo)
|
||||||
: await this._agentService.updateJob(this.ownerUri, this.originalName, jobInfo);
|
: await this._agentService.updateJob(this.ownerUri, this.originalName, jobInfo);
|
||||||
|
|
||||||
if (!result || !result.success) {
|
if (!result || !result.success) {
|
||||||
vscode.window.showErrorMessage(
|
vscode.window.showErrorMessage(
|
||||||
localize('jobData.saveErrorMessage', "Job update failed '{0}'", result.errorMessage ? result.errorMessage : 'Unknown'));
|
localize('jobData.saveErrorMessage', "Job update failed '{0}'", result.errorMessage ? result.errorMessage : 'Unknown'));
|
||||||
@@ -135,18 +136,6 @@ export class JobData implements IAgentDialogData {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public addJobSchedule(schedule: sqlops.AgentJobScheduleInfo) {
|
|
||||||
if (this.jobSchedules) {
|
|
||||||
let existingSchedule = this.jobSchedules.find(item => item.name === schedule.name);
|
|
||||||
if (!existingSchedule) {
|
|
||||||
this.jobSchedules.push(schedule);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.jobSchedules = [];
|
|
||||||
this.jobSchedules.push(schedule);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public toAgentJobInfo(): sqlops.AgentJobInfo {
|
public toAgentJobInfo(): sqlops.AgentJobInfo {
|
||||||
return {
|
return {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
@@ -177,7 +166,7 @@ export class JobData implements IAgentDialogData {
|
|||||||
categoryType: 1, // LocalJob, hard-coding the value, corresponds to the target tab in SSMS
|
categoryType: 1, // LocalJob, hard-coding the value, corresponds to the target tab in SSMS
|
||||||
lastRun: '',
|
lastRun: '',
|
||||||
nextRun: '',
|
nextRun: '',
|
||||||
jobId: ''
|
jobId: this.jobId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,11 +46,13 @@ export class JobStepData implements IAgentDialogData {
|
|||||||
public retryInterval: number;
|
public retryInterval: number;
|
||||||
public proxyName: string;
|
public proxyName: string;
|
||||||
private jobModel: JobData;
|
private jobModel: JobData;
|
||||||
|
private viaJobDialog: boolean;
|
||||||
|
|
||||||
constructor(ownerUri:string, jobModel?: JobData) {
|
constructor(ownerUri:string, jobModel?: JobData, viaJobDialog: boolean = false) {
|
||||||
this.ownerUri = ownerUri;
|
this.ownerUri = ownerUri;
|
||||||
this.jobName = jobModel.name;
|
this.jobName = jobModel.name;
|
||||||
this.jobModel = jobModel;
|
this.jobModel = jobModel;
|
||||||
|
this.viaJobDialog = viaJobDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async initialize() {
|
public async initialize() {
|
||||||
@@ -59,18 +61,16 @@ export class JobStepData implements IAgentDialogData {
|
|||||||
public async save() {
|
public async save() {
|
||||||
let agentService = await AgentUtils.getAgentService();
|
let agentService = await AgentUtils.getAgentService();
|
||||||
let result: any;
|
let result: any;
|
||||||
if (this.dialogMode === AgentDialogMode.CREATE) {
|
// if it's called via the job dialog, add it to the
|
||||||
if (this.jobModel && this.jobModel.dialogMode === AgentDialogMode.CREATE) {
|
// job model
|
||||||
// create job -> create step
|
if (this.viaJobDialog) {
|
||||||
|
if (this.jobModel) {
|
||||||
Promise.resolve(this);
|
Promise.resolve(this);
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
// edit job -> create step
|
|
||||||
result = await agentService.createJobStep(this.ownerUri, JobStepData.convertToAgentJobStepInfo(this));
|
|
||||||
}
|
}
|
||||||
} else if (this.jobModel && this.jobModel.dialogMode === AgentDialogMode.EDIT) {
|
} else {
|
||||||
// edit job -> edit step
|
// has to be a create step
|
||||||
result = await agentService.updateJobStep(this.ownerUri, this.stepName, JobStepData.convertToAgentJobStepInfo(this));
|
result = await agentService.createJobStep(this.ownerUri, JobStepData.convertToAgentJobStepInfo(this));
|
||||||
}
|
}
|
||||||
if (!result || !result.success) {
|
if (!result || !result.success) {
|
||||||
vscode.window.showErrorMessage(
|
vscode.window.showErrorMessage(
|
||||||
|
|||||||
@@ -29,8 +29,6 @@ export class PickScheduleData implements IAgentDialogData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async save() {
|
public async save() {
|
||||||
let agentService = await AgentUtils.getAgentService();
|
|
||||||
this.selectedSchedule.jobName = this.jobName;
|
this.selectedSchedule.jobName = this.jobName;
|
||||||
let result = await agentService.createJobSchedule(this.ownerUri, this.selectedSchedule);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { AgentUtils } from '../agentUtils';
|
|||||||
import { AlertData } from '../data/alertData';
|
import { AlertData } from '../data/alertData';
|
||||||
import { OperatorDialog } from './operatorDialog';
|
import { OperatorDialog } from './operatorDialog';
|
||||||
import { JobDialog } from './jobDialog';
|
import { JobDialog } from './jobDialog';
|
||||||
|
import { JobData } from '../data/jobData';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
@@ -148,14 +149,23 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
private delayMinutesTextBox: sqlops.InputBoxComponent;
|
private delayMinutesTextBox: sqlops.InputBoxComponent;
|
||||||
private delaySecondsTextBox: sqlops.InputBoxComponent;
|
private delaySecondsTextBox: sqlops.InputBoxComponent;
|
||||||
|
|
||||||
private jobs: string[];
|
|
||||||
private databases: string[];
|
private databases: string[];
|
||||||
|
private jobModel: JobData;
|
||||||
|
public jobId: string;
|
||||||
|
public jobName: string;
|
||||||
|
|
||||||
constructor(ownerUri: string, alertInfo: sqlops.AgentAlertInfo = undefined, jobs: string[]) {
|
constructor(
|
||||||
|
ownerUri: string,
|
||||||
|
jobModel: JobData,
|
||||||
|
alertInfo: sqlops.AgentAlertInfo = undefined,
|
||||||
|
viaJobDialog: boolean = false
|
||||||
|
) {
|
||||||
super(ownerUri,
|
super(ownerUri,
|
||||||
new AlertData(ownerUri, alertInfo),
|
new AlertData(ownerUri, alertInfo, jobModel, viaJobDialog),
|
||||||
alertInfo ? AlertDialog.EditDialogTitle : AlertDialog.CreateDialogTitle);
|
alertInfo ? AlertDialog.EditDialogTitle : AlertDialog.CreateDialogTitle);
|
||||||
this.jobs = jobs;
|
this.jobModel = jobModel;
|
||||||
|
this.jobId = this.jobId ? this.jobId : this.jobModel.jobId;
|
||||||
|
this.jobName = this.jobName ? this.jobName : this.jobModel.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
protected async initializeDialog(dialog: sqlops.window.modelviewdialog.Dialog) {
|
||||||
@@ -512,7 +522,8 @@ export class AlertDialog extends AgentDialog<AlertData> {
|
|||||||
protected updateModel() {
|
protected updateModel() {
|
||||||
this.model.name = this.nameTextBox.value;
|
this.model.name = this.nameTextBox.value;
|
||||||
this.model.isEnabled = this.enabledCheckBox.checked;
|
this.model.isEnabled = this.enabledCheckBox.checked;
|
||||||
|
this.model.jobId = this.jobId;
|
||||||
|
this.model.jobName = this.jobName;
|
||||||
this.model.alertType = this.getDropdownValue(this.typeDropDown);
|
this.model.alertType = this.getDropdownValue(this.typeDropDown);
|
||||||
let databaseName = this.getDropdownValue(this.databaseDropDown);
|
let databaseName = this.getDropdownValue(this.databaseDropDown);
|
||||||
this.model.databaseName = (databaseName !== AlertDialog.AllDatabases) ? databaseName : undefined;
|
this.model.databaseName = (databaseName !== AlertDialog.AllDatabases) ? databaseName : undefined;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { PickScheduleDialog } from './pickScheduleDialog';
|
|||||||
import { AlertDialog } from './alertDialog';
|
import { AlertDialog } from './alertDialog';
|
||||||
import { AgentDialog } from './agentDialog';
|
import { AgentDialog } from './agentDialog';
|
||||||
import { AgentUtils } from '../agentUtils';
|
import { AgentUtils } from '../agentUtils';
|
||||||
|
import { JobStepData } from '../data/jobStepData';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
@@ -110,11 +111,19 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
private newAlertButton: sqlops.ButtonComponent;
|
private newAlertButton: sqlops.ButtonComponent;
|
||||||
private isEdit: boolean = false;
|
private isEdit: boolean = false;
|
||||||
|
|
||||||
|
// Job objects
|
||||||
|
private steps: sqlops.AgentJobStepInfo[];
|
||||||
|
private schedules: sqlops.AgentJobScheduleInfo[];
|
||||||
|
private alerts: sqlops.AgentAlertInfo[] = [];
|
||||||
|
|
||||||
constructor(ownerUri: string, jobInfo: sqlops.AgentJobInfo = undefined) {
|
constructor(ownerUri: string, jobInfo: sqlops.AgentJobInfo = undefined) {
|
||||||
super(
|
super(
|
||||||
ownerUri,
|
ownerUri,
|
||||||
new JobData(ownerUri, jobInfo),
|
new JobData(ownerUri, jobInfo),
|
||||||
jobInfo ? JobDialog.EditDialogTitle : JobDialog.CreateDialogTitle);
|
jobInfo ? JobDialog.EditDialogTitle : JobDialog.CreateDialogTitle);
|
||||||
|
this.steps = this.model.jobSteps ? this.model.jobSteps : [];
|
||||||
|
this.schedules = this.model.jobSchedules ? this.model.jobSchedules : [];
|
||||||
|
this.alerts = this.model.alerts ? this.model.alerts : [];
|
||||||
this.isEdit = jobInfo ? true : false;
|
this.isEdit = jobInfo ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,12 +207,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
|
|
||||||
private initializeStepsTab() {
|
private initializeStepsTab() {
|
||||||
this.stepsTab.registerContent(async view => {
|
this.stepsTab.registerContent(async view => {
|
||||||
let previewTag = view.modelBuilder.text()
|
let data = this.steps ? this.convertStepsToData(this.steps) : [];
|
||||||
.withProperties({
|
|
||||||
value: 'Feature Preview'
|
|
||||||
}).component();
|
|
||||||
let steps = this.model.jobSteps ? this.model.jobSteps : [];
|
|
||||||
let data = this.convertStepsToData(steps);
|
|
||||||
this.stepsTable = view.modelBuilder.table()
|
this.stepsTable = view.modelBuilder.table()
|
||||||
.withProperties({
|
.withProperties({
|
||||||
columns: [
|
columns: [
|
||||||
@@ -237,13 +241,11 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
width: 80
|
width: 80
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model);
|
let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, null, true);
|
||||||
stepDialog.onSuccess((step) => {
|
stepDialog.onSuccess((step) => {
|
||||||
if (!this.model.jobSteps) {
|
let stepInfo = JobStepData.convertToAgentJobStepInfo(step);
|
||||||
this.model.jobSteps = [];
|
this.steps.push(stepInfo);
|
||||||
}
|
this.stepsTable.data = this.convertStepsToData(this.steps);
|
||||||
this.model.jobSteps.push(step);
|
|
||||||
this.stepsTable.data = this.convertStepsToData(this.model.jobSteps);
|
|
||||||
});
|
});
|
||||||
this.newStepButton.onDidClick((e)=>{
|
this.newStepButton.onDidClick((e)=>{
|
||||||
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
|
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
|
||||||
@@ -277,7 +279,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.deleteStepButton.enabled = true;
|
this.deleteStepButton.enabled = true;
|
||||||
this.editStepButton.enabled = true;
|
this.editStepButton.enabled = true;
|
||||||
this.editStepButton.onDidClick(() => {
|
this.editStepButton.onDidClick(() => {
|
||||||
let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, stepData);
|
let stepDialog = new JobStepDialog(this.model.ownerUri, '' , this.model, stepData, true);
|
||||||
stepDialog.openDialog();
|
stepDialog.openDialog();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -287,7 +289,6 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
agentService.deleteJobStep(this.ownerUri, stepData).then((result) => {
|
agentService.deleteJobStep(this.ownerUri, stepData).then((result) => {
|
||||||
if (result && result.success) {
|
if (result && result.success) {
|
||||||
delete steps[rowNumber];
|
delete steps[rowNumber];
|
||||||
this.model.jobSteps = steps;
|
|
||||||
let data = this.convertStepsToData(steps);
|
let data = this.convertStepsToData(steps);
|
||||||
this.stepsTable.data = data;
|
this.stepsTable.data = data;
|
||||||
}
|
}
|
||||||
@@ -299,10 +300,6 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
|
|
||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: previewTag,
|
|
||||||
title: ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
component: this.stepsTable,
|
component: this.stepsTable,
|
||||||
title: this.JobStepsTopLabelString,
|
title: this.JobStepsTopLabelString,
|
||||||
actions: [this.moveStepUpButton, this.moveStepDownButton, this.newStepButton, this.editStepButton, this.deleteStepButton]
|
actions: [this.moveStepUpButton, this.moveStepDownButton, this.newStepButton, this.editStepButton, this.deleteStepButton]
|
||||||
@@ -313,10 +310,6 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
|
|
||||||
private initializeAlertsTab() {
|
private initializeAlertsTab() {
|
||||||
this.alertsTab.registerContent(async view => {
|
this.alertsTab.registerContent(async view => {
|
||||||
let previewTag = view.modelBuilder.text()
|
|
||||||
.withProperties({
|
|
||||||
value: 'Feature Preview'
|
|
||||||
}).component();
|
|
||||||
let alerts = this.model.alerts ? this.model.alerts : [];
|
let alerts = this.model.alerts ? this.model.alerts : [];
|
||||||
let data = this.convertAlertsToData(alerts);
|
let data = this.convertAlertsToData(alerts);
|
||||||
this.alertsTable = view.modelBuilder.table()
|
this.alertsTable = view.modelBuilder.table()
|
||||||
@@ -327,7 +320,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.AlertTypeLabelString
|
this.AlertTypeLabelString
|
||||||
],
|
],
|
||||||
data: data,
|
data: data,
|
||||||
height: 430,
|
height: 750,
|
||||||
width: 400
|
width: 400
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
@@ -336,18 +329,24 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
width: 80
|
width: 80
|
||||||
}).component();
|
}).component();
|
||||||
|
|
||||||
this.newAlertButton.onDidClick((e)=>{
|
let alertDialog = new AlertDialog(this.model.ownerUri, this.model, null, true);
|
||||||
let alertDialog = new AlertDialog(this.model.ownerUri, null, []);
|
alertDialog.onSuccess((alert) => {
|
||||||
alertDialog.onSuccess((dialogModel) => {
|
let alertInfo = alert.toAgentAlertInfo();
|
||||||
});
|
this.alerts.push(alertInfo);
|
||||||
alertDialog.openDialog();
|
this.alertsTable.data = this.convertAlertsToData(this.alerts);
|
||||||
|
});
|
||||||
|
this.newAlertButton.onDidClick(()=>{
|
||||||
|
if (this.nameTextBox.value && this.nameTextBox.value.length > 0) {
|
||||||
|
alertDialog.jobId = this.model.jobId;
|
||||||
|
alertDialog.jobName = this.model.name ? this.model.name : this.nameTextBox.value;
|
||||||
|
alertDialog.openDialog();
|
||||||
|
} else {
|
||||||
|
this.dialog.message = { text: this.BlankJobNameErrorText };
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let formModel = view.modelBuilder.formContainer()
|
let formModel = view.modelBuilder.formContainer()
|
||||||
.withFormItems([{
|
.withFormItems([{
|
||||||
component: previewTag,
|
|
||||||
title: ''
|
|
||||||
}, {
|
|
||||||
component: this.alertsTable,
|
component: this.alertsTable,
|
||||||
title: this.AlertsTopLabelString,
|
title: this.AlertsTopLabelString,
|
||||||
actions: [this.newAlertButton]
|
actions: [this.newAlertButton]
|
||||||
@@ -380,8 +379,11 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
pickScheduleDialog.onSuccess((dialogModel) => {
|
pickScheduleDialog.onSuccess((dialogModel) => {
|
||||||
let selectedSchedule = dialogModel.selectedSchedule;
|
let selectedSchedule = dialogModel.selectedSchedule;
|
||||||
if (selectedSchedule) {
|
if (selectedSchedule) {
|
||||||
selectedSchedule.jobName = this.model.name;
|
let existingSchedule = this.schedules.find(item => item.name === selectedSchedule.name);
|
||||||
this.model.addJobSchedule(selectedSchedule);
|
if (!existingSchedule) {
|
||||||
|
selectedSchedule.jobName = this.model.name ? this.model.name : this.nameTextBox.value;
|
||||||
|
this.schedules.push(selectedSchedule);
|
||||||
|
}
|
||||||
this.populateScheduleTable();
|
this.populateScheduleTable();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -402,8 +404,7 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private populateScheduleTable() {
|
private populateScheduleTable() {
|
||||||
let schedules = this.model.jobSchedules ? this.model.jobSchedules : [];
|
let data = this.convertSchedulesToData(this.schedules);
|
||||||
let data = this.convertSchedulesToData(schedules);
|
|
||||||
if (data.length > 0) {
|
if (data.length > 0) {
|
||||||
this.schedulesTable.data = data;
|
this.schedulesTable.data = data;
|
||||||
this.schedulesTable.height = 750;
|
this.schedulesTable.height = 750;
|
||||||
@@ -566,5 +567,17 @@ export class JobDialog extends AgentDialog<JobData> {
|
|||||||
this.model.pageLevel = this.getActualConditionValue(this.pagerCheckBox, this.pagerConditionDropdown);
|
this.model.pageLevel = this.getActualConditionValue(this.pagerCheckBox, this.pagerConditionDropdown);
|
||||||
this.model.eventLogLevel = this.getActualConditionValue(this.eventLogCheckBox, this.eventLogConditionDropdown);
|
this.model.eventLogLevel = this.getActualConditionValue(this.eventLogCheckBox, this.eventLogConditionDropdown);
|
||||||
this.model.deleteLevel = this.getActualConditionValue(this.deleteJobCheckBox, this.deleteJobConditionDropdown);
|
this.model.deleteLevel = this.getActualConditionValue(this.deleteJobCheckBox, this.deleteJobConditionDropdown);
|
||||||
|
if (!this.model.jobSteps) {
|
||||||
|
this.model.jobSteps = [];
|
||||||
|
}
|
||||||
|
this.model.jobSteps = this.steps;
|
||||||
|
if (!this.model.jobSchedules) {
|
||||||
|
this.model.jobSchedules = [];
|
||||||
|
}
|
||||||
|
this.model.jobSchedules = this.schedules;
|
||||||
|
if (!this.model.alerts) {
|
||||||
|
this.model.alerts = [];
|
||||||
|
}
|
||||||
|
this.model.alerts = this.alerts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,9 +118,10 @@ export class JobStepDialog extends AgentDialog<JobStepData> {
|
|||||||
server: string,
|
server: string,
|
||||||
jobModel: JobData,
|
jobModel: JobData,
|
||||||
jobStepInfo?: sqlops.AgentJobStepInfo,
|
jobStepInfo?: sqlops.AgentJobStepInfo,
|
||||||
|
viaJobDialog: boolean = false
|
||||||
) {
|
) {
|
||||||
super(ownerUri,
|
super(ownerUri,
|
||||||
jobStepInfo ? JobStepData.convertToJobStepData(jobStepInfo, jobModel) : new JobStepData(ownerUri, jobModel),
|
jobStepInfo ? JobStepData.convertToJobStepData(jobStepInfo, jobModel) : new JobStepData(ownerUri, jobModel, viaJobDialog),
|
||||||
jobStepInfo ? JobStepDialog.EditDialogTitle : JobStepDialog.NewDialogTitle);
|
jobStepInfo ? JobStepDialog.EditDialogTitle : JobStepDialog.NewDialogTitle);
|
||||||
this.stepId = jobStepInfo ?
|
this.stepId = jobStepInfo ?
|
||||||
jobStepInfo.id : jobModel.jobSteps ?
|
jobStepInfo.id : jobModel.jobSteps ?
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ export class OperatorDialog extends AgentDialog<OperatorData> {
|
|||||||
private static readonly PagerSundayCheckBoxLabel: string = localize('createOperator.PagerSundayCheckBox', 'Sunday');
|
private static readonly PagerSundayCheckBoxLabel: string = localize('createOperator.PagerSundayCheckBox', 'Sunday');
|
||||||
private static readonly WorkdayBeginLabel: string = localize('createOperator.workdayBegin', 'Workday begin');
|
private static readonly WorkdayBeginLabel: string = localize('createOperator.workdayBegin', 'Workday begin');
|
||||||
private static readonly WorkdayEndLabel: string = localize('createOperator.workdayEnd', 'Workday end');
|
private static readonly WorkdayEndLabel: string = localize('createOperator.workdayEnd', 'Workday end');
|
||||||
private static readonly PagerDutyScheduleLabel: string = localize('createOperator.PagerDutySchedule', 'Pager on duty schdule');
|
private static readonly PagerDutyScheduleLabel: string = localize('createOperator.PagerDutySchedule', 'Pager on duty schedule');
|
||||||
|
|
||||||
// Notifications tab strings
|
// Notifications tab strings
|
||||||
private static readonly AlertsTableLabel: string = localize('createOperator.AlertListHeading', 'Alert list');
|
private static readonly AlertsTableLabel: string = localize('createOperator.AlertListHeading', 'Alert list');
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { ProxyDialog } from './dialogs/proxyDialog';
|
|||||||
import { JobStepDialog } from './dialogs/jobStepDialog';
|
import { JobStepDialog } from './dialogs/jobStepDialog';
|
||||||
import { PickScheduleDialog } from './dialogs/pickScheduleDialog';
|
import { PickScheduleDialog } from './dialogs/pickScheduleDialog';
|
||||||
import { JobData } from './data/jobData';
|
import { JobData } from './data/jobData';
|
||||||
|
import { AgentUtils } from './agentUtils';
|
||||||
|
|
||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
@@ -41,17 +42,23 @@ export class MainController {
|
|||||||
let dialog = new JobDialog(ownerUri, jobInfo);
|
let dialog = new JobDialog(ownerUri, jobInfo);
|
||||||
dialog.openDialog();
|
dialog.openDialog();
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, server: string, jobData: JobData, jobStepInfo: sqlops.AgentJobStepInfo) => {
|
vscode.commands.registerCommand('agent.openNewStepDialog', (ownerUri: string, server: string, jobInfo: sqlops.AgentJobInfo, jobStepInfo: sqlops.AgentJobStepInfo) => {
|
||||||
let dialog = new JobStepDialog(ownerUri, server, jobData, jobStepInfo);
|
AgentUtils.getAgentService().then((agentService) => {
|
||||||
dialog.openDialog();
|
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
|
||||||
|
let dialog = new JobStepDialog(ownerUri, server, jobData, jobStepInfo, false);
|
||||||
|
dialog.openDialog();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openPickScheduleDialog', (ownerUri: string, jobName: string) => {
|
vscode.commands.registerCommand('agent.openPickScheduleDialog', (ownerUri: string, jobName: string) => {
|
||||||
let dialog = new PickScheduleDialog(ownerUri, jobName);
|
let dialog = new PickScheduleDialog(ownerUri, jobName);
|
||||||
dialog.showDialog();
|
dialog.showDialog();
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openAlertDialog', (ownerUri: string, alertInfo: sqlops.AgentAlertInfo, jobs: string[]) => {
|
vscode.commands.registerCommand('agent.openAlertDialog', (ownerUri: string, jobInfo: sqlops.AgentJobInfo, alertInfo: sqlops.AgentAlertInfo) => {
|
||||||
let dialog = new AlertDialog(ownerUri, alertInfo, jobs);
|
AgentUtils.getAgentService().then((agentService) => {
|
||||||
dialog.openDialog();
|
let jobData: JobData = new JobData(ownerUri, jobInfo, agentService);
|
||||||
|
let dialog = new AlertDialog(ownerUri, jobData, alertInfo, false);
|
||||||
|
dialog.openDialog();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
vscode.commands.registerCommand('agent.openOperatorDialog', (ownerUri: string, operatorInfo: sqlops.AgentOperatorInfo) => {
|
vscode.commands.registerCommand('agent.openOperatorDialog', (ownerUri: string, operatorInfo: sqlops.AgentOperatorInfo) => {
|
||||||
let dialog = new OperatorDialog(ownerUri, operatorInfo);
|
let dialog = new OperatorDialog(ownerUri, operatorInfo);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "import",
|
"name": "import",
|
||||||
"displayName": "SQL Server Import",
|
"displayName": "SQL Server Import",
|
||||||
"description": "SQL Server Import for Azure Data Studio supports importing CSV or JSON files into SQL Server.",
|
"description": "SQL Server Import for Azure Data Studio supports importing CSV or JSON files into SQL Server.",
|
||||||
"version": "0.3.0",
|
"version": "0.4.0",
|
||||||
"publisher": "Microsoft",
|
"publisher": "Microsoft",
|
||||||
"preview": true,
|
"preview": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -42,33 +42,6 @@
|
|||||||
"mac": "ctrl+i"
|
"mac": "ctrl+i"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"dashboard.tabs": [
|
|
||||||
{
|
|
||||||
"id": "flat-file-import",
|
|
||||||
"title": "Flat File Import",
|
|
||||||
"description": "The flat file importer.",
|
|
||||||
"container": {
|
|
||||||
"flat-file-import-container": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"dashboard.containers": [
|
|
||||||
{
|
|
||||||
"id": "flat-file-import-container",
|
|
||||||
"container": {
|
|
||||||
"widgets-container": [
|
|
||||||
{
|
|
||||||
"name": "Tasks",
|
|
||||||
"widget": {
|
|
||||||
"tasks-widget": [
|
|
||||||
"flatFileImport.start"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"menus": {
|
"menus": {
|
||||||
"objectExplorer/item/context": [
|
"objectExplorer/item/context": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export class FlatFileWizard {
|
|||||||
public async start(p: any, ...args: any[]) {
|
public async start(p: any, ...args: any[]) {
|
||||||
let model = <ImportDataModel>{};
|
let model = <ImportDataModel>{};
|
||||||
|
|
||||||
let profile = <sqlops.IConnectionProfile>p.connectionProfile;
|
let profile = p ? <sqlops.IConnectionProfile>p.connectionProfile : null;
|
||||||
if (profile) {
|
if (profile) {
|
||||||
model.serverId = profile.id;
|
model.serverId = profile.id;
|
||||||
model.database = profile.databaseName;
|
model.database = profile.databaseName;
|
||||||
|
|||||||
@@ -345,7 +345,7 @@
|
|||||||
"specialValueType": null,
|
"specialValueType": null,
|
||||||
"isIdentity": false,
|
"isIdentity": false,
|
||||||
"name": "asynchronousProcessing",
|
"name": "asynchronousProcessing",
|
||||||
"displayName": "Asynchronous processing enabled",
|
"displayName": "Asynchronous processing",
|
||||||
"description": "When true, enables usage of the Asynchronous functionality in the .Net Framework Data Provider",
|
"description": "When true, enables usage of the Asynchronous functionality in the .Net Framework Data Provider",
|
||||||
"groupName": "Initialization",
|
"groupName": "Initialization",
|
||||||
"valueType": "boolean",
|
"valueType": "boolean",
|
||||||
@@ -387,7 +387,7 @@
|
|||||||
"specialValueType": null,
|
"specialValueType": null,
|
||||||
"isIdentity": false,
|
"isIdentity": false,
|
||||||
"name": "columnEncryptionSetting",
|
"name": "columnEncryptionSetting",
|
||||||
"displayName": "Column encryption setting",
|
"displayName": "Column encryption",
|
||||||
"description": "Default column encryption setting for all the commands on the connection",
|
"description": "Default column encryption setting for all the commands on the connection",
|
||||||
"groupName": "Security",
|
"groupName": "Security",
|
||||||
"valueType": "category",
|
"valueType": "category",
|
||||||
|
|||||||
@@ -42,18 +42,18 @@
|
|||||||
"Create a new Table": {
|
"Create a new Table": {
|
||||||
"prefix": "sqlCreateTable",
|
"prefix": "sqlCreateTable",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Create a new table called '[${1:TableName}]' in schema '[${2:SchemaName}]' in database '[${3:DatabaseName}]'",
|
"-- Create a new table called '[${1:TableName}]' in schema '[${2:dbo}]'",
|
||||||
"-- Drop the table if it already exists",
|
"-- Drop the table if it already exists",
|
||||||
"IF OBJECT_ID('[${3:DatabaseName}].[${2:SchemaName}].[${1:TableName}]', 'U') IS NOT NULL",
|
"IF OBJECT_ID('[${2:dbo}].[${1:TableName}]', 'U') IS NOT NULL",
|
||||||
"DROP TABLE [${3:DatabaseName}].[${2:SchemaName}].[${1:TableName}]",
|
"DROP TABLE [${2:dbo}].[${1:TableName}]",
|
||||||
"GO",
|
"GO",
|
||||||
"-- Create the table in the specified database and schema",
|
"-- Create the table in the specified schema",
|
||||||
"CREATE TABLE [${3:DatabaseName}].[${2:SchemaName}].[${1:TableName}]",
|
"CREATE TABLE [${2:dbo}].[${1:TableName}]",
|
||||||
"(",
|
"(",
|
||||||
"\t[${4:ColumnName}]Id INT NOT NULL PRIMARY KEY, -- Primary Key column",
|
"\t[${3:Id}] INT NOT NULL PRIMARY KEY, -- Primary Key column",
|
||||||
"\t[${5:ColumnName1}] [NVARCHAR](50) NOT NULL,",
|
"\t[${4:ColumnName2}] ${5:NVARCHAR(50)} NOT NULL,",
|
||||||
"\t[${6:ColumnName2}] [NVARCHAR](50) NOT NULL",
|
"\t[${6:ColumnName3}] ${7:NVARCHAR(50)} NOT NULL",
|
||||||
"\t-- Specify more columns here",
|
"\t$0-- Specify more columns here",
|
||||||
");",
|
");",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
@@ -64,10 +64,10 @@
|
|||||||
"Drop a Table": {
|
"Drop a Table": {
|
||||||
"prefix": "sqlDropTable",
|
"prefix": "sqlDropTable",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Drop a table called '${3:TableName}' in schema '${2:SchemaName}' in Database '${1:DatabaseName}'",
|
"-- Drop a table called '${1:TableName}' in schema '${2:dbo}'",
|
||||||
"-- Drop the table if it already exists",
|
"-- Drop the table if it already exists",
|
||||||
"IF OBJECT_ID('[${1:DatabaseName}].[${2:SchemaName}].[${3:TableName}]', 'U') IS NOT NULL",
|
"IF OBJECT_ID('[${2:dbo}].[${1:TableName}]', 'U') IS NOT NULL",
|
||||||
"DROP TABLE [${1:DatabaseName}].[${2:SchemaName}].[${3:TableName}]",
|
"DROP TABLE [${2:dbo}].[${1:TableName}]",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
"description": "Drop a Table"
|
"description": "Drop a Table"
|
||||||
@@ -76,9 +76,9 @@
|
|||||||
"Add a new column to a Table": {
|
"Add a new column to a Table": {
|
||||||
"prefix": "sqlAddColumn",
|
"prefix": "sqlAddColumn",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Add a new column '[${1:NewColumnName}]' to table '[${2:TableName}]' in schema '[${3:SchemaName}]' in database '[${4:DatabaseName}]'",
|
"-- Add a new column '[${1:NewColumnName}]' to table '[${2:TableName}]' in schema '[${3:dbo}]'",
|
||||||
"ALTER TABLE [${4:DatabaseName}].[${3:SchemaName}].[${2:TableName}]",
|
"ALTER TABLE [${3:dbo}].[${2:TableName}]",
|
||||||
"\tADD [${1:NewColumnName}] /*new_column_name*/ ${5:int} /*new_column_datatype*/ ${6:NULL} /*new_column_nullability*/",
|
"\tADD [${1:NewColumnName}] /*new_column_name*/ ${4:int} /*new_column_datatype*/ ${5:NULL} /*new_column_nullability*/",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
"description": "Add a new column to a Table"
|
"description": "Add a new column to a Table"
|
||||||
@@ -87,8 +87,8 @@
|
|||||||
"Drop a column from a Table": {
|
"Drop a column from a Table": {
|
||||||
"prefix": "sqlDropColumn",
|
"prefix": "sqlDropColumn",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Drop '[${1:ColumnName}]' from table '[${2:TableName}]' in schema '[${3:SchemaName}]' in database '[${4:DatabaseName}]'",
|
"-- Drop '[${1:ColumnName}]' from table '[${2:TableName}]' in schema '[${3:dbo}]'",
|
||||||
"ALTER TABLE [${4:DatabaseName}].[${3:SchemaName}].[${2:TableName}]",
|
"ALTER TABLE [${3:dbo}].[${2:TableName}]",
|
||||||
"\tDROP COLUMN [${1:ColumnName}]",
|
"\tDROP COLUMN [${1:ColumnName}]",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
@@ -98,9 +98,9 @@
|
|||||||
"Select rows from a Table or a View": {
|
"Select rows from a Table or a View": {
|
||||||
"prefix": "sqlSelect",
|
"prefix": "sqlSelect",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Select rows from a Table or View '[${1:TableOrViewName}]' in schema '[${2:SchemaName}]' in database '[${3:DatabaseName}]'",
|
"-- Select rows from a Table or View '[${1:TableOrViewName}]' in schema '[${2:dbo}]'",
|
||||||
"SELECT * FROM [${3:DatabaseName}].[${2:SchemaName}].[${1:TableOrViewName}]",
|
"SELECT * FROM [${2:dbo}].[${1:TableOrViewName}]",
|
||||||
"WHERE ${4:/* add search conditions here */}",
|
"WHERE ${3:/* add search conditions here */}",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
"description": "Select rows from a Table or a View"
|
"description": "Select rows from a Table or a View"
|
||||||
@@ -109,17 +109,17 @@
|
|||||||
"Insert rows into a Table": {
|
"Insert rows into a Table": {
|
||||||
"prefix": "sqlInsertRows",
|
"prefix": "sqlInsertRows",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Insert rows into table '${1:TableName}' in schema '[${2:SchemaName}]' in database '[${3:DatabaseName}]'",
|
"-- Insert rows into table '${1:TableName}' in schema '[${2:dbo}]'",
|
||||||
"INSERT INTO [${3:DatabaseName}].[${2:SchemaName}].[${1:TableName}]",
|
"INSERT INTO [${2:dbo}].[${1:TableName}]",
|
||||||
"( -- Columns to insert data into",
|
"( -- Columns to insert data into",
|
||||||
" ${4:[ColumnName1], [ColumnName2], [ColumnName3]}",
|
" ${3:[ColumnName1], [ColumnName2], [ColumnName3]}",
|
||||||
")",
|
")",
|
||||||
"VALUES",
|
"VALUES",
|
||||||
"( -- First row: values for the columns in the list above",
|
"( -- First row: values for the columns in the list above",
|
||||||
" ${5:ColumnValue1, ColumnValue2, ColumnValue3}",
|
" ${4:ColumnValue1, ColumnValue2, ColumnValue3}",
|
||||||
"),",
|
"),",
|
||||||
"( -- Second row: values for the columns in the list above",
|
"( -- Second row: values for the columns in the list above",
|
||||||
" ${6:ColumnValue1, ColumnValue2, ColumnValue3}",
|
" ${5:ColumnValue1, ColumnValue2, ColumnValue3}",
|
||||||
")",
|
")",
|
||||||
"-- Add more rows here",
|
"-- Add more rows here",
|
||||||
"GO"
|
"GO"
|
||||||
@@ -130,9 +130,9 @@
|
|||||||
"Delete rows from a Table": {
|
"Delete rows from a Table": {
|
||||||
"prefix": "sqlDeleteRows",
|
"prefix": "sqlDeleteRows",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Delete rows from table '[${1:TableName}]' in schema '[${2:SchemaName}]' in database '[${3:DatabaseName}]'",
|
"-- Delete rows from table '[${1:TableName}]' in schema '[${2:dbo}]'",
|
||||||
"DELETE FROM [${3:DatabaseName}].[${2:SchemaName}].[${1:TableName}]",
|
"DELETE FROM [${2:dbo}].[${1:TableName}]",
|
||||||
"WHERE ${4:/* add search conditions here */}",
|
"WHERE ${3:/* add search conditions here */}",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
"description": "Delete rows from a Table"
|
"description": "Delete rows from a Table"
|
||||||
@@ -141,13 +141,13 @@
|
|||||||
"Update rows in a Table": {
|
"Update rows in a Table": {
|
||||||
"prefix": "sqlUpdateRows",
|
"prefix": "sqlUpdateRows",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Update rows in table '[${1:TableName}]' in schema '[${2:SchemaName}]' in database '[${3:DatabaseName}]'",
|
"-- Update rows in table '[${1:TableName}]' in schema '[${2:dbo}]'",
|
||||||
"UPDATE [${3:DatabaseName}].[${2:SchemaName}].[${1:TableName}]",
|
"UPDATE [${2:dbo}].[${1:TableName}]",
|
||||||
"SET",
|
"SET",
|
||||||
"\t[${4:ColumnName1}] = ${5:ColumnValue1},",
|
"\t[${3:ColumnName1}] = ${4:ColumnValue1},",
|
||||||
"\t[${6:ColumnName2}] = ${7:ColumnValue2}",
|
"\t[${5:ColumnName2}] = ${6:ColumnValue2}",
|
||||||
"\t-- Add more columns and values here",
|
"\t-- Add more columns and values here",
|
||||||
"WHERE ${8:/* add search conditions here */}",
|
"WHERE ${7:/* add search conditions here */}",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
"description": "Update rows in a Table"
|
"description": "Update rows in a Table"
|
||||||
@@ -156,27 +156,27 @@
|
|||||||
"Create a stored procedure": {
|
"Create a stored procedure": {
|
||||||
"prefix": "sqlCreateStoredProc",
|
"prefix": "sqlCreateStoredProc",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Create a new stored procedure called '${1:StoredProcedureName}' in schema '${2:SchemaName}'",
|
"-- Create a new stored procedure called '${1:StoredProcedureName}' in schema '${2:dbo}'",
|
||||||
"-- Drop the stored procedure if it already exists",
|
"-- Drop the stored procedure if it already exists",
|
||||||
"IF EXISTS (",
|
"IF EXISTS (",
|
||||||
"SELECT *",
|
"SELECT *",
|
||||||
"\tFROM INFORMATION_SCHEMA.ROUTINES",
|
"\tFROM INFORMATION_SCHEMA.ROUTINES",
|
||||||
"WHERE SPECIFIC_SCHEMA = N'${2:SchemaName}'",
|
"WHERE SPECIFIC_SCHEMA = N'${2:dbo}'",
|
||||||
"\tAND SPECIFIC_NAME = N'${1:StoredProcedureName}'",
|
"\tAND SPECIFIC_NAME = N'${1:StoredProcedureName}'",
|
||||||
")",
|
")",
|
||||||
"DROP PROCEDURE ${2:SchemaName}.${1:StoredProcedureName}",
|
"DROP PROCEDURE ${2:dbo}.${1:StoredProcedureName}",
|
||||||
"GO",
|
"GO",
|
||||||
"-- Create the stored procedure in the specified schema",
|
"-- Create the stored procedure in the specified schema",
|
||||||
"CREATE PROCEDURE ${2:SchemaName}.${1:StoredProcedureName}",
|
"CREATE PROCEDURE ${2:dbo}.${1:StoredProcedureName}",
|
||||||
"\t$3@param1 /*parameter name*/ int /*datatype_for_param1*/ = 0, /*default_value_for_param1*/",
|
"\t$3@param1 /*parameter name*/ $4int /*datatype_for_param1*/ = 0, /*default_value_for_param1*/",
|
||||||
"\t$4@param2 /*parameter name*/ int /*datatype_for_param1*/ = 0 /*default_value_for_param2*/",
|
"\t$5@param2 /*parameter name*/ $6int /*datatype_for_param1*/ = 0 /*default_value_for_param2*/",
|
||||||
"-- add more stored procedure parameters here",
|
"-- add more stored procedure parameters here",
|
||||||
"AS",
|
"AS",
|
||||||
"\t-- body of the stored procedure",
|
"\t-- body of the stored procedure",
|
||||||
"\tSELECT @param1, @param2",
|
"\tSELECT @param1, @param2",
|
||||||
"GO",
|
"GO",
|
||||||
"-- example to execute the stored procedure we just created",
|
"-- example to execute the stored procedure we just created",
|
||||||
"EXECUTE ${2:SchemaName}.${1:StoredProcedureName} 1 /*value_for_param1*/, 2 /*value_for_param2*/",
|
"EXECUTE ${2:dbo}.${1:StoredProcedureName} 1 /*value_for_param1*/, 2 /*value_for_param2*/",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
"description": "Create a stored procedure"
|
"description": "Create a stored procedure"
|
||||||
@@ -185,14 +185,14 @@
|
|||||||
"Drop a stored procedure": {
|
"Drop a stored procedure": {
|
||||||
"prefix": "sqlDropStoredProc",
|
"prefix": "sqlDropStoredProc",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Drop the stored procedure called '${1:StoredProcedureName}' in schema '${2:SchemaName}'",
|
"-- Drop the stored procedure called '${1:StoredProcedureName}' in schema '${2:dbo}'",
|
||||||
"IF EXISTS (",
|
"IF EXISTS (",
|
||||||
"SELECT *",
|
"SELECT *",
|
||||||
"\tFROM INFORMATION_SCHEMA.ROUTINES",
|
"\tFROM INFORMATION_SCHEMA.ROUTINES",
|
||||||
"WHERE SPECIFIC_SCHEMA = N'${2:SchemaName}'",
|
"WHERE SPECIFIC_SCHEMA = N'${2:dbo}'",
|
||||||
"\tAND SPECIFIC_NAME = N'${1:StoredProcedureName}'",
|
"\tAND SPECIFIC_NAME = N'${1:StoredProcedureName}'",
|
||||||
")",
|
")",
|
||||||
"DROP PROCEDURE ${2:SchemaName}.${1:StoredProcedureName}",
|
"DROP PROCEDURE ${2:dbo}.${1:StoredProcedureName}",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
"description": "Drop a stored procedure"
|
"description": "Drop a stored procedure"
|
||||||
@@ -241,7 +241,7 @@
|
|||||||
"Declare a cursor": {
|
"Declare a cursor": {
|
||||||
"prefix": "sqlCursor",
|
"prefix": "sqlCursor",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Declare a cursor for a Table or a View '${1:TableOrViewName}' in schema '${2:SchemaName}'",
|
"-- Declare a cursor for a Table or a View '${1:TableOrViewName}' in schema '${2:dbo}'",
|
||||||
"DECLARE @ColumnName1 NVARCHAR(50), @ColumnName2 NVARCHAR(50)",
|
"DECLARE @ColumnName1 NVARCHAR(50), @ColumnName2 NVARCHAR(50)",
|
||||||
"",
|
"",
|
||||||
"DECLARE db_cursor CURSOR FOR",
|
"DECLARE db_cursor CURSOR FOR",
|
||||||
@@ -304,8 +304,8 @@
|
|||||||
"prefix": "sqlCreateIndex",
|
"prefix": "sqlCreateIndex",
|
||||||
"body": [
|
"body": [
|
||||||
"-- Create a nonclustered index with or without a unique constraint",
|
"-- Create a nonclustered index with or without a unique constraint",
|
||||||
"-- Or create a clustered index on table '[${1:TableName}]' in schema '[${2:SchemaName}]' in database '[${3:DatabaseName}]'",
|
"-- Or create a clustered index on table '[${1:TableName}]' in schema '[${2:dbo}]' in database '[${3:DatabaseName}]'",
|
||||||
"CREATE ${5:/*UNIQUE or CLUSTERED*/} INDEX IX_${4:IndexName} ON [${3:DatabaseName}].[${2:SchemaName}].[${1:TableName}] ([${6:ColumnName1}] DESC /*Change sort order as needed*/",
|
"CREATE ${5:/*UNIQUE or CLUSTERED*/} INDEX IX_${4:IndexName} ON [${3:DatabaseName}].[${2:dbo}].[${1:TableName}] ([${6:ColumnName1}] DESC /*Change sort order as needed*/",
|
||||||
"GO"
|
"GO"
|
||||||
],
|
],
|
||||||
"description": "Create a new Index"
|
"description": "Create a new Index"
|
||||||
@@ -319,13 +319,13 @@
|
|||||||
"IF OBJECT_ID('tempDB..#${1:TableName}', 'U') IS NOT NULL",
|
"IF OBJECT_ID('tempDB..#${1:TableName}', 'U') IS NOT NULL",
|
||||||
"DROP TABLE #${1:TableName}",
|
"DROP TABLE #${1:TableName}",
|
||||||
"GO",
|
"GO",
|
||||||
"-- Create the temporary table from a physical table called '${4:TableName}' in schema '${3:SchemaName}' in database '${2:DatabaseName}'",
|
"-- Create the temporary table from a physical table called '${4:TableName}' in schema '${3:dbo}' in database '${2:DatabaseName}'",
|
||||||
"SELECT *",
|
"SELECT *",
|
||||||
"INTO #${1:TableName}",
|
"INTO #${1:TableName}",
|
||||||
"FROM [${2:DatabaseName}].[${3:[SchemaName}].[${4:TableName}]",
|
"FROM [${2:DatabaseName}].[${3:[dbo}].[${4:TableName}]",
|
||||||
"WHERE ${5:/* add search conditions here */}"
|
"WHERE ${5:/* add search conditions here */}"
|
||||||
],
|
],
|
||||||
"description": "Create a new Temporary Table"
|
"description": "Create a new Temporary Table"
|
||||||
},
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
||||||
"version": "1.5.0-alpha.48",
|
"version": "1.5.0-alpha.53",
|
||||||
"downloadFileNames": {
|
"downloadFileNames": {
|
||||||
"Windows_86": "win-x86-netcoreapp2.2.zip",
|
"Windows_86": "win-x86-netcoreapp2.2.zip",
|
||||||
"Windows_64": "win-x64-netcoreapp2.2.zip",
|
"Windows_64": "win-x64-netcoreapp2.2.zip",
|
||||||
|
|||||||
@@ -12,9 +12,7 @@ import { CreateSessionData } from '../data/createSessionData';
|
|||||||
const localize = nls.loadMessageBundle();
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
export class CreateSessionDialog {
|
export class CreateSessionDialog {
|
||||||
|
|
||||||
// Top level
|
// Top level
|
||||||
private readonly DialogTitle: string = localize('createSessionDialog.newSession', 'New Session');
|
|
||||||
private readonly CancelButtonText: string = localize('createSessionDialog.cancel', 'Cancel');
|
private readonly CancelButtonText: string = localize('createSessionDialog.cancel', 'Cancel');
|
||||||
private readonly CreateButtonText: string = localize('createSessionDialog.create', 'Create');
|
private readonly CreateButtonText: string = localize('createSessionDialog.create', 'Create');
|
||||||
private readonly DialogTitleText: string = localize('createSessionDialog.title', 'Create New Profiler Session');
|
private readonly DialogTitleText: string = localize('createSessionDialog.title', 'Create New Profiler Session');
|
||||||
@@ -25,23 +23,28 @@ export class CreateSessionDialog {
|
|||||||
private sessionNameBox: sqlops.InputBoxComponent;
|
private sessionNameBox: sqlops.InputBoxComponent;
|
||||||
|
|
||||||
private model: CreateSessionData;
|
private model: CreateSessionData;
|
||||||
|
private readonly _providerType: string;
|
||||||
|
|
||||||
private _onSuccess: vscode.EventEmitter<CreateSessionData> = new vscode.EventEmitter<CreateSessionData>();
|
private _onSuccess: vscode.EventEmitter<CreateSessionData> = new vscode.EventEmitter<CreateSessionData>();
|
||||||
public readonly onSuccess: vscode.Event<CreateSessionData> = this._onSuccess.event;
|
public readonly onSuccess: vscode.Event<CreateSessionData> = this._onSuccess.event;
|
||||||
|
|
||||||
|
|
||||||
constructor(ownerUri: string, templates: Array<sqlops.ProfilerSessionTemplate>) {
|
constructor(ownerUri: string, providerType: string, templates: Array<sqlops.ProfilerSessionTemplate>) {
|
||||||
if (typeof (templates) === 'undefined' || templates === null) {
|
if (typeof (templates) === 'undefined' || templates === null) {
|
||||||
throw new Error(localize('createSessionDialog.templatesInvalid', "Invalid templates list, cannot open dialog"));
|
throw new Error(localize('createSessionDialog.templatesInvalid', "Invalid templates list, cannot open dialog"));
|
||||||
}
|
}
|
||||||
if (typeof (ownerUri) === 'undefined' || ownerUri === null) {
|
if (typeof (ownerUri) === 'undefined' || ownerUri === null) {
|
||||||
throw new Error(localize('createSessionDialog.dialogOwnerInvalid', "Invalid dialog owner, cannot open dialog"));
|
throw new Error(localize('createSessionDialog.dialogOwnerInvalid', "Invalid dialog owner, cannot open dialog"));
|
||||||
}
|
}
|
||||||
|
if (typeof (providerType) === 'undefined' || providerType === null) {
|
||||||
|
throw new Error(localize('createSessionDialog.invalidProviderType', "Invalid provider type, cannot open dialog"));
|
||||||
|
}
|
||||||
|
this._providerType = providerType;
|
||||||
this.model = new CreateSessionData(ownerUri, templates);
|
this.model = new CreateSessionData(ownerUri, templates);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async showDialog(): Promise<void> {
|
public async showDialog(): Promise<void> {
|
||||||
this.dialog = sqlops.window.modelviewdialog.createDialog(this.DialogTitle);
|
this.dialog = sqlops.window.modelviewdialog.createDialog(this.DialogTitleText);
|
||||||
this.initializeContent();
|
this.initializeContent();
|
||||||
this.dialog.okButton.onClick(() => this.execute());
|
this.dialog.okButton.onClick(() => this.execute());
|
||||||
this.dialog.cancelButton.onClick(() => { });
|
this.dialog.cancelButton.onClick(() => { });
|
||||||
@@ -76,7 +79,7 @@ export class CreateSessionDialog {
|
|||||||
|
|
||||||
title: localize('createSessionDialog.enterSessionName', "Enter session name:")
|
title: localize('createSessionDialog.enterSessionName', "Enter session name:")
|
||||||
}],
|
}],
|
||||||
title: this.DialogTitleText
|
title: ''
|
||||||
}]).withLayout({ width: '100%' }).component();
|
}]).withLayout({ width: '100%' }).component();
|
||||||
|
|
||||||
await view.initializeModel(formModel);
|
await view.initializeModel(formModel);
|
||||||
@@ -97,8 +100,7 @@ export class CreateSessionDialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async execute(): Promise<void> {
|
private async execute(): Promise<void> {
|
||||||
let currentConnection = await sqlops.connection.getCurrentConnection();
|
let profilerService = sqlops.dataprotocol.getProvider<sqlops.ProfilerProvider>(this._providerType, sqlops.DataProviderType.ProfilerProvider);
|
||||||
let profilerService = sqlops.dataprotocol.getProvider<sqlops.ProfilerProvider>(currentConnection.providerName, sqlops.DataProviderType.ProfilerProvider);
|
|
||||||
|
|
||||||
let name = this.sessionNameBox.value;
|
let name = this.sessionNameBox.value;
|
||||||
let selected = this.templatesBox.value.toString();
|
let selected = this.templatesBox.value.toString();
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ export class MainController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public activate(): void {
|
public activate(): void {
|
||||||
vscode.commands.registerCommand('profiler.openCreateSessionDialog', (ownerUri: string, templates: Array<sqlops.ProfilerSessionTemplate>) => {
|
vscode.commands.registerCommand('profiler.openCreateSessionDialog', (ownerUri: string, providerType: string, templates: Array<sqlops.ProfilerSessionTemplate>) => {
|
||||||
let dialog = new CreateSessionDialog(ownerUri, templates);
|
let dialog = new CreateSessionDialog(ownerUri, providerType, templates);
|
||||||
dialog.showDialog();
|
dialog.showDialog();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "profiler",
|
"name": "profiler",
|
||||||
"displayName": "SQL Server Profiler",
|
"displayName": "SQL Server Profiler",
|
||||||
"description": "SQL Server Profiler for Azure Data Studio",
|
"description": "SQL Server Profiler for Azure Data Studio",
|
||||||
"version": "0.2.0",
|
"version": "0.3.0",
|
||||||
"publisher": "Microsoft",
|
"publisher": "Microsoft",
|
||||||
"preview": true,
|
"preview": true,
|
||||||
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
|
"license": "https://raw.githubusercontent.com/Microsoft/azuredatastudio/master/LICENSE.txt",
|
||||||
@@ -26,11 +26,10 @@
|
|||||||
"Microsoft.mssql"
|
"Microsoft.mssql"
|
||||||
],
|
],
|
||||||
"contributes": {
|
"contributes": {
|
||||||
|
|
||||||
"commands": [
|
"commands": [
|
||||||
{
|
{
|
||||||
"command": "profiler.newProfiler",
|
"command": "profiler.newProfiler",
|
||||||
"title": "New Profiler",
|
"title": "Launch Profiler",
|
||||||
"category": "Profiler"
|
"category": "Profiler"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -49,6 +48,15 @@
|
|||||||
"category": "Profiler"
|
"category": "Profiler"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"menus": {
|
||||||
|
"objectExplorer/item/context": [
|
||||||
|
{
|
||||||
|
"command": "profiler.newProfiler",
|
||||||
|
"when": "connectionProvider == MSSQL && nodeType && nodeType == Server",
|
||||||
|
"group": "profiler"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"outputChannels": [
|
"outputChannels": [
|
||||||
"sqlprofiler"
|
"sqlprofiler"
|
||||||
]
|
]
|
||||||
@@ -59,4 +67,4 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vscode": "1.0.1"
|
"vscode": "1.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,67 +4,71 @@
|
|||||||
"type": "dark",
|
"type": "dark",
|
||||||
"colors": {
|
"colors": {
|
||||||
|
|
||||||
// base
|
// base
|
||||||
"foreground": "#fffffe",
|
"foreground": "#fffffe",
|
||||||
"focusBorder": "#0E639C",
|
"focusBorder": "#0078d7",
|
||||||
"selection.background": "#3062d6",
|
"selection.background": "#3062d6",
|
||||||
|
|
||||||
//text colors
|
//text colors
|
||||||
"textLinkForeground": "#30B4FF",
|
"textLinkForeground": "#30b4ff",
|
||||||
"textLinkActiveForeground": "#30B4FF",
|
"textLinkActiveForeground": "#30b4ff",
|
||||||
|
|
||||||
//Button control
|
//Button control
|
||||||
"button.background": "#00BCF2",
|
"button.background": "#0078d7cc",
|
||||||
"button.foreground": "#212121",
|
"button.foreground": "#ffffff",
|
||||||
"button.hoverBackground": "#0099BC",
|
"button.hoverBackground": "#0078d7",
|
||||||
|
|
||||||
// TODO add support for these
|
// TODO add support for these
|
||||||
// "button.secondaryBackground": "#c8c8c8",
|
// "button.secondaryBackground": "#c8c8c8",
|
||||||
// "button.secondaryHoverBackground": "#a6a6a6",
|
// "button.secondaryHoverBackground": "#a6a6a6",
|
||||||
// "button.secondaryForeground": "#333333",
|
// "button.secondaryForeground": "#333333",
|
||||||
// "button.disabledBackground": "#444444" ,
|
// "button.disabledBackground": "#444444" ,
|
||||||
// "button.disabledForeground": "#888888" ,
|
// "button.disabledForeground": "#888888" ,
|
||||||
|
|
||||||
//Dropdown Control
|
//Checkbox
|
||||||
"dropdown.background": "#212121",
|
"checkbox.disabled.foreground": "#888888",
|
||||||
"dropdown.foreground": "#fffffe",
|
|
||||||
"dropdown.border": "#888888",
|
|
||||||
|
|
||||||
//Input Control
|
//Dropdown Control
|
||||||
"input.background": "#212121",
|
"dropdown.background": "#212121",
|
||||||
|
"dropdown.foreground": "#fffffe",
|
||||||
|
"dropdown.border": "#888888",
|
||||||
|
|
||||||
|
//Input Control
|
||||||
|
"input.background": "#212121",
|
||||||
"input.border": "#888888",
|
"input.border": "#888888",
|
||||||
"input.disabled.background": "#444444",
|
"input.disabled.background": "#444444",
|
||||||
"input.disabled.foreground": "#888888",
|
"input.disabled.foreground": "#888888",
|
||||||
"inputOption.activeBorder": "#007ACC",
|
"inputOption.activeBorder": "#0078d7",
|
||||||
"input.placeholderForeground": "#888888",
|
"input.placeholderForeground": "#888888",
|
||||||
"inputValidation.errorBackground": "#D02E00",
|
"inputValidation.errorBackground": "#b62e00",
|
||||||
"inputValidation.errorBorder": "#D02E00",
|
"inputValidation.errorBorder": "#b62e00",
|
||||||
|
|
||||||
//List and trees
|
//List and trees
|
||||||
"list.activeSelectionBackground": "#3062d6",
|
"list.activeSelectionBackground": "#3062d6",
|
||||||
"list.hoverBackground": "#444444",
|
"list.hoverBackground": "#444444",
|
||||||
"pickerGroup.border": "#00BCF2",
|
"pickerGroup.border": "#0078d7",
|
||||||
"activityBar.background": "#444444",
|
"activityBar.background": "#444444",
|
||||||
"sideBar.background": "#333333",
|
"sideBar.background": "#333333",
|
||||||
"sideBarTitle.foreground": "#BBBBBB",
|
"sideBarTitle.foreground": "#bbbbbb",
|
||||||
"input.placeholderForeground": "#A6A6A6",
|
"input.placeholderForeground": "#a6a6a6",
|
||||||
"editorGroupHeader.tabsBackground": "#444444",
|
"editorGroupHeader.tabsBackground": "#444444",
|
||||||
"editor.background": "#212121",
|
"editor.background": "#212121",
|
||||||
"editor.foreground": "#ffffff",
|
"editor.foreground": "#ffffff",
|
||||||
"editorWidget.background": "#444444",
|
"editorWidget.background": "#444444",
|
||||||
"editorLink.activeForeground": "#30B4FF",
|
"editorLink.activeForeground": "#30b4ff",
|
||||||
"editorGroup.border": "#333333",
|
"editorGroup.border": "#333333",
|
||||||
"editorGroup.background": "#212121",
|
"editorGroup.background": "#212121",
|
||||||
"editorIndentGuide.activeBackground": "#707070",
|
"editorIndentGuide.activeBackground": "#707070",
|
||||||
"tab.activeBackground": "#212121",
|
"tab.activeBackground": "#212121",
|
||||||
"tab.activeForeground": "#ffffff",
|
"tab.activeForeground": "#ffffff",
|
||||||
"tab.inactiveBackground": "#444444",
|
"tab.inactiveBackground": "#444444",
|
||||||
"tab.inactiveForeground": "#b6b6b6",
|
"tab.inactiveForeground": "#b6b6b6",
|
||||||
"tab.border": "#3c3c3c",
|
"tab.border": "#3c3c3c",
|
||||||
"panel.background": "#212121",
|
"panel.background": "#212121",
|
||||||
"panel.border": "#515151",
|
"panel.border": "#515151",
|
||||||
"panelTitle.activeForeground": "#ffffff",
|
"panelTitle.activeForeground": "#ffffff",
|
||||||
"panelTitle.inactiveForeground": "#888888"
|
"panelTitle.inactiveForeground": "#888888",
|
||||||
|
"panelTitle.activeBorder": "#026dc8"
|
||||||
},
|
},
|
||||||
"tokenColors": [
|
"tokenColors": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,18 +5,18 @@
|
|||||||
"colors": {
|
"colors": {
|
||||||
// base
|
// base
|
||||||
"foreground": "#4a4a4a",
|
"foreground": "#4a4a4a",
|
||||||
"focusBorder": "#00BCF2",
|
"focusBorder": "#0078d7",
|
||||||
"selection.background": "#C9D0D9",
|
"selection.background": "#c9d0d9",
|
||||||
"widget.shadow": "#666666",
|
"widget.shadow": "#666666",
|
||||||
|
|
||||||
// text colors
|
// text colors
|
||||||
"textLinkForeground": "#3062D6",
|
"textLinkForeground": "#3062d6",
|
||||||
"textLinkActiveForeground": "#3062D6",
|
"textLinkActiveForeground": "#3062d6",
|
||||||
|
|
||||||
//Button control
|
//Button control
|
||||||
"button.background": "#00BCF2",
|
"button.background": "#0078d7cc",
|
||||||
"button.foreground": "#212121",
|
"button.foreground": "#ffffff",
|
||||||
"button.hoverBackground": "#0099BC",
|
"button.hoverBackground": "#0078d7",
|
||||||
|
|
||||||
// TODO add support for these
|
// TODO add support for these
|
||||||
// "button.secondaryBackground": "#c8c8c8",
|
// "button.secondaryBackground": "#c8c8c8",
|
||||||
@@ -25,35 +25,38 @@
|
|||||||
// "button.disabledBackground": "#eaeaea",
|
// "button.disabledBackground": "#eaeaea",
|
||||||
// "button.disabledForeground": "#888888",
|
// "button.disabledForeground": "#888888",
|
||||||
|
|
||||||
|
//Checkbox
|
||||||
|
"checkbox.disabled.foreground": "#888888",
|
||||||
|
|
||||||
//Dropdown Control
|
//Dropdown Control
|
||||||
"dropdown.background": "#fffffe",
|
"dropdown.background": "#ffffff",
|
||||||
"dropdown.foreground": "#4a4a4a",
|
"dropdown.foreground": "#4a4a4a",
|
||||||
"dropdown.border": "#C8C8C8",
|
"dropdown.border": "#c8c8c8",
|
||||||
|
|
||||||
//badge
|
//badge
|
||||||
"badge.background": "#777777",
|
"badge.background": "#777777",
|
||||||
"badge.foreground": "#ffffff",
|
"badge.foreground": "#ffffff",
|
||||||
|
|
||||||
//Input Control
|
//Input Control
|
||||||
"input.background": "#fffffe",
|
"input.background": "#ffffff",
|
||||||
"input.border": "#c8c8c8",
|
"input.border": "#c8c8c8",
|
||||||
"input.disabled.background": "#dcdcdc",
|
"input.disabled.background": "#dcdcdc",
|
||||||
"input.disabled.foreground": "#888888",
|
"input.disabled.foreground": "#888888",
|
||||||
"inputOption.activeBorder": "#666666",
|
"inputOption.activeBorder": "#666666",
|
||||||
"input.placeholderForeground": "#767676",
|
"input.placeholderForeground": "#767676",
|
||||||
"inputValidation.errorBackground": "#ffeaea",
|
"inputValidation.errorBackground": "#ffeaea",
|
||||||
"inputValidation.errorBorder": "#f1897f",
|
"inputValidation.errorBorder": "#b62e00",
|
||||||
|
|
||||||
//List and tree
|
//List and tree
|
||||||
"list.activeSelectionBackground": "#3062d6",
|
"list.activeSelectionBackground": "#3062d6",
|
||||||
"list.hoverBackground": "#dcdcdc",
|
"list.hoverBackground": "#dcdcdc",
|
||||||
"pickerGroup.border": "#00BCF2",
|
"pickerGroup.border": "#0078d7",
|
||||||
|
|
||||||
// Workbench: Activity Bar
|
// Workbench: Activity Bar
|
||||||
"activityBar.background": "#212121",
|
"activityBar.background": "#212121",
|
||||||
|
|
||||||
// Workbench: Side Bar
|
// Workbench: Side Bar
|
||||||
"sideBar.background": "#EAEAEA",
|
"sideBar.background": "#eaeaea",
|
||||||
"editorGroupHeader.tabsBackground": "#f4f4f4",
|
"editorGroupHeader.tabsBackground": "#f4f4f4",
|
||||||
"editor.background": "#fffffe",
|
"editor.background": "#fffffe",
|
||||||
"editor.foreground": "#212121",
|
"editor.foreground": "#212121",
|
||||||
@@ -64,17 +67,18 @@
|
|||||||
"editorIndentGuide.activeBackground": "#939393",
|
"editorIndentGuide.activeBackground": "#939393",
|
||||||
|
|
||||||
// Workbench: Tabs
|
// Workbench: Tabs
|
||||||
"tab.activeBackground": "#FFFFFE",
|
"tab.activeBackground": "#ffffff",
|
||||||
"tab.activeForeground": "#4A4A4A",
|
"tab.activeForeground": "#4a4a4a",
|
||||||
"tab.inactiveBackground": "#f4f4f4",
|
"tab.inactiveBackground": "#f4f4f4",
|
||||||
"tab.inactiveForeground": "#707070",
|
"tab.inactiveForeground": "#707070",
|
||||||
"tab.border": "#EAEAEA",
|
"tab.border": "#eaeaea",
|
||||||
"tab.unfocusedInactiveForeground": "#888888",
|
"tab.unfocusedInactiveForeground": "#888888",
|
||||||
"tab.unfocusedActiveForeground": "#212121",
|
"tab.unfocusedActiveForeground": "#212121",
|
||||||
"panel.background": "#FFFFFE",
|
"panel.background": "#ffffff",
|
||||||
"panel.border": "#C8C8C8",
|
"panel.border": "#c8c8c8",
|
||||||
"panelTitle.activeForeground": "#212121",
|
"panelTitle.activeForeground": "#212121",
|
||||||
"panelTitle.inactiveForeground": "#757575"
|
"panelTitle.inactiveForeground": "#757575",
|
||||||
|
"panelTitle.activeBorder": "#026dc8"
|
||||||
},
|
},
|
||||||
"tokenColors": [
|
"tokenColors": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "azuredatastudio",
|
"name": "azuredatastudio",
|
||||||
"version": "1.2.2",
|
"version": "1.3.1",
|
||||||
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
|
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
|
||||||
"author": {
|
"author": {
|
||||||
"name": "Microsoft Corporation"
|
"name": "Microsoft Corporation"
|
||||||
|
|||||||
@@ -611,7 +611,7 @@
|
|||||||
</body></file>
|
</body></file>
|
||||||
<file original="src/sql/parts/connection/common/connectionActions" source-language="en" datatype="plaintext"><body>
|
<file original="src/sql/parts/connection/common/connectionActions" source-language="en" datatype="plaintext"><body>
|
||||||
<trans-unit id="ClearRecentlyUsedLabel">
|
<trans-unit id="ClearRecentlyUsedLabel">
|
||||||
<source xml:lang="en">Clear Recent Connections List</source>
|
<source xml:lang="en">Clear List</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="ClearedRecentConnections">
|
<trans-unit id="ClearedRecentConnections">
|
||||||
<source xml:lang="en">Recent connections list cleared</source>
|
<source xml:lang="en">Recent connections list cleared</source>
|
||||||
@@ -1039,10 +1039,10 @@
|
|||||||
<source xml:lang="en">Connection</source>
|
<source xml:lang="en">Connection</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="recentConnectionTitle">
|
<trans-unit id="recentConnectionTitle">
|
||||||
<source xml:lang="en">Recent connections</source>
|
<source xml:lang="en">Recent Connections</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="savedConnectionTitle">
|
<trans-unit id="savedConnectionTitle">
|
||||||
<source xml:lang="en">Saved connections</source>
|
<source xml:lang="en">Saved Connections</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="connectType">
|
<trans-unit id="connectType">
|
||||||
<source xml:lang="en">Connection type</source>
|
<source xml:lang="en">Connection type</source>
|
||||||
@@ -1520,9 +1520,6 @@
|
|||||||
</trans-unit>
|
</trans-unit>
|
||||||
</body></file>
|
</body></file>
|
||||||
<file original="src/sql/parts/profiler/contrib/profilerActions" source-language="en" datatype="plaintext"><body>
|
<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">
|
<trans-unit id="profilerAction.disconnect">
|
||||||
<source xml:lang="en">Disconnect</source>
|
<source xml:lang="en">Disconnect</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -1533,16 +1530,13 @@
|
|||||||
<source xml:lang="en">Start</source>
|
<source xml:lang="en">Start</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="create">
|
<trans-unit id="create">
|
||||||
<source xml:lang="en">Create</source>
|
<source xml:lang="en">New Session</source>
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="profiler.capture">
|
|
||||||
<source xml:lang="en">Pause Capture</source>
|
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="profilerAction.resumeCapture">
|
<trans-unit id="profilerAction.resumeCapture">
|
||||||
<source xml:lang="en">Resume Capture</source>
|
<source xml:lang="en">Resume</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="profilerAction.pauseCapture">
|
<trans-unit id="profilerAction.pauseCapture">
|
||||||
<source xml:lang="en">Pause Capture</source>
|
<source xml:lang="en">Pause</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="profilerStop.stop">
|
<trans-unit id="profilerStop.stop">
|
||||||
<source xml:lang="en">Stop</source>
|
<source xml:lang="en">Stop</source>
|
||||||
@@ -1550,9 +1544,6 @@
|
|||||||
<trans-unit id="profiler.clear">
|
<trans-unit id="profiler.clear">
|
||||||
<source xml:lang="en">Clear Data</source>
|
<source xml:lang="en">Clear Data</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="profiler.autoscrollOn">
|
|
||||||
<source xml:lang="en">Auto Scroll: On</source>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="profilerAction.autoscrollOn">
|
<trans-unit id="profilerAction.autoscrollOn">
|
||||||
<source xml:lang="en">Auto Scroll: On</source>
|
<source xml:lang="en">Auto Scroll: On</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
@@ -1572,7 +1563,7 @@
|
|||||||
<source xml:lang="en">Find Previous String</source>
|
<source xml:lang="en">Find Previous String</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="profilerAction.newProfiler">
|
<trans-unit id="profilerAction.newProfiler">
|
||||||
<source xml:lang="en">New Profiler</source>
|
<source xml:lang="en">Launch Profiler</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
</body></file>
|
</body></file>
|
||||||
<file original="src/sql/base/browser/ui/selectBox/selectBox" source-language="en" datatype="plaintext"><body>
|
<file original="src/sql/base/browser/ui/selectBox/selectBox" source-language="en" datatype="plaintext"><body>
|
||||||
@@ -1644,7 +1635,7 @@
|
|||||||
</body></file>
|
</body></file>
|
||||||
<file original="src/sql/parts/connection/connectionDialog/advancedPropertiesController" source-language="en" datatype="plaintext"><body>
|
<file original="src/sql/parts/connection/connectionDialog/advancedPropertiesController" source-language="en" datatype="plaintext"><body>
|
||||||
<trans-unit id="connectionAdvancedProperties">
|
<trans-unit id="connectionAdvancedProperties">
|
||||||
<source xml:lang="en">Advanced properties</source>
|
<source xml:lang="en">Advanced Properties</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="advancedProperties.discard">
|
<trans-unit id="advancedProperties.discard">
|
||||||
<source xml:lang="en">Discard</source>
|
<source xml:lang="en">Discard</source>
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
|
<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>
|
<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">
|
<trans-unit id="createSessionDialog.cancel">
|
||||||
<source xml:lang="en">Cancel</source>
|
<source xml:lang="en">Cancel</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
|||||||
@@ -12,12 +12,18 @@ set CODE=".build\electron\%NAMESHORT%"
|
|||||||
|
|
||||||
rem TFS Builds
|
rem TFS Builds
|
||||||
if not "%BUILD_BUILDID%" == "" (
|
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
|
rem Otherwise
|
||||||
if "%BUILD_BUILDID%" == "" (
|
if "%BUILD_BUILDID%" == "" (
|
||||||
%CODE% .\node_modules\mocha\bin\_mocha --reporter dot %*
|
%CODE% .\node_modules\mocha\bin\_mocha --reporter mocha-junit-reporter %*
|
||||||
)
|
)
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
if [[ "$OSTYPE" == "darwin"* ]] || [[ "$AGENT_OS" == "Darwin"* ]]; then
|
||||||
realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; }
|
realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; }
|
||||||
ROOT=$(dirname $(dirname $(realpath "$0")))
|
ROOT=$(dirname $(dirname $(realpath "$0")))
|
||||||
|
|
||||||
@@ -14,7 +14,7 @@ fi
|
|||||||
|
|
||||||
cd $ROOT
|
cd $ROOT
|
||||||
|
|
||||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
if [[ "$OSTYPE" == "darwin"* ]] || [[ "$AGENT_OS" == "Darwin"* ]]; then
|
||||||
NAME=`node -p "require('./product.json').nameLong"`
|
NAME=`node -p "require('./product.json').nameLong"`
|
||||||
CODE="./.build/electron/$NAME.app/Contents/MacOS/Electron"
|
CODE="./.build/electron/$NAME.app/Contents/MacOS/Electron"
|
||||||
else
|
else
|
||||||
@@ -30,7 +30,7 @@ node build/lib/electron.js || ./node_modules/.bin/gulp electron
|
|||||||
|
|
||||||
# Unit Tests
|
# Unit Tests
|
||||||
export ELECTRON_RUN_AS_NODE=1
|
export ELECTRON_RUN_AS_NODE=1
|
||||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
if [[ "$OSTYPE" == "darwin"* ]] || [[ "$AGENT_OS" == "Darwin"* ]]; then
|
||||||
cd $ROOT ; ulimit -n 4096 ; \
|
cd $ROOT ; ulimit -n 4096 ; \
|
||||||
"$CODE" \
|
"$CODE" \
|
||||||
node_modules/mocha/bin/_mocha "$@"
|
node_modules/mocha/bin/_mocha "$@"
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { Color } from 'vs/base/common/color';
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||||
import { Widget } from 'vs/base/browser/ui/widget';
|
import { Widget } from 'vs/base/browser/ui/widget';
|
||||||
@@ -15,9 +16,14 @@ export interface ICheckboxOptions {
|
|||||||
ariaLabel?: string;
|
ariaLabel?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ICheckboxStyles {
|
||||||
|
disabledCheckboxForeground?: Color;
|
||||||
|
}
|
||||||
|
|
||||||
export class Checkbox extends Widget {
|
export class Checkbox extends Widget {
|
||||||
private _el: HTMLInputElement;
|
private _el: HTMLInputElement;
|
||||||
private _label: HTMLSpanElement;
|
private _label: HTMLSpanElement;
|
||||||
|
private disabledCheckboxForeground: Color;
|
||||||
|
|
||||||
private _onChange = new Emitter<boolean>();
|
private _onChange = new Emitter<boolean>();
|
||||||
public readonly onChange: Event<boolean> = this._onChange.event;
|
public readonly onChange: Event<boolean> = this._onChange.event;
|
||||||
@@ -65,6 +71,7 @@ export class Checkbox extends Widget {
|
|||||||
|
|
||||||
public set enabled(val: boolean) {
|
public set enabled(val: boolean) {
|
||||||
this._el.disabled = !val;
|
this._el.disabled = !val;
|
||||||
|
this.updateStyle();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get enabled(): boolean {
|
public get enabled(): boolean {
|
||||||
@@ -90,4 +97,13 @@ export class Checkbox extends Widget {
|
|||||||
public enable(): void {
|
public enable(): void {
|
||||||
this.enabled = true;
|
this.enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public style(styles: ICheckboxStyles): void {
|
||||||
|
this.disabledCheckboxForeground = styles.disabledCheckboxForeground;
|
||||||
|
this.updateStyle();
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateStyle(): void {
|
||||||
|
this._label.style.color = !this.enabled && this.disabledCheckboxForeground ? this.disabledCheckboxForeground.toString() : 'inherit';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@
|
|||||||
|
|
||||||
.modal .modal-title {
|
.modal .modal-title {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal .modal-title-icon {
|
.modal .modal-title-icon {
|
||||||
@@ -66,14 +67,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.monaco-shell .modal.flyout-dialog .modal-body,
|
.monaco-shell .modal.flyout-dialog .modal-body,
|
||||||
.monaco-shell .modal.flyout-dialog .angular-modal-body {
|
.monaco-shell .modal.flyout-dialog .angular-modal-body,
|
||||||
margin-bottom: auto;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Style for body and footer in modal dialog. This should be applied to dialog created with angular component. */
|
/* Style for body and footer in modal dialog. This should be applied to dialog created with angular component. */
|
||||||
.monaco-shell .modal.flyout-dialog .modal-body-and-footer {
|
.monaco-shell .modal.flyout-dialog .modal-body-and-footer {
|
||||||
height: 100%;
|
flex: 1 1;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* modl body content style(excluding dialogErrorMessage section) for angulr component dialog */
|
/* modl body content style(excluding dialogErrorMessage section) for angulr component dialog */
|
||||||
@@ -85,6 +83,8 @@
|
|||||||
|
|
||||||
.modal.flyout-dialog .angular-form {
|
.modal.flyout-dialog .angular-form {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal.flyout-dialog .dialog-label {
|
.modal.flyout-dialog .dialog-label {
|
||||||
@@ -105,10 +105,6 @@
|
|||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal.flyout-dialog .modal-body {
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vs-dark.monaco-shell .modal.flyout-dialog .input {
|
.vs-dark.monaco-shell .modal.flyout-dialog .input {
|
||||||
background-color: #3C3C3C;
|
background-color: #3C3C3C;
|
||||||
}
|
}
|
||||||
@@ -152,7 +148,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.modal .footer-button {
|
.modal .footer-button {
|
||||||
margin-right: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal .right-footer .footer-button:last-of-type {
|
.modal .right-footer .footer-button:last-of-type {
|
||||||
@@ -187,7 +183,6 @@
|
|||||||
|
|
||||||
.modal.flyout-dialog .dialog-message-header {
|
.modal.flyout-dialog .dialog-message-header {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
overflow-y: hidden;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
@@ -241,8 +236,8 @@
|
|||||||
|
|
||||||
.modal.flyout-dialog .dialog-message-detail {
|
.modal.flyout-dialog .dialog-message-detail {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
white-space: normal;
|
white-space: pre-wrap;
|
||||||
-webkit-user-select: text;
|
user-select: text;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,11 +20,34 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.optionsDialog-options-groups {
|
.optionsDialog-options-groups {
|
||||||
padding: 15px;
|
margin-top: 10px;
|
||||||
height: calc(100% - 150px);
|
flex: 1 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.optionsDialog-options-groups {
|
||||||
|
margin: 10px 0px;
|
||||||
|
flex: 1 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs .optionsDialog-options-groups {
|
||||||
|
box-shadow: 0 1px 4px 1px rgba(220, 220, 220, 0.71);
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark .optionsDialog-options-groups {
|
||||||
|
box-shadow: 0 4px 5px 0px rgba(0, 0, 0, 0.71);
|
||||||
|
}
|
||||||
|
|
||||||
|
.optionsDialog-options-groups .split-view-view .header {
|
||||||
|
padding-left: 28px !important;
|
||||||
|
background-position-x: 8px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.optionsDialog-options-groups .split-view-view .body {
|
||||||
|
padding-left: 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
.backButtonIcon {
|
.backButtonIcon {
|
||||||
content: url('back.svg');
|
content: url('back.svg');
|
||||||
width: 20px;
|
width: 20px;
|
||||||
@@ -33,21 +56,42 @@
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vs-dark.monaco-shell .backButtonIcon {
|
.hc-black .backButtonIcon,
|
||||||
|
.vs-dark .backButtonIcon {
|
||||||
content: url('back_inverse.svg');
|
content: url('back_inverse.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
.optionsDialog-description {
|
.optionsDialog-description {
|
||||||
padding: 15px;
|
height: 90px;
|
||||||
overflow-y: auto;
|
margin: 15px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.optionsDialog-description .modal-title {
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 2px center;
|
||||||
|
padding-left: 25px;
|
||||||
|
background-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs .optionsDialog-description .modal-title {
|
||||||
|
background-image: url('info_notification.svg')
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs-dark .optionsDialog-description .modal-title,
|
||||||
|
.hc-black .optionsDialog-description .modal-title {
|
||||||
|
background-image: url('info_notification_inverse.svg')
|
||||||
}
|
}
|
||||||
|
|
||||||
.optionsDialog-options {
|
.optionsDialog-options {
|
||||||
height: calc(100% - 30px);
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.optionsDialog-description-content {
|
.optionsDialog-description-content {
|
||||||
padding: 10px;
|
padding-top: 10px;
|
||||||
|
padding-left: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.optionsDialog-table{
|
.optionsDialog-table{
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import { IThemeService } from 'vs/platform/theme/common/themeService';
|
|||||||
|
|
||||||
export const MODAL_SHOWING_KEY = 'modalShowing';
|
export const MODAL_SHOWING_KEY = 'modalShowing';
|
||||||
export const MODAL_SHOWING_CONTEXT = new RawContextKey<Array<string>>(MODAL_SHOWING_KEY, []);
|
export const MODAL_SHOWING_CONTEXT = new RawContextKey<Array<string>>(MODAL_SHOWING_KEY, []);
|
||||||
const INFO_ALT_TEXT = localize('infoAltText', 'Infomation');
|
const INFO_ALT_TEXT = localize('infoAltText', 'Information');
|
||||||
const WARNING_ALT_TEXT = localize('warningAltText', 'Warning');
|
const WARNING_ALT_TEXT = localize('warningAltText', 'Warning');
|
||||||
const ERROR_ALT_TEXT = localize('errorAltText', 'Error');
|
const ERROR_ALT_TEXT = localize('errorAltText', 'Error');
|
||||||
const SHOW_DETAILS_TEXT = localize('showMessageDetails', 'Show Details');
|
const SHOW_DETAILS_TEXT = localize('showMessageDetails', 'Show Details');
|
||||||
@@ -72,8 +72,8 @@ const defaultOptions: IModalOptions = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export abstract class Modal extends Disposable implements IThemable {
|
export abstract class Modal extends Disposable implements IThemable {
|
||||||
|
protected _useDefaultMessageBoxLocation: boolean = true;
|
||||||
private _messageElement: HTMLElement;
|
protected _messageElement: HTMLElement;
|
||||||
private _messageIcon: HTMLElement;
|
private _messageIcon: HTMLElement;
|
||||||
private _messageSeverity: Builder;
|
private _messageSeverity: Builder;
|
||||||
private _messageSummary: Builder;
|
private _messageSummary: Builder;
|
||||||
@@ -253,7 +253,9 @@ export abstract class Modal extends Disposable implements IThemable {
|
|||||||
this._messageElement = this._modalMessageSection.getHTMLElement();
|
this._messageElement = this._modalMessageSection.getHTMLElement();
|
||||||
this.updateElementVisibility(this._messageElement, false);
|
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
|
// This modal body section refers to the body of of the dialog
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ export class OptionsDialog extends Modal {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let builder = new Builder(this._body);
|
let builder = new Builder(this._body);
|
||||||
builder.div({ class: 'Connection-divider' }, (dividerContainer) => {
|
builder.div({}, (dividerContainer) => {
|
||||||
this._dividerBuilder = dividerContainer;
|
this._dividerBuilder = dividerContainer;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ panel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tabbedPanel .tabList .tab .tabLabel {
|
.tabbedPanel .tabList .tab .tabLabel {
|
||||||
text-transform: uppercase;
|
font-size: 14px;
|
||||||
font-size: 13px;
|
|
||||||
padding-bottom: 4px;
|
padding-bottom: 4px;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabbedPanel.vertical .tabList .tab .tabLabel {
|
.tabbedPanel.vertical .tabList .tab .tabLabel {
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ export interface IPanelTab {
|
|||||||
interface IInternalPanelTab extends IPanelTab {
|
interface IInternalPanelTab extends IPanelTab {
|
||||||
header: HTMLElement;
|
header: HTMLElement;
|
||||||
label: HTMLElement;
|
label: HTMLElement;
|
||||||
dispose(): void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultOptions: IPanelOptions = {
|
const defaultOptions: IPanelOptions = {
|
||||||
@@ -143,8 +142,6 @@ export class TabbedPanel extends Disposable implements IThemable {
|
|||||||
this.tabList.appendChild(tabHeaderElement);
|
this.tabList.appendChild(tabHeaderElement);
|
||||||
tab.header = tabHeaderElement;
|
tab.header = tabHeaderElement;
|
||||||
tab.label = tabLabel;
|
tab.label = tabLabel;
|
||||||
tab.dispose = () => { };
|
|
||||||
this._register(tab);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public showTab(id: PanelTabIdentifier): void {
|
public showTab(id: PanelTabIdentifier): void {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ registerThemingParticipant((theme: ITheme, collector: ICssStyleCollector) => {
|
|||||||
.tabbedPanel > .title .tabList .tab .tabLabel.active {
|
.tabbedPanel > .title .tabList .tab .tabLabel.active {
|
||||||
color: ${titleActive};
|
color: ${titleActive};
|
||||||
border-bottom-color: ${titleActiveBorder};
|
border-bottom-color: ${titleActiveBorder};
|
||||||
|
border-bottom-width: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabbedPanel > .title .tabList .tab-header.active {
|
.tabbedPanel > .title .tabList .tab-header.active {
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ import { ScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElemen
|
|||||||
import { HeightMap, IView as HeightIView, IViewItem as HeightIViewItem } from './heightMap';
|
import { HeightMap, IView as HeightIView, IViewItem as HeightIViewItem } from './heightMap';
|
||||||
import { ArrayIterator } from 'vs/base/common/iterator';
|
import { ArrayIterator } from 'vs/base/common/iterator';
|
||||||
import { mixin } from 'vs/base/common/objects';
|
import { mixin } from 'vs/base/common/objects';
|
||||||
|
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||||
export { Orientation } from 'vs/base/browser/ui/sash/sash';
|
export { Orientation } from 'vs/base/browser/ui/sash/sash';
|
||||||
|
|
||||||
export interface ISplitViewOptions {
|
export interface ISplitViewOptions {
|
||||||
orientation?: Orientation; // default Orientation.VERTICAL
|
orientation?: Orientation; // default Orientation.VERTICAL
|
||||||
enableResizing?: boolean;
|
enableResizing?: boolean;
|
||||||
|
verticalScrollbarVisibility?: ScrollbarVisibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultOptions: ISplitViewOptions = {
|
const defaultOptions: ISplitViewOptions = {
|
||||||
@@ -127,7 +129,7 @@ export class ScrollableSplitView extends HeightMap implements IDisposable {
|
|||||||
this.options = mixin(options, defaultOptions, false);
|
this.options = mixin(options, defaultOptions, false);
|
||||||
|
|
||||||
this.el = document.createElement('div');
|
this.el = document.createElement('div');
|
||||||
this.scrollable = new ScrollableElement(this.el, {});
|
this.scrollable = new ScrollableElement(this.el, { vertical: options.verticalScrollbarVisibility });
|
||||||
debounceEvent(this.scrollable.onScroll, (l, e) => e, 25)(e => {
|
debounceEvent(this.scrollable.onScroll, (l, e) => e, 25)(e => {
|
||||||
this.render(e.scrollTop, e.height);
|
this.render(e.scrollTop, e.height);
|
||||||
this.relayout();
|
this.relayout();
|
||||||
|
|||||||
@@ -89,10 +89,6 @@
|
|||||||
-moz-transition-property: width;
|
-moz-transition-property: width;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hc-black .split-view-view .action-label {
|
|
||||||
background: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hc-black .split-view-view > .header .action-label:before {
|
.hc-black .split-view-view > .header .action-label:before {
|
||||||
top: 4px !important;
|
top: 4px !important;
|
||||||
}
|
}
|
||||||
@@ -3,11 +3,14 @@
|
|||||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { IDisposableDataProvider } from 'sql/base/browser/ui/table/interfaces';
|
||||||
|
|
||||||
export interface IObservableCollection<T> {
|
export interface IObservableCollection<T> {
|
||||||
getLength(): number;
|
getLength(): number;
|
||||||
at(index: number): T;
|
at(index: number): T;
|
||||||
getRange(start: number, end: number): T[];
|
getRange(start: number, end: number): T[];
|
||||||
setCollectionChangedCallback(callback: (change: CollectionChange, startIndex: number, count: number) => void): void;
|
setCollectionChangedCallback(callback: (change: CollectionChange, startIndex: number, count: number) => void): void;
|
||||||
|
dispose(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IGridDataRow {
|
export interface IGridDataRow {
|
||||||
@@ -24,24 +27,27 @@ class LoadCancellationToken {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DataWindow<TData> {
|
class DataWindow<TData> {
|
||||||
private _dataSourceLength: number;
|
|
||||||
private _data: TData[];
|
private _data: TData[];
|
||||||
private _length: number = 0;
|
private _length: number = 0;
|
||||||
private _offsetFromDataSource: number = -1;
|
private _offsetFromDataSource: number = -1;
|
||||||
|
|
||||||
private loadFunction: (offset: number, count: number) => Thenable<TData[]>;
|
|
||||||
private lastLoadCancellationToken: LoadCancellationToken;
|
private lastLoadCancellationToken: LoadCancellationToken;
|
||||||
private loadCompleteCallback: (start: number, end: number) => void;
|
|
||||||
private placeholderItemGenerator: (index: number) => TData;
|
|
||||||
|
|
||||||
constructor(dataSourceLength: number,
|
constructor(
|
||||||
loadFunction: (offset: number, count: number) => Thenable<TData[]>,
|
private loadFunction: (offset: number, count: number) => Thenable<TData[]>,
|
||||||
placeholderItemGenerator: (index: number) => TData,
|
private placeholderItemGenerator: (index: number) => TData,
|
||||||
loadCompleteCallback: (start: number, end: number) => void) {
|
private loadCompleteCallback: (start: number, end: number) => void
|
||||||
this._dataSourceLength = dataSourceLength;
|
) {
|
||||||
this.loadFunction = loadFunction;
|
}
|
||||||
this.placeholderItemGenerator = placeholderItemGenerator;
|
|
||||||
this.loadCompleteCallback = loadCompleteCallback;
|
dispose() {
|
||||||
|
this._data = undefined;
|
||||||
|
this.loadFunction = undefined;
|
||||||
|
this.placeholderItemGenerator = undefined;
|
||||||
|
this.loadCompleteCallback = undefined;
|
||||||
|
if (this.lastLoadCancellationToken) {
|
||||||
|
this.lastLoadCancellationToken.isCancelled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getStartIndex(): number {
|
getStartIndex(): number {
|
||||||
@@ -76,10 +82,9 @@ class DataWindow<TData> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cancellationToken = new LoadCancellationToken();
|
this.lastLoadCancellationToken = new LoadCancellationToken();
|
||||||
this.lastLoadCancellationToken = cancellationToken;
|
|
||||||
this.loadFunction(offset, length).then(data => {
|
this.loadFunction(offset, length).then(data => {
|
||||||
if (!cancellationToken.isCancelled) {
|
if (!this.lastLoadCancellationToken.isCancelled) {
|
||||||
this._data = data;
|
this._data = data;
|
||||||
this.loadCompleteCallback(this._offsetFromDataSource, this._offsetFromDataSource + this._length);
|
this.loadCompleteCallback(this._offsetFromDataSource, this._offsetFromDataSource + this._length);
|
||||||
}
|
}
|
||||||
@@ -97,10 +102,12 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
|
|||||||
|
|
||||||
private collectionChangedCallback: (change: CollectionChange, startIndex: number, count: number) => void;
|
private collectionChangedCallback: (change: CollectionChange, startIndex: number, count: number) => void;
|
||||||
|
|
||||||
constructor(windowSize: number,
|
constructor(
|
||||||
|
windowSize: number,
|
||||||
length: number,
|
length: number,
|
||||||
loadFn: (offset: number, count: number) => Thenable<TData[]>,
|
loadFn: (offset: number, count: number) => Thenable<TData[]>,
|
||||||
private _placeHolderGenerator: (index: number) => TData) {
|
private _placeHolderGenerator: (index: number) => TData
|
||||||
|
) {
|
||||||
this._windowSize = windowSize;
|
this._windowSize = windowSize;
|
||||||
this._length = length;
|
this._length = length;
|
||||||
|
|
||||||
@@ -110,9 +117,15 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this._bufferWindowBefore = new DataWindow(length, loadFn, _placeHolderGenerator, loadCompleteCallback);
|
this._bufferWindowBefore = new DataWindow(loadFn, _placeHolderGenerator, loadCompleteCallback);
|
||||||
this._window = new DataWindow(length, loadFn, _placeHolderGenerator, loadCompleteCallback);
|
this._window = new DataWindow(loadFn, _placeHolderGenerator, loadCompleteCallback);
|
||||||
this._bufferWindowAfter = new DataWindow(length, loadFn, _placeHolderGenerator, loadCompleteCallback);
|
this._bufferWindowAfter = new DataWindow(loadFn, _placeHolderGenerator, loadCompleteCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this._bufferWindowAfter.dispose();
|
||||||
|
this._bufferWindowBefore.dispose();
|
||||||
|
this._window.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
setCollectionChangedCallback(callback: (change: CollectionChange, startIndex: number, count: number) => void): void {
|
setCollectionChangedCallback(callback: (change: CollectionChange, startIndex: number, count: number) => void): void {
|
||||||
@@ -197,7 +210,7 @@ export class VirtualizedCollection<TData> implements IObservableCollection<TData
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AsyncDataProvider<TData extends IGridDataRow> implements Slick.DataProvider<TData> {
|
export class AsyncDataProvider<TData extends IGridDataRow> implements IDisposableDataProvider<TData> {
|
||||||
|
|
||||||
constructor(private dataRows: IObservableCollection<TData>) { }
|
constructor(private dataRows: IObservableCollection<TData>) { }
|
||||||
|
|
||||||
@@ -212,4 +225,8 @@ export class AsyncDataProvider<TData extends IGridDataRow> implements Slick.Data
|
|||||||
public getRange(start: number, end: number): TData[] {
|
public getRange(start: number, end: number): TData[] {
|
||||||
return !this.dataRows ? undefined : this.dataRows.getRange(start, end);
|
return !this.dataRows ? undefined : this.dataRows.getRange(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this.dataRows.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
31
src/sql/base/browser/ui/table/interfaces.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { IListStyles } from 'vs/base/browser/ui/list/listWidget';
|
||||||
|
import { Color } from 'vs/base/common/color';
|
||||||
|
|
||||||
|
export interface IDisposableDataProvider<T> extends Slick.DataProvider<T> {
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITableMouseEvent {
|
||||||
|
anchor: HTMLElement | { x: number, y: number };
|
||||||
|
cell?: { row: number, cell: number };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITableStyles extends IListStyles {
|
||||||
|
tableHeaderBackground?: Color;
|
||||||
|
tableHeaderForeground?: Color;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITableSorter<T> {
|
||||||
|
sort(args: Slick.OnSortEventArgs<T>);
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITableConfiguration<T> {
|
||||||
|
dataProvider?: IDisposableDataProvider<T> | Array<T>;
|
||||||
|
columns?: Slick.Column<T>[];
|
||||||
|
sorter?: ITableSorter<T>;
|
||||||
|
}
|
||||||
@@ -5,28 +5,18 @@
|
|||||||
|
|
||||||
import 'vs/css!./media/table';
|
import 'vs/css!./media/table';
|
||||||
import { TableDataView } from './tableDataView';
|
import { TableDataView } from './tableDataView';
|
||||||
|
import { IDisposableDataProvider, ITableSorter, ITableMouseEvent, ITableConfiguration, ITableStyles } from 'sql/base/browser/ui/table/interfaces';
|
||||||
|
|
||||||
import { IThemable } from 'vs/platform/theme/common/styler';
|
import { IThemable } from 'vs/platform/theme/common/styler';
|
||||||
import { IListStyles } from 'vs/base/browser/ui/list/listWidget';
|
|
||||||
import * as DOM from 'vs/base/browser/dom';
|
import * as DOM from 'vs/base/browser/dom';
|
||||||
import { Color } from 'vs/base/common/color';
|
|
||||||
import { mixin } from 'vs/base/common/objects';
|
import { mixin } from 'vs/base/common/objects';
|
||||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||||
import { Orientation } from 'vs/base/browser/ui/splitview/splitview';
|
import { Orientation } from 'vs/base/browser/ui/splitview/splitview';
|
||||||
import { Widget } from 'vs/base/browser/ui/widget';
|
import { Widget } from 'vs/base/browser/ui/widget';
|
||||||
import { isArray, isBoolean } from 'vs/base/common/types';
|
import { isArray, isBoolean } from 'vs/base/common/types';
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
import { range } from 'vs/base/common/arrays';
|
import { range } from 'vs/base/common/arrays';
|
||||||
|
import { $ } from 'vs/base/browser/builder';
|
||||||
export interface ITableMouseEvent {
|
|
||||||
anchor: HTMLElement | { x: number, y: number };
|
|
||||||
cell?: { row: number, cell: number };
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ITableStyles extends IListStyles {
|
|
||||||
tableHeaderBackground?: Color;
|
|
||||||
tableHeaderForeground?: Color;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDefaultOptions<T>(): Slick.GridOptions<T> {
|
function getDefaultOptions<T>(): Slick.GridOptions<T> {
|
||||||
return <Slick.GridOptions<T>>{
|
return <Slick.GridOptions<T>>{
|
||||||
@@ -35,23 +25,13 @@ function getDefaultOptions<T>(): Slick.GridOptions<T> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITableSorter<T> {
|
|
||||||
sort(args: Slick.OnSortEventArgs<T>);
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ITableConfiguration<T> {
|
|
||||||
dataProvider?: Slick.DataProvider<T> | Array<T>;
|
|
||||||
columns?: Slick.Column<T>[];
|
|
||||||
sorter?: ITableSorter<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Table<T extends Slick.SlickData> extends Widget implements IThemable, IDisposable {
|
export class Table<T extends Slick.SlickData> extends Widget implements IThemable, IDisposable {
|
||||||
private styleElement: HTMLStyleElement;
|
private styleElement: HTMLStyleElement;
|
||||||
private idPrefix: string;
|
private idPrefix: string;
|
||||||
|
|
||||||
private _grid: Slick.Grid<T>;
|
private _grid: Slick.Grid<T>;
|
||||||
private _columns: Slick.Column<T>[];
|
private _columns: Slick.Column<T>[];
|
||||||
private _data: Slick.DataProvider<T>;
|
private _data: IDisposableDataProvider<T>;
|
||||||
private _sorter: ITableSorter<T>;
|
private _sorter: ITableSorter<T>;
|
||||||
|
|
||||||
private _autoscroll: boolean;
|
private _autoscroll: boolean;
|
||||||
@@ -60,8 +40,6 @@ export class Table<T extends Slick.SlickData> extends Widget implements IThemabl
|
|||||||
|
|
||||||
private _classChangeTimeout: number;
|
private _classChangeTimeout: number;
|
||||||
|
|
||||||
private _disposables: IDisposable[] = [];
|
|
||||||
|
|
||||||
private _onContextMenu = new Emitter<ITableMouseEvent>();
|
private _onContextMenu = new Emitter<ITableMouseEvent>();
|
||||||
public readonly onContextMenu: Event<ITableMouseEvent> = this._onContextMenu.event;
|
public readonly onContextMenu: Event<ITableMouseEvent> = this._onContextMenu.event;
|
||||||
|
|
||||||
@@ -76,6 +54,8 @@ export class Table<T extends Slick.SlickData> extends Widget implements IThemabl
|
|||||||
this._data = configuration.dataProvider;
|
this._data = configuration.dataProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._register(this._data);
|
||||||
|
|
||||||
if (configuration && configuration.columns) {
|
if (configuration && configuration.columns) {
|
||||||
this._columns = configuration.columns;
|
this._columns = configuration.columns;
|
||||||
} else {
|
} else {
|
||||||
@@ -117,6 +97,12 @@ export class Table<T extends Slick.SlickData> extends Widget implements IThemabl
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._register({
|
||||||
|
dispose: () => {
|
||||||
|
this._grid.destroy();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.mapMouseEvent(this._grid.onContextMenu, this._onContextMenu);
|
this.mapMouseEvent(this._grid.onContextMenu, this._onContextMenu);
|
||||||
this.mapMouseEvent(this._grid.onClick, this._onClick);
|
this.mapMouseEvent(this._grid.onClick, this._onClick);
|
||||||
}
|
}
|
||||||
@@ -131,7 +117,8 @@ export class Table<T extends Slick.SlickData> extends Widget implements IThemabl
|
|||||||
}
|
}
|
||||||
|
|
||||||
public dispose() {
|
public dispose() {
|
||||||
dispose(this._disposables);
|
$(this._container).dispose();
|
||||||
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public invalidateRows(rows: number[], keepEditor: boolean) {
|
public invalidateRows(rows: number[], keepEditor: boolean) {
|
||||||
@@ -166,7 +153,7 @@ export class Table<T extends Slick.SlickData> extends Widget implements IThemabl
|
|||||||
this._grid.setData(this._data, true);
|
this._grid.setData(this._data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
getData(): Slick.DataProvider<T> {
|
getData(): IDisposableDataProvider<T> {
|
||||||
return this._data;
|
return this._data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import { Event, Emitter } from 'vs/base/common/event';
|
|||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
import * as types from 'vs/base/common/types';
|
import * as types from 'vs/base/common/types';
|
||||||
|
|
||||||
|
import { IDisposableDataProvider } from 'sql/base/browser/ui/table/interfaces';
|
||||||
|
|
||||||
export interface IFindPosition {
|
export interface IFindPosition {
|
||||||
col: number;
|
col: number;
|
||||||
row: number;
|
row: number;
|
||||||
@@ -20,7 +22,7 @@ function defaultSort<T>(args: Slick.OnSortEventArgs<T>, data: Array<T>): Array<T
|
|||||||
return data.sort((a, b) => (a[field] === b[field] ? 0 : (a[field] > b[field] ? 1 : -1)) * sign);
|
return data.sort((a, b) => (a[field] === b[field] ? 0 : (a[field] > b[field] ? 1 : -1)) * sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TableDataView<T extends Slick.SlickData> implements Slick.DataProvider<T> {
|
export class TableDataView<T extends Slick.SlickData> implements IDisposableDataProvider<T> {
|
||||||
private _data: Array<T>;
|
private _data: Array<T>;
|
||||||
private _findArray: Array<IFindPosition>;
|
private _findArray: Array<IFindPosition>;
|
||||||
private _findObs: Observable<IFindPosition>;
|
private _findObs: Observable<IFindPosition>;
|
||||||
@@ -154,4 +156,10 @@ export class TableDataView<T extends Slick.SlickData> implements Slick.DataProvi
|
|||||||
get findCount(): number {
|
get findCount(): number {
|
||||||
return types.isUndefinedOrNull(this._findArray) ? 0 : this._findArray.length;
|
return types.isUndefinedOrNull(this._findArray) ? 0 : this._findArray.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this._data = undefined;
|
||||||
|
this._findArray = undefined;
|
||||||
|
this._findObs = undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
.carbon-taskbar.monaco-toolbar .monaco-action-bar.animated .actions-container {
|
.carbon-taskbar.monaco-toolbar .monaco-action-bar.animated .actions-container {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
padding-left: 15px;
|
padding: 5px 5px 5px 15px;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export const tableHeaderForeground = registerColor('table.headerForeground', { d
|
|||||||
export const disabledInputBackground = registerColor('input.disabled.background', { dark: '#444444', light: '#dcdcdc', hc: Color.black }, nls.localize('disabledInputBoxBackground', "Disabled Input box background."));
|
export const disabledInputBackground = registerColor('input.disabled.background', { dark: '#444444', light: '#dcdcdc', hc: Color.black }, nls.localize('disabledInputBoxBackground', "Disabled Input box background."));
|
||||||
export const disabledInputForeground = registerColor('input.disabled.foreground', { dark: '#888888', light: '#888888', hc: foreground }, nls.localize('disabledInputBoxForeground', "Disabled Input box foreground."));
|
export const disabledInputForeground = registerColor('input.disabled.foreground', { dark: '#888888', light: '#888888', hc: foreground }, nls.localize('disabledInputBoxForeground', "Disabled Input box foreground."));
|
||||||
export const buttonFocusOutline = registerColor('button.focusOutline', { dark: '#eaeaea', light: '#666666', hc: null }, nls.localize('buttonFocusOutline', "Button outline color when focused."));
|
export const buttonFocusOutline = registerColor('button.focusOutline', { dark: '#eaeaea', light: '#666666', hc: null }, nls.localize('buttonFocusOutline', "Button outline color when focused."));
|
||||||
|
export const disabledCheckboxForeground = registerColor('checkbox.disabled.foreground', { dark: '#888888', light: '#888888', hc: Color.black }, nls.localize('disabledCheckboxforeground', "Disabled checkbox foreground."));
|
||||||
|
|
||||||
export const listFocusAndSelectionBackground = registerColor('list.focusAndSelectionBackground', { dark: '#2c3295', light: '#2c3295', hc: null }, nls.localize('listFocusAndSelectionBackground', "List/Table background color for the selected and focus item when the list/table is active"));
|
export const listFocusAndSelectionBackground = registerColor('list.focusAndSelectionBackground', { dark: '#2c3295', light: '#2c3295', hc: null }, nls.localize('listFocusAndSelectionBackground', "List/Table background color for the selected and focus item when the list/table is active"));
|
||||||
|
|
||||||
|
|||||||
@@ -255,3 +255,10 @@ export function attachButtonStyler(widget: IThemable, themeService: IThemeServic
|
|||||||
buttonFocusOutline: (style && style.buttonFocusOutline) || sqlcolors.buttonFocusOutline
|
buttonFocusOutline: (style && style.buttonFocusOutline) || sqlcolors.buttonFocusOutline
|
||||||
}, widget);
|
}, widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function attachCheckboxStyler(widget: IThemable, themeService: IThemeService, style?: { disabledCheckboxForeground?: cr.ColorIdentifier })
|
||||||
|
: IDisposable {
|
||||||
|
return attachStyler(themeService, {
|
||||||
|
disabledCheckboxForeground: (style && style.disabledCheckboxForeground) || sqlcolors.disabledCheckboxForeground
|
||||||
|
}, widget);
|
||||||
|
}
|
||||||
|
|||||||
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;
|
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 {
|
.small {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
height: 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 |
17
src/sql/parts/commandLine/common/commandLine.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
export interface ICommandLineProcessing {
|
||||||
|
_serviceBrand: any;
|
||||||
|
/**
|
||||||
|
* Interprets the various Azure Data Studio-specific command line switches and
|
||||||
|
* performs the requisite tasks such as connecting to a server
|
||||||
|
*/
|
||||||
|
processCommandLine() : void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ICommandLineProcessing = createDecorator<ICommandLineProcessing>('commandLineService');
|
||||||
75
src/sql/parts/commandLine/common/commandLineService.ts
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* 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 { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||||
|
import { ICommandLineProcessing } from 'sql/parts/commandLine/common/commandLine';
|
||||||
|
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
||||||
|
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
||||||
|
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||||
|
import * as Constants from 'sql/parts/connection/common/constants';
|
||||||
|
import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService';
|
||||||
|
import * as platform from 'vs/platform/registry/common/platform';
|
||||||
|
import { ConnectionProviderProperties, IConnectionProviderRegistry, Extensions as ConnectionProviderExtensions } from 'sql/workbench/parts/connection/common/connectionProviderExtension';
|
||||||
|
import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
|
||||||
|
import { IObjectExplorerService } from 'sql/parts/objectExplorer/common/objectExplorerService';
|
||||||
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
|
|
||||||
|
export class CommandLineService implements ICommandLineProcessing {
|
||||||
|
private _connectionProfile: ConnectionProfile;
|
||||||
|
private _showConnectionDialog: boolean;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
||||||
|
@ICapabilitiesService private _capabilitiesService: ICapabilitiesService,
|
||||||
|
@IEnvironmentService private _environmentService: IEnvironmentService,
|
||||||
|
@IQueryEditorService private _queryEditorService: IQueryEditorService,
|
||||||
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
||||||
|
@IEditorService private _editorService: IEditorService,
|
||||||
|
) {
|
||||||
|
let profile = null;
|
||||||
|
if (this._environmentService && this._environmentService.args.server) {
|
||||||
|
profile = new ConnectionProfile(_capabilitiesService, null);
|
||||||
|
// We want connection store to use any matching password it finds
|
||||||
|
profile.savePassword = true;
|
||||||
|
profile.providerName = Constants.mssqlProviderName;
|
||||||
|
profile.serverName = _environmentService.args.server;
|
||||||
|
profile.databaseName = _environmentService.args.database ? _environmentService.args.database : '';
|
||||||
|
profile.userName = _environmentService.args.user ? _environmentService.args.user : '';
|
||||||
|
profile.authenticationType = _environmentService.args.integrated ? 'Integrated' : 'SqlLogin';
|
||||||
|
profile.connectionName = '';
|
||||||
|
profile.setOptionValue('applicationName', Constants.applicationName);
|
||||||
|
profile.setOptionValue('databaseDisplayName', profile.databaseName);
|
||||||
|
profile.setOptionValue('groupId', profile.groupId);
|
||||||
|
}
|
||||||
|
this._connectionProfile = profile;
|
||||||
|
const registry = platform.Registry.as<IConnectionProviderRegistry>(ConnectionProviderExtensions.ConnectionProviderContributions);
|
||||||
|
let sqlProvider = registry.getProperties(Constants.mssqlProviderName);
|
||||||
|
// We can't connect to object explorer until the MSSQL connection provider is registered
|
||||||
|
if (sqlProvider) {
|
||||||
|
this.processCommandLine();
|
||||||
|
} else {
|
||||||
|
registry.onNewProvider(e => {
|
||||||
|
if (e.id === Constants.mssqlProviderName) {
|
||||||
|
this.processCommandLine();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public _serviceBrand: any;
|
||||||
|
public processCommandLine(): void {
|
||||||
|
if (!this._connectionProfile && !this._connectionManagementService.hasRegisteredServers()) {
|
||||||
|
// prompt the user for a new connection on startup if no profiles are registered
|
||||||
|
this._connectionManagementService.showConnectionDialog();
|
||||||
|
} else if (this._connectionProfile) {
|
||||||
|
this._connectionManagementService.connectIfNotConnected(this._connectionProfile, 'connection')
|
||||||
|
.then(result => TaskUtilities.newQuery(this._connectionProfile,
|
||||||
|
this._connectionManagementService,
|
||||||
|
this._queryEditorService,
|
||||||
|
this._objectExplorerService,
|
||||||
|
this._editorService))
|
||||||
|
.catch(() => { });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,7 +26,7 @@ import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService
|
|||||||
export class ClearRecentConnectionsAction extends Action {
|
export class ClearRecentConnectionsAction extends Action {
|
||||||
|
|
||||||
public static ID = 'clearRecentConnectionsAction';
|
public static ID = 'clearRecentConnectionsAction';
|
||||||
public static LABEL = nls.localize('ClearRecentlyUsedLabel', 'Clear Recent Connections List');
|
public static LABEL = nls.localize('ClearRecentlyUsedLabel', 'Clear List');
|
||||||
public static ICON = 'search-action clear-search-results';
|
public static ICON = 'search-action clear-search-results';
|
||||||
|
|
||||||
private _onRecentConnectionsRemoved = new Emitter<void>();
|
private _onRecentConnectionsRemoved = new Emitter<void>();
|
||||||
@@ -83,7 +83,7 @@ export class ClearRecentConnectionsAction extends Action {
|
|||||||
{ key: nls.localize('connectionAction.no', 'No'), value: false }
|
{ key: nls.localize('connectionAction.no', 'No'), value: false }
|
||||||
];
|
];
|
||||||
|
|
||||||
self._quickOpenService.pick(choices.map(x => x.key), { placeHolder: nls.localize('ClearRecentlyUsedLabel', 'Clear Recent Connections List'), ignoreFocusLost: true }).then((choice) => {
|
self._quickOpenService.pick(choices.map(x => x.key), { placeHolder: nls.localize('ClearRecentlyUsedLabel', 'Clear List'), ignoreFocusLost: true }).then((choice) => {
|
||||||
let confirm = choices.find(x => x.key === choice);
|
let confirm = choices.find(x => x.key === choice);
|
||||||
resolve(confirm && confirm.value);
|
resolve(confirm && confirm.value);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -77,7 +77,6 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
|||||||
private _onConnectRequestSent = new Emitter<void>();
|
private _onConnectRequestSent = new Emitter<void>();
|
||||||
private _onConnectionChanged = new Emitter<IConnectionParams>();
|
private _onConnectionChanged = new Emitter<IConnectionParams>();
|
||||||
private _onLanguageFlavorChanged = new Emitter<sqlops.DidChangeLanguageFlavorParams>();
|
private _onLanguageFlavorChanged = new Emitter<sqlops.DidChangeLanguageFlavorParams>();
|
||||||
|
|
||||||
private _connectionGlobalStatus = new ConnectionGlobalStatus(this._statusBarService);
|
private _connectionGlobalStatus = new ConnectionGlobalStatus(this._statusBarService);
|
||||||
|
|
||||||
private _configurationEditService: ConfigurationEditingService;
|
private _configurationEditService: ConfigurationEditingService;
|
||||||
@@ -124,16 +123,6 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
|||||||
100 /* High Priority */
|
100 /* High Priority */
|
||||||
));
|
));
|
||||||
|
|
||||||
if (_capabilitiesService && Object.keys(_capabilitiesService.providers).length > 0 && !this.hasRegisteredServers()) {
|
|
||||||
// prompt the user for a new connection on startup if no profiles are registered
|
|
||||||
this.showConnectionDialog();
|
|
||||||
} else if (_capabilitiesService && !this.hasRegisteredServers()) {
|
|
||||||
_capabilitiesService.onCapabilitiesRegistered(e => {
|
|
||||||
// prompt the user for a new connection on startup if no profiles are registered
|
|
||||||
this.showConnectionDialog();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const registry = platform.Registry.as<IConnectionProviderRegistry>(ConnectionProviderExtensions.ConnectionProviderContributions);
|
const registry = platform.Registry.as<IConnectionProviderRegistry>(ConnectionProviderExtensions.ConnectionProviderContributions);
|
||||||
|
|
||||||
let providerRegistration = (p: { id: string, properties: ConnectionProviderProperties }) => {
|
let providerRegistration = (p: { id: string, properties: ConnectionProviderProperties }) => {
|
||||||
@@ -282,29 +271,30 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
|||||||
* @param options to use after the connection is complete
|
* @param options to use after the connection is complete
|
||||||
*/
|
*/
|
||||||
private tryConnect(connection: IConnectionProfile, owner: IConnectableInput, options?: IConnectionCompletionOptions): Promise<IConnectionResult> {
|
private tryConnect(connection: IConnectionProfile, owner: IConnectableInput, options?: IConnectionCompletionOptions): Promise<IConnectionResult> {
|
||||||
|
let self = this;
|
||||||
return new Promise<IConnectionResult>((resolve, reject) => {
|
return new Promise<IConnectionResult>((resolve, reject) => {
|
||||||
// Load the password if it's not already loaded
|
// Load the password if it's not already loaded
|
||||||
this._connectionStore.addSavedPassword(connection).then(result => {
|
self._connectionStore.addSavedPassword(connection).then(result => {
|
||||||
let newConnection = result.profile;
|
let newConnection = result.profile;
|
||||||
let foundPassword = result.savedCred;
|
let foundPassword = result.savedCred;
|
||||||
|
|
||||||
// If there is no password, try to load it from an existing connection
|
// If there is no password, try to load it from an existing connection
|
||||||
if (!foundPassword && this._connectionStore.isPasswordRequired(newConnection)) {
|
if (!foundPassword && self._connectionStore.isPasswordRequired(newConnection)) {
|
||||||
let existingConnection = this._connectionStatusManager.findConnectionProfile(connection);
|
let existingConnection = self._connectionStatusManager.findConnectionProfile(connection);
|
||||||
if (existingConnection && existingConnection.connectionProfile) {
|
if (existingConnection && existingConnection.connectionProfile) {
|
||||||
newConnection.password = existingConnection.connectionProfile.password;
|
newConnection.password = existingConnection.connectionProfile.password;
|
||||||
foundPassword = true;
|
foundPassword = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If the password is required and still not loaded show the dialog
|
// If the password is required and still not loaded show the dialog
|
||||||
if (!foundPassword && this._connectionStore.isPasswordRequired(newConnection) && !newConnection.password) {
|
if (!foundPassword && self._connectionStore.isPasswordRequired(newConnection) && !newConnection.password) {
|
||||||
resolve(this.showConnectionDialogOnError(connection, owner, { connected: false, errorMessage: undefined, callStack: undefined, errorCode: undefined }, options));
|
resolve(self.showConnectionDialogOnError(connection, owner, { connected: false, errorMessage: undefined, callStack: undefined, errorCode: undefined }, options));
|
||||||
} else {
|
} else {
|
||||||
// Try to connect
|
// Try to connect
|
||||||
this.connectWithOptions(newConnection, owner.uri, options, owner).then(connectionResult => {
|
self.connectWithOptions(newConnection, owner.uri, options, owner).then(connectionResult => {
|
||||||
if (!connectionResult.connected && !connectionResult.errorHandled) {
|
if (!connectionResult.connected && !connectionResult.errorHandled) {
|
||||||
// If connection fails show the dialog
|
// If connection fails show the dialog
|
||||||
resolve(this.showConnectionDialogOnError(connection, owner, connectionResult, options));
|
resolve(self.showConnectionDialogOnError(connection, owner, connectionResult, options));
|
||||||
} else {
|
} else {
|
||||||
//Resolve with the connection result
|
//Resolve with the connection result
|
||||||
resolve(connectionResult);
|
resolve(connectionResult);
|
||||||
@@ -390,7 +380,14 @@ export class ConnectionManagementService extends Disposable implements IConnecti
|
|||||||
if (this._connectionStatusManager.isConnected(ownerUri)) {
|
if (this._connectionStatusManager.isConnected(ownerUri)) {
|
||||||
resolve(this._connectionStatusManager.getOriginalOwnerUri(ownerUri));
|
resolve(this._connectionStatusManager.getOriginalOwnerUri(ownerUri));
|
||||||
} else {
|
} else {
|
||||||
this.connect(connection, ownerUri).then(connectionResult => {
|
const options: IConnectionCompletionOptions = {
|
||||||
|
saveTheConnection: false,
|
||||||
|
showConnectionDialogOnError: true,
|
||||||
|
showDashboard: purpose === 'dashboard',
|
||||||
|
params: undefined,
|
||||||
|
showFirewallRuleOnError: true,
|
||||||
|
};
|
||||||
|
this.connect(connection, ownerUri, options).then(connectionResult => {
|
||||||
if (connectionResult && connectionResult.connected) {
|
if (connectionResult && connectionResult.connected) {
|
||||||
resolve(this._connectionStatusManager.getOriginalOwnerUri(ownerUri));
|
resolve(this._connectionStatusManager.getOriginalOwnerUri(ownerUri));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -23,9 +23,7 @@ export class ConnectionStatusbarItem implements IStatusbarItem {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
||||||
@IEditorGroupsService private _editorGroupService: IEditorGroupsService,
|
|
||||||
@IEditorService private _editorService: EditorServiceImpl,
|
@IEditorService private _editorService: EditorServiceImpl,
|
||||||
@ICapabilitiesService private _capabilitiesService: ICapabilitiesService,
|
|
||||||
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ export function parseTimeString(value: string): number | boolean {
|
|||||||
* @param value The number of milliseconds to convert to a timespan string
|
* @param value The number of milliseconds to convert to a timespan string
|
||||||
* @returns A properly formatted timespan string.
|
* @returns A properly formatted timespan string.
|
||||||
*/
|
*/
|
||||||
export function parseNumAsTimeString(value: number): string {
|
export function parseNumAsTimeString(value: number, includeFraction: boolean = true): string {
|
||||||
let tempVal = value;
|
let tempVal = value;
|
||||||
let h = Math.floor(tempVal / msInH);
|
let h = Math.floor(tempVal / msInH);
|
||||||
tempVal %= msInH;
|
tempVal %= msInH;
|
||||||
@@ -85,7 +85,7 @@ export function parseNumAsTimeString(value: number): string {
|
|||||||
|
|
||||||
let rs = hs + ':' + ms + ':' + ss;
|
let rs = hs + ':' + ms + ':' + ss;
|
||||||
|
|
||||||
return tempVal > 0 ? rs + '.' + mss : rs;
|
return tempVal > 0 && includeFraction ? rs + '.' + mss : rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateUri(connection: IConnectionProfile, purpose?: 'dashboard' | 'insights' | 'connection'): string {
|
export function generateUri(connection: IConnectionProfile, purpose?: 'dashboard' | 'insights' | 'connection'): string {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export class AdvancedPropertiesController {
|
|||||||
public get advancedDialog() {
|
public get advancedDialog() {
|
||||||
if (!this._advancedDialog) {
|
if (!this._advancedDialog) {
|
||||||
this._advancedDialog = this._instantiationService.createInstance(
|
this._advancedDialog = this._instantiationService.createInstance(
|
||||||
OptionsDialog, localize('connectionAdvancedProperties', 'Advanced properties'), TelemetryKeys.ConnectionAdvancedProperties, { hasBackButton: true });
|
OptionsDialog, localize('connectionAdvancedProperties', 'Advanced Properties'), TelemetryKeys.ConnectionAdvancedProperties, { hasBackButton: true });
|
||||||
this._advancedDialog.cancelLabel = localize('advancedProperties.discard', 'Discard');
|
this._advancedDialog.cancelLabel = localize('advancedProperties.discard', 'Discard');
|
||||||
this._advancedDialog.onCloseEvent(() => this._onCloseAdvancedProperties());
|
this._advancedDialog.onCloseEvent(() => this._onCloseAdvancedProperties());
|
||||||
this._advancedDialog.onOk(() => this.handleOnOk());
|
this._advancedDialog.onOk(() => this.handleOnOk());
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import * as styler from 'vs/platform/theme/common/styler';
|
|||||||
import * as DOM from 'vs/base/browser/dom';
|
import * as DOM from 'vs/base/browser/dom';
|
||||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||||
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
|
||||||
|
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
|
||||||
|
|
||||||
export interface OnShowUIResponse {
|
export interface OnShowUIResponse {
|
||||||
selectedProviderType: string;
|
selectedProviderType: string;
|
||||||
@@ -49,7 +50,7 @@ export class ConnectionDialogWidget extends Modal {
|
|||||||
private _noRecentConnectionBuilder: Builder;
|
private _noRecentConnectionBuilder: Builder;
|
||||||
private _savedConnectionBuilder: Builder;
|
private _savedConnectionBuilder: Builder;
|
||||||
private _noSavedConnectionBuilder: Builder;
|
private _noSavedConnectionBuilder: Builder;
|
||||||
private _dividerBuilder: Builder;
|
private _connectionDetailTitle: Builder;
|
||||||
private _connectButton: Button;
|
private _connectButton: Button;
|
||||||
private _closeButton: Button;
|
private _closeButton: Button;
|
||||||
private _providerTypeSelectBox: SelectBox;
|
private _providerTypeSelectBox: SelectBox;
|
||||||
@@ -143,7 +144,7 @@ export class ConnectionDialogWidget extends Modal {
|
|||||||
this._panel = new TabbedPanel(connectionContainer.getHTMLElement());
|
this._panel = new TabbedPanel(connectionContainer.getHTMLElement());
|
||||||
this._recentConnectionTabId = this._panel.pushTab({
|
this._recentConnectionTabId = this._panel.pushTab({
|
||||||
identifier: 'recent_connection',
|
identifier: 'recent_connection',
|
||||||
title: localize('recentConnectionTitle', 'Recent connections'),
|
title: localize('recentConnectionTitle', 'Recent Connections'),
|
||||||
view: {
|
view: {
|
||||||
render: c => {
|
render: c => {
|
||||||
recentConnectionTab.appendTo(c);
|
recentConnectionTab.appendTo(c);
|
||||||
@@ -154,7 +155,7 @@ export class ConnectionDialogWidget extends Modal {
|
|||||||
|
|
||||||
let savedConnectionTabId = this._panel.pushTab({
|
let savedConnectionTabId = this._panel.pushTab({
|
||||||
identifier: 'saved_connection',
|
identifier: 'saved_connection',
|
||||||
title: localize('savedConnectionTitle', 'Saved connections'),
|
title: localize('savedConnectionTitle', 'Saved Connections'),
|
||||||
view: {
|
view: {
|
||||||
layout: () => { },
|
layout: () => { },
|
||||||
render: c => {
|
render: c => {
|
||||||
@@ -179,8 +180,9 @@ export class ConnectionDialogWidget extends Modal {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this._bodyBuilder.div({ class: 'Connection-divider' }, (dividerContainer) => {
|
this._bodyBuilder.div({ class: 'connection-details-title' }, (dividerContainer) => {
|
||||||
this._dividerBuilder = dividerContainer;
|
this._connectionDetailTitle = dividerContainer;
|
||||||
|
this._connectionDetailTitle.text(localize('connectionDetailsTitle', 'Connection Details'));
|
||||||
});
|
});
|
||||||
|
|
||||||
this._bodyBuilder.div({ class: 'connection-type' }, (modelTableContent) => {
|
this._bodyBuilder.div({ class: 'connection-type' }, (modelTableContent) => {
|
||||||
@@ -217,10 +219,12 @@ export class ConnectionDialogWidget extends Modal {
|
|||||||
private updateTheme(theme: IColorTheme): void {
|
private updateTheme(theme: IColorTheme): void {
|
||||||
let borderColor = theme.getColor(contrastBorder);
|
let borderColor = theme.getColor(contrastBorder);
|
||||||
let border = borderColor ? borderColor.toString() : null;
|
let border = borderColor ? borderColor.toString() : null;
|
||||||
if (this._dividerBuilder) {
|
let backgroundColor = theme.getColor(SIDE_BAR_BACKGROUND);
|
||||||
this._dividerBuilder.style('border-top-width', border ? '1px' : null);
|
if (this._connectionDetailTitle) {
|
||||||
this._dividerBuilder.style('border-top-style', border ? 'solid' : null);
|
this._connectionDetailTitle.style('border-width', border ? '1px 0px' : null);
|
||||||
this._dividerBuilder.style('border-top-color', border);
|
this._connectionDetailTitle.style('border-style', border ? 'solid none' : null);
|
||||||
|
this._connectionDetailTitle.style('border-color', border);
|
||||||
|
this._connectionDetailTitle.style('background-color', backgroundColor ? backgroundColor.toString() : null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,17 +281,13 @@ export class ConnectionDialogWidget extends Modal {
|
|||||||
|
|
||||||
private createRecentConnectionList(): void {
|
private createRecentConnectionList(): void {
|
||||||
this._recentConnectionBuilder.div({ class: 'connection-recent-content' }, (recentConnectionContainer) => {
|
this._recentConnectionBuilder.div({ class: 'connection-recent-content' }, (recentConnectionContainer) => {
|
||||||
let recentHistoryLabel = localize('recentHistory', 'Recent history');
|
|
||||||
recentConnectionContainer.div({ class: 'recent-titles-container' }, (container) => {
|
recentConnectionContainer.div({ class: 'recent-titles-container' }, (container) => {
|
||||||
container.div({ class: 'connection-history-label' }, (recentTitle) => {
|
|
||||||
recentTitle.text(recentHistoryLabel);
|
|
||||||
});
|
|
||||||
container.div({ class: 'connection-history-actions' }, (actionsContainer) => {
|
container.div({ class: 'connection-history-actions' }, (actionsContainer) => {
|
||||||
this._actionbar = this._register(new ActionBar(actionsContainer.getHTMLElement(), { animated: false }));
|
this._actionbar = this._register(new ActionBar(actionsContainer.getHTMLElement(), { animated: false }));
|
||||||
let clearAction = this._instantiationService.createInstance(ClearRecentConnectionsAction, ClearRecentConnectionsAction.ID, ClearRecentConnectionsAction.LABEL);
|
let clearAction = this._instantiationService.createInstance(ClearRecentConnectionsAction, ClearRecentConnectionsAction.ID, ClearRecentConnectionsAction.LABEL);
|
||||||
clearAction.useConfirmationMessage = true;
|
clearAction.useConfirmationMessage = true;
|
||||||
clearAction.onRecentConnectionsRemoved(() => this.open(false));
|
clearAction.onRecentConnectionsRemoved(() => this.open(false));
|
||||||
this._actionbar.push(clearAction, { icon: true, label: false });
|
this._actionbar.push(clearAction, { icon: true, label: true });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
recentConnectionContainer.div({ class: 'server-explorer-viewlet' }, (divContainer: Builder) => {
|
recentConnectionContainer.div({ class: 'server-explorer-viewlet' }, (divContainer: Builder) => {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
|||||||
import { ConnectionOptionSpecialType } from 'sql/workbench/api/common/sqlExtHostTypes';
|
import { ConnectionOptionSpecialType } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||||
import * as Constants from 'sql/parts/connection/common/constants';
|
import * as Constants from 'sql/parts/connection/common/constants';
|
||||||
import { ConnectionProfileGroup, IConnectionProfileGroup } from 'sql/parts/connection/common/connectionProfileGroup';
|
import { ConnectionProfileGroup, IConnectionProfileGroup } from 'sql/parts/connection/common/connectionProfileGroup';
|
||||||
import { attachInputBoxStyler, attachButtonStyler, attachEditableDropdownStyler } from 'sql/common/theme/styler';
|
import { attachButtonStyler, attachCheckboxStyler, attachEditableDropdownStyler, attachInputBoxStyler } from 'sql/common/theme/styler';
|
||||||
import { Dropdown } from 'sql/base/browser/ui/editableDropdown/dropdown';
|
import { Dropdown } from 'sql/base/browser/ui/editableDropdown/dropdown';
|
||||||
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
||||||
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
||||||
@@ -83,7 +83,7 @@ export class ConnectionWidget {
|
|||||||
};
|
};
|
||||||
public NoneServerGroup: IConnectionProfileGroup = {
|
public NoneServerGroup: IConnectionProfileGroup = {
|
||||||
id: '',
|
id: '',
|
||||||
name: localize('noneServerGroup', '<None>'),
|
name: localize('noneServerGroup', '<Do not save>'),
|
||||||
parentId: undefined,
|
parentId: undefined,
|
||||||
color: undefined,
|
color: undefined,
|
||||||
description: undefined,
|
description: undefined,
|
||||||
@@ -274,6 +274,7 @@ export class ConnectionWidget {
|
|||||||
this._toDispose.push(attachInputBoxStyler(this._passwordInputBox, this._themeService));
|
this._toDispose.push(attachInputBoxStyler(this._passwordInputBox, this._themeService));
|
||||||
this._toDispose.push(styler.attachSelectBoxStyler(this._serverGroupSelectBox, this._themeService));
|
this._toDispose.push(styler.attachSelectBoxStyler(this._serverGroupSelectBox, this._themeService));
|
||||||
this._toDispose.push(attachButtonStyler(this._advancedButton, this._themeService));
|
this._toDispose.push(attachButtonStyler(this._advancedButton, this._themeService));
|
||||||
|
this._toDispose.push(attachCheckboxStyler(this._rememberPasswordCheckBox, this._themeService));
|
||||||
|
|
||||||
if (this._authTypeSelectBox) {
|
if (this._authTypeSelectBox) {
|
||||||
// Theme styler
|
// Theme styler
|
||||||
|
|||||||
@@ -9,25 +9,35 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.connection-input {
|
.connection-input {
|
||||||
padding-right:8px;
|
|
||||||
width: 200px;
|
width: 200px;
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connection-dialog {
|
.connection-dialog {
|
||||||
height: calc(100% - 20px);
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connection-dialog .tabbedPanel {
|
.connection-dialog .tabbedPanel {
|
||||||
border-top-color: transparent;
|
border-top-color: transparent;
|
||||||
height: calc(100% - 350px);
|
flex: 1 1;
|
||||||
display: block;
|
|
||||||
min-height: 120px;
|
min-height: 120px;
|
||||||
|
overflow: hidden;
|
||||||
|
margin: 0px 11px;
|
||||||
|
}
|
||||||
|
.connection-dialog .tabBody {
|
||||||
|
overflow: hidden;
|
||||||
|
flex: 1 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connection-recent, .connection-saved {
|
.connection-recent, .connection-saved {
|
||||||
margin: 15px;
|
margin: 5px;
|
||||||
height: calc(100% - 60px);
|
flex: 1 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,6 +55,8 @@
|
|||||||
.recent-titles-container {
|
.recent-titles-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
margin: 5px;
|
||||||
|
flex: 0 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connection-provider-info {
|
.connection-provider-info {
|
||||||
@@ -53,7 +65,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.connection-recent-content {
|
.connection-recent-content {
|
||||||
height: calc(100% - 20px);
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.connection-recent-content .server-explorer-viewlet {
|
||||||
|
flex: 1 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connection-table-content {
|
.connection-table-content {
|
||||||
@@ -66,8 +84,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.connection-type {
|
.connection-type {
|
||||||
margin: 15px;
|
flex: 0 0 auto;
|
||||||
overflow-y: hidden;
|
overflow: hidden;
|
||||||
|
margin: 0px 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.connection-dialog .connection-history-actions .action-label.icon {
|
.connection-dialog .connection-history-actions .action-label.icon {
|
||||||
@@ -76,8 +95,9 @@
|
|||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
min-width: 20px;
|
min-width: 20px;
|
||||||
background-size: 16px;
|
background-size: 16px;
|
||||||
background-position: center center;
|
background-position: 2px center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
|
padding-left: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-action.clear-search-results {
|
.search-action.clear-search-results {
|
||||||
@@ -87,4 +107,11 @@
|
|||||||
.vs-dark .search-action.clear-search-results,
|
.vs-dark .search-action.clear-search-results,
|
||||||
.hc-black .search-action.clear-search-results {
|
.hc-black .search-action.clear-search-results {
|
||||||
background: url('clear-search-results-dark.svg');
|
background: url('clear-search-results-dark.svg');
|
||||||
|
}
|
||||||
|
|
||||||
|
.connection-details-title {
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 5px 0px;
|
||||||
|
padding: 5px 15px;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,5 @@
|
|||||||
|
|
||||||
.advanced-button {
|
.advanced-button {
|
||||||
width: 100px;
|
width: 100px;
|
||||||
padding-right:8px;
|
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ import { ModalFooterStyle } from 'sql/base/browser/ui/modal/modal';
|
|||||||
import { CategoryView } from 'sql/base/browser/ui/modal/optionsDialog';
|
import { CategoryView } from 'sql/base/browser/ui/modal/optionsDialog';
|
||||||
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
|
import { SelectBox } from 'sql/base/browser/ui/selectBox/selectBox';
|
||||||
import { SplitView } from 'sql/base/browser/ui/splitview/splitview';
|
import { SplitView } from 'sql/base/browser/ui/splitview/splitview';
|
||||||
import { attachButtonStyler, attachListBoxStyler, attachInputBoxStyler, attachSelectBoxStyler } from 'sql/common/theme/styler';
|
import { attachButtonStyler, attachListBoxStyler, attachInputBoxStyler, attachSelectBoxStyler, attachCheckboxStyler } from 'sql/common/theme/styler';
|
||||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||||
import * as BackupConstants from 'sql/parts/disasterRecovery/backup/constants';
|
import * as BackupConstants from 'sql/parts/disasterRecovery/backup/constants';
|
||||||
import { IBackupService, IBackupUiService, TaskExecutionMode } from 'sql/parts/disasterRecovery/backup/common/backupService';
|
import { IBackupService, IBackupUiService, TaskExecutionMode } from 'sql/parts/disasterRecovery/backup/common/backupService';
|
||||||
@@ -523,6 +523,11 @@ export class BackupComponent {
|
|||||||
this._toDispose.push(attachInputBoxStyler(this.mediaNameBox, this.themeService));
|
this._toDispose.push(attachInputBoxStyler(this.mediaNameBox, this.themeService));
|
||||||
this._toDispose.push(attachInputBoxStyler(this.mediaDescriptionBox, this.themeService));
|
this._toDispose.push(attachInputBoxStyler(this.mediaDescriptionBox, this.themeService));
|
||||||
this._toDispose.push(attachInputBoxStyler(this.backupRetainDaysBox, this.themeService));
|
this._toDispose.push(attachInputBoxStyler(this.backupRetainDaysBox, this.themeService));
|
||||||
|
this._toDispose.push(attachCheckboxStyler(this.copyOnlyCheckBox, this.themeService));
|
||||||
|
this._toDispose.push(attachCheckboxStyler(this.encryptCheckBox, this.themeService));
|
||||||
|
this._toDispose.push(attachCheckboxStyler(this.verifyCheckBox, this.themeService));
|
||||||
|
this._toDispose.push(attachCheckboxStyler(this.checksumCheckBox, this.themeService));
|
||||||
|
this._toDispose.push(attachCheckboxStyler(this.continueOnErrorCheckBox, this.themeService));
|
||||||
|
|
||||||
this._toDispose.push(this.backupTypeSelectBox.onDidSelect(selected => this.onBackupTypeChanged()));
|
this._toDispose.push(this.backupTypeSelectBox.onDidSelect(selected => this.onBackupTypeChanged()));
|
||||||
this.addButtonClickHandler(this.addPathButton, () => this.onAddClick());
|
this.addButtonClickHandler(this.addPathButton, () => this.onAddClick());
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.backup-dialog {
|
.backup-dialog {
|
||||||
height: calc(100% - 15px)
|
height: 100%
|
||||||
}
|
}
|
||||||
|
|
||||||
.backup-dialog .advanced-main-header {
|
.backup-dialog .advanced-main-header {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ import { Table } from 'sql/base/browser/ui/table/table';
|
|||||||
import { TableDataView } from 'sql/base/browser/ui/table/tableDataView';
|
import { TableDataView } from 'sql/base/browser/ui/table/tableDataView';
|
||||||
import * as DialogHelper from 'sql/base/browser/ui/modal/dialogHelper';
|
import * as DialogHelper from 'sql/base/browser/ui/modal/dialogHelper';
|
||||||
import { Modal } from 'sql/base/browser/ui/modal/modal';
|
import { Modal } from 'sql/base/browser/ui/modal/modal';
|
||||||
import { attachButtonStyler, attachModalDialogStyler, attachTableStyler, attachInputBoxStyler, attachSelectBoxStyler, attachEditableDropdownStyler } from 'sql/common/theme/styler';
|
import { attachButtonStyler, attachModalDialogStyler, attachTableStyler, attachInputBoxStyler, attachSelectBoxStyler, attachEditableDropdownStyler, attachCheckboxStyler } from 'sql/common/theme/styler';
|
||||||
import * as TelemetryKeys from 'sql/common/telemetryKeys';
|
import * as TelemetryKeys from 'sql/common/telemetryKeys';
|
||||||
import * as BackupConstants from 'sql/parts/disasterRecovery/backup/constants';
|
import * as BackupConstants from 'sql/parts/disasterRecovery/backup/constants';
|
||||||
import { RestoreViewModel, RestoreOptionParam, SouceDatabaseNamesParam } from 'sql/parts/disasterRecovery/restore/restoreViewModel';
|
import { RestoreViewModel, RestoreOptionParam, SouceDatabaseNamesParam } from 'sql/parts/disasterRecovery/restore/restoreViewModel';
|
||||||
@@ -532,6 +532,7 @@ export class RestoreDialog extends Modal {
|
|||||||
ariaLabel: label
|
ariaLabel: label
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
this._register(attachCheckboxStyler(checkbox, this._themeService));
|
||||||
return checkbox;
|
return checkbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
div.qp-node {
|
div.qp-node {
|
||||||
background-color: #FFFFCC;
|
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
border: 1px solid black;
|
border: 1px solid;
|
||||||
}
|
}
|
||||||
div.qp-statement-header {
|
div.qp-statement-header {
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
@@ -33,8 +32,7 @@ div[class|='qp-icon'] {
|
|||||||
.qp-tt {
|
.qp-tt {
|
||||||
top: 4em;
|
top: 4em;
|
||||||
left: 2em;
|
left: 2em;
|
||||||
border: 1px solid black;
|
border: 1px solid;
|
||||||
background-color: #FFFFEE;
|
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
width: 30em;
|
width: 30em;
|
||||||
}
|
}
|
||||||
@@ -56,7 +54,7 @@ div[class|='qp-icon'] {
|
|||||||
.qp-tt td,
|
.qp-tt td,
|
||||||
.qp-tt th {
|
.qp-tt th {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
border-bottom: solid 1px Black;
|
border-bottom: solid 1px;
|
||||||
padding: 1px;
|
padding: 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -204,8 +202,6 @@ div.qp-node:hover .qp-tt {
|
|||||||
.qp-root {
|
.qp-root {
|
||||||
display: table;
|
display: table;
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: #fff;
|
|
||||||
color: #000;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.qp-root svg {
|
.qp-root svg {
|
||||||
|
|||||||
@@ -219,14 +219,10 @@ export class NewStepAction extends Action {
|
|||||||
|
|
||||||
public run(context: JobHistoryComponent): TPromise<boolean> {
|
public run(context: JobHistoryComponent): TPromise<boolean> {
|
||||||
let ownerUri = context.ownerUri;
|
let ownerUri = context.ownerUri;
|
||||||
let jobName = context.agentJobInfo.name;
|
|
||||||
let server = context.serverName;
|
let server = context.serverName;
|
||||||
let stepId = 0;
|
let jobInfo = context.agentJobInfo;
|
||||||
if (context.agentJobHistoryInfo && context.agentJobHistoryInfo.steps) {
|
|
||||||
stepId = context.agentJobHistoryInfo.steps.length + 1;
|
|
||||||
}
|
|
||||||
return new TPromise<boolean>((resolve, reject) => {
|
return new TPromise<boolean>((resolve, reject) => {
|
||||||
resolve(this._commandService.executeCommand('agent.openNewStepDialog', ownerUri, jobName, server, stepId));
|
resolve(this._commandService.executeCommand('agent.openNewStepDialog', ownerUri, server, jobInfo , null));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -923,33 +923,17 @@ export class JobsViewComponent extends JobManagementView implements OnInit {
|
|||||||
let steps = this.jobSteps[jobId];
|
let steps = this.jobSteps[jobId];
|
||||||
job[0].JobSteps = steps;
|
job[0].JobSteps = steps;
|
||||||
}
|
}
|
||||||
let jobHistories = this.jobHistories[job[0].jobId];
|
|
||||||
let schedules: sqlops.AgentJobScheduleInfo[] = this.jobSchedules[job[0].jobId];
|
|
||||||
let alerts: sqlops.AgentAlertInfo[] = this.jobAlerts[job[0].jobId];
|
|
||||||
if (jobHistories && jobHistories[jobHistories.length-1]) {
|
|
||||||
|
|
||||||
// add schedules
|
// add schedules
|
||||||
if (schedules && schedules.length > 0) {
|
if (this.jobSchedules && this.jobSchedules[jobId]) {
|
||||||
if (!job[0].JobSchedules) {
|
let schedules = this.jobSchedules[jobId];
|
||||||
job[0].JobSchedules = [];
|
job[0].JobSchedules = schedules;
|
||||||
}
|
}
|
||||||
if (job[0].JobSchedules.length !== schedules.length) {
|
|
||||||
job[0].JobSchedules = [];
|
// add alerts
|
||||||
schedules.forEach(schedule => {
|
if (this.jobAlerts && this.jobAlerts[jobId]) {
|
||||||
job[0].JobSchedules.push(schedule);
|
let alerts = this.jobAlerts[jobId];
|
||||||
});
|
job[0].Alerts = alerts;
|
||||||
}
|
|
||||||
}
|
|
||||||
// add alerts
|
|
||||||
if (!job[0].Alerts) {
|
|
||||||
job[0].Alerts = [];
|
|
||||||
}
|
|
||||||
if (job[0].Alerts.length !== alerts.length) {
|
|
||||||
job[0].Alerts = [];
|
|
||||||
alerts.forEach(alert => {
|
|
||||||
job[0].Alerts.push(alert);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return job && job.length > 0 ? job[0] : undefined;
|
return job && job.length > 0 ? job[0] : undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import { ComponentBase } from 'sql/parts/modelComponents/componentBase';
|
|||||||
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces';
|
import { IComponent, IComponentDescriptor, IModelStore, ComponentEventType } from 'sql/parts/modelComponents/interfaces';
|
||||||
import { Checkbox, ICheckboxOptions } from 'sql/base/browser/ui/checkbox/checkbox';
|
import { Checkbox, ICheckboxOptions } from 'sql/base/browser/ui/checkbox/checkbox';
|
||||||
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
import { CommonServiceInterface } from 'sql/services/common/commonServiceInterface.service';
|
||||||
|
import { attachCheckboxStyler } from 'sql/common/theme/styler';
|
||||||
|
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'modelview-checkbox',
|
selector: 'modelview-checkbox',
|
||||||
@@ -30,7 +32,8 @@ export default class CheckBoxComponent extends ComponentBase implements ICompone
|
|||||||
constructor(
|
constructor(
|
||||||
@Inject(forwardRef(() => CommonServiceInterface)) private _commonService: CommonServiceInterface,
|
@Inject(forwardRef(() => CommonServiceInterface)) private _commonService: CommonServiceInterface,
|
||||||
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
|
@Inject(forwardRef(() => ChangeDetectorRef)) changeRef: ChangeDetectorRef,
|
||||||
@Inject(forwardRef(() => ElementRef)) el: ElementRef) {
|
@Inject(IWorkbenchThemeService) private themeService: IWorkbenchThemeService,
|
||||||
|
@Inject(forwardRef(() => ElementRef)) el: ElementRef,) {
|
||||||
super(changeRef, el);
|
super(changeRef, el);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,6 +58,7 @@ export default class CheckBoxComponent extends ComponentBase implements ICompone
|
|||||||
args: e
|
args: e
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
this._register(attachCheckboxStyler(this._input, this.themeService));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import { TreeNode } from 'sql/parts/objectExplorer/common/treeNode';
|
|||||||
import { NodeType } from 'sql/parts/objectExplorer/common/nodeType';
|
import { NodeType } from 'sql/parts/objectExplorer/common/nodeType';
|
||||||
import { ConnectionProfileGroup } from 'sql/parts/connection/common/connectionProfileGroup';
|
import { ConnectionProfileGroup } from 'sql/parts/connection/common/connectionProfileGroup';
|
||||||
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
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 { TreeUpdateUtils } from 'sql/parts/objectExplorer/viewlet/treeUpdateUtils';
|
||||||
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
||||||
import { MenuId, IMenuService } from 'vs/platform/actions/common/actions';
|
import { MenuId, IMenuService } from 'vs/platform/actions/common/actions';
|
||||||
@@ -90,9 +89,11 @@ export class ServerTreeActionProvider extends ContributableActionProvider {
|
|||||||
* Return actions for connection elements
|
* Return actions for connection elements
|
||||||
*/
|
*/
|
||||||
public getConnectionActions(tree: ITree, profile: ConnectionProfile): IAction[] {
|
public getConnectionActions(tree: ITree, profile: ConnectionProfile): IAction[] {
|
||||||
|
let node = new TreeNode(NodeType.Server, '', false, '', '', '', undefined, undefined, undefined, undefined);
|
||||||
return this.getAllActions({
|
return this.getAllActions({
|
||||||
tree: tree,
|
tree: tree,
|
||||||
profile: profile
|
profile: profile,
|
||||||
|
treeNode: node
|
||||||
}, (context) => this.getBuiltinConnectionActions(context));
|
}, (context) => this.getBuiltinConnectionActions(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,10 +126,6 @@ export class ServerTreeActionProvider extends ContributableActionProvider {
|
|||||||
actions.push(this._instantiationService.createInstance(DeleteConnectionAction, DeleteConnectionAction.ID, DeleteConnectionAction.DELETE_CONNECTION_LABEL, context.profile));
|
actions.push(this._instantiationService.createInstance(DeleteConnectionAction, DeleteConnectionAction.ID, DeleteConnectionAction.DELETE_CONNECTION_LABEL, context.profile));
|
||||||
actions.push(this._instantiationService.createInstance(RefreshAction, RefreshAction.ID, RefreshAction.LABEL, context.tree, context.profile));
|
actions.push(this._instantiationService.createInstance(RefreshAction, RefreshAction.ID, RefreshAction.LABEL, context.tree, context.profile));
|
||||||
|
|
||||||
if (process.env['VSCODE_DEV'] && constants.MssqlProviderId === context.profile.providerName) {
|
|
||||||
actions.push(this._instantiationService.createInstance(OEAction, NewProfilerAction.ID, NewProfilerAction.LABEL));
|
|
||||||
}
|
|
||||||
|
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,8 +31,8 @@ export class TreeCreationUtils {
|
|||||||
|
|
||||||
return new Tree(treeContainer, { dataSource, renderer, controller, dnd, filter, sorter, accessibilityProvider },
|
return new Tree(treeContainer, { dataSource, renderer, controller, dnd, filter, sorter, accessibilityProvider },
|
||||||
{
|
{
|
||||||
indentPixels: 10,
|
indentPixels: 0,
|
||||||
twistiePixels: 20,
|
twistiePixels: 0,
|
||||||
ariaLabel: nls.localize('treeAriaLabel', "Recent Connections")
|
ariaLabel: nls.localize('treeAriaLabel', "Recent Connections")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiati
|
|||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||||
import { IEditorService, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
import { IEditorService, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||||
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
import { IConnectionManagementService, IConnectionDialogService} from 'sql/parts/connection/common/connectionManagement';
|
||||||
import { IObjectExplorerService } from '../../objectExplorer/common/objectExplorerService';
|
import { IObjectExplorerService } from '../../objectExplorer/common/objectExplorerService';
|
||||||
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
@@ -18,6 +18,10 @@ import { IProfilerService } from '../service/interfaces';
|
|||||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||||
import { KeyCode, KeyMod } from 'vs/editor/editor.api';
|
import { KeyCode, KeyMod } from 'vs/editor/editor.api';
|
||||||
import { ProfilerEditor } from '../editor/profilerEditor';
|
import { ProfilerEditor } from '../editor/profilerEditor';
|
||||||
|
import { ObjectExplorerActionsContext } from 'sql/parts/objectExplorer/viewlet/objectExplorerActions';
|
||||||
|
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||||
|
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
||||||
|
import { mssqlProviderName } from 'sql/parts/connection/common/constants';
|
||||||
|
|
||||||
// Contribute Global Actions
|
// Contribute Global Actions
|
||||||
const category = nls.localize('profilerCategory', "Profiler");
|
const category = nls.localize('profilerCategory', "Profiler");
|
||||||
@@ -30,15 +34,45 @@ const newProfilerSchema: IJSONSchema = {
|
|||||||
|
|
||||||
CommandsRegistry.registerCommand({
|
CommandsRegistry.registerCommand({
|
||||||
id: 'profiler.newProfiler',
|
id: 'profiler.newProfiler',
|
||||||
handler: (accessor: ServicesAccessor) => {
|
handler: (accessor: ServicesAccessor, ...args: any[]) => {
|
||||||
let editorService: IEditorService = accessor.get(IEditorService);
|
let connectionProfile: ConnectionProfile = undefined;
|
||||||
let instantiationService: IInstantiationService = accessor.get(IInstantiationService);
|
let instantiationService: IInstantiationService = accessor.get(IInstantiationService);
|
||||||
|
let editorService: IEditorService = accessor.get(IEditorService);
|
||||||
let connectionService: IConnectionManagementService = accessor.get(IConnectionManagementService);
|
let connectionService: IConnectionManagementService = accessor.get(IConnectionManagementService);
|
||||||
let objectExplorerService: IObjectExplorerService = accessor.get(IObjectExplorerService);
|
let objectExplorerService: IObjectExplorerService = accessor.get(IObjectExplorerService);
|
||||||
|
let connectionDialogService: IConnectionDialogService = accessor.get(IConnectionDialogService);
|
||||||
|
let capabilitiesService: ICapabilitiesService = accessor.get(ICapabilitiesService);
|
||||||
|
|
||||||
let connectionProfile = TaskUtilities.getCurrentGlobalConnection(objectExplorerService, connectionService, editorService);
|
// If a context is available if invoked from the context menu, we will use the connection profiler of the server node
|
||||||
let profilerInput = instantiationService.createInstance(ProfilerInput, connectionProfile);
|
if (args && args.length === 1 && args[0] && args[0] instanceof ObjectExplorerActionsContext) {
|
||||||
return editorService.openEditor(profilerInput, { pinned: true }, ACTIVE_GROUP).then(() => TPromise.as(true));
|
let context = args[0] as ObjectExplorerActionsContext;
|
||||||
|
connectionProfile = ConnectionProfile.fromIConnectionProfile(capabilitiesService, context.connectionProfile);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// No context available, we will try to get the current global active connection
|
||||||
|
connectionProfile = TaskUtilities.getCurrentGlobalConnection(objectExplorerService, connectionService, editorService) as ConnectionProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
let promise;
|
||||||
|
if (connectionProfile) {
|
||||||
|
promise = connectionService.connectIfNotConnected(connectionProfile);
|
||||||
|
} else {
|
||||||
|
// if still no luck, we will open the Connection dialog and let user connect to a server
|
||||||
|
promise = connectionDialogService.openDialogAndWait(connectionService, { connectionType: 1, providers: [mssqlProviderName] }).then((profile) => {
|
||||||
|
connectionProfile = profile as ConnectionProfile;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return promise.then(() => {
|
||||||
|
if (!connectionProfile) {
|
||||||
|
connectionProfile = TaskUtilities.getCurrentGlobalConnection(objectExplorerService, connectionService, editorService) as ConnectionProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connectionProfile && connectionProfile.providerName === mssqlProviderName) {
|
||||||
|
let profilerInput = instantiationService.createInstance(ProfilerInput, connectionProfile);
|
||||||
|
editorService.openEditor(profilerInput, { pinned: true }, ACTIVE_GROUP).then(() => TPromise.as(true));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { IProfilerController } from 'sql/parts/profiler/editor/controller/interf
|
|||||||
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
||||||
import { BaseActionContext } from 'sql/workbench/common/actions';
|
import { BaseActionContext } from 'sql/workbench/common/actions';
|
||||||
import { Task } from 'sql/platform/tasks/common/tasks';
|
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 { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||||
import { IConnectionManagementService, IConnectionCompletionOptions, ConnectionType } from 'sql/parts/connection/common/connectionManagement';
|
import { IConnectionManagementService, IConnectionCompletionOptions, ConnectionType } from 'sql/parts/connection/common/connectionManagement';
|
||||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
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';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
|
|
||||||
export class ProfilerConnect extends Action {
|
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 ID = 'profiler.connect';
|
||||||
public static LABEL = nls.localize('profiler.connect', "Connect");
|
public static LABEL = ProfilerConnect.ConnectText;
|
||||||
|
|
||||||
private _connected: boolean = false;
|
private _connected: boolean = false;
|
||||||
|
|
||||||
@@ -59,7 +61,7 @@ export class ProfilerConnect extends Action {
|
|||||||
public set connected(value: boolean) {
|
public set connected(value: boolean) {
|
||||||
this._connected = value;
|
this._connected = value;
|
||||||
this._setClass(value ? 'disconnect' : 'connect');
|
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 {
|
public get connected(): boolean {
|
||||||
@@ -75,7 +77,7 @@ export class ProfilerStart extends Action {
|
|||||||
id: string, label: string,
|
id: string, label: string,
|
||||||
@IProfilerService private _profilerService: IProfilerService
|
@IProfilerService private _profilerService: IProfilerService
|
||||||
) {
|
) {
|
||||||
super(id, label, 'start');
|
super(id, label, 'sql start');
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(input: ProfilerInput): TPromise<boolean> {
|
public run(input: ProfilerInput): TPromise<boolean> {
|
||||||
@@ -86,7 +88,7 @@ export class ProfilerStart extends Action {
|
|||||||
|
|
||||||
export class ProfilerCreate extends Action {
|
export class ProfilerCreate extends Action {
|
||||||
public static ID = 'profiler.create';
|
public static ID = 'profiler.create';
|
||||||
public static LABEL = nls.localize('create', "Create");
|
public static LABEL = nls.localize('create', "New Session");
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
id: string, label: string,
|
id: string, label: string,
|
||||||
@@ -105,8 +107,13 @@ export class ProfilerCreate extends Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ProfilerPause 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 ID = 'profiler.pause';
|
||||||
public static LABEL = nls.localize('profiler.capture', "Pause Capture");
|
public static LABEL = ProfilerPause.PauseText;
|
||||||
|
|
||||||
private _paused: boolean = false;
|
private _paused: boolean = false;
|
||||||
|
|
||||||
@@ -114,7 +121,7 @@ export class ProfilerPause extends Action {
|
|||||||
id: string, label: string,
|
id: string, label: string,
|
||||||
@IProfilerService private _profilerService: IProfilerService
|
@IProfilerService private _profilerService: IProfilerService
|
||||||
) {
|
) {
|
||||||
super(id, label, 'stop');
|
super(id, label, ProfilerPause.PauseCssClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(input: ProfilerInput): TPromise<boolean> {
|
public run(input: ProfilerInput): TPromise<boolean> {
|
||||||
@@ -127,8 +134,8 @@ export class ProfilerPause extends Action {
|
|||||||
|
|
||||||
public set paused(value: boolean) {
|
public set paused(value: boolean) {
|
||||||
this._paused = value;
|
this._paused = value;
|
||||||
this._setClass(value ? 'start' : 'stop');
|
this._setClass(value ? ProfilerPause.ResumeCssClass : ProfilerPause.PauseCssClass);
|
||||||
this._setLabel(value ? nls.localize('profilerAction.resumeCapture', "Resume Capture") : nls.localize('profilerAction.pauseCapture', "Pause Capture"));
|
this._setLabel(value ? ProfilerPause.ResumeText : ProfilerPause.PauseText);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get paused(): boolean {
|
public get paused(): boolean {
|
||||||
@@ -144,7 +151,7 @@ export class ProfilerStop extends Action {
|
|||||||
id: string, label: string,
|
id: string, label: string,
|
||||||
@IProfilerService private _profilerService: IProfilerService
|
@IProfilerService private _profilerService: IProfilerService
|
||||||
) {
|
) {
|
||||||
super(id, label, 'stop');
|
super(id, label, 'sql stop');
|
||||||
}
|
}
|
||||||
|
|
||||||
public run(input: ProfilerInput): TPromise<boolean> {
|
public run(input: ProfilerInput): TPromise<boolean> {
|
||||||
@@ -167,16 +174,21 @@ export class ProfilerClear extends Action {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ProfilerAutoScroll 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 ID = 'profiler.autoscroll';
|
||||||
public static LABEL = nls.localize('profiler.autoscrollOn', "Auto Scroll: On");
|
public static LABEL = ProfilerAutoScroll.AutoScrollOnText;
|
||||||
|
|
||||||
constructor(id: string, label: string) {
|
constructor(id: string, label: string) {
|
||||||
super(id, label);
|
super(id, label, ProfilerAutoScroll.CheckedCssClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
run(input: ProfilerInput): TPromise<boolean> {
|
run(input: ProfilerInput): TPromise<boolean> {
|
||||||
this.checked = !this.checked;
|
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 });
|
input.state.change({ autoscroll: this.checked });
|
||||||
return TPromise.as(true);
|
return TPromise.as(true);
|
||||||
}
|
}
|
||||||
@@ -256,7 +268,7 @@ export class ProfilerFindPrevious implements IEditorAction {
|
|||||||
|
|
||||||
export class NewProfilerAction extends Task {
|
export class NewProfilerAction extends Task {
|
||||||
public static readonly ID = 'profiler.newProfiler';
|
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';
|
public static readonly ICON = 'profile';
|
||||||
|
|
||||||
private _connectionProfile: ConnectionProfile;
|
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 _viewTemplates: Array<IProfilerViewTemplate>;
|
||||||
private _sessionSelector: SelectBox;
|
private _sessionSelector: SelectBox;
|
||||||
private _sessionsList: Array<string>;
|
private _sessionsList: Array<string>;
|
||||||
private _connectionInfoText: HTMLElement;
|
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
private _connectAction: Actions.ProfilerConnect;
|
private _connectAction: Actions.ProfilerConnect;
|
||||||
@@ -211,6 +210,7 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
|
|
||||||
this._viewTemplates = this._profilerService.getViewTemplates();
|
this._viewTemplates = this._profilerService.getViewTemplates();
|
||||||
this._viewTemplateSelector = new SelectBox(this._viewTemplates.map(i => i.name), 'Standard View', this._contextViewService);
|
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 => {
|
this._register(this._viewTemplateSelector.onDidSelect(e => {
|
||||||
if (this.input) {
|
if (this.input) {
|
||||||
this.input.viewTemplate = this._viewTemplates.find(i => i.name === e.selected);
|
this.input.viewTemplate = this._viewTemplates.find(i => i.name === e.selected);
|
||||||
@@ -223,6 +223,7 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
|
|
||||||
this._sessionsList = [''];
|
this._sessionsList = [''];
|
||||||
this._sessionSelector = new SelectBox(this._sessionsList, '', this._contextViewService);
|
this._sessionSelector = new SelectBox(this._sessionsList, '', this._contextViewService);
|
||||||
|
this._sessionSelector.setAriaLabel(nls.localize('profiler.sessionSelectAccessibleName', 'Select Session'));
|
||||||
this._register(this._sessionSelector.onDidSelect(e => {
|
this._register(this._sessionSelector.onDidSelect(e => {
|
||||||
if (this.input) {
|
if (this.input) {
|
||||||
this.input.sessionName = e.selected;
|
this.input.sessionName = e.selected;
|
||||||
@@ -233,32 +234,36 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
sessionsContainer.style.paddingRight = '5px';
|
sessionsContainer.style.paddingRight = '5px';
|
||||||
this._sessionSelector.render(sessionsContainer);
|
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._viewTemplateSelector, this.themeService));
|
||||||
this._register(attachSelectBoxStyler(this._sessionSelector, this.themeService));
|
this._register(attachSelectBoxStyler(this._sessionSelector, this.themeService));
|
||||||
|
|
||||||
this._actionBar.setContent([
|
this._actionBar.setContent([
|
||||||
{ action: this._startAction },
|
|
||||||
{ action: this._stopAction },
|
|
||||||
{ element: sessionsContainer },
|
|
||||||
{ action: this._createAction },
|
{ action: this._createAction },
|
||||||
{ element: Taskbar.createTaskbarSeparator() },
|
{ 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._pauseAction },
|
||||||
{ action: this._autoscrollAction },
|
|
||||||
{ action: this._instantiationService.createInstance(Actions.ProfilerClear, Actions.ProfilerClear.ID, Actions.ProfilerClear.LABEL) },
|
|
||||||
{ element: Taskbar.createTaskbarSeparator() },
|
{ element: Taskbar.createTaskbarSeparator() },
|
||||||
|
{ element: this._createTextElement(nls.localize('profiler.viewSelectLabel', 'Select View:')) },
|
||||||
{ element: viewTemplateContainer },
|
{ element: viewTemplateContainer },
|
||||||
{ element: Taskbar.createTaskbarSeparator() },
|
{ 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 {
|
private _createProfilerTable(): HTMLElement {
|
||||||
let profilerTableContainer = document.createElement('div');
|
let profilerTableContainer = document.createElement('div');
|
||||||
profilerTableContainer.className = 'profiler-table monaco-editor';
|
profilerTableContainer.className = 'profiler-table monaco-editor';
|
||||||
@@ -417,7 +422,6 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
autoscroll: true,
|
autoscroll: true,
|
||||||
isPanelCollapsed: true
|
isPanelCollapsed: true
|
||||||
});
|
});
|
||||||
this._connectionInfoText.innerText = input.connectionName;
|
|
||||||
this._profilerTableEditor.updateState();
|
this._profilerTableEditor.updateState();
|
||||||
this._splitView.layout();
|
this._splitView.layout();
|
||||||
this._profilerTableEditor.focus();
|
this._profilerTableEditor.focus();
|
||||||
@@ -464,34 +468,16 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
this._connectAction.connected = this.input.state.isConnected;
|
this._connectAction.connected = this.input.state.isConnected;
|
||||||
|
|
||||||
if (this.input.state.isConnected) {
|
if (this.input.state.isConnected) {
|
||||||
|
|
||||||
this._updateToolbar();
|
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);
|
// Launch the create session dialog if openning a new window.
|
||||||
this._sessionsList = r;
|
let uiState = this._profilerService.getSessionViewState(this.input.id);
|
||||||
if ((this.input.sessionName === undefined || this.input.sessionName === '') && this._sessionsList.length > 0) {
|
let previousSessionName = uiState && uiState.previousSessionName;
|
||||||
let sessionIndex: number = 0;
|
if (!this.input.sessionName && !previousSessionName) {
|
||||||
let uiState = this._profilerService.getSessionViewState(this.input.id);
|
this._profilerService.launchCreateSessionDialog(this.input);
|
||||||
if (uiState && uiState.previousSessionName) {
|
}
|
||||||
sessionIndex = this._sessionsList.indexOf(uiState.previousSessionName);
|
|
||||||
} else {
|
|
||||||
this._profilerService.launchCreateSessionDialog(this.input);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sessionIndex < 0) {
|
this._updateSessionSelector(previousSessionName);
|
||||||
sessionIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.input.sessionName = this._sessionsList[sessionIndex];
|
|
||||||
this._sessionSelector.selectWithOptionName(this.input.sessionName);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
this._startAction.enabled = false;
|
this._startAction.enabled = false;
|
||||||
this._stopAction.enabled = false;
|
this._stopAction.enabled = false;
|
||||||
@@ -517,23 +503,35 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
}
|
}
|
||||||
if (this.input.state.isStopped) {
|
if (this.input.state.isStopped) {
|
||||||
this._updateToolbar();
|
this._updateToolbar();
|
||||||
this._sessionSelector.enable();
|
this._updateSessionSelector();
|
||||||
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];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
private _updateToolbar(): void {
|
||||||
this._startAction.enabled = !this.input.state.isRunning && !this.input.state.isPaused && this.input.state.isConnected;
|
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;
|
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 * as nls from 'vs/nls';
|
||||||
|
|
||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
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 { IEditorModel } from 'vs/platform/editor/common/editor';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
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 { escape } from 'sql/base/common/strings';
|
||||||
import * as types from 'vs/base/common/types';
|
import * as types from 'vs/base/common/types';
|
||||||
import URI from 'vs/base/common/uri';
|
import URI from 'vs/base/common/uri';
|
||||||
|
import Severity from 'vs/base/common/severity';
|
||||||
|
|
||||||
export class ProfilerInput extends EditorInput implements IProfilerSession {
|
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;
|
public onColumnsChanged: Event<Slick.Column<Slick.SlickData>[]> = this._onColumnsChanged.event;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _connection: IConnectionProfile,
|
public connection: IConnectionProfile,
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||||
@IProfilerService private _profilerService: IProfilerService,
|
@IProfilerService private _profilerService: IProfilerService,
|
||||||
@INotificationService private _notificationService: INotificationService,
|
@INotificationService private _notificationService: INotificationService,
|
||||||
@@ -58,7 +59,7 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
autoscroll: true
|
autoscroll: true
|
||||||
});
|
});
|
||||||
|
|
||||||
this._profilerService.registerSession(generateUuid(), _connection, this).then((id) => {
|
this._profilerService.registerSession(generateUuid(), connection, this).then((id) => {
|
||||||
this._id = id;
|
this._id = id;
|
||||||
this.state.change({ isConnected: true });
|
this.state.change({ isConnected: true });
|
||||||
});
|
});
|
||||||
@@ -72,23 +73,10 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
this._data = new TableDataView<Slick.SlickData>(undefined, searchFn);
|
this._data = new TableDataView<Slick.SlickData>(undefined, searchFn);
|
||||||
|
}
|
||||||
|
|
||||||
this.onDispose(() => {
|
public get providerType(): string {
|
||||||
if (this._state.isRunning || this.state.isPaused) {
|
return this.connection ? this.connection.providerName : undefined;
|
||||||
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 set viewTemplate(template: IProfilerViewTemplate) {
|
public set viewTemplate(template: IProfilerViewTemplate) {
|
||||||
@@ -114,7 +102,7 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public set sessionName(name: string) {
|
public set sessionName(name: string) {
|
||||||
if (!this._state.isRunning || !this.state.isPaused) {
|
if (!this.state.isRunning || !this.state.isPaused) {
|
||||||
this._sessionName = name;
|
this._sessionName = name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,10 +121,10 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
|
|
||||||
public getName(): string {
|
public getName(): string {
|
||||||
let name: string = nls.localize('profilerInput.profiler', 'Profiler');
|
let name: string = nls.localize('profilerInput.profiler', 'Profiler');
|
||||||
if (!this._connection) {
|
if (!this.connection) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
name += ': ' + this._connection.serverName.substring(0, 20);
|
name += ': ' + this.connection.serverName.substring(0, 20);
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,11 +166,11 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get connectionName(): string {
|
public get connectionName(): string {
|
||||||
if (!types.isUndefinedOrNull(this._connection)) {
|
if (!types.isUndefinedOrNull(this.connection)) {
|
||||||
if (this._connection.databaseName) {
|
if (this.connection.databaseName) {
|
||||||
return `${this._connection.serverName} ${this._connection.databaseName}`;
|
return `${this.connection.serverName} ${this.connection.databaseName}`;
|
||||||
} else {
|
} else {
|
||||||
return `${this._connection.serverName}`;
|
return `${this.connection.serverName}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -199,7 +187,7 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public onSessionStopped(notification: sqlops.ProfilerSessionStoppedParams) {
|
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({
|
this.state.change({
|
||||||
isStopped: true,
|
isStopped: true,
|
||||||
@@ -240,7 +228,7 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
|
|
||||||
public onMoreRows(eventMessage: sqlops.ProfilerSessionEvents) {
|
public onMoreRows(eventMessage: sqlops.ProfilerSessionEvents) {
|
||||||
if (eventMessage.eventsLost) {
|
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) {
|
for (let i: number = 0; i < eventMessage.events.length && i < 500; ++i) {
|
||||||
@@ -264,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 });
|
this._sessionMap.get(this._idMap.reverseGet(id)).onSessionStateChanged({ isStopped: true, isPaused: false, isRunning: false });
|
||||||
return true;
|
return true;
|
||||||
}, (reason) => {
|
}, (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 });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,6 +231,6 @@ export class ProfilerService implements IProfilerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public launchCreateSessionDialog(input?: ProfilerInput): Thenable<void> {
|
public launchCreateSessionDialog(input?: ProfilerInput): Thenable<void> {
|
||||||
return this._commandService.executeCommand('profiler.openCreateSessionDialog', input.id, this.getSessionTemplates());
|
return this._commandService.executeCommand('profiler.openCreateSessionDialog', input.id, input.providerType, this.getSessionTemplates());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -339,7 +339,7 @@ let registryProperties = {
|
|||||||
'sql.showConnectionInfoInTitle': {
|
'sql.showConnectionInfoInTitle': {
|
||||||
'type': 'boolean',
|
'type': 'boolean',
|
||||||
'description': localize('showConnectionInfoInTitle', "Controls whether to show the connection info for a tab in the title."),
|
'description': localize('showConnectionInfoInTitle', "Controls whether to show the connection info for a tab in the title."),
|
||||||
'default': false
|
'default': true
|
||||||
},
|
},
|
||||||
'mssql.intelliSense.enableIntelliSense': {
|
'mssql.intelliSense.enableIntelliSense': {
|
||||||
'type': 'boolean',
|
'type': 'boolean',
|
||||||
|
|||||||
@@ -32,9 +32,6 @@ export interface IQueryEditorService {
|
|||||||
// Creates new edit data session
|
// Creates new edit data session
|
||||||
newEditDataEditor(schemaName: string, tableName: string, queryString: string): Promise<IConnectableInput>;
|
newEditDataEditor(schemaName: string, tableName: string, queryString: string): Promise<IConnectableInput>;
|
||||||
|
|
||||||
// Clears any QueryEditor data for the given URI held by this service
|
|
||||||
onQueryInputClosed(uri: string): void;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles updating of SQL files on a save as event. These need special consideration
|
* Handles updating of SQL files on a save as event. These need special consideration
|
||||||
* due to query results and other information being tied to the URI of the file
|
* due to query results and other information being tied to the URI of the file
|
||||||
|
|||||||
@@ -116,11 +116,11 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this._configurationService) {
|
if (this._configurationService) {
|
||||||
this._configurationService.onDidChangeConfiguration(e => {
|
this._toDispose.push(this._configurationService.onDidChangeConfiguration(e => {
|
||||||
if (e.affectedKeys.includes('sql.showConnectionInfoInTitle')) {
|
if (e.affectedKeys.includes('sql.showConnectionInfoInTitle')) {
|
||||||
this._onDidChangeLabel.fire();
|
this._onDidChangeLabel.fire();
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.onDisconnect();
|
this.onDisconnect();
|
||||||
@@ -196,17 +196,17 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec
|
|||||||
|
|
||||||
// State update funtions
|
// State update funtions
|
||||||
public runQuery(selection: ISelectionData, executePlanOptions?: ExecutionPlanOptions): void {
|
public runQuery(selection: ISelectionData, executePlanOptions?: ExecutionPlanOptions): void {
|
||||||
this._queryModelService.runQuery(this.uri, selection, this.uri, this, executePlanOptions);
|
this._queryModelService.runQuery(this.uri, selection, this, executePlanOptions);
|
||||||
this.showQueryResultsEditor();
|
this.showQueryResultsEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public runQueryStatement(selection: ISelectionData): void {
|
public runQueryStatement(selection: ISelectionData): void {
|
||||||
this._queryModelService.runQueryStatement(this.uri, selection, this.uri, this);
|
this._queryModelService.runQueryStatement(this.uri, selection, this);
|
||||||
this.showQueryResultsEditor();
|
this.showQueryResultsEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public runQueryString(text: string): void {
|
public runQueryString(text: string): void {
|
||||||
this._queryModelService.runQueryString(this.uri, text, this.uri, this);
|
this._queryModelService.runQueryString(this.uri, text, this);
|
||||||
this.showQueryResultsEditor();
|
this.showQueryResultsEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,7 +276,6 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec
|
|||||||
|
|
||||||
// Clean up functions
|
// Clean up functions
|
||||||
public dispose(): void {
|
public dispose(): void {
|
||||||
this._queryModelService.disposeQuery(this.uri);
|
|
||||||
this._sql.dispose();
|
this._sql.dispose();
|
||||||
this._results.dispose();
|
this._results.dispose();
|
||||||
this._toDispose = dispose(this._toDispose);
|
this._toDispose = dispose(this._toDispose);
|
||||||
@@ -285,7 +284,7 @@ export class QueryInput extends EditorInput implements IEncodingSupport, IConnec
|
|||||||
}
|
}
|
||||||
|
|
||||||
public close(): void {
|
public close(): void {
|
||||||
this._queryEditorService.onQueryInputClosed(this.uri);
|
this._queryModelService.disposeQuery(this.uri);
|
||||||
this._connectionManagementService.disconnectEditor(this, true);
|
this._connectionManagementService.disconnectEditor(this, true);
|
||||||
|
|
||||||
this._sql.close();
|
this._sql.close();
|
||||||
|
|||||||
@@ -215,6 +215,7 @@ export class QueryManagementService implements IQueryManagementService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
public disposeQuery(ownerUri: string): Thenable<void> {
|
public disposeQuery(ownerUri: string): Thenable<void> {
|
||||||
|
this._queryRunners.delete(ownerUri);
|
||||||
return this._runAction(ownerUri, (runner) => {
|
return this._runAction(ownerUri, (runner) => {
|
||||||
return runner.disposeQuery(ownerUri);
|
return runner.disposeQuery(ownerUri);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -29,6 +29,13 @@ export class ResultsViewState {
|
|||||||
constructor(@IConfigurationService private configurationService: IConfigurationService) {
|
constructor(@IConfigurationService private configurationService: IConfigurationService) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this.gridPanelState.dispose();
|
||||||
|
this.messagePanelState.dispose();
|
||||||
|
this.chartState.dispose();
|
||||||
|
this.queryPlanState.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,7 +57,11 @@ export class QueryResultsInput extends EditorInput {
|
|||||||
public readonly onRestoreViewStateEmitter = new Emitter<void>();
|
public readonly onRestoreViewStateEmitter = new Emitter<void>();
|
||||||
public readonly onSaveViewStateEmitter = new Emitter<void>();
|
public readonly onSaveViewStateEmitter = new Emitter<void>();
|
||||||
|
|
||||||
public readonly state = new ResultsViewState(this.configurationService);
|
private _state = new ResultsViewState(this.configurationService);
|
||||||
|
|
||||||
|
public get state(): ResultsViewState {
|
||||||
|
return this._state;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(private _uri: string,
|
constructor(private _uri: string,
|
||||||
@IConfigurationService private configurationService: IConfigurationService
|
@IConfigurationService private configurationService: IConfigurationService
|
||||||
@@ -60,6 +71,12 @@ export class QueryResultsInput extends EditorInput {
|
|||||||
this._hasBootstrapped = false;
|
this._hasBootstrapped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.state.dispose();
|
||||||
|
this._state = undefined;
|
||||||
|
super.close();
|
||||||
|
}
|
||||||
|
|
||||||
getTypeId(): string {
|
getTypeId(): string {
|
||||||
return QueryResultsInput.ID;
|
return QueryResultsInput.ID;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
|||||||
|
|
||||||
import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
|
import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
|
||||||
import { IDisposable, combinedDisposable, dispose } from 'vs/base/common/lifecycle';
|
import { IDisposable, combinedDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||||
import { IEditorGroupsService } from 'vs/workbench/services/group/common/editorGroupsService';
|
|
||||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
import { IEditorCloseEvent } from 'vs/workbench/common/editor';
|
import { IEditorCloseEvent } from 'vs/workbench/common/editor';
|
||||||
import { append, $, hide, show } from 'vs/base/browser/dom';
|
import { append, $, hide, show } from 'vs/base/browser/dom';
|
||||||
@@ -25,7 +24,6 @@ export class RowCountStatusBarItem implements IStatusbarItem {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@IEditorService private _editorService: EditorServiceImpl,
|
@IEditorService private _editorService: EditorServiceImpl,
|
||||||
@IEditorGroupsService private _editorGroupService: IEditorGroupsService,
|
|
||||||
@IQueryModelService private _queryModelService: IQueryModelService
|
@IQueryModelService private _queryModelService: IQueryModelService
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
@@ -36,7 +34,7 @@ export class RowCountStatusBarItem implements IStatusbarItem {
|
|||||||
];
|
];
|
||||||
|
|
||||||
this._element = append(container, $('.query-statusbar-group'));
|
this._element = append(container, $('.query-statusbar-group'));
|
||||||
this._flavorElement = append(this._element, $('a.editor-status-selection'));
|
this._flavorElement = append(this._element, $('.editor-status-selection'));
|
||||||
this._flavorElement.title = nls.localize('rowStatus', "Row Count");
|
this._flavorElement.title = nls.localize('rowStatus', "Row Count");
|
||||||
hide(this._flavorElement);
|
hide(this._flavorElement);
|
||||||
|
|
||||||
@@ -65,11 +63,10 @@ export class RowCountStatusBarItem implements IStatusbarItem {
|
|||||||
if (queryRunner) {
|
if (queryRunner) {
|
||||||
if (queryRunner.hasCompleted) {
|
if (queryRunner.hasCompleted) {
|
||||||
this._displayValue(queryRunner);
|
this._displayValue(queryRunner);
|
||||||
} else if (queryRunner.isExecuting) {
|
|
||||||
this.dispose = queryRunner.addListener('complete', () => {
|
|
||||||
this._displayValue(queryRunner);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
this.dispose = queryRunner.onQueryEnd(e => {
|
||||||
|
this._displayValue(queryRunner);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.dispose = this._queryModelService.onRunQueryComplete(e => {
|
this.dispose = this._queryModelService.onRunQueryComplete(e => {
|
||||||
if (e === currentUri) {
|
if (e === currentUri) {
|
||||||
|
|||||||
107
src/sql/parts/query/common/timeElapsedStatus.ts
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import * as WorkbenchUtils from 'sql/workbench/common/sqlWorkbenchUtils';
|
||||||
|
import { IQueryModelService } from '../execution/queryModel';
|
||||||
|
import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
||||||
|
import { parseNumAsTimeString } from 'sql/parts/connection/common/utils';
|
||||||
|
|
||||||
|
import { IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
|
||||||
|
import { IDisposable, combinedDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||||
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
|
import { IEditorCloseEvent } from 'vs/workbench/common/editor';
|
||||||
|
import { append, $, hide, show } from 'vs/base/browser/dom';
|
||||||
|
import * as nls from 'vs/nls';
|
||||||
|
import { EditorServiceImpl } from 'vs/workbench/browser/parts/editor/editor';
|
||||||
|
import { IntervalTimer } from 'vs/base/common/async';
|
||||||
|
|
||||||
|
export class TimeElapsedStatusBarItem implements IStatusbarItem {
|
||||||
|
|
||||||
|
private _element: HTMLElement;
|
||||||
|
private _flavorElement: HTMLElement;
|
||||||
|
|
||||||
|
private dispose: IDisposable[] = [];
|
||||||
|
private intervalTimer = new IntervalTimer();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@IEditorService private _editorService: EditorServiceImpl,
|
||||||
|
@IQueryModelService private _queryModelService: IQueryModelService
|
||||||
|
) { }
|
||||||
|
|
||||||
|
render(container: HTMLElement): IDisposable {
|
||||||
|
let disposables = [
|
||||||
|
this._editorService.onDidVisibleEditorsChange(() => this._onEditorsChanged()),
|
||||||
|
this._editorService.onDidCloseEditor(event => this._onEditorClosed(event))
|
||||||
|
];
|
||||||
|
|
||||||
|
this._element = append(container, $('.query-statusbar-group'));
|
||||||
|
this._flavorElement = append(this._element, $('.editor-status-selection'));
|
||||||
|
this._flavorElement.title = nls.localize('timeElapsed', "Time Elapsed");
|
||||||
|
hide(this._flavorElement);
|
||||||
|
|
||||||
|
this._showStatus();
|
||||||
|
|
||||||
|
return combinedDisposable(disposables);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onEditorsChanged() {
|
||||||
|
this._showStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _onEditorClosed(event: IEditorCloseEvent) {
|
||||||
|
hide(this._flavorElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show/hide query status for active editor
|
||||||
|
private _showStatus(): void {
|
||||||
|
this.intervalTimer.cancel();
|
||||||
|
hide(this._flavorElement);
|
||||||
|
dispose(this.dispose);
|
||||||
|
this._flavorElement.innerText = '';
|
||||||
|
this.dispose = [];
|
||||||
|
let activeEditor = this._editorService.activeControl;
|
||||||
|
if (activeEditor) {
|
||||||
|
let currentUri = WorkbenchUtils.getEditorUri(activeEditor.input);
|
||||||
|
if (currentUri) {
|
||||||
|
let queryRunner = this._queryModelService.getQueryRunner(currentUri);
|
||||||
|
if (queryRunner) {
|
||||||
|
if (queryRunner.hasCompleted || queryRunner.isExecuting) {
|
||||||
|
this._displayValue(queryRunner);
|
||||||
|
}
|
||||||
|
this.dispose.push(queryRunner.onQueryStart(e => {
|
||||||
|
this._displayValue(queryRunner);
|
||||||
|
}));
|
||||||
|
this.dispose.push(queryRunner.onQueryEnd(e => {
|
||||||
|
this._displayValue(queryRunner);
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
this.dispose.push(this._queryModelService.onRunQueryStart(e => {
|
||||||
|
if (e === currentUri) {
|
||||||
|
this._displayValue(this._queryModelService.getQueryRunner(currentUri));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
this.dispose.push(this._queryModelService.onRunQueryComplete(e => {
|
||||||
|
if (e === currentUri) {
|
||||||
|
this._displayValue(this._queryModelService.getQueryRunner(currentUri));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _displayValue(runner: QueryRunner) {
|
||||||
|
this.intervalTimer.cancel();
|
||||||
|
if (runner.isExecuting) {
|
||||||
|
this.intervalTimer.cancelAndSet(() => {
|
||||||
|
this._flavorElement.innerText = parseNumAsTimeString(Date.now() - runner.queryStartTime.getTime(), false);
|
||||||
|
}, 1000);
|
||||||
|
this._flavorElement.innerText = parseNumAsTimeString(Date.now() - runner.queryStartTime.getTime(), false);
|
||||||
|
} else {
|
||||||
|
this._flavorElement.innerText = parseNumAsTimeString(runner.queryEndTime.getTime() - runner.queryStartTime.getTime(), false);
|
||||||
|
}
|
||||||
|
show(this._flavorElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,4 +33,8 @@ export class ChartTab implements IPanelTab {
|
|||||||
public dispose() {
|
public dispose() {
|
||||||
this.view.dispose();
|
this.view.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clear() {
|
||||||
|
this.view.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,10 @@ export class ChartState {
|
|||||||
options: IInsightOptions = {
|
options: IInsightOptions = {
|
||||||
type: ChartType.Bar
|
type: ChartType.Bar
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare class Proxy {
|
declare class Proxy {
|
||||||
@@ -134,6 +138,15 @@ export class ChartView extends Disposable implements IPanelView {
|
|||||||
this.buildOptions();
|
this.buildOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clear() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public dispose() {
|
||||||
|
dispose(this.optionDisposables);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
render(container: HTMLElement): void {
|
render(container: HTMLElement): void {
|
||||||
if (!this.container) {
|
if (!this.container) {
|
||||||
this.container = $('div.chart-parent-container');
|
this.container = $('div.chart-parent-container');
|
||||||
@@ -326,7 +339,7 @@ export class ChartView extends Disposable implements IPanelView {
|
|||||||
this.optionDisposables.push(attachInputBoxStyler(numberInput, this._themeService));
|
this.optionDisposables.push(attachInputBoxStyler(numberInput, this._themeService));
|
||||||
break;
|
break;
|
||||||
case ControlType.dateInput:
|
case ControlType.dateInput:
|
||||||
let dateInput = new InputBox(optionContainer, this._contextViewService, { type: 'date' });
|
let dateInput = new InputBox(optionContainer, this._contextViewService, { type: 'datetime-local' });
|
||||||
dateInput.value = value || '';
|
dateInput.value = value || '';
|
||||||
dateInput.onDidChange(e => {
|
dateInput.onDidChange(e => {
|
||||||
if (this.options[option.configEntry] !== e) {
|
if (this.options[option.configEntry] !== e) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { ChartType, DataDirection, LegendPosition, DataType, IPointDataSet, cust
|
|||||||
|
|
||||||
const noneLineGraphs = [ChartType.Doughnut, ChartType.Pie];
|
const noneLineGraphs = [ChartType.Doughnut, ChartType.Pie];
|
||||||
|
|
||||||
const timeSeriesScales = {
|
const timeSeriesScales: ChartJs.ChartOptions = {
|
||||||
scales: {
|
scales: {
|
||||||
xAxes: [{
|
xAxes: [{
|
||||||
type: 'time',
|
type: 'time',
|
||||||
@@ -64,7 +64,7 @@ export class Graph implements IInsight {
|
|||||||
this._theme = e;
|
this._theme = e;
|
||||||
this.data = this._data;
|
this.data = this._data;
|
||||||
});
|
});
|
||||||
this._options = mixin(options, defaultOptions, false);
|
this.options = mixin(options, defaultOptions, false);
|
||||||
|
|
||||||
let canvasContainer = document.createElement('div');
|
let canvasContainer = document.createElement('div');
|
||||||
canvasContainer.style.width = '100%';
|
canvasContainer.style.width = '100%';
|
||||||
@@ -89,9 +89,12 @@ export class Graph implements IInsight {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public set data(data: IInsightData) {
|
public set data(data: IInsightData) {
|
||||||
|
if (!data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
this._data = data;
|
this._data = data;
|
||||||
let chartData: Array<ChartJs.ChartDataSets>;
|
|
||||||
let labels: Array<string>;
|
let labels: Array<string>;
|
||||||
|
let chartData: Array<ChartJs.ChartDataSets>;
|
||||||
|
|
||||||
if (this.options.dataDirection === DataDirection.Horizontal) {
|
if (this.options.dataDirection === DataDirection.Horizontal) {
|
||||||
if (this.options.labelFirstColumn) {
|
if (this.options.labelFirstColumn) {
|
||||||
@@ -158,19 +161,19 @@ export class Graph implements IInsight {
|
|||||||
if (this.chartjs) {
|
if (this.chartjs) {
|
||||||
this.chartjs.data.datasets = chartData;
|
this.chartjs.data.datasets = chartData;
|
||||||
this.chartjs.config.type = this.options.type;
|
this.chartjs.config.type = this.options.type;
|
||||||
this.chartjs.data.labels = labels;
|
// we don't want to include lables for timeSeries
|
||||||
|
this.chartjs.data.labels = this.originalType === 'timeSeries' ? [] : labels;
|
||||||
this.chartjs.options = this.transformOptions(this.options);
|
this.chartjs.options = this.transformOptions(this.options);
|
||||||
this.chartjs.update(0);
|
this.chartjs.update(0);
|
||||||
} else {
|
} else {
|
||||||
this.chartjs = new ChartJs(this.canvas.getContext('2d'), {
|
this.chartjs = new ChartJs(this.canvas.getContext('2d'), {
|
||||||
data: {
|
data: {
|
||||||
labels: labels,
|
// we don't want to include lables for timeSeries
|
||||||
|
labels: this.originalType === 'timeSeries' ? [] : labels,
|
||||||
datasets: chartData
|
datasets: chartData
|
||||||
},
|
},
|
||||||
type: this.options.type,
|
type: this.options.type,
|
||||||
options: {
|
options: this.transformOptions(this.options)
|
||||||
maintainAspectRatio: false
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,15 +200,21 @@ export class Graph implements IInsight {
|
|||||||
display: options.xAxisLabel ? true : false
|
display: options.xAxisLabel ? true : false
|
||||||
},
|
},
|
||||||
ticks: {
|
ticks: {
|
||||||
fontColor: foreground,
|
fontColor: foreground
|
||||||
max: options.xAxisMax,
|
|
||||||
min: options.xAxisMin
|
|
||||||
},
|
},
|
||||||
gridLines: {
|
gridLines: {
|
||||||
color: gridLines
|
color: gridLines
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
if (options.xAxisMax) {
|
||||||
|
retval.scales = mixin(retval.scales, { xAxes: [{ ticks: { max: options.xAxisMax } }] }, true, customMixin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.xAxisMin) {
|
||||||
|
retval.scales = mixin(retval.scales, { xAxes: [{ ticks: { min: options.xAxisMin } }] }, true, customMixin);
|
||||||
|
}
|
||||||
|
|
||||||
retval.scales.yAxes = [{
|
retval.scales.yAxes = [{
|
||||||
scaleLabel: {
|
scaleLabel: {
|
||||||
fontColor: foreground,
|
fontColor: foreground,
|
||||||
@@ -213,22 +222,27 @@ export class Graph implements IInsight {
|
|||||||
display: options.yAxisLabel ? true : false
|
display: options.yAxisLabel ? true : false
|
||||||
},
|
},
|
||||||
ticks: {
|
ticks: {
|
||||||
fontColor: foreground,
|
fontColor: foreground
|
||||||
max: options.yAxisMax,
|
|
||||||
min: options.yAxisMin
|
|
||||||
},
|
},
|
||||||
gridLines: {
|
gridLines: {
|
||||||
color: gridLines
|
color: gridLines
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
if (options.yAxisMax) {
|
||||||
|
retval.scales = mixin(retval.scales, { yAxes: [{ ticks: { max: options.yAxisMax } }] }, true, customMixin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.yAxisMin) {
|
||||||
|
retval.scales = mixin(retval.scales, { yAxes: [{ ticks: { min: options.yAxisMin } }] }, true, customMixin);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.originalType === ChartType.TimeSeries) {
|
if (this.originalType === ChartType.TimeSeries) {
|
||||||
retval = mixin(retval, timeSeriesScales, true, customMixin);
|
retval = mixin(retval, timeSeriesScales, true, customMixin);
|
||||||
if (options.xAxisMax) {
|
if (options.xAxisMax) {
|
||||||
retval = mixin(retval, {
|
retval = mixin(retval, {
|
||||||
scales: {
|
scales: {
|
||||||
xAxes: [{
|
xAxes: [{
|
||||||
type: 'time',
|
|
||||||
time: {
|
time: {
|
||||||
max: options.xAxisMax
|
max: options.xAxisMax
|
||||||
}
|
}
|
||||||
@@ -241,7 +255,6 @@ export class Graph implements IInsight {
|
|||||||
retval = mixin(retval, {
|
retval = mixin(retval, {
|
||||||
scales: {
|
scales: {
|
||||||
xAxes: [{
|
xAxes: [{
|
||||||
type: 'time',
|
|
||||||
time: {
|
time: {
|
||||||
min: options.xAxisMin
|
min: options.xAxisMin
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
import { attachTableStyler } from 'sql/common/theme/styler';
|
import { attachTableStyler } from 'sql/common/theme/styler';
|
||||||
import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
||||||
import { VirtualizedCollection, AsyncDataProvider } from 'sql/base/browser/ui/table/asyncDataView';
|
import { VirtualizedCollection, AsyncDataProvider } from 'sql/base/browser/ui/table/asyncDataView';
|
||||||
import { Table, ITableStyles, ITableMouseEvent } from 'sql/base/browser/ui/table/table';
|
import { Table } from 'sql/base/browser/ui/table/table';
|
||||||
import { ScrollableSplitView } from 'sql/base/browser/ui/scrollableSplitview/scrollableSplitview';
|
import { ScrollableSplitView } from 'sql/base/browser/ui/scrollableSplitview/scrollableSplitview';
|
||||||
import { MouseWheelSupport } from 'sql/base/browser/ui/table/plugins/mousewheelTableScroll.plugin';
|
import { MouseWheelSupport } from 'sql/base/browser/ui/table/plugins/mousewheelTableScroll.plugin';
|
||||||
import { AutoColumnSize } from 'sql/base/browser/ui/table/plugins/autoSizeColumns.plugin';
|
import { AutoColumnSize } from 'sql/base/browser/ui/table/plugins/autoSizeColumns.plugin';
|
||||||
@@ -19,6 +19,7 @@ import { escape } from 'sql/base/common/strings';
|
|||||||
import { hyperLinkFormatter, textFormatter } from 'sql/parts/grid/services/sharedServices';
|
import { hyperLinkFormatter, textFormatter } from 'sql/parts/grid/services/sharedServices';
|
||||||
import { CopyKeybind } from 'sql/base/browser/ui/table/plugins/copyKeybind.plugin';
|
import { CopyKeybind } from 'sql/base/browser/ui/table/plugins/copyKeybind.plugin';
|
||||||
import { AdditionalKeyBindings } from 'sql/base/browser/ui/table/plugins/additionalKeyBindings.plugin';
|
import { AdditionalKeyBindings } from 'sql/base/browser/ui/table/plugins/additionalKeyBindings.plugin';
|
||||||
|
import { ITableStyles, ITableMouseEvent } from 'sql/base/browser/ui/table/interfaces';
|
||||||
|
|
||||||
import * as sqlops from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import * as pretty from 'pretty-data';
|
import * as pretty from 'pretty-data';
|
||||||
@@ -42,13 +43,14 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
|
|||||||
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
|
import { IUntitledEditorService } from 'vs/workbench/services/untitled/common/untitledEditorService';
|
||||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
import { IAction } from 'vs/base/common/actions';
|
import { IAction } from 'vs/base/common/actions';
|
||||||
|
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||||
|
|
||||||
const ROW_HEIGHT = 29;
|
const ROW_HEIGHT = 29;
|
||||||
const HEADER_HEIGHT = 26;
|
const HEADER_HEIGHT = 26;
|
||||||
const MIN_GRID_HEIGHT_ROWS = 8;
|
const MIN_GRID_HEIGHT_ROWS = 8;
|
||||||
const ESTIMATED_SCROLL_BAR_HEIGHT = 10;
|
const ESTIMATED_SCROLL_BAR_HEIGHT = 10;
|
||||||
const BOTTOM_PADDING = 15;
|
const BOTTOM_PADDING = 15;
|
||||||
const ACTIONBAR_WIDTH = 26;
|
const ACTIONBAR_WIDTH = 36;
|
||||||
|
|
||||||
// minimum height needed to show the full actionbar
|
// minimum height needed to show the full actionbar
|
||||||
const ACTIONBAR_HEIGHT = 100;
|
const ACTIONBAR_HEIGHT = 100;
|
||||||
@@ -60,6 +62,10 @@ export class GridPanelState {
|
|||||||
public tableStates: GridTableState[] = [];
|
public tableStates: GridTableState[] = [];
|
||||||
public scrollPosition: number;
|
public scrollPosition: number;
|
||||||
public collapsed = false;
|
public collapsed = false;
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
dispose(this.tableStates);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IGridTableState {
|
export interface IGridTableState {
|
||||||
@@ -67,14 +73,14 @@ export interface IGridTableState {
|
|||||||
maximized: boolean;
|
maximized: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GridTableState {
|
export class GridTableState extends Disposable {
|
||||||
|
|
||||||
private _maximized: boolean;
|
private _maximized: boolean;
|
||||||
|
|
||||||
private _onMaximizedChange = new Emitter<boolean>();
|
private _onMaximizedChange = this._register(new Emitter<boolean>());
|
||||||
public onMaximizedChange: Event<boolean> = this._onMaximizedChange.event;
|
public onMaximizedChange: Event<boolean> = this._onMaximizedChange.event;
|
||||||
|
|
||||||
private _onCanBeMaximizedChange = new Emitter<boolean>();
|
private _onCanBeMaximizedChange = this._register(new Emitter<boolean>());
|
||||||
public onCanBeMaximizedChange: Event<boolean> = this._onCanBeMaximizedChange.event;
|
public onCanBeMaximizedChange: Event<boolean> = this._onCanBeMaximizedChange.event;
|
||||||
|
|
||||||
private _canBeMaximized: boolean;
|
private _canBeMaximized: boolean;
|
||||||
@@ -85,6 +91,7 @@ export class GridTableState {
|
|||||||
public activeCell: Slick.Cell;
|
public activeCell: Slick.Cell;
|
||||||
|
|
||||||
constructor(public readonly resultId: number, public readonly batchId: number) {
|
constructor(public readonly resultId: number, public readonly batchId: number) {
|
||||||
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get canBeMaximized(): boolean {
|
public get canBeMaximized(): boolean {
|
||||||
@@ -134,7 +141,7 @@ export class GridPanel extends ViewletPanel {
|
|||||||
@IInstantiationService private instantiationService: IInstantiationService
|
@IInstantiationService private instantiationService: IInstantiationService
|
||||||
) {
|
) {
|
||||||
super(options, keybindingService, contextMenuService, configurationService);
|
super(options, keybindingService, contextMenuService, configurationService);
|
||||||
this.splitView = new ScrollableSplitView(this.container, { enableResizing: false });
|
this.splitView = new ScrollableSplitView(this.container, { enableResizing: false, verticalScrollbarVisibility: ScrollbarVisibility.Visible });
|
||||||
this.splitView.onScroll(e => {
|
this.splitView.onScroll(e => {
|
||||||
if (this.state) {
|
if (this.state) {
|
||||||
this.state.scrollPosition = e;
|
this.state.scrollPosition = e;
|
||||||
@@ -216,13 +223,13 @@ export class GridPanel extends ViewletPanel {
|
|||||||
}
|
}
|
||||||
let table = this.instantiationService.createInstance(GridTable, this.runner, set);
|
let table = this.instantiationService.createInstance(GridTable, this.runner, set);
|
||||||
table.state = tableState;
|
table.state = tableState;
|
||||||
tableState.onMaximizedChange(e => {
|
this.tableDisposable.push(tableState.onMaximizedChange(e => {
|
||||||
if (e) {
|
if (e) {
|
||||||
this.maximizeTable(table.id);
|
this.maximizeTable(table.id);
|
||||||
} else {
|
} else {
|
||||||
this.minimizeTables();
|
this.minimizeTables();
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
this.tableDisposable.push(attachTableStyler(table, this.themeService));
|
this.tableDisposable.push(attachTableStyler(table, this.themeService));
|
||||||
|
|
||||||
tables.push(table);
|
tables.push(table);
|
||||||
@@ -237,11 +244,17 @@ export class GridPanel extends ViewletPanel {
|
|||||||
this.tables = this.tables.concat(tables);
|
this.tables = this.tables.concat(tables);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clear() {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
private reset() {
|
private reset() {
|
||||||
for (let i = this.splitView.length - 1; i >= 0; i--) {
|
for (let i = this.splitView.length - 1; i >= 0; i--) {
|
||||||
this.splitView.removeView(i);
|
this.splitView.removeView(i);
|
||||||
}
|
}
|
||||||
dispose(this.tables);
|
dispose(this.tables);
|
||||||
|
dispose(this.tableDisposable);
|
||||||
|
this.tableDisposable = [];
|
||||||
this.tables = [];
|
this.tables = [];
|
||||||
this.maximizedGrid = undefined;
|
this.maximizedGrid = undefined;
|
||||||
|
|
||||||
@@ -292,6 +305,15 @@ export class GridPanel extends ViewletPanel {
|
|||||||
public get state(): GridPanelState {
|
public get state(): GridPanelState {
|
||||||
return this._state;
|
return this._state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public dispose() {
|
||||||
|
dispose(this.queryRunnerDisposables);
|
||||||
|
dispose(this.tableDisposable);
|
||||||
|
dispose(this.tables);
|
||||||
|
this.tableDisposable = undefined;
|
||||||
|
this.tables = undefined;
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class GridTable<T> extends Disposable implements IView {
|
class GridTable<T> extends Disposable implements IView {
|
||||||
@@ -443,9 +465,9 @@ class GridTable<T> extends Disposable implements IView {
|
|||||||
|
|
||||||
private setupState() {
|
private setupState() {
|
||||||
// change actionbar on maximize change
|
// change actionbar on maximize change
|
||||||
this.state.onMaximizedChange(this.rebuildActionBar, this);
|
this._register(this.state.onMaximizedChange(this.rebuildActionBar, this));
|
||||||
|
|
||||||
this.state.onCanBeMaximizedChange(this.rebuildActionBar, this);
|
this._register(this.state.onCanBeMaximizedChange(this.rebuildActionBar, this));
|
||||||
|
|
||||||
if (this.state.scrollPosition) {
|
if (this.state.scrollPosition) {
|
||||||
// most of the time this won't do anything
|
// most of the time this won't do anything
|
||||||
@@ -655,6 +677,8 @@ class GridTable<T> extends Disposable implements IView {
|
|||||||
|
|
||||||
public dispose() {
|
public dispose() {
|
||||||
$(this.container).destroy();
|
$(this.container).destroy();
|
||||||
|
this.table.dispose();
|
||||||
|
this.actionBar.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
import 'vs/css!./media/messagePanel';
|
import 'vs/css!./media/messagePanel';
|
||||||
import { IMessagesActionContext, SelectAllMessagesAction, CopyMessagesAction } from './actions';
|
import { IMessagesActionContext, SelectAllMessagesAction, CopyMessagesAction } from './actions';
|
||||||
import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
import QueryRunner from 'sql/parts/query/execution/queryRunner';
|
||||||
|
import { QueryInput } from 'sql/parts/query/common/queryInput';
|
||||||
|
|
||||||
import { IResultMessage, ISelectionData } from 'sqlops';
|
import { IResultMessage, ISelectionData } from 'sqlops';
|
||||||
|
|
||||||
@@ -28,8 +29,6 @@ import { $ } from 'vs/base/browser/builder';
|
|||||||
import { isArray, isUndefinedOrNull } from 'vs/base/common/types';
|
import { isArray, isUndefinedOrNull } from 'vs/base/common/types';
|
||||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
import { IEditor } from 'vs/editor/common/editorCommon';
|
|
||||||
import { QueryInput } from 'sql/parts/query/common/queryInput';
|
|
||||||
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
|
||||||
|
|
||||||
export interface IResultMessageIntern extends IResultMessage {
|
export interface IResultMessageIntern extends IResultMessage {
|
||||||
@@ -71,6 +70,10 @@ export class MessagePanelState {
|
|||||||
this.collapsed = !messagesOpenedSettings;
|
this.collapsed = !messagesOpenedSettings;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MessagePanel extends ViewletPanel {
|
export class MessagePanel extends ViewletPanel {
|
||||||
@@ -102,6 +105,7 @@ export class MessagePanel extends ViewletPanel {
|
|||||||
renderer: this.renderer,
|
renderer: this.renderer,
|
||||||
controller: this.controller
|
controller: this.controller
|
||||||
}, { keyboardSupport: false, horizontalScrollMode: ScrollbarVisibility.Auto });
|
}, { keyboardSupport: false, horizontalScrollMode: ScrollbarVisibility.Auto });
|
||||||
|
this.disposables.push(this.tree);
|
||||||
this.tree.onDidScroll(e => {
|
this.tree.onDidScroll(e => {
|
||||||
if (this.state) {
|
if (this.state) {
|
||||||
this.state.scrollPosition = this.tree.getScrollPosition();
|
this.state.scrollPosition = this.tree.getScrollPosition();
|
||||||
@@ -117,7 +121,7 @@ export class MessagePanel extends ViewletPanel {
|
|||||||
protected renderBody(container: HTMLElement): void {
|
protected renderBody(container: HTMLElement): void {
|
||||||
this.container.style.width = '100%';
|
this.container.style.width = '100%';
|
||||||
this.container.style.height = '100%';
|
this.container.style.height = '100%';
|
||||||
attachListStyler(this.tree, this.themeService);
|
this.disposables.push(attachListStyler(this.tree, this.themeService));
|
||||||
container.appendChild(this.container);
|
container.appendChild(this.container);
|
||||||
this.tree.setInput(this.model);
|
this.tree.setInput(this.model);
|
||||||
}
|
}
|
||||||
@@ -193,9 +197,19 @@ export class MessagePanel extends ViewletPanel {
|
|||||||
}
|
}
|
||||||
this.setExpanded(!this.state.collapsed);
|
this.setExpanded(!this.state.collapsed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get state(): MessagePanelState {
|
public get state(): MessagePanelState {
|
||||||
return this._state;
|
return this._state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clear() {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public dispose() {
|
||||||
|
dispose(this.queryRunnerDisposables);
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MessageDataSource implements IDataSource {
|
class MessageDataSource implements IDataSource {
|
||||||
|
|||||||
@@ -478,11 +478,11 @@ export class QueryEditor extends BaseEditor {
|
|||||||
|
|
||||||
this.setTaskbarContent();
|
this.setTaskbarContent();
|
||||||
|
|
||||||
this._configurationService.onDidChangeConfiguration(e => {
|
this._toDispose.push(this._configurationService.onDidChangeConfiguration(e => {
|
||||||
if (e.affectedKeys.includes('workbench.enablePreviewFeatures')) {
|
if (e.affectedKeys.includes('workbench.enablePreviewFeatures')) {
|
||||||
this.setTaskbarContent();
|
this.setTaskbarContent();
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
private setTaskbarContent(): void {
|
private setTaskbarContent(): void {
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ export class QueryResultsEditor extends BaseEditor {
|
|||||||
public static ID: string = 'workbench.editor.queryResultsEditor';
|
public static ID: string = 'workbench.editor.queryResultsEditor';
|
||||||
public static AngularSelectorString: string = 'slickgrid-container.slickgridContainer';
|
public static AngularSelectorString: string = 'slickgrid-container.slickgridContainer';
|
||||||
protected _rawOptions: BareResultsGridInfo;
|
protected _rawOptions: BareResultsGridInfo;
|
||||||
protected _input: QueryResultsInput;
|
|
||||||
|
|
||||||
private resultsView: QueryResultsView;
|
private resultsView: QueryResultsView;
|
||||||
private styleSheet = DOM.createStyleSheet();
|
private styleSheet = DOM.createStyleSheet();
|
||||||
@@ -104,17 +103,17 @@ export class QueryResultsEditor extends BaseEditor {
|
|||||||
) {
|
) {
|
||||||
super(QueryResultsEditor.ID, telemetryService, themeService);
|
super(QueryResultsEditor.ID, telemetryService, themeService);
|
||||||
this._rawOptions = BareResultsGridInfo.createFromRawSettings(this._configurationService.getValue('resultsGrid'), getZoomLevel());
|
this._rawOptions = BareResultsGridInfo.createFromRawSettings(this._configurationService.getValue('resultsGrid'), getZoomLevel());
|
||||||
this._configurationService.onDidChangeConfiguration(e => {
|
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||||
if (e.affectsConfiguration('resultsGrid')) {
|
if (e.affectsConfiguration('resultsGrid')) {
|
||||||
this._rawOptions = BareResultsGridInfo.createFromRawSettings(this._configurationService.getValue('resultsGrid'), getZoomLevel());
|
this._rawOptions = BareResultsGridInfo.createFromRawSettings(this._configurationService.getValue('resultsGrid'), getZoomLevel());
|
||||||
this.applySettings();
|
this.applySettings();
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
this.applySettings();
|
this.applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get input(): QueryResultsInput {
|
public get input(): QueryResultsInput {
|
||||||
return this._input;
|
return this._input as QueryResultsInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
private applySettings() {
|
private applySettings() {
|
||||||
@@ -133,10 +132,16 @@ export class QueryResultsEditor extends BaseEditor {
|
|||||||
this.styleSheet.remove();
|
this.styleSheet.remove();
|
||||||
parent.appendChild(this.styleSheet);
|
parent.appendChild(this.styleSheet);
|
||||||
if (!this.resultsView) {
|
if (!this.resultsView) {
|
||||||
this.resultsView = new QueryResultsView(parent, this._instantiationService, this._queryModelService);
|
this.resultsView = this._register(new QueryResultsView(parent, this._instantiationService, this._queryModelService));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
this.styleSheet.remove();
|
||||||
|
this.styleSheet = undefined;
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
layout(dimension: DOM.Dimension): void {
|
layout(dimension: DOM.Dimension): void {
|
||||||
this.resultsView.layout(dimension);
|
this.resultsView.layout(dimension);
|
||||||
}
|
}
|
||||||
@@ -147,6 +152,11 @@ export class QueryResultsEditor extends BaseEditor {
|
|||||||
return TPromise.wrap<void>(null);
|
return TPromise.wrap<void>(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearInput() {
|
||||||
|
this.resultsView.clearInput();
|
||||||
|
super.clearInput();
|
||||||
|
}
|
||||||
|
|
||||||
public chart(dataId: { batchId: number, resultId: number }) {
|
public chart(dataId: { batchId: number, resultId: number }) {
|
||||||
this.resultsView.chartData(dataId);
|
this.resultsView.chartData(dataId);
|
||||||
}
|
}
|
||||||
@@ -154,11 +164,4 @@ export class QueryResultsEditor extends BaseEditor {
|
|||||||
public showQueryPlan(xml: string) {
|
public showQueryPlan(xml: string) {
|
||||||
this.resultsView.showPlan(xml);
|
this.resultsView.showPlan(xml);
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose(): void {
|
|
||||||
super.dispose();
|
|
||||||
if (this.resultsView) {
|
|
||||||
this.resultsView.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,6 +111,15 @@ class ResultsView extends Disposable implements IPanelView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public clear() {
|
||||||
|
this.gridPanel.clear();
|
||||||
|
this.messagePanel.clear();
|
||||||
|
}
|
||||||
|
|
||||||
remove(): void {
|
remove(): void {
|
||||||
this.container.remove();
|
this.container.remove();
|
||||||
}
|
}
|
||||||
@@ -151,6 +160,10 @@ class ResultsTab implements IPanelTab {
|
|||||||
public dispose() {
|
public dispose() {
|
||||||
dispose(this.view);
|
dispose(this.view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public clear() {
|
||||||
|
this.view.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class QueryResultsView extends Disposable {
|
export class QueryResultsView extends Disposable {
|
||||||
@@ -221,8 +234,11 @@ export class QueryResultsView extends Disposable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose() {
|
clearInput() {
|
||||||
this._panelView.dispose();
|
this._input = undefined;
|
||||||
|
this.resultsTab.clear();
|
||||||
|
this.qpTab.clear();
|
||||||
|
this.chartTab.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get input(): QueryResultsInput {
|
public get input(): QueryResultsInput {
|
||||||
@@ -264,4 +280,8 @@ export class QueryResultsView extends Disposable {
|
|||||||
this._panelView.removeTab(this.qpTab.identifier);
|
this._panelView.removeTab(this.qpTab.identifier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public dispose() {
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||